github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/prow/cmd/hook/main.go (about) 1 /* 2 Copyright 2016 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 package main 18 19 import ( 20 "bytes" 21 "flag" 22 "io/ioutil" 23 "net/http" 24 "net/url" 25 "os/signal" 26 "strconv" 27 "syscall" 28 "time" 29 30 "github.com/prometheus/client_golang/prometheus" 31 "github.com/prometheus/client_golang/prometheus/promhttp" 32 "github.com/prometheus/client_golang/prometheus/push" 33 "github.com/sirupsen/logrus" 34 35 "k8s.io/test-infra/prow/config" 36 "k8s.io/test-infra/prow/git" 37 "k8s.io/test-infra/prow/github" 38 "k8s.io/test-infra/prow/hook" 39 "k8s.io/test-infra/prow/kube" 40 "k8s.io/test-infra/prow/plugins" 41 "k8s.io/test-infra/prow/slack" 42 ) 43 44 var ( 45 port = flag.Int("port", 8888, "Port to listen on.") 46 47 configPath = flag.String("config-path", "/etc/config/config", "Path to config.yaml.") 48 pluginConfig = flag.String("plugin-config", "/etc/plugins/plugins", "Path to plugin config file.") 49 50 local = flag.Bool("local", false, "Run locally for testing purposes only. Does not require secret files.") 51 dryRun = flag.Bool("dry-run", true, "Dry run for testing. Uses API tokens but does not mutate.") 52 53 _ = flag.String("github-bot-name", "", "Deprecated.") 54 githubEndpoint = flag.String("github-endpoint", "https://api.github.com", "GitHub's API endpoint.") 55 githubTokenFile = flag.String("github-token-file", "/etc/github/oauth", "Path to the file containing the GitHub OAuth secret.") 56 57 webhookSecretFile = flag.String("hmac-secret-file", "/etc/webhook/hmac", "Path to the file containing the GitHub HMAC secret.") 58 slackTokenFile = flag.String("slack-token-file", "", "Path to the file containing the Slack token to use.") 59 ) 60 61 func main() { 62 flag.Parse() 63 64 configAgent := &config.Agent{} 65 if err := configAgent.Start(*configPath); err != nil { 66 logrus.WithError(err).Fatal("Error starting config agent.") 67 } 68 69 var webhookSecret []byte 70 var githubClient *github.Client 71 var kubeClient *kube.Client 72 var slackClient *slack.Client 73 if *local { 74 logrus.Warning("Running in local mode for dev only.") 75 76 logrus.Print("HMAC Secret: abcde12345") 77 webhookSecret = []byte("abcde12345") 78 79 githubClient = github.NewFakeClient() 80 kubeClient = kube.NewFakeClient() 81 } else { 82 logrus.SetFormatter(&logrus.JSONFormatter{}) 83 84 // Ignore SIGTERM so that we don't drop hooks when the pod is removed. 85 // We'll get SIGTERM first and then SIGKILL after our graceful termination 86 // deadline. 87 signal.Ignore(syscall.SIGTERM) 88 89 webhookSecretRaw, err := ioutil.ReadFile(*webhookSecretFile) 90 if err != nil { 91 logrus.WithError(err).Fatal("Could not read webhook secret file.") 92 } 93 webhookSecret = bytes.TrimSpace(webhookSecretRaw) 94 95 oauthSecretRaw, err := ioutil.ReadFile(*githubTokenFile) 96 if err != nil { 97 logrus.WithError(err).Fatal("Could not read oauth secret file.") 98 } 99 oauthSecret := string(bytes.TrimSpace(oauthSecretRaw)) 100 101 var teamToken string 102 if *slackTokenFile != "" { 103 teamTokenRaw, err := ioutil.ReadFile(*slackTokenFile) 104 if err != nil { 105 logrus.WithError(err).Fatal("Could not read slack token file.") 106 } 107 teamToken = string(bytes.TrimSpace(teamTokenRaw)) 108 } 109 110 _, err = url.Parse(*githubEndpoint) 111 if err != nil { 112 logrus.WithError(err).Fatal("Must specify a valid --github-endpoint URL.") 113 } 114 115 if *dryRun { 116 githubClient = github.NewDryRunClient(oauthSecret, *githubEndpoint) 117 } else { 118 githubClient = github.NewClient(oauthSecret, *githubEndpoint) 119 } 120 121 kubeClient, err = kube.NewClientInCluster(configAgent.Config().ProwJobNamespace) 122 if err != nil { 123 logrus.WithError(err).Fatal("Error getting kube client.") 124 } 125 126 if !*dryRun && teamToken != "" { 127 logrus.Info("Using real slack client.") 128 slackClient = slack.NewClient(teamToken) 129 } 130 } 131 if slackClient == nil { 132 logrus.Info("Using fake slack client.") 133 slackClient = slack.NewFakeClient() 134 } 135 136 gitClient, err := git.NewClient() 137 if err != nil { 138 logrus.WithError(err).Fatal("Error getting git client.") 139 } 140 141 logger := logrus.StandardLogger() 142 githubClient.Logger = logger.WithField("client", "github") 143 kubeClient.Logger = logger.WithField("client", "kube") 144 gitClient.Logger = logger.WithField("client", "git") 145 slackClient.Logger = logger.WithField("client", "slack") 146 147 pluginAgent := &plugins.PluginAgent{ 148 PluginClient: plugins.PluginClient{ 149 GitHubClient: githubClient, 150 KubeClient: kubeClient, 151 GitClient: gitClient, 152 SlackClient: slackClient, 153 Logger: logrus.NewEntry(logrus.StandardLogger()), 154 }, 155 } 156 if err := pluginAgent.Start(*pluginConfig); err != nil { 157 logrus.WithError(err).Fatal("Error starting plugins.") 158 } 159 160 metrics, err := hook.NewMetrics() 161 if err != nil { 162 logrus.WithError(err).Fatal("Failed to initialize metrics.") 163 } 164 165 if configAgent.Config().PushGateway.Endpoint != "" { 166 go func() { 167 for { 168 time.Sleep(time.Minute) 169 if err := push.FromGatherer("hook", push.HostnameGroupingKey(), configAgent.Config().PushGateway.Endpoint, prometheus.DefaultGatherer); err != nil { 170 logrus.WithError(err).Error("Failed to push metrics.") 171 } 172 } 173 }() 174 } 175 176 server := &hook.Server{ 177 HMACSecret: webhookSecret, 178 ConfigAgent: configAgent, 179 Plugins: pluginAgent, 180 Metrics: metrics, 181 } 182 183 // Return 200 on / for health checks. 184 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {}) 185 http.Handle("/metrics", promhttp.Handler()) 186 // For /hook, handle a webhook normally. 187 http.Handle("/hook", server) 188 logrus.Fatal(http.ListenAndServe(":"+strconv.Itoa(*port), nil)) 189 }