github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/sub/main.go (about) 1 /* 2 Copyright 2018 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 "context" 21 "flag" 22 "net/http" 23 "os" 24 "os/exec" 25 "strconv" 26 "time" 27 28 "github.com/sirupsen/logrus" 29 30 utilerrors "k8s.io/apimachinery/pkg/util/errors" 31 "sigs.k8s.io/prow/pkg/config" 32 "sigs.k8s.io/prow/pkg/crier/reporters/pubsub" 33 "sigs.k8s.io/prow/pkg/flagutil" 34 prowflagutil "sigs.k8s.io/prow/pkg/flagutil" 35 configflagutil "sigs.k8s.io/prow/pkg/flagutil/config" 36 "sigs.k8s.io/prow/pkg/interrupts" 37 "sigs.k8s.io/prow/pkg/logrusutil" 38 "sigs.k8s.io/prow/pkg/metrics" 39 "sigs.k8s.io/prow/pkg/moonraker" 40 "sigs.k8s.io/prow/pkg/pjutil/pprof" 41 "sigs.k8s.io/prow/pkg/pubsub/subscriber" 42 ) 43 44 type options struct { 45 client prowflagutil.KubernetesOptions 46 github prowflagutil.GitHubOptions 47 port int 48 cookiefilePath string 49 50 config configflagutil.ConfigOptions 51 52 dryRun bool 53 gracePeriod time.Duration 54 instrumentationOptions prowflagutil.InstrumentationOptions 55 } 56 57 func (o *options) validate() error { 58 var errs []error 59 for _, group := range []flagutil.OptionGroup{&o.client, &o.github, &o.instrumentationOptions, &o.config} { 60 if err := group.Validate(o.dryRun); err != nil { 61 errs = append(errs, err) 62 } 63 } 64 65 return utilerrors.NewAggregate(errs) 66 } 67 68 func gatherOptions(fs *flag.FlagSet, args ...string) options { 69 var o options 70 fs.IntVar(&o.port, "port", 80, "HTTP Port.") 71 fs.BoolVar(&o.dryRun, "dry-run", true, "Dry run for testing. Uses API tokens but does not mutate.") 72 fs.DurationVar(&o.gracePeriod, "grace-period", 180*time.Second, "On shutdown, try to handle remaining events for the specified duration. ") 73 fs.StringVar(&o.cookiefilePath, "cookiefile", "", "Path to git http.cookiefile, leave empty for github or anonymous") 74 for _, group := range []flagutil.OptionGroup{&o.client, &o.github, &o.instrumentationOptions, &o.config} { 75 group.AddFlags(fs) 76 } 77 78 fs.Parse(args) 79 80 return o 81 } 82 83 func main() { 84 logrusutil.ComponentInit() 85 86 o := gatherOptions(flag.NewFlagSet(os.Args[0], flag.ExitOnError), os.Args[1:]...) 87 if err := o.validate(); err != nil { 88 logrus.WithError(err).Fatal("Invalid options") 89 } 90 91 configAgent, err := o.config.ConfigAgent() 92 if err != nil { 93 logrus.WithError(err).Fatal("Error starting config agent.") 94 } 95 96 prowjobClient, err := o.client.ProwJobClient(configAgent.Config().ProwJobNamespace, o.dryRun) 97 if err != nil { 98 logrus.WithError(err).Fatal("unable to create prow job client") 99 } 100 101 promMetrics := subscriber.NewMetrics() 102 103 defer interrupts.WaitForGracefulShutdown() 104 105 // Expose prometheus and pprof metrics 106 metrics.ExposeMetrics("sub", configAgent.Config().PushGateway, o.instrumentationOptions.MetricsPort) 107 pprof.Instrument(o.instrumentationOptions) 108 109 // If we are provided credentials for Git hosts, use them. These credentials 110 // hold per-host information in them so it's safe to set them globally. 111 if o.cookiefilePath != "" { 112 cmd := exec.Command("git", "config", "--global", "http.cookiefile", o.cookiefilePath) 113 if err := cmd.Run(); err != nil { 114 logrus.WithError(err).Fatal("unable to set cookiefile") 115 } 116 } 117 118 s := &subscriber.Subscriber{ 119 ConfigAgent: configAgent, 120 Metrics: promMetrics, 121 ProwJobClient: prowjobClient, 122 Reporter: pubsub.NewReporter(configAgent.Config), // reuse crier reporter 123 } 124 125 if o.config.MoonrakerAddress != "" { 126 moonrakerClient, err := moonraker.NewClient(o.config.MoonrakerAddress, configAgent) 127 if err != nil { 128 logrus.WithError(err).Fatal("Error getting Moonraker client.") 129 } 130 s.InRepoConfigGetter = moonrakerClient 131 } else { 132 gitClient, err := o.github.GitClientFactory(o.cookiefilePath, &o.config.InRepoConfigCacheDirBase, o.dryRun, false) 133 if err != nil { 134 logrus.WithError(err).Fatal("Error getting Git client.") 135 } 136 ircc, err := config.NewInRepoConfigCache(o.config.InRepoConfigCacheSize, configAgent, gitClient) 137 if err != nil { 138 logrus.WithError(err).Fatal("Error creating InRepoConfigCacheGetter.") 139 } 140 s.InRepoConfigGetter = ircc 141 } 142 143 subMux := http.NewServeMux() 144 // Return 200 on / for health checks. 145 subMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {}) 146 147 // Setting up Pull Server 148 logrus.Info("Setting up Pull Server") 149 pullServer := subscriber.NewPullServer(s) 150 interrupts.Run(func(ctx context.Context) { 151 if err := pullServer.Run(ctx); err != nil { 152 logrus.WithError(err).Fatal("Failed to run Pull Server") 153 } 154 }) 155 156 httpServer := &http.Server{Addr: ":" + strconv.Itoa(o.port), Handler: subMux} 157 interrupts.ListenAndServe(httpServer, o.gracePeriod) 158 }