sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/cmd/pipeline/main.go (about) 1 /* 2 Copyright 2019 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 "fmt" 23 "os" 24 "time" 25 26 "github.com/sirupsen/logrus" 27 apierrors "k8s.io/apimachinery/pkg/api/errors" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/client-go/kubernetes" 30 "k8s.io/client-go/rest" 31 "sigs.k8s.io/prow/pkg/pjutil/pprof" 32 33 _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // support gcp users in .kube/config 34 prowjobset "sigs.k8s.io/prow/pkg/client/clientset/versioned" 35 prowjobinfo "sigs.k8s.io/prow/pkg/client/informers/externalversions" 36 prowflagutil "sigs.k8s.io/prow/pkg/flagutil" 37 configflagutil "sigs.k8s.io/prow/pkg/flagutil/config" 38 "sigs.k8s.io/prow/pkg/interrupts" 39 "sigs.k8s.io/prow/pkg/kube" 40 "sigs.k8s.io/prow/pkg/logrusutil" 41 pipelineset "sigs.k8s.io/prow/pkg/pipeline/clientset/versioned" 42 pipelineinfo "sigs.k8s.io/prow/pkg/pipeline/informers/externalversions" 43 pipelineinfov1beta1 "sigs.k8s.io/prow/pkg/pipeline/informers/externalversions/pipeline/v1beta1" 44 ) 45 46 type options struct { 47 allContexts bool 48 config configflagutil.ConfigOptions 49 kubernetes prowflagutil.KubernetesOptions 50 totURL string 51 instrumentationOptions prowflagutil.InstrumentationOptions 52 } 53 54 func parseOptions() options { 55 var o options 56 if err := o.parse(flag.CommandLine, os.Args[1:]); err != nil { 57 logrus.Fatalf("Invalid flags: %v", err) 58 } 59 return o 60 } 61 62 func (o *options) parse(flags *flag.FlagSet, args []string) error { 63 o.config.ConfigPathFlagName = "config" 64 flags.BoolVar(&o.allContexts, "all-contexts", false, "Monitor all cluster contexts, not just default") 65 flags.StringVar(&o.totURL, "tot-url", "", "Tot URL") 66 o.kubernetes.AddFlags(flags) 67 o.instrumentationOptions.AddFlags(flags) 68 o.config.AddFlags(flags) 69 if err := flags.Parse(args); err != nil { 70 return fmt.Errorf("Parse flags: %w", err) 71 } 72 if err := o.config.Validate(false); err != nil { 73 return err 74 } 75 return nil 76 } 77 78 type pipelineConfig struct { 79 client pipelineset.Interface 80 informer pipelineinfov1beta1.PipelineRunInformer 81 } 82 83 // newPipelineConfig returns a client and informer capable of mutating and monitoring the specified config. 84 func newPipelineConfig(cfg rest.Config, stop <-chan struct{}) (*pipelineConfig, error) { 85 bc, err := pipelineset.NewForConfig(&cfg) 86 if err != nil { 87 return nil, err 88 } 89 90 // Ensure the pipeline CRD is deployed 91 // TODO(fejta): probably a better way to do this 92 if _, err := bc.TektonV1beta1().PipelineRuns("").List(context.TODO(), metav1.ListOptions{Limit: 1}); err != nil { 93 return nil, err 94 } 95 96 // Assume watches receive updates, but resync every 30m in case something wonky happens 97 bif := pipelineinfo.NewSharedInformerFactory(bc, 30*time.Minute) 98 bif.Tekton().V1beta1().PipelineRuns().Lister() 99 go bif.Start(stop) 100 return &pipelineConfig{ 101 client: bc, 102 informer: bif.Tekton().V1beta1().PipelineRuns(), 103 }, nil 104 } 105 106 func main() { 107 logrusutil.ComponentInit() 108 109 o := parseOptions() 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("failed to load prow config") 118 } 119 120 configs, err := o.kubernetes.LoadClusterConfigs(func() { 121 logrus.Fatal("Kubeconfig changed, exiting to trigger a restart") 122 }) 123 if err != nil { 124 logrus.WithError(err).Fatal("Error building client configs") 125 } 126 127 local := configs[kube.InClusterContext] 128 if !o.allContexts { 129 logrus.Warn("Truncating to default context") 130 configs = map[string]rest.Config{ 131 kube.DefaultClusterAlias: configs[kube.DefaultClusterAlias], 132 } 133 } else { 134 // the InClusterContext is always mapped to DefaultClusterAlias in the controller, so there is no need to watch for this config. 135 delete(configs, kube.InClusterContext) 136 } 137 138 kc, err := kubernetes.NewForConfig(&local) 139 if err != nil { 140 logrus.WithError(err).Fatalf("Failed to create local kubernetes client") 141 } 142 pjc, err := prowjobset.NewForConfig(&local) 143 if err != nil { 144 logrus.WithError(err).Fatal("Failed to create prowjob client") 145 } 146 pjif := prowjobinfo.NewSharedInformerFactory(pjc, 30*time.Minute) 147 pjif.Prow().V1().ProwJobs().Lister() 148 go pjif.Start(interrupts.Context().Done()) 149 150 pipelineConfigs := map[string]pipelineConfig{} 151 for context, cfg := range configs { 152 var bc *pipelineConfig 153 bc, err = newPipelineConfig(cfg, interrupts.Context().Done()) 154 if apierrors.IsNotFound(err) { 155 logrus.WithError(err).Infof("Ignoring cluster context %s: tekton pipeline CRD not deployed", context) 156 continue 157 } 158 // Don't panic when a build cluster cannot be reached 159 if err != nil { 160 logrus.WithError(err).Warningf("Failed to create %s pipeline client", context) 161 continue 162 } 163 pipelineConfigs[context] = *bc 164 } 165 166 opts := controllerOptions{ 167 kc: kc, 168 pjc: pjc, 169 pji: pjif.Prow().V1().ProwJobs(), 170 pipelineConfigs: pipelineConfigs, 171 totURL: o.totURL, 172 prowConfig: configAgent.Config, 173 rl: kube.RateLimiter(controllerName), 174 } 175 controller, err := newController(opts) 176 if err != nil { 177 logrus.WithError(err).Fatal("Error creating controller") 178 } 179 180 if err := controller.Run(2, interrupts.Context().Done()); err != nil { 181 logrus.WithError(err).Fatal("Error running controller") 182 } 183 logrus.Info("Finished") 184 }