github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/fly/commands/watch.go (about) 1 package commands 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/url" 7 "os" 8 "strconv" 9 10 "github.com/pf-qiu/concourse/v6/atc" 11 "github.com/pf-qiu/concourse/v6/fly/commands/internal/flaghelpers" 12 "github.com/pf-qiu/concourse/v6/fly/eventstream" 13 "github.com/pf-qiu/concourse/v6/fly/rc" 14 ) 15 16 type WatchCommand struct { 17 Job flaghelpers.JobFlag `short:"j" long:"job" value-name:"PIPELINE/JOB" description:"Watches builds of the given job"` 18 Build string `short:"b" long:"build" description:"Watches a specific build"` 19 Url string `short:"u" long:"url" description:"URL for the build or job to watch"` 20 Timestamp bool `short:"t" long:"timestamps" description:"Print with local timestamp"` 21 IgnoreEventParsingErrors bool `long:"ignore-event-parsing-errors" description:"Ignore event parsing errors"` 22 } 23 24 func getBuildIDFromURL(target rc.Target, urlParam string) (int, error) { 25 var buildId int 26 client := target.Client() 27 28 u, err := url.Parse(urlParam) 29 if err != nil { 30 return 0, err 31 } 32 33 urlMap := parseUrlPath(u.Path) 34 35 parsedTargetUrl := url.URL{ 36 Scheme: u.Scheme, 37 Host: u.Host, 38 } 39 40 host := parsedTargetUrl.String() 41 if host != target.URL() { 42 err = fmt.Errorf("URL doesn't match target (%s, %s)", urlParam, target.URL()) 43 return 0, err 44 } 45 46 team := urlMap["teams"] 47 if team != "" && team != target.Team().Name() { 48 err = fmt.Errorf("Team in URL doesn't match the current team of the target (%s, %s)", urlParam, team) 49 return 0, err 50 } 51 52 if urlMap["pipelines"] != "" && urlMap["jobs"] != "" { 53 pipelineRef := atc.PipelineRef{Name: urlMap["pipelines"]} 54 if instanceVars := u.Query().Get("instance_vars"); instanceVars != "" { 55 err := json.Unmarshal([]byte(instanceVars), &pipelineRef.InstanceVars) 56 if err != nil { 57 err = fmt.Errorf("Failed to parse query params in (%s, %s)", urlParam, target.URL()) 58 return 0, err 59 } 60 } 61 build, err := GetBuild(client, target.Team(), urlMap["jobs"], urlMap["builds"], pipelineRef) 62 63 if err != nil { 64 return 0, err 65 } 66 buildId = build.ID 67 } else if urlMap["builds"] != "" { 68 buildId, err = strconv.Atoi(urlMap["builds"]) 69 70 if err != nil { 71 return 0, err 72 } 73 } else { 74 return 0, fmt.Errorf("No build found in %s", urlParam) 75 } 76 return buildId, nil 77 } 78 79 func (command *WatchCommand) Execute(args []string) error { 80 target, err := rc.LoadTarget(Fly.Target, Fly.Verbose) 81 if err != nil { 82 return err 83 } 84 85 err = target.Validate() 86 if err != nil { 87 return err 88 } 89 90 var buildId int 91 client := target.Client() 92 if command.Job.JobName != "" || command.Build == "" && command.Url == "" { 93 build, err := GetBuild(client, target.Team(), command.Job.JobName, command.Build, command.Job.PipelineRef) 94 if err != nil { 95 return err 96 } 97 buildId = build.ID 98 } else if command.Build != "" { 99 buildId, err = strconv.Atoi(command.Build) 100 101 if err != nil { 102 return err 103 } 104 } else if command.Url != "" { 105 buildId, err = getBuildIDFromURL(target, command.Url) 106 107 if err != nil { 108 return err 109 } 110 } 111 112 eventSource, err := client.BuildEvents(fmt.Sprintf("%d", buildId)) 113 if err != nil { 114 return err 115 } 116 117 renderOptions := eventstream.RenderOptions{ 118 ShowTimestamp: command.Timestamp, 119 IgnoreEventParsingErrors: command.IgnoreEventParsingErrors, 120 } 121 122 exitCode := eventstream.Render(os.Stdout, eventSource, renderOptions) 123 124 eventSource.Close() 125 126 os.Exit(exitCode) 127 128 return nil 129 }