func determineSkippedPresubmits(toTrigger, toSkipSuperset []config.Presubmit, logger *logrus.Entry) []config.Presubmit {
	triggeredContexts := sets.NewString()
	for _, presubmit := range toTrigger {
		triggeredContexts.Insert(presubmit.Context)
	}
	var toSkip []config.Presubmit
	for _, presubmit := range toSkipSuperset {
		if triggeredContexts.Has(presubmit.Context) {
			logger.WithFields(logrus.Fields{"context": presubmit.Context, "job": presubmit.Name}).Debug("Not skipping job as context will be created by a triggered job.")
			continue
		}
		toSkip = append(toSkip, presubmit)
	}
	return toSkip
}

func determineSkippedPresubmits ( toTrigger , toSkipSuperset [ ] config . Presubmit , logger * logrus . Entry ) [ ] config . Presubmit { triggeredContexts := sets . NewString ( ) for _ , presubmit := range toTrigger { triggeredContexts . Insert ( presubmit . Context ) } var toSkip [ ] config . Presubmit for _ , presubmit := range toSkipSuperset { if triggeredContexts . Has ( presubmit . Context ) { logger . WithFields ( logrus . Fields { " " : presubmit . Context , " " : presubmit . Name } ) . Debug ( " " ) continue } toSkip = append ( toSkip , presubmit ) } return toSkip }

// determineSkippedPresubmits identifies the largest set of contexts we can actually
// post skipped contexts for, given a set of presubmits we're triggering. We don't
// want to skip a job that posts a context that will be written to by a job we just
// identified for triggering or the skipped context will override the triggered one

determineSkippedPresubmits identifies the largest set of contexts we can actually post skipped contexts for given a set of presubmits we re triggering . We don t want to skip a job that posts a context that will be written to by a job we just identified for triggering or the skipped context will override the triggered one


func Dispatch(plugin plugins.Plugin, DB *InfluxDB, issues chan sql.Issue, eventsCommentsChannel chan interface{}) {
	for {
		var points []plugins.Point
		select {
		case issue, ok := <-issues:
			if !ok {
				return
			}
			points = plugin.ReceiveIssue(issue)
		case event, ok := <-eventsCommentsChannel:
			if !ok {
				return
			}
			switch event := event.(type) {
			case sql.IssueEvent:
				points = plugin.ReceiveIssueEvent(event)
			case sql.Comment:
				points = plugin.ReceiveComment(event)
			default:
				glog.Fatal("Received invalid object: ", event)
			}
		}

		for _, point := range points {
			if err := DB.Push(point.Tags, point.Values, point.Date); err != nil {
				glog.Fatal("Failed to push point: ", err)
			}
		}
	}
}

func Dispatch ( plugin plugins . Plugin , DB * InfluxDB , issues chan sql . Issue , eventsCommentsChannel chan interface { } ) { for { var points [ ] plugins . Point select { case issue , ok := <- issues : if ! ok { return } points = plugin . ReceiveIssue ( issue ) case event , ok := <- eventsCommentsChannel : if ! ok { return } switch event := event . ( type ) { case sql . IssueEvent : points = plugin . ReceiveIssueEvent ( event ) case sql . Comment : points = plugin . ReceiveComment ( event ) default : glog . Fatal ( " " , event ) } } for _ , point := range points { if err := DB . Push ( point . Tags , point . Values , point . Date ) ; err != nil { glog . Fatal ( " " , err ) } } } }

// Dispatch receives channels to each type of events, and dispatch them to each plugins.

Dispatch receives channels to each type of events and dispatch them to each plugins .


func (c *Client) CreateIssue(org, repo, title, body string, labels, assignees []string) (*github.Issue, error) {
	glog.Infof("CreateIssue(dry=%t) Title:%q, Labels:%q, Assignees:%q\n", c.dryRun, title, labels, assignees)
	if c.dryRun {
		return nil, nil
	}

	issue := &github.IssueRequest{
		Title: &title,
		Body:  &body,
	}
	if len(labels) > 0 {
		issue.Labels = &labels
	}
	if len(assignees) > 0 {
		issue.Assignees = &assignees
	}

	var result *github.Issue
	_, err := c.retry(
		fmt.Sprintf("creating issue '%s'", title),
		func() (*github.Response, error) {
			var resp *github.Response
			var err error
			result, resp, err = c.issueService.Create(context.Background(), org, repo, issue)
			return resp, err
		},
	)
	return result, err
}

func ( c * Client ) CreateIssue ( org , repo , title , body string , labels , assignees [ ] string ) ( * github . Issue , error ) { glog . Infof ( " \n " , c . dryRun , title , labels , assignees ) if c . dryRun { return nil , nil } issue := & github . IssueRequest { Title : & title , Body : & body , } if len ( labels ) > 0 { issue . Labels = & labels } if len ( assignees ) > 0 { issue . Assignees = & assignees } var result * github . Issue _ , err := c . retry ( fmt . Sprintf ( " " , title ) , func ( ) ( * github . Response , error ) { var resp * github . Response var err error result , resp , err = c . issueService . Create ( context . Background ( ) , org , repo , issue ) return resp , err } , ) return result , err }

// CreateIssue tries to create and return a new github issue.

CreateIssue tries to create and return a new github issue .


func (c *Client) CreateStatus(owner, repo, ref string, status *github.RepoStatus) (*github.RepoStatus, error) {
	glog.Infof("CreateStatus(dry=%t) ref:%s: %s:%s", c.dryRun, ref, *status.Context, *status.State)
	if c.dryRun {
		return nil, nil
	}
	var result *github.RepoStatus
	msg := fmt.Sprintf("creating status for ref '%s'", ref)
	_, err := c.retry(msg, func() (*github.Response, error) {
		var resp *github.Response
		var err error
		result, resp, err = c.repoService.CreateStatus(context.Background(), owner, repo, ref, status)
		return resp, err
	})
	return result, err
}

func ( c * Client ) CreateStatus ( owner , repo , ref string , status * github . RepoStatus ) ( * github . RepoStatus , error ) { glog . Infof ( " " , c . dryRun , ref , * status . Context , * status . State ) if c . dryRun { return nil , nil } var result * github . RepoStatus msg := fmt . Sprintf ( " " , ref ) _ , err := c . retry ( msg , func ( ) ( * github . Response , error ) { var resp * github . Response var err error result , resp , err = c . repoService . CreateStatus ( context . Background ( ) , owner , repo , ref , status ) return resp , err } ) return result , err }

// CreateStatus creates or updates a status context on the indicated reference.

CreateStatus creates or updates a status context on the indicated reference .


func (c *Client) ForEachPR(owner, repo string, opts *github.PullRequestListOptions, continueOnError bool, mungePR PRMungeFunc) error {
	var lastPage int
	// Munge each page as we get it (or in other words, wait until we are ready to munge the next
	// page of issues before getting it). We use depaginate to make the calls, but don't care about
	// the slice it returns since we consume the pages as we go.
	_, err := c.depaginate(
		"processing PRs",
		&opts.ListOptions,
		func() ([]interface{}, *github.Response, error) {
			list, resp, err := c.prService.List(context.Background(), owner, repo, opts)
			if err == nil {
				for _, pr := range list {
					if pr == nil {
						glog.Errorln("Received a nil PR from go-github while listing PRs. Skipping...")
					}
					if mungeErr := mungePR(pr); mungeErr != nil {
						if pr.Number == nil {
							mungeErr = fmt.Errorf("error munging pull request with nil Number field: %v", mungeErr)
						} else {
							mungeErr = fmt.Errorf("error munging pull request #%d: %v", *pr.Number, mungeErr)
						}
						if !continueOnError {
							return nil, resp, &retryAbort{mungeErr}
						}
						glog.Errorf("%v\n", mungeErr)
					}
				}
				if resp.LastPage > 0 {
					lastPage = resp.LastPage
				}
				glog.Infof("ForEachPR processed page %d/%d\n", opts.ListOptions.Page, lastPage)
			}
			return nil, resp, err
		},
	)
	return err
}

// ForEachPR iterates over all PRs that fit the specified criteria, calling the munge function on every PR.
// If the munge function returns a non-nil error, ForEachPR will return immediately with a non-nil
// error unless continueOnError is true in which case an error will be logged and the remaining PRs will be munged.

ForEachPR iterates over all PRs that fit the specified criteria calling the munge function on every PR . If the munge function returns a non - nil error ForEachPR will return immediately with a non - nil error unless continueOnError is true in which case an error will be logged and the remaining PRs will be munged .


func (c *Client) GetCollaborators(org, repo string) ([]*github.User, error) {
	opts := &github.ListCollaboratorsOptions{}
	collaborators, err := c.depaginate(
		fmt.Sprintf("getting collaborators for '%s/%s'", org, repo),
		&opts.ListOptions,
		func() ([]interface{}, *github.Response, error) {
			page, resp, err := c.repoService.ListCollaborators(context.Background(), org, repo, opts)

			var interfaceList []interface{}
			if err == nil {
				interfaceList = make([]interface{}, 0, len(page))
				for _, user := range page {
					interfaceList = append(interfaceList, user)
				}
			}
			return interfaceList, resp, err
		},
	)

	result := make([]*github.User, 0, len(collaborators))
	for _, user := range collaborators {
		result = append(result, user.(*github.User))
	}
	return result, err
}

func ( c * Client ) GetCollaborators ( org , repo string ) ( [ ] * github . User , error ) { opts := & github . ListCollaboratorsOptions { } collaborators , err := c . depaginate ( fmt . Sprintf ( " " , org , repo ) , & opts . ListOptions , func ( ) ( [ ] interface { } , * github . Response , error ) { page , resp , err := c . repoService . ListCollaborators ( context . Background ( ) , org , repo , opts ) var interfaceList [ ] interface { } if err == nil { interfaceList = make ( [ ] interface { } , 0 , len ( page ) ) for _ , user := range page { interfaceList = append ( interfaceList , user ) } } return interfaceList , resp , err } , ) result := make ( [ ] * github . User , 0 , len ( collaborators ) ) for _ , user := range collaborators { result = append ( result , user . ( * github . User ) ) } return result , err }

// GetCollaborators returns all github users who are members or outside collaborators of the repo.

GetCollaborators returns all github users who are members or outside collaborators of the repo .


func (c *Client) GetCombinedStatus(owner, repo, ref string) (*github.CombinedStatus, error) {
	var result *github.CombinedStatus
	listOpts := &github.ListOptions{}

	statuses, err := c.depaginate(
		fmt.Sprintf("getting combined status for ref '%s'", ref),
		listOpts,
		func() ([]interface{}, *github.Response, error) {
			combined, resp, err := c.repoService.GetCombinedStatus(
				context.Background(),
				owner,
				repo,
				ref,
				listOpts,
			)
			if result == nil {
				result = combined
			}

			var interfaceList []interface{}
			if err == nil {
				interfaceList = make([]interface{}, 0, len(combined.Statuses))
				for _, status := range combined.Statuses {
					interfaceList = append(interfaceList, status)
				}
			}
			return interfaceList, resp, err
		},
	)

	if result != nil {
		result.Statuses = make([]github.RepoStatus, 0, len(statuses))
		for _, status := range statuses {
			result.Statuses = append(result.Statuses, status.(github.RepoStatus))
		}
	}

	return result, err
}

func ( c * Client ) GetCombinedStatus ( owner , repo , ref string ) ( * github . CombinedStatus , error ) { var result * github . CombinedStatus listOpts := & github . ListOptions { } statuses , err := c . depaginate ( fmt . Sprintf ( " " , ref ) , listOpts , func ( ) ( [ ] interface { } , * github . Response , error ) { combined , resp , err := c . repoService . GetCombinedStatus ( context . Background ( ) , owner , repo , ref , listOpts , ) if result == nil { result = combined } var interfaceList [ ] interface { } if err == nil { interfaceList = make ( [ ] interface { } , 0 , len ( combined . Statuses ) ) for _ , status := range combined . Statuses { interfaceList = append ( interfaceList , status ) } } return interfaceList , resp , err } , ) if result != nil { result . Statuses = make ( [ ] github . RepoStatus , 0 , len ( statuses ) ) for _ , status := range statuses { result . Statuses = append ( result . Statuses , status . ( github . RepoStatus ) ) } } return result , err }

// GetCombinedStatus retrieves the CombinedStatus for the specified reference.

GetCombinedStatus retrieves the CombinedStatus for the specified reference .


func (c *Client) GetIssues(org, repo string, opts *github.IssueListByRepoOptions) ([]*github.Issue, error) {
	issues, err := c.depaginate(
		fmt.Sprintf("getting issues from '%s/%s'", org, repo),
		&opts.ListOptions,
		func() ([]interface{}, *github.Response, error) {
			page, resp, err := c.issueService.ListByRepo(context.Background(), org, repo, opts)

			var interfaceList []interface{}
			if err == nil {
				interfaceList = make([]interface{}, 0, len(page))
				for _, issue := range page {
					interfaceList = append(interfaceList, issue)
				}
			}
			return interfaceList, resp, err
		},
	)

	result := make([]*github.Issue, 0, len(issues))
	for _, issue := range issues {
		result = append(result, issue.(*github.Issue))
	}
	return result, err
}

func ( c * Client ) GetIssues ( org , repo string , opts * github . IssueListByRepoOptions ) ( [ ] * github . Issue , error ) { issues , err := c . depaginate ( fmt . Sprintf ( " " , org , repo ) , & opts . ListOptions , func ( ) ( [ ] interface { } , * github . Response , error ) { page , resp , err := c . issueService . ListByRepo ( context . Background ( ) , org , repo , opts ) var interfaceList [ ] interface { } if err == nil { interfaceList = make ( [ ] interface { } , 0 , len ( page ) ) for _ , issue := range page { interfaceList = append ( interfaceList , issue ) } } return interfaceList , resp , err } , ) result := make ( [ ] * github . Issue , 0 , len ( issues ) ) for _ , issue := range issues { result = append ( result , issue . ( * github . Issue ) ) } return result , err }

// GetIssues gets all the issues in a repo that meet the list options.

GetIssues gets all the issues in a repo that meet the list options .


func (c *Client) GetRepoLabels(org, repo string) ([]*github.Label, error) {
	opts := &github.ListOptions{}
	labels, err := c.depaginate(
		fmt.Sprintf("getting valid labels for '%s/%s'", org, repo),
		opts,
		func() ([]interface{}, *github.Response, error) {
			page, resp, err := c.issueService.ListLabels(context.Background(), org, repo, opts)

			var interfaceList []interface{}
			if err == nil {
				interfaceList = make([]interface{}, 0, len(page))
				for _, label := range page {
					interfaceList = append(interfaceList, label)
				}
			}
			return interfaceList, resp, err
		},
	)

	result := make([]*github.Label, 0, len(labels))
	for _, label := range labels {
		result = append(result, label.(*github.Label))
	}
	return result, err
}

func ( c * Client ) GetRepoLabels ( org , repo string ) ( [ ] * github . Label , error ) { opts := & github . ListOptions { } labels , err := c . depaginate ( fmt . Sprintf ( " " , org , repo ) , opts , func ( ) ( [ ] interface { } , * github . Response , error ) { page , resp , err := c . issueService . ListLabels ( context . Background ( ) , org , repo , opts ) var interfaceList [ ] interface { } if err == nil { interfaceList = make ( [ ] interface { } , 0 , len ( page ) ) for _ , label := range page { interfaceList = append ( interfaceList , label ) } } return interfaceList , resp , err } , ) result := make ( [ ] * github . Label , 0 , len ( labels ) ) for _ , label := range labels { result = append ( result , label . ( * github . Label ) ) } return result , err }

// GetRepoLabels gets all the labels that valid in the specified repo.

GetRepoLabels gets all the labels that valid in the specified repo .


func (c *Client) GetUser(login string) (*github.User, error) {
	var result *github.User
	_, err := c.retry(
		fmt.Sprintf("getting user '%s'", login),
		func() (*github.Response, error) {
			var resp *github.Response
			var err error
			result, resp, err = c.userService.Get(context.Background(), login)
			return resp, err
		},
	)
	return result, err
}

func ( c * Client ) GetUser ( login string ) ( * github . User , error ) { var result * github . User _ , err := c . retry ( fmt . Sprintf ( " " , login ) , func ( ) ( * github . Response , error ) { var resp * github . Response var err error result , resp , err = c . userService . Get ( context . Background ( ) , login ) return resp , err } , ) return result , err }

// GetUser gets the github user with the specified login or the currently authenticated user.
// To get the currently authenticated user specify a login of "".

GetUser gets the github user with the specified login or the currently authenticated user . To get the currently authenticated user specify a login of .


func checkConfigValidity() error {
	glog.Info("Verifying if a valid config has been provided through the flags")
	if *nodeName == "" {
		return fmt.Errorf("Flag --node-name has its value unspecified")
	}
	if *gcsPath == "" {
		return fmt.Errorf("Flag --gcs-path has its value unspecified")
	}
	if _, err := os.Stat(*gcloudAuthFilePath); err != nil {
		return fmt.Errorf("Could not find the gcloud service account file: %v", err)
	} else {
		glog.Infof("Running gcloud auth activate-service-account --key-file=%s\n", *gcloudAuthFilePath)
		cmd := exec.Command("gcloud", "auth", "activate-service-account", "--key-file="+*gcloudAuthFilePath)
		var stderr, stdout bytes.Buffer
		cmd.Stderr, cmd.Stdout = &stderr, &stdout
		err = cmd.Run()
		glog.Infof("Stdout:\n%s\n", stdout.String())
		glog.Infof("Stderr:\n%s\n", stderr.String())
		if err != nil {
			return fmt.Errorf("Failed to activate gcloud service account: %v", err)
		}
	}
	return nil
}

func checkConfigValidity ( ) error { glog . Info ( " " ) if * nodeName == " " { return fmt . Errorf ( " " ) } if * gcsPath == " " { return fmt . Errorf ( " " ) } if _ , err := os . Stat ( * gcloudAuthFilePath ) ; err != nil { return fmt . Errorf ( " " , err ) } else { glog . Infof ( " \n " , * gcloudAuthFilePath ) cmd := exec . Command ( " " , " " , " " , " " + * gcloudAuthFilePath ) var stderr , stdout bytes . Buffer cmd . Stderr , cmd . Stdout = & stderr , & stdout err = cmd . Run ( ) glog . Infof ( " \n \n " , stdout . String ( ) ) glog . Infof ( " \n \n " , stderr . String ( ) ) if err != nil { return fmt . Errorf ( " " , err ) } } return nil }

// Check if the config provided through the flags take valid values.

Check if the config provided through the flags take valid values .


func createSystemdLogfile(service string, outputMode string, outputDir string) error {
	// Generate the journalctl command.
	journalCmdArgs := []string{fmt.Sprintf("--output=%v", outputMode), "-D", *journalPath}
	if service == "kern" {
		journalCmdArgs = append(journalCmdArgs, "-k")
	} else {
		journalCmdArgs = append(journalCmdArgs, "-u", fmt.Sprintf("%v.service", service))
	}
	cmd := exec.Command("journalctl", journalCmdArgs...)

	// Run the command and record the output to a file.
	output, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("Journalctl command for '%v' service failed: %v", service, err)
	}
	logfile := filepath.Join(outputDir, service+".log")
	if err := ioutil.WriteFile(logfile, output, 0444); err != nil {
		return fmt.Errorf("Writing to file of journalctl logs for '%v' service failed: %v", service, err)
	}
	return nil
}

// Create logfile for systemd service in outputDir with the given journalctl outputMode.

Create logfile for systemd service in outputDir with the given journalctl outputMode .


func createFullSystemdLogfile(outputDir string) error {
	cmd := exec.Command("journalctl", "--output=short-precise", "-D", *journalPath)
	// Run the command and record the output to a file.
	output, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("Journalctl command failed: %v", err)
	}
	logfile := filepath.Join(outputDir, "systemd.log")
	if err := ioutil.WriteFile(logfile, output, 0444); err != nil {
		return fmt.Errorf("Writing full journalctl logs to file failed: %v", err)
	}
	return nil
}

// createFullSystemdLogfile creates logfile for full systemd journal in the outputDir.

createFullSystemdLogfile creates logfile for full systemd journal in the outputDir .


func createSystemdLogfiles(outputDir string) {
	services := append(systemdServices, nodeSystemdServices...)
	for _, service := range services {
		if err := createSystemdLogfile(service, "cat", outputDir); err != nil {
			glog.Warningf("Failed to record journalctl logs: %v", err)
		}
	}
	// Service logs specific to VM setup.
	for _, service := range systemdSetupServices {
		if err := createSystemdLogfile(service, "short-precise", outputDir); err != nil {
			glog.Warningf("Failed to record journalctl logs: %v", err)
		}
	}
	if *dumpSystemdJournal {
		if err := createFullSystemdLogfile(outputDir); err != nil {
			glog.Warningf("Failed to record journalctl logs: %v", err)
		}
	}
}

func
createSystemdLogfiles
(
outputDir
string
)
{
services
:=
append
(
systemdServices
,
nodeSystemdServices
...
)
for
_
,
service
:=
range
services
{
if
err
:=
createSystemdLogfile
(
service
,
"
"
,
outputDir
)
;
err
!=
{
glog
.
Warningf
(
"
"
,
err
)
}
}
// Service logs specific to VM setup.
for
_
,
service
:=
range
systemdSetupServices
{
if
err
:=
createSystemdLogfile
(
service
,
"
"
,
outputDir
)
;
err
!=
{
glog
.
Warningf
(
"
"
,
err
)
}
}
if
*
dumpSystemdJournal
{
if
err
:=
createFullSystemdLogfile
(
outputDir
)
;
err
!=
{
glog
.
Warningf
(
"
"
,
err
)
}
}
}

// Create logfiles for systemd services in outputDir.

Create logfiles for systemd services in outputDir .


func prepareLogfiles(logDir string) {
	glog.Info("Preparing logfiles relevant to this node")
	logfiles := nodeLogs[:]

	switch *cloudProvider {
	case "gce", "gke":
		logfiles = append(logfiles, gceLogs...)
	case "aws":
		logfiles = append(logfiles, awsLogs...)
	default:
		glog.Errorf("Unknown cloud provider '%v' provided, skipping any provider specific logs", *cloudProvider)
	}

	// Grab kubemark logs too, if asked for.
	if *enableHollowNodeLogs {
		logfiles = append(logfiles, kubemarkLogs...)
	}

	// Select system/service specific logs.
	if _, err := os.Stat("/workspace/etc/systemd/journald.conf"); err == nil {
		glog.Info("Journalctl found on host. Collecting systemd logs")
		createSystemdLogfiles(logDir)
	} else {
		glog.Infof("Journalctl not found on host (%v). Collecting supervisord logs instead", err)
		logfiles = append(logfiles, kernelLog)
		logfiles = append(logfiles, initdLogs...)
		logfiles = append(logfiles, supervisordLogs...)
	}

	// Copy all the logfiles that exist, to logDir.
	for _, logfile := range logfiles {
		logfileFullPath := filepath.Join(localLogPath, logfile+".log*") // Append .log* to copy rotated logs too.
		cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("cp %v %v", logfileFullPath, logDir))
		if err := cmd.Run(); err != nil {
			glog.Warningf("Failed to copy any logfiles with pattern '%v': %v", logfileFullPath, err)
		}
	}
}

// Copy logfiles specific to this node based on the cloud-provider, system services, etc
// to a temporary directory. Also create logfiles for systemd services if journalctl is present.
// We do not expect this function to see an error.

Copy logfiles specific to this node based on the cloud - provider system services etc to a temporary directory . Also create logfiles for systemd services if journalctl is present . We do not expect this function to see an error .


func writeSuccessMarkerFile() error {
	markerFilePath := *gcsPath + "/logexported-nodes-registry/" + *nodeName + ".txt"
	cmd := exec.Command("gsutil", "-q", "cp", "-a", "public-read", "-", markerFilePath)
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return fmt.Errorf("Failed to get stdin pipe to write marker file: %v", err)
	}
	io.WriteString(stdin, "")
	stdin.Close()
	if err = cmd.Run(); err != nil {
		return fmt.Errorf("Failed to write marker file to GCS: %v", err)
	}
	return nil
}

func writeSuccessMarkerFile ( ) error { markerFilePath := * gcsPath + " " + * nodeName + " " cmd := exec . Command ( " " , " " , " " , " " , " " , " " , markerFilePath ) stdin , err := cmd . StdinPipe ( ) if err != nil { return fmt . Errorf ( " " , err ) } io . WriteString ( stdin , " " ) stdin . Close ( ) if err = cmd . Run ( ) ; err != nil { return fmt . Errorf ( " " , err ) } return nil }

// Write a marker file to GCS named after this node to indicate logexporter's success.
// The directory to which we write this file can then be used as a registry to quickly
// fetch the list of nodes on which logexporter succeeded.

Write a marker file to GCS named after this node to indicate logexporter s success . The directory to which we write this file can then be used as a registry to quickly fetch the list of nodes on which logexporter succeeded .


func MakeCommand() *cobra.Command {
	flags := &flags{}
	cmd := &cobra.Command{
		Use:   "junit [profile]",
		Short: "Summarize coverage profile and produce the result in junit xml format.",
		Long: `Summarize coverage profile and produce the result in junit xml format.
Summary done at per-file and per-package level. Any coverage below coverage-threshold will be marked
with a <failure> tag in the xml produced.`,
		Run: func(cmd *cobra.Command, args []string) {
			run(flags, cmd, args)
		},
	}
	cmd.Flags().StringVarP(&flags.outputFile, "output", "o", "-", "output file")
	cmd.Flags().Float32VarP(&flags.threshold, "threshold", "t", .8, "code coverage threshold")
	return cmd
}

// MakeCommand returns a `junit` command.


func warnDeprecated(last *time.Time, freq time.Duration, msg string) {
	// have we warned within the last freq?
	warnLock.RLock()
	fresh := time.Now().Sub(*last) <= freq
	warnLock.RUnlock()
	if fresh { // we've warned recently
		return
	}
	// Warning is stale, will we win the race to warn?
	warnLock.Lock()
	defer warnLock.Unlock()
	now := time.Now()           // Recalculate now, we might wait awhile for the lock
	if now.Sub(*last) <= freq { // Nope, we lost
		return
	}
	*last = now
	logrus.Warn(msg)
}

// warnDeprecated prints a deprecation warning for a particular configuration
// option.

warnDeprecated prints a deprecation warning for a particular configuration option .


func (r RequireMatchingLabel) Describe() string {
	str := &strings.Builder{}
	fmt.Fprintf(str, "Applies the '%s' label ", r.MissingLabel)
	if r.MissingComment == "" {
		fmt.Fprint(str, "to ")
	} else {
		fmt.Fprint(str, "and comments on ")
	}

	if r.Issues {
		fmt.Fprint(str, "Issues ")
		if r.PRs {
			fmt.Fprint(str, "and ")
		}
	}
	if r.PRs {
		if r.Branch != "" {
			fmt.Fprintf(str, "'%s' branch ", r.Branch)
		}
		fmt.Fprint(str, "PRs ")
	}

	if r.Repo == "" {
		fmt.Fprintf(str, "in the '%s' GitHub org ", r.Org)
	} else {
		fmt.Fprintf(str, "in the '%s/%s' GitHub repo ", r.Org, r.Repo)
	}
	fmt.Fprintf(str, "that have no labels matching the regular expression '%s'.", r.Regexp)
	return str.String()
}

func ( r RequireMatchingLabel ) Describe ( ) string { str := & strings . Builder { } fmt . Fprintf ( str , " " , r . MissingLabel ) if r . MissingComment == " " { fmt . Fprint ( str , " " ) } else { fmt . Fprint ( str , " " ) } if r . Issues { fmt . Fprint ( str , " " ) if r . PRs { fmt . Fprint ( str , " " ) } } if r . PRs { if r . Branch != " " { fmt . Fprintf ( str , " " , r . Branch ) } fmt . Fprint ( str , " " ) } if r . Repo == " " { fmt . Fprintf ( str , " " , r . Org ) } else { fmt . Fprintf ( str , " " , r . Org , r . Repo ) } fmt . Fprintf ( str , " " , r . Regexp ) return str . String ( ) }

// Describe generates a human readable description of the behavior that this
// configuration specifies.

Describe generates a human readable description of the behavior that this configuration specifies .


func (c *Configuration) TriggerFor(org, repo string) Trigger {
	for _, tr := range c.Triggers {
		for _, r := range tr.Repos {
			if r == org || r == fmt.Sprintf("%s/%s", org, repo) {
				return tr
			}
		}
	}
	return Trigger{}
}

func ( c * Configuration ) TriggerFor ( org , repo string ) Trigger { for _ , tr := range c . Triggers { for _ , r := range tr . Repos { if r == org || r == fmt . Sprintf ( " " , org , repo ) { return tr } } } return Trigger { } }

// TriggerFor finds the Trigger for a repo, if one exists
// a trigger can be listed for the repo itself or for the
// owning organization

TriggerFor finds the Trigger for a repo if one exists a trigger can be listed for the repo itself or for the owning organization


func (c *Configuration) EnabledReposForPlugin(plugin string) (orgs, repos []string) {
	for repo, plugins := range c.Plugins {
		found := false
		for _, candidate := range plugins {
			if candidate == plugin {
				found = true
				break
			}
		}
		if found {
			if strings.Contains(repo, "/") {
				repos = append(repos, repo)
			} else {
				orgs = append(orgs, repo)
			}
		}
	}
	return
}

func ( c * Configuration ) EnabledReposForPlugin ( plugin string ) ( orgs , repos [ ] string ) { for repo , plugins := range c . Plugins { found := false for _ , candidate := range plugins { if candidate == plugin { found = true break } } if found { if strings . Contains ( repo , " " ) { repos = append ( repos , repo ) } else { orgs = append ( orgs , repo ) } } } return }

// EnabledReposForPlugin returns the orgs and repos that have enabled the passed plugin.

EnabledReposForPlugin returns the orgs and repos that have enabled the passed plugin .


func (c *Configuration) EnabledReposForExternalPlugin(plugin string) (orgs, repos []string) {
	for repo, plugins := range c.ExternalPlugins {
		found := false
		for _, candidate := range plugins {
			if candidate.Name == plugin {
				found = true
				break
			}
		}
		if found {
			if strings.Contains(repo, "/") {
				repos = append(repos, repo)
			} else {
				orgs = append(orgs, repo)
			}
		}
	}
	return
}

func ( c * Configuration ) EnabledReposForExternalPlugin ( plugin string ) ( orgs , repos [ ] string ) { for repo , plugins := range c . ExternalPlugins { found := false for _ , candidate := range plugins { if candidate . Name == plugin { found = true break } } if found { if strings . Contains ( repo , " " ) { repos = append ( repos , repo ) } else { orgs = append ( orgs , repo ) } } } return }

// EnabledReposForExternalPlugin returns the orgs and repos that have enabled the passed
// external plugin.

EnabledReposForExternalPlugin returns the orgs and repos that have enabled the passed external plugin .


func (c *ConfigUpdater) SetDefaults() {
	if len(c.Maps) == 0 {
		cf := c.ConfigFile
		if cf == "" {
			cf = "prow/config.yaml"
		} else {
			logrus.Warnf(`config_file is deprecated, please switch to "maps": {"%s": "config"} before July 2018`, cf)
		}
		pf := c.PluginFile
		if pf == "" {
			pf = "prow/plugins.yaml"
		} else {
			logrus.Warnf(`plugin_file is deprecated, please switch to "maps": {"%s": "plugins"} before July 2018`, pf)
		}
		c.Maps = map[string]ConfigMapSpec{
			cf: {
				Name: "config",
			},
			pf: {
				Name: "plugins",
			},
		}
	}

	for name, spec := range c.Maps {
		spec.Namespaces = append([]string{spec.Namespace}, spec.AdditionalNamespaces...)
		c.Maps[name] = spec
	}
}

// SetDefaults sets default options for config updating


func validatePlugins(plugins map[string][]string) error {
	var errors []string
	for _, configuration := range plugins {
		for _, plugin := range configuration {
			if _, ok := pluginHelp[plugin]; !ok {
				errors = append(errors, fmt.Sprintf("unknown plugin: %s", plugin))
			}
		}
	}
	for repo, repoConfig := range plugins {
		if strings.Contains(repo, "/") {
			org := strings.Split(repo, "/")[0]
			if dupes := findDuplicatedPluginConfig(repoConfig, plugins[org]); len(dupes) > 0 {
				errors = append(errors, fmt.Sprintf("plugins %v are duplicated for %s and %s", dupes, repo, org))
			}
		}
	}

	if len(errors) > 0 {
		return fmt.Errorf("invalid plugin configuration:\n\t%v", strings.Join(errors, "\n\t"))
	}
	return nil
}

func validatePlugins ( plugins map [ string ] [ ] string ) error { var errors [ ] string for _ , configuration := range plugins { for _ , plugin := range configuration { if _ , ok := pluginHelp [ plugin ] ; ! ok { errors = append ( errors , fmt . Sprintf ( " " , plugin ) ) } } } for repo , repoConfig := range plugins { if strings . Contains ( repo , " " ) { org := strings . Split ( repo , " " ) [ 0 ] if dupes := findDuplicatedPluginConfig ( repoConfig , plugins [ org ] ) ; len ( dupes ) > 0 { errors = append ( errors , fmt . Sprintf ( " " , dupes , repo , org ) ) } } } if len ( errors ) > 0 { return fmt . Errorf ( " \n \t " , strings . Join ( errors , " \n \t " ) ) } return nil }

// validatePlugins will return error if
// there are unknown or duplicated plugins.

validatePlugins will return error if there are unknown or duplicated plugins .


func (c *Client) ShouldReport(pj *v1.ProwJob) bool {

	if pj.Status.State == v1.TriggeredState || pj.Status.State == v1.PendingState {
		// not done yet
		logrus.WithField("prowjob", pj.ObjectMeta.Name).Info("PJ not finished")
		return false
	}

	if pj.Status.State == v1.AbortedState {
		// aborted (new patchset)
		logrus.WithField("prowjob", pj.ObjectMeta.Name).Info("PJ aborted")
		return false
	}

	// has gerrit metadata (scheduled by gerrit adapter)
	if pj.ObjectMeta.Annotations[client.GerritID] == "" ||
		pj.ObjectMeta.Annotations[client.GerritInstance] == "" ||
		pj.ObjectMeta.Labels[client.GerritRevision] == "" {
		logrus.WithField("prowjob", pj.ObjectMeta.Name).Info("Not a gerrit job")
		return false
	}

	// Only report when all jobs of the same type on the same revision finished
	selector := labels.Set{
		client.GerritRevision: pj.ObjectMeta.Labels[client.GerritRevision],
		kube.ProwJobTypeLabel: pj.ObjectMeta.Labels[kube.ProwJobTypeLabel],
	}

	if pj.ObjectMeta.Labels[client.GerritReportLabel] == "" {
		// Shouldn't happen, adapter should already have defaulted to Code-Review
		logrus.Errorf("Gerrit report label not set for job %s", pj.Spec.Job)
	} else {
		selector[client.GerritReportLabel] = pj.ObjectMeta.Labels[client.GerritReportLabel]
	}

	pjs, err := c.lister.List(selector.AsSelector())
	if err != nil {
		logrus.WithError(err).Errorf("Cannot list prowjob with selector %v", selector)
		return false
	}

	for _, pjob := range pjs {
		if pjob.Status.State == v1.TriggeredState || pjob.Status.State == v1.PendingState {
			// other jobs with same label are still running on this revision, skip report
			logrus.WithField("prowjob", pjob.ObjectMeta.Name).Info("Other jobs with same label are still running on this revision")
			return false
		}
	}

	return true
}

// ShouldReport returns if this prowjob should be reported by the gerrit reporter


func Run(refs prowapi.Refs, dir, gitUserName, gitUserEmail, cookiePath string, env []string) Record {
	logrus.WithFields(logrus.Fields{"refs": refs}).Info("Cloning refs")
	record := Record{Refs: refs}

	// This function runs the provided commands in order, logging them as they run,
	// aborting early and returning if any command fails.
	runCommands := func(commands []cloneCommand) error {
		for _, command := range commands {
			formattedCommand, output, err := command.run()
			logrus.WithFields(logrus.Fields{"command": formattedCommand, "output": output, "error": err}).Info("Ran command")
			message := ""
			if err != nil {
				message = err.Error()
				record.Failed = true
			}
			record.Commands = append(record.Commands, Command{Command: formattedCommand, Output: output, Error: message})
			if err != nil {
				return err
			}
		}
		return nil
	}

	g := gitCtxForRefs(refs, dir, env)
	if err := runCommands(g.commandsForBaseRef(refs, gitUserName, gitUserEmail, cookiePath)); err != nil {
		return record
	}

	timestamp, err := g.gitHeadTimestamp()
	if err != nil {
		timestamp = int(time.Now().Unix())
	}
	if err := runCommands(g.commandsForPullRefs(refs, timestamp)); err != nil {
		return record
	}

	finalSHA, err := g.gitRevParse()
	if err != nil {
		logrus.WithError(err).Warnf("Cannot resolve finalSHA for ref %#v", refs)
	} else {
		record.FinalSHA = finalSHA
	}

	return record
}

// Run clones the refs under the prescribed directory and optionally
// configures the git username and email in the repository as well.

Run clones the refs under the prescribed directory and optionally configures the git username and email in the repository as well .


func PathForRefs(baseDir string, refs prowapi.Refs) string {
	var clonePath string
	if refs.PathAlias != "" {
		clonePath = refs.PathAlias
	} else {
		clonePath = fmt.Sprintf("github.com/%s/%s", refs.Org, refs.Repo)
	}
	return fmt.Sprintf("%s/src/%s", baseDir, clonePath)
}

func PathForRefs ( baseDir string , refs prowapi . Refs ) string { var clonePath string if refs . PathAlias != " " { clonePath = refs . PathAlias } else { clonePath = fmt . Sprintf ( " " , refs . Org , refs . Repo ) } return fmt . Sprintf ( " " , baseDir , clonePath ) }

// PathForRefs determines the full path to where
// refs should be cloned

PathForRefs determines the full path to where refs should be cloned


func gitCtxForRefs(refs prowapi.Refs, baseDir string, env []string) gitCtx {
	g := gitCtx{
		cloneDir:      PathForRefs(baseDir, refs),
		env:           env,
		repositoryURI: fmt.Sprintf("https://github.com/%s/%s.git", refs.Org, refs.Repo),
	}
	if refs.CloneURI != "" {
		g.repositoryURI = refs.CloneURI
	}
	return g
}

func gitCtxForRefs ( refs prowapi . Refs , baseDir string , env [ ] string ) gitCtx { g := gitCtx { cloneDir : PathForRefs ( baseDir , refs ) , env : env , repositoryURI : fmt . Sprintf ( " " , refs . Org , refs . Repo ) , } if refs . CloneURI != " " { g . repositoryURI = refs . CloneURI } return g }

// gitCtxForRefs creates a gitCtx based on the provide refs and baseDir.

gitCtxForRefs creates a gitCtx based on the provide refs and baseDir .


func (g *gitCtx) commandsForBaseRef(refs prowapi.Refs, gitUserName, gitUserEmail, cookiePath string) []cloneCommand {
	commands := []cloneCommand{{dir: "/", env: g.env, command: "mkdir", args: []string{"-p", g.cloneDir}}}

	commands = append(commands, g.gitCommand("init"))
	if gitUserName != "" {
		commands = append(commands, g.gitCommand("config", "user.name", gitUserName))
	}
	if gitUserEmail != "" {
		commands = append(commands, g.gitCommand("config", "user.email", gitUserEmail))
	}
	if cookiePath != "" {
		commands = append(commands, g.gitCommand("config", "http.cookiefile", cookiePath))
	}
	commands = append(commands, g.gitCommand("fetch", g.repositoryURI, "--tags", "--prune"))
	commands = append(commands, g.gitCommand("fetch", g.repositoryURI, refs.BaseRef))

	var target string
	if refs.BaseSHA != "" {
		target = refs.BaseSHA
	} else {
		target = "FETCH_HEAD"
	}
	// we need to be "on" the target branch after the sync
	// so we need to set the branch to point to the base ref,
	// but we cannot update a branch we are on, so in case we
	// are on the branch we are syncing, we check out the SHA
	// first and reset the branch second, then check out the
	// branch we just reset to be in the correct final state
	commands = append(commands, g.gitCommand("checkout", target))
	commands = append(commands, g.gitCommand("branch", "--force", refs.BaseRef, target))
	commands = append(commands, g.gitCommand("checkout", refs.BaseRef))

	return commands
}

// commandsForBaseRef returns the list of commands needed to initialize and
// configure a local git directory, as well as fetch and check out the provided
// base ref.

commandsForBaseRef returns the list of commands needed to initialize and configure a local git directory as well as fetch and check out the provided base ref .


func gitTimestampEnvs(timestamp int) []string {
	return []string{
		fmt.Sprintf("GIT_AUTHOR_DATE=%d", timestamp),
		fmt.Sprintf("GIT_COMMITTER_DATE=%d", timestamp),
	}
}

func gitTimestampEnvs ( timestamp int ) [ ] string { return [ ] string { fmt . Sprintf ( " " , timestamp ) , fmt . Sprintf ( " " , timestamp ) , } }

// gitTimestampEnvs returns the list of environment variables needed to override
// git's author and commit timestamps when creating new commits.

gitTimestampEnvs returns the list of environment variables needed to override git s author and commit timestamps when creating new commits .


func (g *gitCtx) gitRevParse() (string, error) {
	gitRevParseCommand := g.gitCommand("rev-parse", "HEAD")
	_, commit, err := gitRevParseCommand.run()
	if err != nil {
		logrus.WithError(err).Error("git rev-parse HEAD failed!")
		return "", err
	}
	return strings.TrimSpace(commit), nil
}

func ( g * gitCtx ) gitRevParse ( ) ( string , error ) { gitRevParseCommand := g . gitCommand ( " " , " " ) _ , commit , err := gitRevParseCommand . run ( ) if err != nil { logrus . WithError ( err ) . Error ( " " ) return " " , err } return strings . TrimSpace ( commit ) , nil }

// gitRevParse returns current commit from HEAD in a git tree


func (g *gitCtx) commandsForPullRefs(refs prowapi.Refs, fakeTimestamp int) []cloneCommand {
	var commands []cloneCommand
	for _, prRef := range refs.Pulls {
		ref := fmt.Sprintf("pull/%d/head", prRef.Number)
		if prRef.Ref != "" {
			ref = prRef.Ref
		}
		commands = append(commands, g.gitCommand("fetch", g.repositoryURI, ref))
		var prCheckout string
		if prRef.SHA != "" {
			prCheckout = prRef.SHA
		} else {
			prCheckout = "FETCH_HEAD"
		}
		fakeTimestamp++
		gitMergeCommand := g.gitCommand("merge", "--no-ff", prCheckout)
		gitMergeCommand.env = append(gitMergeCommand.env, gitTimestampEnvs(fakeTimestamp)...)
		commands = append(commands, gitMergeCommand)
	}

	// unless the user specifically asks us not to, init submodules
	if !refs.SkipSubmodules {
		commands = append(commands, g.gitCommand("submodule", "update", "--init", "--recursive"))
	}

	return commands
}

// commandsForPullRefs returns the list of commands needed to fetch and
// merge any pull refs as well as submodules. These commands should be run only
// after the commands provided by commandsForBaseRef have been run
// successfully.
// Each merge commit will be created at sequential seconds after fakeTimestamp.
// It's recommended that fakeTimestamp be set to the timestamp of the base ref.
// This enables reproducible timestamps and git tree digests every time the same
// set of base and pull refs are used.

commandsForPullRefs returns the list of commands needed to fetch and merge any pull refs as well as submodules . These commands should be run only after the commands provided by commandsForBaseRef have been run successfully . Each merge commit will be created at sequential seconds after fakeTimestamp . It s recommended that fakeTimestamp be set to the timestamp of the base ref . This enables reproducible timestamps and git tree digests every time the same set of base and pull refs are used .


func ProduceCovList(profiles []*cover.Profile) *CoverageList {
	covList := newCoverageList("summary")
	for _, prof := range profiles {
		covList.Group = append(covList.Group, summarizeBlocks(prof))
	}
	return covList
}

func ProduceCovList ( profiles [ ] * cover . Profile ) * CoverageList { covList := newCoverageList ( " " ) for _ , prof := range profiles { covList . Group = append ( covList . Group , summarizeBlocks ( prof ) ) } return covList }

// ProduceCovList summarizes profiles and returns the result


func popRandom(set sets.String) string {
	list := set.List()
	sort.Strings(list)
	sel := list[rand.Intn(len(list))]
	set.Delete(sel)
	return sel
}

func popRandom ( set sets . String ) string { list := set . List ( ) sort . Strings ( list ) sel := list [ rand . Intn ( len ( list ) ) ] set . Delete ( sel ) return sel }

// popRandom randomly selects an element of 'set' and pops it.

popRandom randomly selects an element of set and pops it .


func (o *ExperimentalKubernetesOptions) resolve(dryRun bool) (err error) {
	if o.resolved {
		return nil
	}

	o.dryRun = dryRun
	if dryRun {
		return nil
	}

	clusterConfigs, err := kube.LoadClusterConfigs(o.kubeconfig, o.buildCluster)
	if err != nil {
		return fmt.Errorf("load --kubeconfig=%q --build-cluster=%q configs: %v", o.kubeconfig, o.buildCluster, err)
	}
	clients := map[string]kubernetes.Interface{}
	for context, config := range clusterConfigs {
		client, err := kubernetes.NewForConfig(&config)
		if err != nil {
			return fmt.Errorf("create %s kubernetes client: %v", context, err)
		}
		clients[context] = client
	}

	localCfg := clusterConfigs[kube.InClusterContext]
	pjClient, err := prow.NewForConfig(&localCfg)
	if err != nil {
		return err
	}

	o.prowJobClientset = pjClient
	o.kubernetesClientsByContext = clients
	o.resolved = true

	return nil
}

func ( o * ExperimentalKubernetesOptions ) resolve ( dryRun bool ) ( err error ) { if o . resolved { return nil } o . dryRun = dryRun if dryRun { return nil } clusterConfigs , err := kube . LoadClusterConfigs ( o . kubeconfig , o . buildCluster ) if err != nil { return fmt . Errorf ( " " , o . kubeconfig , o . buildCluster , err ) } clients := map [ string ] kubernetes . Interface { } for context , config := range clusterConfigs { client , err := kubernetes . NewForConfig ( & config ) if err != nil { return fmt . Errorf ( " " , context , err ) } clients [ context ] = client } localCfg := clusterConfigs [ kube . InClusterContext ] pjClient , err := prow . NewForConfig ( & localCfg ) if err != nil { return err } o . prowJobClientset = pjClient o . kubernetesClientsByContext = clients o . resolved = true return nil }

// resolve loads all of the clients we need and caches them for future calls.

resolve loads all of the clients we need and caches them for future calls .


func (o *ExperimentalKubernetesOptions) ProwJobClientset(namespace string, dryRun bool) (prowJobClientset prow.Interface, err error) {
	if err := o.resolve(dryRun); err != nil {
		return nil, err
	}

	if o.dryRun {
		return nil, errors.New("no dry-run prowjob clientset is supported in dry-run mode")
	}

	return o.prowJobClientset, nil
}

func ( o * ExperimentalKubernetesOptions ) ProwJobClientset ( namespace string , dryRun bool ) ( prowJobClientset prow . Interface , err error ) { if err := o . resolve ( dryRun ) ; err != nil { return nil , err } if o . dryRun { return nil , errors . New ( " " ) } return o . prowJobClientset , nil }

// ProwJobClientset returns a ProwJob clientset for use in informer factories.

ProwJobClientset returns a ProwJob clientset for use in informer factories .


func (o *ExperimentalKubernetesOptions) ProwJobClient(namespace string, dryRun bool) (prowJobClient prowv1.ProwJobInterface, err error) {
	if err := o.resolve(dryRun); err != nil {
		return nil, err
	}

	if o.dryRun {
		return kube.NewDryRunProwJobClient(o.DeckURI), nil
	}

	return o.prowJobClientset.ProwV1().ProwJobs(namespace), nil
}

func ( o * ExperimentalKubernetesOptions ) ProwJobClient ( namespace string , dryRun bool ) ( prowJobClient prowv1 . ProwJobInterface , err error ) { if err := o . resolve ( dryRun ) ; err != nil { return nil , err } if o . dryRun { return kube . NewDryRunProwJobClient ( o . DeckURI ) , nil } return o . prowJobClientset . ProwV1 ( ) . ProwJobs ( namespace ) , nil }

// ProwJobClient returns a ProwJob client.

ProwJobClient returns a ProwJob client .


func (o *ExperimentalKubernetesOptions) InfrastructureClusterClient(dryRun bool) (kubernetesClient kubernetes.Interface, err error) {
	if err := o.resolve(dryRun); err != nil {
		return nil, err
	}

	if o.dryRun {
		return nil, errors.New("no dry-run kubernetes client is supported in dry-run mode")
	}

	return o.kubernetesClientsByContext[kube.InClusterContext], nil
}

func ( o * ExperimentalKubernetesOptions ) InfrastructureClusterClient ( dryRun bool ) ( kubernetesClient kubernetes . Interface , err error ) { if err := o . resolve ( dryRun ) ; err != nil { return nil , err } if o . dryRun { return nil , errors . New ( " " ) } return o . kubernetesClientsByContext [ kube . InClusterContext ] , nil }

// InfrastructureClusterClient returns a Kubernetes client for the infrastructure cluster.

InfrastructureClusterClient returns a Kubernetes client for the infrastructure cluster .


func (o *ExperimentalKubernetesOptions) BuildClusterClients(namespace string, dryRun bool) (buildClusterClients map[string]corev1.PodInterface, err error) {
	if err := o.resolve(dryRun); err != nil {
		return nil, err
	}

	if o.dryRun {
		return nil, errors.New("no dry-run pod client is supported for build clusters in dry-run mode")
	}

	buildClients := map[string]corev1.PodInterface{}
	for context, client := range o.kubernetesClientsByContext {
		buildClients[context] = client.CoreV1().Pods(namespace)
	}
	return buildClients, nil
}

func ( o * ExperimentalKubernetesOptions ) BuildClusterClients ( namespace string , dryRun bool ) ( buildClusterClients map [ string ] corev1 . PodInterface , err error ) { if err := o . resolve ( dryRun ) ; err != nil { return nil , err } if o . dryRun { return nil , errors . New ( " " ) } buildClients := map [ string ] corev1 . PodInterface { } for context , client := range o . kubernetesClientsByContext { buildClients [ context ] = client . CoreV1 ( ) . Pods ( namespace ) } return buildClients , nil }

// BuildClusterClients returns Pod clients for build clusters.

BuildClusterClients returns Pod clients for build clusters .


func (a *ActiveState) Age(t time.Time) time.Duration {
	return t.Sub(a.startTime)
}

func ( a * ActiveState ) Age ( t time . Time ) time . Duration { return t . Sub ( a . startTime ) }

// Age gives the time since the state has been activated.

Age gives the time since the state has been activated .


func (a *ActiveState) ReceiveEvent(eventName, label string, t time.Time) (State, bool) {
	if a.exit.Match(eventName, label) {
		return &InactiveState{
			entry: a.exit.Opposite(),
		}, true
	}
	return a, false
}

func ( a * ActiveState ) ReceiveEvent ( eventName , label string , t time . Time ) ( State , bool ) { if a . exit . Match ( eventName , label ) { return & InactiveState { entry : a . exit . Opposite ( ) , } , true } return a , false }

// ReceiveEvent checks if the event matches the exit criteria.
// Returns a new InactiveState or self, and true if it changed.

ReceiveEvent checks if the event matches the exit criteria . Returns a new InactiveState or self and true if it changed .


func (i *InactiveState) ReceiveEvent(eventName, label string, t time.Time) (State, bool) {
	if i.entry.Match(eventName, label) {
		return &ActiveState{
			startTime: t,
			exit:      i.entry.Opposite(),
		}, true
	}
	return i, false
}

func ( i * InactiveState ) ReceiveEvent ( eventName , label string , t time . Time ) ( State , bool ) { if i . entry . Match ( eventName , label ) { return & ActiveState { startTime : t , exit : i . entry . Opposite ( ) , } , true } return i , false }

// ReceiveEvent checks if the event matches the entry criteria
// Returns a new ActiveState or self, and true if it changed.

ReceiveEvent checks if the event matches the entry criteria Returns a new ActiveState or self and true if it changed .


func (m *MultiState) Active() bool {
	for _, state := range m.states {
		if !state.Active() {
			return false
		}
	}
	return true
}

func ( m * MultiState ) Active ( ) bool { for _ , state := range m . states { if ! state . Active ( ) { return false } } return true }

// Active is true if all the states are active.

Active is true if all the states are active .


func (m *MultiState) Age(t time.Time) time.Duration {
	minAge := time.Duration(1<<63 - 1)
	for _, state := range m.states {
		stateAge := state.Age(t)
		if stateAge < minAge {
			minAge = stateAge
		}
	}
	return minAge
}

func ( m * MultiState ) Age ( t time . Time ) time . Duration { minAge := time . Duration ( 1 << 63 - 1 ) for _ , state := range m . states { stateAge := state . Age ( t ) if stateAge < minAge { minAge = stateAge } } return minAge }

// Age returns the time since all states have been activated.
// It will panic if any of the state is not active.

Age returns the time since all states have been activated . It will panic if any of the state is not active .


func (m *MultiState) ReceiveEvent(eventName, label string, t time.Time) (State, bool) {
	oneChanged := false
	for i := range m.states {
		state, changed := m.states[i].ReceiveEvent(eventName, label, t)
		if changed {
			oneChanged = true
		}
		m.states[i] = state

	}
	return m, oneChanged
}

func ( m * MultiState ) ReceiveEvent ( eventName , label string , t time . Time ) ( State , bool ) { oneChanged := false for i := range m . states { state , changed := m . states [ i ] . ReceiveEvent ( eventName , label , t ) if changed { oneChanged = true } m . states [ i ] = state } return m , oneChanged }

// ReceiveEvent will send the event to each individual state, and update
// them if they change.

ReceiveEvent will send the event to each individual state and update them if they change .


func (v *version) ProwJobs() ProwJobInformer {
	return &prowJobInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

func ( v * version ) ProwJobs ( ) ProwJobInformer { return & prowJobInformer { factory : v . factory , namespace : v . namespace , tweakListOptions : v . tweakListOptions } }


func ItemToResourcesConfig(i Item) (ResourcesConfig, error) {
	conf, ok := i.(ResourcesConfig)
	if !ok {
		return ResourcesConfig{}, fmt.Errorf("cannot construct Resource from received object %v", i)
	}
	return conf, nil
}

func ItemToResourcesConfig ( i Item ) ( ResourcesConfig , error ) { conf , ok := i . ( ResourcesConfig ) if ! ok { return ResourcesConfig { } , fmt . Errorf ( " " , i ) } return conf , nil }

// ItemToResourcesConfig casts an Item object to a ResourcesConfig


func (t TypeToResources) Copy() TypeToResources {
	n := TypeToResources{}
	for k, v := range t {
		n[k] = v
	}
	return n
}

func ( t TypeToResources ) Copy ( ) TypeToResources { n := TypeToResources { } for k , v := range t { n [ k ] = v } return n }

// Copy returns a copy of the TypeToResources


func MakeCommand() *cobra.Command {
	flags := &flags{}
	cmd := &cobra.Command{
		Use:   "aggregate [files...]",
		Short: "Aggregates multiple Go coverage files.",
		Long: `Given multiple Go coverage files from identical binaries recorded in
"count" or "atomic" mode, produces a new Go coverage file in the same mode
that counts how many of those coverage profiles hit a block at least once.`,
		Run: func(cmd *cobra.Command, args []string) {
			run(flags, cmd, args)
		},
	}
	cmd.Flags().StringVarP(&flags.OutputFile, "output", "o", "-", "output file")
	return cmd
}

// MakeCommand returns an `aggregate` command.

MakeCommand returns an aggregate command .


func (c *Controller) incrementNumPendingJobs(job string) {
	c.lock.Lock()
	defer c.lock.Unlock()
	c.pendingJobs[job]++
}

func ( c * Controller ) incrementNumPendingJobs ( job string ) { c . lock . Lock ( ) defer c . lock . Unlock ( ) c . pendingJobs [ job ] ++ }

// incrementNumPendingJobs increments the amount of
// pending ProwJobs for the given job identifier

incrementNumPendingJobs increments the amount of pending ProwJobs for the given job identifier


func (c *Controller) setPreviousReportState(pj prowapi.ProwJob) error {
	// fetch latest before replace
	latestPJ, err := c.kc.GetProwJob(pj.ObjectMeta.Name)
	if err != nil {
		return err
	}

	if latestPJ.Status.PrevReportStates == nil {
		latestPJ.Status.PrevReportStates = map[string]prowapi.ProwJobState{}
	}
	latestPJ.Status.PrevReportStates[reporter.GitHubReporterName] = latestPJ.Status.State
	_, err = c.kc.ReplaceProwJob(latestPJ.ObjectMeta.Name, latestPJ)
	return err
}

func
(
c
*
Controller
)
setPreviousReportState
(
pj
prowapi
.
ProwJob
)
error
{
// fetch latest before replace
latestPJ
,
err
:=
c
.
kc
.
GetProwJob
(
pj
.
ObjectMeta
.
Name
)
if
err
!=
{
return
err
}
if
latestPJ
.
Status
.
PrevReportStates
==
{
latestPJ
.
Status
.
PrevReportStates
=
map
[
string
]
prowapi
.
ProwJobState
{
}
}
latestPJ
.
Status
.
PrevReportStates
[
reporter
.
GitHubReporterName
]
=
latestPJ
.
Status
.
State
_
,
err
=
c
.
kc
.
ReplaceProwJob
(
latestPJ
.
ObjectMeta
.
Name
,
latestPJ
)
return
err
}

// setPreviousReportState sets the github key for PrevReportStates
// to current state. This is a work-around for plank -> crier
// migration to become seamless.

setPreviousReportState sets the github key for PrevReportStates to current state . This is a work - around for plank - > crier migration to become seamless .


func (c *Controller) SyncMetrics() {
	c.pjLock.RLock()
	defer c.pjLock.RUnlock()
	kube.GatherProwJobMetrics(c.pjs)
}

func ( c * Controller ) SyncMetrics ( ) { c . pjLock . RLock ( ) defer c . pjLock . RUnlock ( ) kube . GatherProwJobMetrics ( c . pjs ) }

// SyncMetrics records metrics for the cached prowjobs.

SyncMetrics records metrics for the cached prowjobs .


func DumpProfile(profiles []*cover.Profile, writer io.Writer) error {
	if len(profiles) == 0 {
		return errors.New("can't write an empty profile")
	}
	if _, err := io.WriteString(writer, "mode: "+profiles[0].Mode+"\n"); err != nil {
		return err
	}
	for _, profile := range profiles {
		for _, block := range profile.Blocks {
			if _, err := fmt.Fprintf(writer, "%s:%d.%d,%d.%d %d %d\n", profile.FileName, block.StartLine, block.StartCol, block.EndLine, block.EndCol, block.NumStmt, block.Count); err != nil {
				return err
			}
		}
	}
	return nil
}

func DumpProfile ( profiles [ ] * cover . Profile , writer io . Writer ) error { if len ( profiles ) == 0 { return errors . New ( " " ) } if _ , err := io . WriteString ( writer , " " + profiles [ 0 ] . Mode + " \n " ) ; err != nil { return err } for _ , profile := range profiles { for _ , block := range profile . Blocks { if _ , err := fmt . Fprintf ( writer , " \n " , profile . FileName , block . StartLine , block . StartCol , block . EndLine , block . EndCol , block . NumStmt , block . Count ) ; err != nil { return err } } } return nil }

// DumpProfile dumps the profiles given to writer in go coverage format.

DumpProfile dumps the profiles given to writer in go coverage format .


func blocksEqual(a cover.ProfileBlock, b cover.ProfileBlock) bool {
	return a.StartCol == b.StartCol && a.StartLine == b.StartLine &&
		a.EndCol == b.EndCol && a.EndLine == b.EndLine && a.NumStmt == b.NumStmt
}

func blocksEqual ( a cover . ProfileBlock , b cover . ProfileBlock ) bool { return a . StartCol == b . StartCol && a . StartLine == b . StartLine && a . EndCol == b . EndCol && a . EndLine == b . EndLine && a . NumStmt == b . NumStmt }

// blocksEqual returns true if the blocks refer to the same code, otherwise false.
// It does not care about Count.

blocksEqual returns true if the blocks refer to the same code otherwise false . It does not care about Count .


func NewProwJobInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
	return NewFilteredProwJobInformer(client, namespace, resyncPeriod, indexers, nil)
}

func NewProwJobInformer ( client versioned . Interface , namespace string , resyncPeriod time . Duration , indexers cache . Indexers ) cache . SharedIndexInformer { return NewFilteredProwJobInformer ( client , namespace , resyncPeriod , indexers , nil ) }

// NewProwJobInformer constructs a new informer for ProwJob type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.

NewProwJobInformer constructs a new informer for ProwJob type . Always prefer using an informer factory to get a shared informer instead of getting an independent one . This reduces memory footprint and number of connections to the server .


func NewFilteredProwJobInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
	return cache.NewSharedIndexInformer(
		&cache.ListWatch{
			ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
				if tweakListOptions != nil {
					tweakListOptions(&options)
				}
				return client.ProwV1().ProwJobs(namespace).List(options)
			},
			WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
				if tweakListOptions != nil {
					tweakListOptions(&options)
				}
				return client.ProwV1().ProwJobs(namespace).Watch(options)
			},
		},
		&prowjobsv1.ProwJob{},
		resyncPeriod,
		indexers,
	)
}

func NewFilteredProwJobInformer ( client versioned . Interface , namespace string , resyncPeriod time . Duration , indexers cache . Indexers , tweakListOptions internalinterfaces . TweakListOptionsFunc ) cache . SharedIndexInformer { return cache . NewSharedIndexInformer ( & cache . ListWatch { ListFunc : func ( options metav1 . ListOptions ) ( runtime . Object , error ) { if tweakListOptions != nil { tweakListOptions ( & options ) } return client . ProwV1 ( ) . ProwJobs ( namespace ) . List ( options ) } , WatchFunc : func ( options metav1 . ListOptions ) ( watch . Interface , error ) { if tweakListOptions != nil { tweakListOptions ( & options ) } return client . ProwV1 ( ) . ProwJobs ( namespace ) . Watch ( options ) } , } , & prowjobsv1 . ProwJob { } , resyncPeriod , indexers , ) }

// NewFilteredProwJobInformer constructs a new informer for ProwJob type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.

NewFilteredProwJobInformer constructs a new informer for ProwJob type . Always prefer using an informer factory to get a shared informer instead of getting an independent one . This reduces memory footprint and number of connections to the server .


func New(ja *jobs.JobAgent, cfg config.Getter, c *storage.Client, ctx context.Context) *Spyglass {
	return &Spyglass{
		JobAgent:              ja,
		config:                cfg,
		PodLogArtifactFetcher: NewPodLogArtifactFetcher(ja),
		GCSArtifactFetcher:    NewGCSArtifactFetcher(c),
		testgrid: &TestGrid{
			conf:   cfg,
			client: c,
			ctx:    ctx,
		},
	}
}

func New ( ja * jobs . JobAgent , cfg config . Getter , c * storage . Client , ctx context . Context ) * Spyglass { return & Spyglass { JobAgent : ja , config : cfg , PodLogArtifactFetcher : NewPodLogArtifactFetcher ( ja ) , GCSArtifactFetcher : NewGCSArtifactFetcher ( c ) , testgrid : & TestGrid { conf : cfg , client : c , ctx : ctx , } , } }

// New constructs a Spyglass object from a JobAgent, a config.Agent, and a storage Client.

New constructs a Spyglass object from a JobAgent a config . Agent and a storage Client .


func (s *Spyglass) Lenses(matchCache map[string][]string) []lenses.Lens {
	ls := []lenses.Lens{}
	for lensName, matches := range matchCache {
		if len(matches) == 0 {
			continue
		}
		lens, err := lenses.GetLens(lensName)
		if err != nil {
			logrus.WithField("lensName", lens).WithError(err).Error("Could not find artifact lens")
		} else {
			ls = append(ls, lens)
		}
	}
	// Make sure lenses are rendered in order by ascending priority
	sort.Slice(ls, func(i, j int) bool {
		iconf := ls[i].Config()
		jconf := ls[j].Config()
		iname := iconf.Name
		jname := jconf.Name
		pi := iconf.Priority
		pj := jconf.Priority
		if pi == pj {
			return iname < jname
		}
		return pi < pj
	})
	return ls
}

// Lenses gets all views of all artifact files matching each regexp with a registered lens


func (s *Spyglass) JobPath(src string) (string, error) {
	src = strings.TrimSuffix(src, "/")
	keyType, key, err := splitSrc(src)
	if err != nil {
		return "", fmt.Errorf("error parsing src: %v", src)
	}
	split := strings.Split(key, "/")
	switch keyType {
	case gcsKeyType:
		if len(split) < 4 {
			return "", fmt.Errorf("invalid key %s: expected <bucket-name>/<log-type>/.../<job-name>/<build-id>", key)
		}
		// see https://github.com/kubernetes/test-infra/tree/master/gubernator
		bktName := split[0]
		logType := split[1]
		jobName := split[len(split)-2]
		if logType == gcs.NonPRLogs {
			return path.Dir(key), nil
		} else if logType == gcs.PRLogs {
			return path.Join(bktName, gcs.PRLogs, "directory", jobName), nil
		}
		return "", fmt.Errorf("unrecognized GCS key: %s", key)
	case prowKeyType:
		if len(split) < 2 {
			return "", fmt.Errorf("invalid key %s: expected <job-name>/<build-id>", key)
		}
		jobName := split[0]
		buildID := split[1]
		job, err := s.jobAgent.GetProwJob(jobName, buildID)
		if err != nil {
			return "", fmt.Errorf("failed to get prow job from src %q: %v", key, err)
		}
		if job.Spec.DecorationConfig == nil {
			return "", fmt.Errorf("failed to locate GCS upload bucket for %s: job is undecorated", jobName)
		}
		if job.Spec.DecorationConfig.GCSConfiguration == nil {
			return "", fmt.Errorf("failed to locate GCS upload bucket for %s: missing GCS configuration", jobName)
		}
		bktName := job.Spec.DecorationConfig.GCSConfiguration.Bucket
		if job.Spec.Type == prowapi.PresubmitJob {
			return path.Join(bktName, gcs.PRLogs, "directory", jobName), nil
		}
		return path.Join(bktName, gcs.NonPRLogs, jobName), nil
	default:
		return "", fmt.Errorf("unrecognized key type for src: %v", src)
	}
}

// JobPath returns a link to the GCS directory for the job specified in src


func (s *Spyglass) RunPath(src string) (string, error) {
	src = strings.TrimSuffix(src, "/")
	keyType, key, err := splitSrc(src)
	if err != nil {
		return "", fmt.Errorf("error parsing src: %v", src)
	}
	switch keyType {
	case gcsKeyType:
		return key, nil
	case prowKeyType:
		return s.prowToGCS(key)
	default:
		return "", fmt.Errorf("unrecognized key type for src: %v", src)
	}
}

func ( s * Spyglass ) RunPath ( src string ) ( string , error ) { src = strings . TrimSuffix ( src , " " ) keyType , key , err := splitSrc ( src ) if err != nil { return " " , fmt . Errorf ( " " , src ) } switch keyType { case gcsKeyType : return key , nil case prowKeyType : return s . prowToGCS ( key ) default : return " " , fmt . Errorf ( " " , src ) } }

// RunPath returns the path to the GCS directory for the job run specified in src.

RunPath returns the path to the GCS directory for the job run specified in src .


func (sg *Spyglass) ExtraLinks(src string) ([]ExtraLink, error) {
	artifacts, err := sg.FetchArtifacts(src, "", 1000000, []string{"started.json"})
	// Failing to find started.json is okay, just return nothing quietly.
	if err != nil || len(artifacts) == 0 {
		logrus.WithError(err).Debugf("Failed to find started.json while looking for extra links.")
		return nil, nil
	}
	// Failing to read an artifact we already know to exist shouldn't happen, so that's an error.
	content, err := artifacts[0].ReadAll()
	if err != nil {
		return nil, err
	}
	// Being unable to parse a successfully fetched started.json correctly is also an error.
	started := metadata.Started{}
	if err := json.Unmarshal(content, &started); err != nil {
		return nil, err
	}
	// Not having any links is fine.
	links, ok := started.Metadata.Meta("links")
	if !ok {
		return nil, nil
	}
	extraLinks := make([]ExtraLink, 0, len(*links))
	for _, name := range links.Keys() {
		m, ok := links.Meta(name)
		if !ok {
			// This should never happen, because Keys() should only return valid Metas.
			logrus.Debugf("Got bad link key %q from %s, but that should be impossible.", name, artifacts[0].CanonicalLink())
			continue
		}
		s := m.Strings()
		link := ExtraLink{
			Name:        name,
			URL:         s["url"],
			Description: s["description"],
		}
		if link.URL == "" || link.Name == "" {
			continue
		}
		extraLinks = append(extraLinks, link)
	}
	return extraLinks, nil
}

// ExtraLinks fetches started.json and extracts links from metadata.links.

ExtraLinks fetches started . json and extracts links from metadata . links .


func (s *Server) needDemux(eventType, srcRepo string) []plugins.ExternalPlugin {
	var matching []plugins.ExternalPlugin
	srcOrg := strings.Split(srcRepo, "/")[0]

	for repo, plugins := range s.Plugins.Config().ExternalPlugins {
		// Make sure the repositories match
		if repo != srcRepo && repo != srcOrg {
			continue
		}

		// Make sure the events match
		for _, p := range plugins {
			if len(p.Events) == 0 {
				matching = append(matching, p)
			} else {
				for _, et := range p.Events {
					if et != eventType {
						continue
					}
					matching = append(matching, p)
					break
				}
			}
		}
	}
	return matching
}

func
(
s
*
Server
)
needDemux
(
eventType
,
srcRepo
string
)
[
]
plugins
.
ExternalPlugin
{
var
matching
[
]
plugins
.
ExternalPlugin
srcOrg
:=
strings
.
Split
(
srcRepo
,
"
"
)
[
0
]
for
repo
,
plugins
:=
range
s
.
Plugins
.
Config
(
)
.
ExternalPlugins
{
// Make sure the repositories match
if
repo
!=
srcRepo
&&
repo
!=
srcOrg
{
continue
}
// Make sure the events match
for
_
,
p
:=
range
plugins
{
if
len
(
p
.
Events
)
==
0
{
matching
=
append
(
matching
,
p
)
}
else
{
for
_
,
et
:=
range
p
.
Events
{
if
et
!=
eventType
{
continue
}
matching
=
append
(
matching
,
p
)
break
}
}
}
}
return
matching
}

// needDemux returns whether there are any external plugins that need to
// get the present event.

needDemux returns whether there are any external plugins that need to get the present event .


func (s *Server) demuxExternal(l *logrus.Entry, externalPlugins []plugins.ExternalPlugin, payload []byte, h http.Header) {
	h.Set("User-Agent", "ProwHook")
	for _, p := range externalPlugins {
		s.wg.Add(1)
		go func(p plugins.ExternalPlugin) {
			defer s.wg.Done()
			if err := s.dispatch(p.Endpoint, payload, h); err != nil {
				l.WithError(err).WithField("external-plugin", p.Name).Error("Error dispatching event to external plugin.")
			} else {
				l.WithField("external-plugin", p.Name).Info("Dispatched event to external plugin")
			}
		}(p)
	}
}

func ( s * Server ) demuxExternal ( l * logrus . Entry , externalPlugins [ ] plugins . ExternalPlugin , payload [ ] byte , h http . Header ) { h . Set ( " " , " " ) for _ , p := range externalPlugins { s . wg . Add ( 1 ) go func ( p plugins . ExternalPlugin ) { defer s . wg . Done ( ) if err := s . dispatch ( p . Endpoint , payload , h ) ; err != nil { l . WithError ( err ) . WithField ( " " , p . Name ) . Error ( " " ) } else { l . WithField ( " " , p . Name ) . Info ( " " ) } } ( p ) } }

// demuxExternal dispatches the provided payload to the external plugins.

demuxExternal dispatches the provided payload to the external plugins .


func (s *Server) dispatch(endpoint string, payload []byte, h http.Header) error {
	req, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewBuffer(payload))
	if err != nil {
		return err
	}
	req.Header = h
	resp, err := s.do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	rb, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		return fmt.Errorf("response has status %q and body %q", resp.Status, string(rb))
	}
	return nil
}

func ( s * Server ) dispatch ( endpoint string , payload [ ] byte , h http . Header ) error { req , err := http . NewRequest ( http . MethodPost , endpoint , bytes . NewBuffer ( payload ) ) if err != nil { return err } req . Header = h resp , err := s . do ( req ) if err != nil { return err } defer resp . Body . Close ( ) rb , err := ioutil . ReadAll ( resp . Body ) if err != nil { return err } if resp . StatusCode < 200 || resp . StatusCode > 299 { return fmt . Errorf ( " " , resp . Status , string ( rb ) ) } return nil }

// dispatch creates a new request using the provided payload and headers
// and dispatches the request to the provided endpoint.

dispatch creates a new request using the provided payload and headers and dispatches the request to the provided endpoint .


func (s *StatePlugin) AddFlags(cmd *cobra.Command) {
	cmd.Flags().StringVar(&s.desc, "state", "", "Description of the state (eg: `opened,!merged,labeled:cool`)")
	cmd.Flags().IntSliceVar(&s.percentiles, "percentiles", []int{}, "Age percentiles for state")
}

func ( s * StatePlugin ) AddFlags ( cmd * cobra . Command ) { cmd . Flags ( ) . StringVar ( & s . desc , " " , " " , " " ) cmd . Flags ( ) . IntSliceVar ( & s . percentiles , " " , [ ] int { } , " " ) }

// AddFlags adds "state" and "percentiles" to the command help

AddFlags adds state and percentiles to the command help


func (s *StatePlugin) CheckFlags() error {
	s.states = NewBundledStates(s.desc)
	return nil
}

func ( s * StatePlugin ) CheckFlags ( ) error { s . states = NewBundledStates ( s . desc ) return nil }

// CheckFlags configures which states to monitor


func (s *StatePlugin) ReceiveIssueEvent(event sql.IssueEvent) []Point {
	label := ""
	if event.Label != nil {
		label = *event.Label
	}

	if !s.states.ReceiveEvent(event.IssueID, event.Event, label, event.EventCreatedAt) {
		return nil
	}

	total, sum := s.states.Total(event.EventCreatedAt)
	values := map[string]interface{}{
		"count": total,
		"sum":   int(sum),
	}
	for _, percentile := range s.percentiles {
		values[fmt.Sprintf("%d%%", percentile)] = int(s.states.Percentile(event.EventCreatedAt, percentile))
	}

	return []Point{
		{
			Values: values,
			Date:   event.EventCreatedAt,
		},
	}
}

func ( s * StatePlugin ) ReceiveIssueEvent ( event sql . IssueEvent ) [ ] Point { label := " " if event . Label != nil { label = * event . Label } if ! s . states . ReceiveEvent ( event . IssueID , event . Event , label , event . EventCreatedAt ) { return nil } total , sum := s . states . Total ( event . EventCreatedAt ) values := map [ string ] interface { } { " " : total , " " : int ( sum ) , } for _ , percentile := range s . percentiles { values [ fmt . Sprintf ( " " , percentile ) ] = int ( s . states . Percentile ( event . EventCreatedAt , percentile ) ) } return [ ] Point { { Values : values , Date : event . EventCreatedAt , } , } }

// ReceiveIssueEvent computes age percentiles and saves them to InfluxDB


func Load(prowConfig, jobConfig string) (c *Config, err error) {
	// we never want config loading to take down the prow components
	defer func() {
		if r := recover(); r != nil {
			c, err = nil, fmt.Errorf("panic loading config: %v", r)
		}
	}()
	c, err = loadConfig(prowConfig, jobConfig)
	if err != nil {
		return nil, err
	}
	if err := c.finalizeJobConfig(); err != nil {
		return nil, err
	}
	if err := c.validateComponentConfig(); err != nil {
		return nil, err
	}
	if err := c.validateJobConfig(); err != nil {
		return nil, err
	}
	return c, nil
}

// Load loads and parses the config at path.

Load loads and parses the config at path .


func loadConfig(prowConfig, jobConfig string) (*Config, error) {
	stat, err := os.Stat(prowConfig)
	if err != nil {
		return nil, err
	}

	if stat.IsDir() {
		return nil, fmt.Errorf("prowConfig cannot be a dir - %s", prowConfig)
	}

	var nc Config
	if err := yamlToConfig(prowConfig, &nc); err != nil {
		return nil, err
	}
	if err := parseProwConfig(&nc); err != nil {
		return nil, err
	}

	// TODO(krzyzacy): temporary allow empty jobconfig
	//                 also temporary allow job config in prow config
	if jobConfig == "" {
		return &nc, nil
	}

	stat, err = os.Stat(jobConfig)
	if err != nil {
		return nil, err
	}

	if !stat.IsDir() {
		// still support a single file
		var jc JobConfig
		if err := yamlToConfig(jobConfig, &jc); err != nil {
			return nil, err
		}
		if err := nc.mergeJobConfig(jc); err != nil {
			return nil, err
		}
		return &nc, nil
	}

	// we need to ensure all config files have unique basenames,
	// since updateconfig plugin will use basename as a key in the configmap
	uniqueBasenames := sets.String{}

	err = filepath.Walk(jobConfig, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			logrus.WithError(err).Errorf("walking path %q.", path)
			// bad file should not stop us from parsing the directory
			return nil
		}

		if strings.HasPrefix(info.Name(), "..") {
			// kubernetes volumes also include files we
			// should not look be looking into for keys
			if info.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		if filepath.Ext(path) != ".yaml" && filepath.Ext(path) != ".yml" {
			return nil
		}

		if info.IsDir() {
			return nil
		}

		base := filepath.Base(path)
		if uniqueBasenames.Has(base) {
			return fmt.Errorf("duplicated basename is not allowed: %s", base)
		}
		uniqueBasenames.Insert(base)

		var subConfig JobConfig
		if err := yamlToConfig(path, &subConfig); err != nil {
			return err
		}
		return nc.mergeJobConfig(subConfig)
	})

	if err != nil {
		return nil, err
	}

	return &nc, nil
}

// loadConfig loads one or multiple config files and returns a config object.

loadConfig loads one or multiple config files and returns a config object .


func yamlToConfig(path string, nc interface{}) error {
	b, err := ReadFileMaybeGZIP(path)
	if err != nil {
		return fmt.Errorf("error reading %s: %v", path, err)
	}
	if err := yaml.Unmarshal(b, nc); err != nil {
		return fmt.Errorf("error unmarshaling %s: %v", path, err)
	}
	var jc *JobConfig
	switch v := nc.(type) {
	case *JobConfig:
		jc = v
	case *Config:
		jc = &v.JobConfig
	}
	for rep := range jc.Presubmits {
		var fix func(*Presubmit)
		fix = func(job *Presubmit) {
			job.SourcePath = path
		}
		for i := range jc.Presubmits[rep] {
			fix(&jc.Presubmits[rep][i])
		}
	}
	for rep := range jc.Postsubmits {
		var fix func(*Postsubmit)
		fix = func(job *Postsubmit) {
			job.SourcePath = path
		}
		for i := range jc.Postsubmits[rep] {
			fix(&jc.Postsubmits[rep][i])
		}
	}

	var fix func(*Periodic)
	fix = func(job *Periodic) {
		job.SourcePath = path
	}
	for i := range jc.Periodics {
		fix(&jc.Periodics[i])
	}
	return nil
}

func yamlToConfig ( path string , nc interface { } ) error { b , err := ReadFileMaybeGZIP ( path ) if err != nil { return fmt . Errorf ( " " , path , err ) } if err := yaml . Unmarshal ( b , nc ) ; err != nil { return fmt . Errorf ( " " , path , err ) } var jc * JobConfig switch v := nc . ( type ) { case * JobConfig : jc = v case * Config : jc = & v . JobConfig } for rep := range jc . Presubmits { var fix func ( * Presubmit ) fix = func ( job * Presubmit ) { job . SourcePath = path } for i := range jc . Presubmits [ rep ] { fix ( & jc . Presubmits [ rep ] [ i ] ) } } for rep := range jc . Postsubmits { var fix func ( * Postsubmit ) fix = func ( job * Postsubmit ) { job . SourcePath = path } for i := range jc . Postsubmits [ rep ] { fix ( & jc . Postsubmits [ rep ] [ i ] ) } } var fix func ( * Periodic ) fix = func ( job * Periodic ) { job . SourcePath = path } for i := range jc . Periodics { fix ( & jc . Periodics [ i ] ) } return nil }

// yamlToConfig converts a yaml file into a Config object


func ReadFileMaybeGZIP(path string) ([]byte, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	// check if file contains gzip header: http://www.zlib.org/rfc-gzip.html
	if !bytes.HasPrefix(b, []byte("\x1F\x8B")) {
		// go ahead and return the contents if not gzipped
		return b, nil
	}
	// otherwise decode
	gzipReader, err := gzip.NewReader(bytes.NewBuffer(b))
	if err != nil {
		return nil, err
	}
	return ioutil.ReadAll(gzipReader)
}

// ReadFileMaybeGZIP wraps ioutil.ReadFile, returning the decompressed contents
// if the file is gzipped, or otherwise the raw contents

ReadFileMaybeGZIP wraps ioutil . ReadFile returning the decompressed contents if the file is gzipped or otherwise the raw contents


func (c *Config) finalizeJobConfig() error {
	if c.decorationRequested() {
		if c.Plank.DefaultDecorationConfig == nil {
			return errors.New("no default decoration config provided for plank")
		}
		if c.Plank.DefaultDecorationConfig.UtilityImages == nil {
			return errors.New("no default decoration image pull specs provided for plank")
		}
		if c.Plank.DefaultDecorationConfig.GCSConfiguration == nil {
			return errors.New("no default GCS decoration config provided for plank")
		}
		if c.Plank.DefaultDecorationConfig.GCSCredentialsSecret == "" {
			return errors.New("no default GCS credentials secret provided for plank")
		}

		for _, vs := range c.Presubmits {
			for i := range vs {
				setPresubmitDecorationDefaults(c, &vs[i])
			}
		}

		for _, js := range c.Postsubmits {
			for i := range js {
				setPostsubmitDecorationDefaults(c, &js[i])
			}
		}

		for i := range c.Periodics {
			setPeriodicDecorationDefaults(c, &c.Periodics[i])
		}
	}

	// Ensure that regexes are valid and set defaults.
	for _, vs := range c.Presubmits {
		c.defaultPresubmitFields(vs)
		if err := SetPresubmitRegexes(vs); err != nil {
			return fmt.Errorf("could not set regex: %v", err)
		}
	}
	for _, js := range c.Postsubmits {
		c.defaultPostsubmitFields(js)
		if err := SetPostsubmitRegexes(js); err != nil {
			return fmt.Errorf("could not set regex: %v", err)
		}
	}

	c.defaultPeriodicFields(c.Periodics)

	for _, v := range c.AllPresubmits(nil) {
		if err := resolvePresets(v.Name, v.Labels, v.Spec, v.BuildSpec, c.Presets); err != nil {
			return err
		}
	}

	for _, v := range c.AllPostsubmits(nil) {
		if err := resolvePresets(v.Name, v.Labels, v.Spec, v.BuildSpec, c.Presets); err != nil {
			return err
		}
	}

	for _, v := range c.AllPeriodics() {
		if err := resolvePresets(v.Name, v.Labels, v.Spec, v.BuildSpec, c.Presets); err != nil {
			return err
		}
	}

	return nil
}

// finalizeJobConfig mutates and fixes entries for jobspecs


func (c *Config) validateComponentConfig() error {
	if c.Plank.JobURLPrefix != "" && c.Plank.JobURLPrefixConfig["*"] != "" {
		return errors.New(`Planks job_url_prefix must be unset when job_url_prefix_config["*"] is set. The former is deprecated, use the latter`)
	}
	for k, v := range c.Plank.JobURLPrefixConfig {
		if _, err := url.Parse(v); err != nil {
			return fmt.Errorf(`Invalid value for Planks job_url_prefix_config["%s"]: %v`, k, err)
		}
	}

	if c.SlackReporter != nil {
		if err := c.SlackReporter.DefaultAndValidate(); err != nil {
			return fmt.Errorf("failed to validate slackreporter config: %v", err)
		}
	}
	return nil
}

// validateComponentConfig validates the infrastructure component configuration


func ConfigPath(value string) string {

	if value != "" {
		return value
	}
	logrus.Warningf("defaulting to %s until 15 July 2019, please migrate", DefaultConfigPath)
	return DefaultConfigPath
}

func ConfigPath ( value string ) string { if value != " " { return value } logrus . Warningf ( " " , DefaultConfigPath ) return DefaultConfigPath }

// ConfigPath returns the value for the component's configPath if provided
// explicitly or default otherwise.

ConfigPath returns the value for the component s configPath if provided explicitly or default otherwise .


func ValidateController(c *Controller) error {
	urlTmpl, err := template.New("JobURL").Parse(c.JobURLTemplateString)
	if err != nil {
		return fmt.Errorf("parsing template: %v", err)
	}
	c.JobURLTemplate = urlTmpl

	reportTmpl, err := template.New("Report").Parse(c.ReportTemplateString)
	if err != nil {
		return fmt.Errorf("parsing template: %v", err)
	}
	c.ReportTemplate = reportTmpl
	if c.MaxConcurrency < 0 {
		return fmt.Errorf("controller has invalid max_concurrency (%d), it needs to be a non-negative number", c.MaxConcurrency)
	}
	if c.MaxGoroutines == 0 {
		c.MaxGoroutines = 20
	}
	if c.MaxGoroutines <= 0 {
		return fmt.Errorf("controller has invalid max_goroutines (%d), it needs to be a positive number", c.MaxGoroutines)
	}
	return nil
}

func ValidateController ( c * Controller ) error { urlTmpl , err := template . New ( " " ) . Parse ( c . JobURLTemplateString ) if err != nil { return fmt . Errorf ( " " , err ) } c . JobURLTemplate = urlTmpl reportTmpl , err := template . New ( " " ) . Parse ( c . ReportTemplateString ) if err != nil { return fmt . Errorf ( " " , err ) } c . ReportTemplate = reportTmpl if c . MaxConcurrency < 0 { return fmt . Errorf ( " " , c . MaxConcurrency ) } if c . MaxGoroutines == 0 { c . MaxGoroutines = 20 } if c . MaxGoroutines <= 0 { return fmt . Errorf ( " " , c . MaxGoroutines ) } return nil }

// ValidateController validates the provided controller config.

ValidateController validates the provided controller config .


func (c *ProwConfig) defaultJobBase(base *JobBase) {
	if base.Agent == "" { // Use kubernetes by default
		base.Agent = string(prowapi.KubernetesAgent)
	}
	if base.Namespace == nil || *base.Namespace == "" {
		s := c.PodNamespace
		base.Namespace = &s
	}
	if base.Cluster == "" {
		base.Cluster = kube.DefaultClusterAlias
	}
}

func
(
c
*
ProwConfig
)
defaultJobBase
(
base
*
JobBase
)
{
if
base
.
Agent
==
"
"
{
// Use kubernetes by default
base
.
Agent
=
string
(
prowapi
.
KubernetesAgent
)
}
if
base
.
Namespace
==
||
*
base
.
Namespace
==
"
"
{
s
:=
c
.
PodNamespace
base
.
Namespace
=
&
s
}
if
base
.
Cluster
==
"
"
{
base
.
Cluster
=
kube
.
DefaultClusterAlias
}
}

// defaultJobBase configures common parameters, currently Agent and Namespace.

defaultJobBase configures common parameters currently Agent and Namespace .


func SetPresubmitRegexes(js []Presubmit) error {
	for i, j := range js {
		if re, err := regexp.Compile(j.Trigger); err == nil {
			js[i].re = re
		} else {
			return fmt.Errorf("could not compile trigger regex for %s: %v", j.Name, err)
		}
		if !js[i].re.MatchString(j.RerunCommand) {
			return fmt.Errorf("for job %s, rerun command \"%s\" does not match trigger \"%s\"", j.Name, j.RerunCommand, j.Trigger)
		}
		b, err := setBrancherRegexes(j.Brancher)
		if err != nil {
			return fmt.Errorf("could not set branch regexes for %s: %v", j.Name, err)
		}
		js[i].Brancher = b

		c, err := setChangeRegexes(j.RegexpChangeMatcher)
		if err != nil {
			return fmt.Errorf("could not set change regexes for %s: %v", j.Name, err)
		}
		js[i].RegexpChangeMatcher = c
	}
	return nil
}

func SetPresubmitRegexes ( js [ ] Presubmit ) error { for i , j := range js { if re , err := regexp . Compile ( j . Trigger ) ; err == nil { js [ i ] . re = re } else { return fmt . Errorf ( " " , j . Name , err ) } if ! js [ i ] . re . MatchString ( j . RerunCommand ) { return fmt . Errorf ( " \" \" \" \" " , j . Name , j . RerunCommand , j . Trigger ) } b , err := setBrancherRegexes ( j . Brancher ) if err != nil { return fmt . Errorf ( " " , j . Name , err ) } js [ i ] . Brancher = b c , err := setChangeRegexes ( j . RegexpChangeMatcher ) if err != nil { return fmt . Errorf ( " " , j . Name , err ) } js [ i ] . RegexpChangeMatcher = c } return nil }

// SetPresubmitRegexes compiles and validates all the regular expressions for
// the provided presubmits.

SetPresubmitRegexes compiles and validates all the regular expressions for the provided presubmits .


func setBrancherRegexes(br Brancher) (Brancher, error) {
	if len(br.Branches) > 0 {
		if re, err := regexp.Compile(strings.Join(br.Branches, `|`)); err == nil {
			br.re = re
		} else {
			return br, fmt.Errorf("could not compile positive branch regex: %v", err)
		}
	}
	if len(br.SkipBranches) > 0 {
		if re, err := regexp.Compile(strings.Join(br.SkipBranches, `|`)); err == nil {
			br.reSkip = re
		} else {
			return br, fmt.Errorf("could not compile negative branch regex: %v", err)
		}
	}
	return br, nil
}

func setBrancherRegexes ( br Brancher ) ( Brancher , error ) { if len ( br . Branches ) > 0 { if re , err := regexp . Compile ( strings . Join ( br . Branches , `|` ) ) ; err == nil { br . re = re } else { return br , fmt . Errorf ( " " , err ) } } if len ( br . SkipBranches ) > 0 { if re , err := regexp . Compile ( strings . Join ( br . SkipBranches , `|` ) ) ; err == nil { br . reSkip = re } else { return br , fmt . Errorf ( " " , err ) } } return br , nil }

// setBrancherRegexes compiles and validates all the regular expressions for
// the provided branch specifiers.

setBrancherRegexes compiles and validates all the regular expressions for the provided branch specifiers .


func SetPostsubmitRegexes(ps []Postsubmit) error {
	for i, j := range ps {
		b, err := setBrancherRegexes(j.Brancher)
		if err != nil {
			return fmt.Errorf("could not set branch regexes for %s: %v", j.Name, err)
		}
		ps[i].Brancher = b
		c, err := setChangeRegexes(j.RegexpChangeMatcher)
		if err != nil {
			return fmt.Errorf("could not set change regexes for %s: %v", j.Name, err)
		}
		ps[i].RegexpChangeMatcher = c
	}
	return nil
}

func SetPostsubmitRegexes ( ps [ ] Postsubmit ) error { for i , j := range ps { b , err := setBrancherRegexes ( j . Brancher ) if err != nil { return fmt . Errorf ( " " , j . Name , err ) } ps [ i ] . Brancher = b c , err := setChangeRegexes ( j . RegexpChangeMatcher ) if err != nil { return fmt . Errorf ( " " , j . Name , err ) } ps [ i ] . RegexpChangeMatcher = c } return nil }

// SetPostsubmitRegexes compiles and validates all the regular expressions for
// the provided postsubmits.

SetPostsubmitRegexes compiles and validates all the regular expressions for the provided postsubmits .


func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	var buf bytes.Buffer
	type MetadataViewData struct {
		Status       string
		StartTime    time.Time
		FinishedTime time.Time
		Elapsed      time.Duration
		Metadata     map[string]string
	}
	metadataViewData := MetadataViewData{Status: "Pending"}
	started := gcs.Started{}
	finished := gcs.Finished{}
	for _, a := range artifacts {
		read, err := a.ReadAll()
		if err != nil {
			logrus.WithError(err).Error("Failed reading from artifact.")
		}
		if a.JobPath() == "started.json" {
			if err = json.Unmarshal(read, &started); err != nil {
				logrus.WithError(err).Error("Error unmarshaling started.json")
			}
			metadataViewData.StartTime = time.Unix(started.Timestamp, 0)
		} else if a.JobPath() == "finished.json" {
			if err = json.Unmarshal(read, &finished); err != nil {
				logrus.WithError(err).Error("Error unmarshaling finished.json")
			}
			if finished.Timestamp != nil {
				metadataViewData.FinishedTime = time.Unix(*finished.Timestamp, 0)
			}
			metadataViewData.Status = finished.Result
		}
	}

	if !metadataViewData.StartTime.IsZero() {
		if metadataViewData.FinishedTime.IsZero() {
			metadataViewData.Elapsed = time.Now().Sub(metadataViewData.StartTime)
		} else {
			metadataViewData.Elapsed =
				metadataViewData.FinishedTime.Sub(metadataViewData.StartTime)
		}
		metadataViewData.Elapsed = metadataViewData.Elapsed.Round(time.Second)
	}

	metadataViewData.Metadata = map[string]string{"node": started.Node}

	metadatas := []metadata.Metadata{started.Metadata, finished.Metadata}
	for _, m := range metadatas {
		for k, v := range m {
			if s, ok := v.(string); ok && v != "" {
				metadataViewData.Metadata[k] = s
			}
		}
	}

	metadataTemplate, err := template.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		return fmt.Sprintf("Failed to load template: %v", err)
	}

	if err := metadataTemplate.ExecuteTemplate(&buf, "body", metadataViewData); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}
	return buf.String()
}

func ( lens Lens ) Body ( artifacts [ ] lenses . Artifact , resourceDir string , data string ) string { var buf bytes . Buffer type MetadataViewData struct { Status string StartTime time . Time FinishedTime time . Time Elapsed time . Duration Metadata map [ string ] string } metadataViewData := MetadataViewData { Status : " " } started := gcs . Started { } finished := gcs . Finished { } for _ , a := range artifacts { read , err := a . ReadAll ( ) if err != nil { logrus . WithError ( err ) . Error ( " " ) } if a . JobPath ( ) == " " { if err = json . Unmarshal ( read , & started ) ; err != nil { logrus . WithError ( err ) . Error ( " " ) } metadataViewData . StartTime = time . Unix ( started . Timestamp , 0 ) } else if a . JobPath ( ) == " " { if err = json . Unmarshal ( read , & finished ) ; err != nil { logrus . WithError ( err ) . Error ( " " ) } if finished . Timestamp != nil { metadataViewData . FinishedTime = time . Unix ( * finished . Timestamp , 0 ) } metadataViewData . Status = finished . Result } } if ! metadataViewData . StartTime . IsZero ( ) { if metadataViewData . FinishedTime . IsZero ( ) { metadataViewData . Elapsed = time . Now ( ) . Sub ( metadataViewData . StartTime ) } else { metadataViewData . Elapsed = metadataViewData . FinishedTime . Sub ( metadataViewData . StartTime ) } metadataViewData . Elapsed = metadataViewData . Elapsed . Round ( time . Second ) } metadataViewData . Metadata = map [ string ] string { " " : started . Node } metadatas := [ ] metadata . Metadata { started . Metadata , finished . Metadata } for _ , m := range metadatas { for k , v := range m { if s , ok := v . ( string ) ; ok && v != " " { metadataViewData . Metadata [ k ] = s } } } metadataTemplate , err := template . ParseFiles ( filepath . Join ( resourceDir , " " ) ) if err != nil { return fmt . Sprintf ( " " , err ) } if err := metadataTemplate . ExecuteTemplate ( & buf , " " , metadataViewData ) ; err != nil { logrus . WithError ( err ) . Error ( " " ) } return buf . String ( ) }

// Body creates a view for prow job metadata.

Body creates a view for prow job metadata .


func NewBoskosHandler(r *ranch.Ranch) *http.ServeMux {
	mux := http.NewServeMux()
	mux.Handle("/", handleDefault(r))
	mux.Handle("/acquire", handleAcquire(r))
	mux.Handle("/acquirebystate", handleAcquireByState(r))
	mux.Handle("/release", handleRelease(r))
	mux.Handle("/reset", handleReset(r))
	mux.Handle("/update", handleUpdate(r))
	mux.Handle("/metric", handleMetric(r))
	return mux
}

func NewBoskosHandler ( r * ranch . Ranch ) * http . ServeMux { mux := http . NewServeMux ( ) mux . Handle ( " " , handleDefault ( r ) ) mux . Handle ( " " , handleAcquire ( r ) ) mux . Handle ( " " , handleAcquireByState ( r ) ) mux . Handle ( " " , handleRelease ( r ) ) mux . Handle ( " " , handleReset ( r ) ) mux . Handle ( " " , handleUpdate ( r ) ) mux . Handle ( " " , handleMetric ( r ) ) return mux }

//NewBoskosHandler constructs the boskos handler.

NewBoskosHandler constructs the boskos handler .


func ErrorToStatus(err error) int {
	switch err.(type) {
	default:
		return http.StatusInternalServerError
	case *ranch.OwnerNotMatch:
		return http.StatusUnauthorized
	case *ranch.ResourceNotFound:
		return http.StatusNotFound
	case *ranch.ResourceTypeNotFound:
		return http.StatusNotFound
	case *ranch.StateNotMatch:
		return http.StatusConflict
	}
}

func ErrorToStatus ( err error ) int { switch err . ( type ) { default : return http . StatusInternalServerError case * ranch . OwnerNotMatch : return http . StatusUnauthorized case * ranch . ResourceNotFound : return http . StatusNotFound case * ranch . ResourceTypeNotFound : return http . StatusNotFound case * ranch . StateNotMatch : return http . StatusConflict } }

// ErrorToStatus translates error into http code


func DumpProfile(destination string, profile []*cover.Profile) error {
	var output io.Writer
	if destination == "-" {
		output = os.Stdout
	} else {
		f, err := os.Create(destination)
		if err != nil {
			return fmt.Errorf("failed to open %s: %v", destination, err)
		}
		defer f.Close()
		output = f
	}
	err := cov.DumpProfile(profile, output)
	if err != nil {
		return fmt.Errorf("failed to dump profile: %v", err)
	}
	return nil
}

func DumpProfile ( destination string , profile [ ] * cover . Profile ) error { var output io . Writer if destination == " " { output = os . Stdout } else { f , err := os . Create ( destination ) if err != nil { return fmt . Errorf ( " " , destination , err ) } defer f . Close ( ) output = f } err := cov . DumpProfile ( profile , output ) if err != nil { return fmt . Errorf ( " " , err ) } return nil }

// DumpProfile dumps the profile to the given file destination.
// If the destination is "-", it instead writes to stdout.

DumpProfile dumps the profile to the given file destination . If the destination is - it instead writes to stdout .


func LoadProfile(origin string) ([]*cover.Profile, error) {
	filename := origin
	if origin == "-" {
		// Annoyingly, ParseProfiles only accepts a filename, so we have to write the bytes to disk
		// so it can read them back.
		// We could probably also just give it /dev/stdin, but that'll break on Windows.
		tf, err := ioutil.TempFile("", "")
		if err != nil {
			return nil, fmt.Errorf("failed to create temp file: %v", err)
		}
		defer tf.Close()
		defer os.Remove(tf.Name())
		if _, err := io.Copy(tf, os.Stdin); err != nil {
			return nil, fmt.Errorf("failed to copy stdin to temp file: %v", err)
		}
		filename = tf.Name()
	}
	return cover.ParseProfiles(filename)
}

// LoadProfile loads a profile from the given filename.
// If the filename is "-", it instead reads from stdin.

LoadProfile loads a profile from the given filename . If the filename is - it instead reads from stdin .


func NewClient() (*Client, error) {
	g, err := exec.LookPath("git")
	if err != nil {
		return nil, err
	}
	t, err := ioutil.TempDir("", "git")
	if err != nil {
		return nil, err
	}
	return &Client{
		logger:    logrus.WithField("client", "git"),
		dir:       t,
		git:       g,
		base:      fmt.Sprintf("https://%s", github),
		repoLocks: make(map[string]*sync.Mutex),
	}, nil
}

func NewClient ( ) ( * Client , error ) { g , err := exec . LookPath ( " " ) if err != nil { return nil , err } t , err := ioutil . TempDir ( " " , " " ) if err != nil { return nil , err } return & Client { logger : logrus . WithField ( " " , " " ) , dir : t , git : g , base : fmt . Sprintf ( " " , github ) , repoLocks : make ( map [ string ] * sync . Mutex ) , } , nil }

// NewClient returns a client that talks to GitHub. It will fail if git is not
// in the PATH.

NewClient returns a client that talks to GitHub . It will fail if git is not in the PATH .


func (c *Client) SetCredentials(user string, tokenGenerator func() []byte) {
	c.credLock.Lock()
	defer c.credLock.Unlock()
	c.user = user
	c.tokenGenerator = tokenGenerator
}

func ( c * Client ) SetCredentials ( user string , tokenGenerator func ( ) [ ] byte ) { c . credLock . Lock ( ) defer c . credLock . Unlock ( ) c . user = user c . tokenGenerator = tokenGenerator }

// SetCredentials sets credentials in the client to be used for pushing to
// or pulling from remote repositories.

SetCredentials sets credentials in the client to be used for pushing to or pulling from remote repositories .


func (r *Repo) Checkout(commitlike string) error {
	r.logger.Infof("Checkout %s.", commitlike)
	co := r.gitCommand("checkout", commitlike)
	if b, err := co.CombinedOutput(); err != nil {
		return fmt.Errorf("error checking out %s: %v. output: %s", commitlike, err, string(b))
	}
	return nil
}

func ( r * Repo ) Checkout ( commitlike string ) error { r . logger . Infof ( " " , commitlike ) co := r . gitCommand ( " " , commitlike ) if b , err := co . CombinedOutput ( ) ; err != nil { return fmt . Errorf ( " " , commitlike , err , string ( b ) ) } return nil }


func (r *Repo) CheckoutNewBranch(branch string) error {
	r.logger.Infof("Create and checkout %s.", branch)
	co := r.gitCommand("checkout", "-b", branch)
	if b, err := co.CombinedOutput(); err != nil {
		return fmt.Errorf("error checking out %s: %v. output: %s", branch, err, string(b))
	}
	return nil
}

func ( r * Repo ) CheckoutNewBranch ( branch string ) error { r . logger . Infof ( " " , branch ) co := r . gitCommand ( " " , " " , branch ) if b , err := co . CombinedOutput ( ) ; err != nil { return fmt . Errorf ( " " , branch , err , string ( b ) ) } return nil }

// CheckoutNewBranch creates a new branch and checks it out.

CheckoutNewBranch creates a new branch and checks it out .