github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/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/secret" 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 := &secret.Agent{} 124 if err := secretAgent.Start(tokens); err != nil { 125 logrus.WithError(err).Fatal("Error starting secrets agent.") 126 } 127 128 // TODO: 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 }