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  }