github.com/abayer/test-infra@v0.0.5/prow/cmd/artifact-uploader/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 "encoding/json" 21 "errors" 22 "flag" 23 "fmt" 24 25 "github.com/sirupsen/logrus" 26 "k8s.io/client-go/kubernetes" 27 "k8s.io/client-go/rest" 28 "k8s.io/client-go/tools/clientcmd" 29 "k8s.io/test-infra/prow/kube" 30 31 "k8s.io/test-infra/prow/artifact-uploader" 32 "k8s.io/test-infra/prow/gcsupload" 33 "k8s.io/test-infra/prow/logrusutil" 34 "k8s.io/test-infra/prow/pod-utils/options" 35 ) 36 37 // newOptions returns an empty Options with no nil fields 38 func newOptions() *Options { 39 return &Options{ 40 Options: gcsupload.NewOptions(), 41 } 42 } 43 44 // Options holds info about parallelism, how to upload and cluster credentials. 45 type Options struct { 46 // NumWorkers determines the number of workers that consume 47 // the controller's work queue 48 NumWorkers int `json:"num_workers"` 49 // ProwJobNamespace is the namespace in the cluster that holds 50 // ProwJob objects 51 ProwJobNamespace string `json:"'prow_job_namespace'"` 52 53 *gcsupload.Options 54 55 clusterConfig *rest.Config 56 } 57 58 // Validate ensures that the set of options are 59 // self-consistent and valid 60 func (o *Options) Validate() error { 61 if o.NumWorkers == 0 { 62 return errors.New("number of workers cannot be zero") 63 } 64 65 if o.ProwJobNamespace == "" { 66 return errors.New("namespace containing ProwJobs not configured") 67 } 68 69 return o.Options.Validate() 70 } 71 72 const ( 73 // JSONConfigEnvVar is the environment variable that 74 // utilities expect to find a full JSON configuration 75 // in when run. 76 JSONConfigEnvVar = "ARTIFACTUPLOAD_OPTIONS" 77 ) 78 79 // ConfigVar exposes the environment variable used 80 // to store serialized configuration 81 func (o *Options) ConfigVar() string { 82 return JSONConfigEnvVar 83 } 84 85 // LoadConfig loads options from serialized config 86 func (o *Options) LoadConfig(config string) error { 87 return json.Unmarshal([]byte(config), o) 88 } 89 90 // BindOptions binds flags to options 91 func (o *Options) BindOptions(flags *flag.FlagSet) { 92 flags.IntVar(&o.NumWorkers, "num-workers", 25, "Number of threads to use for processing updates.") 93 flags.StringVar(&o.ProwJobNamespace, "prow-job-ns", "", "Namespace containing ProwJobs.") 94 gcsupload.BindOptions(o.Options, flags) 95 } 96 97 // Complete internalizes command line arguments 98 func (o *Options) Complete(args []string) { 99 o.Options.Complete(args) 100 } 101 102 // loadClusterConfig loads connection configuration 103 // for the cluster we're deploying to. We prefer to 104 // use in-cluster configuration if possible, but will 105 // fall back to using default rules otherwise. 106 func loadClusterConfig() (*rest.Config, error) { 107 clusterConfig, err := rest.InClusterConfig() 108 if err == nil { 109 return clusterConfig, nil 110 } 111 112 credentials, err := clientcmd.NewDefaultClientConfigLoadingRules().Load() 113 if err != nil { 114 return nil, fmt.Errorf("could not load credentials from config: %v", err) 115 } 116 117 clusterConfig, err = clientcmd.NewDefaultClientConfig(*credentials, &clientcmd.ConfigOverrides{}).ClientConfig() 118 if err != nil { 119 return nil, fmt.Errorf("could not load client configuration: %v", err) 120 } 121 return clusterConfig, nil 122 } 123 124 // Run uploads artifacts with the specified options forever. 125 // 126 // Sends a stop message to the artifact uploader when it is interrupted. 127 func (o *Options) Run() error { 128 clusterConfig, err := loadClusterConfig() 129 if err != nil { 130 return fmt.Errorf("failed to load cluster config: %v", err) 131 } 132 133 client, err := kubernetes.NewForConfig(clusterConfig) 134 if err != nil { 135 return err 136 } 137 138 prowJobClient, err := kube.NewClientInCluster(o.ProwJobNamespace) 139 if err != nil { 140 return err 141 } 142 143 controller := artifact_uploader.NewController(client.CoreV1(), prowJobClient, o.Options) 144 145 stop := make(chan struct{}) 146 defer close(stop) 147 go controller.Run(o.NumWorkers, stop) 148 149 // Wait forever 150 select {} 151 } 152 153 func main() { 154 o := newOptions() 155 if err := options.Load(o); err != nil { 156 logrus.Fatalf("Could not resolve options: %v", err) 157 } 158 159 if err := o.Validate(); err != nil { 160 logrus.Fatalf("Invalid options: %v", err) 161 } 162 163 logrus.SetFormatter( 164 logrusutil.NewDefaultFieldsFormatter(nil, logrus.Fields{"component": "artifact-uploader"}), 165 ) 166 167 if err := o.Run(); err != nil { 168 logrus.WithError(err).Fatal("Failed to run the GCS uploader controller") 169 } 170 }