github.com/abayer/test-infra@v0.0.5/experiment/manual-trigger/manual-trigger.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // manual-trigger triggers jenkins jobs based a specified github pull request
    18  package main
    19  
    20  import (
    21  	"flag"
    22  	"fmt"
    23  	"log"
    24  	"net/url"
    25  	"strings"
    26  
    27  	"github.com/sirupsen/logrus"
    28  
    29  	"k8s.io/test-infra/prow/config"
    30  	"k8s.io/test-infra/prow/github"
    31  	"k8s.io/test-infra/prow/jenkins"
    32  	"k8s.io/test-infra/prow/kube"
    33  	"k8s.io/test-infra/prow/pod-utils/downwardapi"
    34  )
    35  
    36  type options struct {
    37  	githubEndpoint         string
    38  	githubTokenFile        string
    39  	jenkinsBearerTokenFile string
    40  	jenkinsURL             string
    41  	jenkinsTokenFile       string
    42  	jenkinsUserName        string
    43  	jobName                string
    44  	num                    int
    45  	org                    string
    46  	repo                   string
    47  }
    48  
    49  func flagOptions() options {
    50  	o := options{}
    51  
    52  	flag.StringVar(&o.jenkinsBearerTokenFile, "jenkins-bearer-token-file", "", "Path to the file containing the Jenkins API bearer token.")
    53  	flag.StringVar(&o.jenkinsURL, "jenkins-url", "", "Jenkins URL.")
    54  	flag.StringVar(&o.jenkinsTokenFile, "jenkins-token-file", "", "Path to the file containing the Jenkins API token.")
    55  	flag.StringVar(&o.jenkinsUserName, "jenkins-user-name", "", "Jenkins username.")
    56  
    57  	flag.StringVar(&o.githubEndpoint, "github-endpoint", "https://api.github.com", "GitHub's API endpoint.")
    58  	flag.StringVar(&o.githubTokenFile, "github-token-file", "", "Path to file containing GitHub OAuth token.")
    59  
    60  	flag.StringVar(&o.jobName, "job-name", "", "Name of Jenkins job")
    61  
    62  	flag.IntVar(&o.num, "num", 0, "GitHub issue number")
    63  	flag.StringVar(&o.org, "org", "", "GitHub organization")
    64  	flag.StringVar(&o.repo, "repo", "", "GitHub repository")
    65  	flag.Parse()
    66  	return o
    67  }
    68  
    69  func sanityCheckFlags(o options) error {
    70  	if o.num <= 0 {
    71  		return fmt.Errorf("empty or invalid --num")
    72  	}
    73  	if o.org == "" {
    74  		return fmt.Errorf("empty --org")
    75  	}
    76  	if o.repo == "" {
    77  		return fmt.Errorf("empty --repo")
    78  	}
    79  	if o.githubTokenFile == "" {
    80  		return fmt.Errorf("empty --github-token-file")
    81  	}
    82  	if o.jobName == "" {
    83  		return fmt.Errorf("empty --job-name")
    84  	}
    85  
    86  	if o.jenkinsBearerTokenFile == "" && (o.jenkinsUserName == "" || o.jenkinsTokenFile == "") {
    87  		return fmt.Errorf("neither --jenkins-bearer-token-file nor the combination of --jenkins-user-name and --jenkins-token-file were provided")
    88  	}
    89  
    90  	if o.githubEndpoint == "" {
    91  		return fmt.Errorf("empty --github-endpoint")
    92  	} else if _, err := url.Parse(o.githubEndpoint); err != nil {
    93  		return fmt.Errorf("bad --github-endpoint provided: %v", err)
    94  	}
    95  
    96  	if o.jenkinsURL == "" {
    97  		return fmt.Errorf("empty --jenkins-url")
    98  	} else if _, err := url.Parse(o.jenkinsURL); err != nil {
    99  		return fmt.Errorf("bad --jenkins-url provided: %v", err)
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  func main() {
   106  	o := flagOptions()
   107  	err := sanityCheckFlags(o)
   108  	if err != nil {
   109  		log.Fatal(err)
   110  	}
   111  
   112  	var tokens []string
   113  	tokens = append(tokens, o.githubTokenFile)
   114  
   115  	if o.jenkinsTokenFile != "" {
   116  		tokens = append(tokens, o.jenkinsTokenFile)
   117  	}
   118  
   119  	if o.jenkinsBearerTokenFile != "" {
   120  		tokens = append(tokens, o.jenkinsBearerTokenFile)
   121  	}
   122  
   123  	secretAgent := &config.SecretAgent{}
   124  	if err := secretAgent.Start(tokens); err != nil {
   125  		logrus.WithError(err).Fatal("Error starting secrets agent.")
   126  	}
   127  
   128  	// TODO(kargakis): dry this out
   129  	ac := jenkins.AuthConfig{}
   130  	if o.jenkinsTokenFile != "" {
   131  		ac.Basic = &jenkins.BasicAuthConfig{
   132  			User:     o.jenkinsUserName,
   133  			GetToken: secretAgent.GetTokenGenerator(o.jenkinsTokenFile),
   134  		}
   135  	} else if o.jenkinsBearerTokenFile != "" {
   136  		ac.BearerToken = &jenkins.BearerTokenAuthConfig{
   137  			GetToken: secretAgent.GetTokenGenerator(o.jenkinsBearerTokenFile),
   138  		}
   139  	} else {
   140  		log.Fatalf("no jenkins auth token provided")
   141  	}
   142  
   143  	jc, err := jenkins.NewClient(o.jenkinsURL, false, nil, &ac, nil, nil)
   144  	if err != nil {
   145  		log.Fatalf("cannot setup Jenkins client: %v", err)
   146  	}
   147  
   148  	gc := github.NewClient(secretAgent.GetTokenGenerator(o.githubTokenFile), o.githubEndpoint)
   149  
   150  	pr, err := gc.GetPullRequest(o.org, o.repo, o.num)
   151  	if err != nil {
   152  		log.Fatalf("Unable to get information on pull request %s/%s#%d: %v", o.org, o.repo, o.num, err)
   153  	}
   154  
   155  	spec := kube.ProwJobSpec{
   156  		Type: kube.PresubmitJob,
   157  		Job:  o.jobName,
   158  		Refs: &kube.Refs{
   159  			Org:     o.org,
   160  			Repo:    o.repo,
   161  			BaseRef: pr.Base.Ref,
   162  			BaseSHA: pr.Base.SHA,
   163  			Pulls: []kube.Pull{
   164  				{
   165  					Number: pr.Number,
   166  					Author: pr.User.Login,
   167  					SHA:    pr.Head.SHA,
   168  				},
   169  			},
   170  		},
   171  
   172  		Report:         false,
   173  		Context:        "",
   174  		RerunCommand:   "",
   175  		MaxConcurrency: 1,
   176  	}
   177  
   178  	if err = jc.BuildFromSpec(&spec, "0", o.jobName); err != nil {
   179  		log.Println("Submitting the following to Jenkins:")
   180  		env, _ := downwardapi.EnvForSpec(downwardapi.NewJobSpec(spec, "0", o.jobName))
   181  		for k, v := range env {
   182  			log.Printf("  %s=%s\n", k, v)
   183  		}
   184  		log.Fatalf("for %s/%s#%d resulted in an error: %v", o.org, o.repo, o.num, err)
   185  	} else {
   186  		slash := "/"
   187  		if strings.HasSuffix(o.jenkinsURL, "/") {
   188  			slash = ""
   189  		}
   190  		log.Printf("Successfully submitted job to %s%sjob/%s", o.jenkinsURL, slash, o.jobName)
   191  	}
   192  }