github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/cmd/status-reconciler/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 "os" 23 "time" 24 25 "github.com/sirupsen/logrus" 26 "k8s.io/apimachinery/pkg/util/sets" 27 "sigs.k8s.io/prow/pkg/pjutil/pprof" 28 29 "sigs.k8s.io/prow/pkg/flagutil" 30 prowflagutil "sigs.k8s.io/prow/pkg/flagutil" 31 configflagutil "sigs.k8s.io/prow/pkg/flagutil/config" 32 pluginsflagutil "sigs.k8s.io/prow/pkg/flagutil/plugins" 33 "sigs.k8s.io/prow/pkg/interrupts" 34 "sigs.k8s.io/prow/pkg/logrusutil" 35 "sigs.k8s.io/prow/pkg/statusreconciler" 36 ) 37 38 const ( 39 defaultTokens = 300 40 defaultBurst = 100 41 ) 42 43 type options struct { 44 config configflagutil.ConfigOptions 45 pluginsConfig pluginsflagutil.PluginOptions 46 47 continueOnError bool 48 addedPresubmitDenylist prowflagutil.Strings 49 addedPresubmitDenylistAll prowflagutil.Strings 50 dryRun bool 51 kubernetes prowflagutil.KubernetesOptions 52 github prowflagutil.GitHubOptions 53 storage prowflagutil.StorageClientOptions 54 instrumentationOptions prowflagutil.InstrumentationOptions 55 56 // statusURI where Status-reconciler stores last known state, i.e. configuration. 57 // Can be /local/path, gs://path/to/object or s3://path/to/object. 58 // GCS writes will use the bucket's default acl for new objects. Ensure both that 59 // a) the gcs credentials can write to this bucket 60 // b) the default acls do not expose any private info 61 statusURI string 62 } 63 64 func gatherOptions(fs *flag.FlagSet, args ...string) options { 65 o := options{config: configflagutil.ConfigOptions{ConfigPath: "/etc/config/config.yaml"}} 66 67 fs.StringVar(&o.statusURI, "status-path", "", "The /local/path, gs://path/to/object or s3://path/to/object to store status controller state. GCS writes will use the default object ACL for the bucket.") 68 69 fs.BoolVar(&o.continueOnError, "continue-on-error", false, "Indicates that the migration should continue if context migration fails for an individual PR.") 70 fs.Var(&o.addedPresubmitDenylist, "denylist", "Org or org/repo to ignore new added presubmits for, set more than once to add more.") 71 fs.Var(&o.addedPresubmitDenylistAll, "denylist-all", "Org or org/repo to ignore reconciling, set more than once to add more.") 72 fs.BoolVar(&o.dryRun, "dry-run", true, "Whether or not to make mutating API calls to GitHub.") 73 o.github.AddCustomizedFlags(fs, prowflagutil.ThrottlerDefaults(defaultTokens, defaultBurst)) 74 o.pluginsConfig.PluginConfigPathDefault = "/etc/plugins/plugins.yaml" 75 for _, group := range []flagutil.OptionGroup{&o.kubernetes, &o.storage, &o.instrumentationOptions, &o.config, &o.pluginsConfig} { 76 group.AddFlags(fs) 77 } 78 fs.Parse(args) 79 return o 80 } 81 82 func (o *options) Validate() error { 83 for _, group := range []flagutil.OptionGroup{&o.kubernetes, &o.github, &o.storage, &o.config, &o.pluginsConfig} { 84 if err := group.Validate(o.dryRun); err != nil { 85 return err 86 } 87 } 88 89 return nil 90 } 91 92 func (o *options) getDenyList() sets.Set[string] { 93 denyList := o.addedPresubmitDenylist.Strings() 94 95 return sets.New[string](denyList...) 96 } 97 98 func (o *options) getDenyListAll() sets.Set[string] { 99 denyListAll := o.addedPresubmitDenylistAll.Strings() 100 return sets.New[string](denyListAll...) 101 } 102 103 func main() { 104 logrusutil.ComponentInit() 105 106 o := gatherOptions(flag.NewFlagSet(os.Args[0], flag.ExitOnError), os.Args[1:]...) 107 if err := o.Validate(); err != nil { 108 logrus.WithError(err).Fatal("Invalid options") 109 } 110 111 defer interrupts.WaitForGracefulShutdown() 112 113 pprof.Instrument(o.instrumentationOptions) 114 115 configAgent, err := o.config.ConfigAgent() 116 if err != nil { 117 logrus.WithError(err).Fatal("Error starting config agent.") 118 } 119 120 pluginAgent, err := o.pluginsConfig.PluginAgent() 121 if err != nil { 122 logrus.WithError(err).Fatal("Error starting plugin configuration agent.") 123 } 124 125 githubClient, err := o.github.GitHubClient(o.dryRun) 126 if err != nil { 127 logrus.WithError(err).Fatal("Error getting GitHub client.") 128 } 129 130 prowJobClient, err := o.kubernetes.ProwJobClient(configAgent.Config().ProwJobNamespace, o.dryRun) 131 if err != nil { 132 logrus.WithError(err).Fatal("Error getting kube client.") 133 } 134 135 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 136 defer cancel() 137 opener, err := o.storage.StorageClient(ctx) 138 if err != nil { 139 logrus.WithError(err).Fatal("Cannot create opener") 140 } 141 142 c := statusreconciler.NewController(o.continueOnError, o.getDenyList(), o.getDenyListAll(), opener, o.config, o.statusURI, prowJobClient, githubClient, pluginAgent) 143 interrupts.Run(func(ctx context.Context) { 144 c.Run(ctx) 145 }) 146 }