sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/gcsupload/options.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 gcsupload 18 19 import ( 20 "encoding/json" 21 "errors" 22 "flag" 23 "fmt" 24 "strings" 25 26 "github.com/GoogleCloudPlatform/testgrid/util/gcs" 27 28 prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 29 prowflagutil "sigs.k8s.io/prow/pkg/flagutil" 30 ) 31 32 // NewOptions returns an empty Options with no nil fields. 33 func NewOptions() *Options { 34 return &Options{ 35 GCSConfiguration: &prowapi.GCSConfiguration{}, 36 } 37 } 38 39 // Options exposes the configuration necessary 40 // for defining where in storage an upload will land. 41 type Options struct { 42 // Items are files or directories to upload. 43 Items []string `json:"items,omitempty"` 44 45 // SubDir is appended to the GCS path. 46 SubDir string `json:"sub_dir,omitempty"` 47 48 *prowapi.GCSConfiguration 49 50 prowflagutil.StorageClientOptions 51 52 DryRun bool `json:"dry_run"` 53 54 // mediaTypes holds additional extension media types to add to Go's 55 // builtin's and the local system's defaults. Values are 56 // colon-delimited {extension}:{media-type}, for example: 57 // log:text/plain. 58 mediaTypes prowflagutil.Strings 59 60 // gcsPath is used to store human-provided GCS 61 // paths that are parsed to get more granular 62 // fields. 63 gcsPath gcs.Path 64 } 65 66 // Validate ensures that the set of options are 67 // self-consistent and valid. 68 func (o *Options) Validate() error { 69 if o.LocalOutputDir != "" { 70 return nil 71 } 72 if o.gcsPath.String() != "" { 73 o.Bucket = o.gcsPath.Bucket() 74 o.PathPrefix = o.gcsPath.Object() 75 } 76 77 if !o.DryRun { 78 if o.Bucket == "" { 79 return errors.New("GCS upload was requested no GCS bucket was provided") 80 } 81 } 82 83 return o.GCSConfiguration.Validate() 84 } 85 86 // ConfigVar exposes the environment variable used 87 // to store serialized configuration. 88 func (o *Options) ConfigVar() string { 89 return JSONConfigEnvVar 90 } 91 92 // LoadConfig loads options from serialized config 93 func (o *Options) LoadConfig(config string) error { 94 return json.Unmarshal([]byte(config), o) 95 } 96 97 // Complete internalizes command line arguments 98 func (o *Options) Complete(args []string) { 99 o.Items = args 100 101 for _, extensionMediaType := range o.mediaTypes.Strings() { 102 parts := strings.SplitN(extensionMediaType, ":", 2) 103 if len(parts) != 2 { 104 panic(fmt.Sprintf("invalid extension media type %q: missing colon delimiter", extensionMediaType)) 105 } 106 extension, mediaType := parts[0], parts[1] 107 if o.GCSConfiguration.MediaTypes == nil { 108 o.GCSConfiguration.MediaTypes = map[string]string{} 109 } 110 o.GCSConfiguration.MediaTypes[extension] = mediaType 111 } 112 o.mediaTypes = prowflagutil.NewStrings() 113 } 114 115 // AddFlags adds flags to the FlagSet that populate 116 // the GCS upload options struct given. 117 func (o *Options) AddFlags(fs *flag.FlagSet) { 118 fs.StringVar(&o.SubDir, "sub-dir", "", "Optional sub-directory of the job's path to which artifacts are uploaded") 119 120 fs.StringVar(&o.PathStrategy, "path-strategy", prowapi.PathStrategyExplicit, "how to encode org and repo into GCS paths") 121 fs.StringVar(&o.DefaultOrg, "default-org", "", "optional default org for GCS path encoding") 122 fs.StringVar(&o.DefaultRepo, "default-repo", "", "optional default repo for GCS path encoding") 123 124 fs.Var(&o.gcsPath, "gcs-path", "GCS path to upload into") 125 fs.BoolVar(&o.DryRun, "dry-run", true, "do not interact with GCS") 126 127 fs.Var(&o.mediaTypes, "media-type", "Optional comma-delimited set of extension media types. Each entry is colon-delimited {extension}:{media-type}, for example, log:text/plain.") 128 129 fs.StringVar(&o.LocalOutputDir, "local-output-dir", "", "If specified, files are copied to this dir instead of uploading to GCS.") 130 131 o.StorageClientOptions.AddFlags(fs) 132 } 133 134 const ( 135 // JSONConfigEnvVar is the environment variable that 136 // utilities expect to find a full JSON configuration 137 // in when run. 138 JSONConfigEnvVar = "GCSUPLOAD_OPTIONS" 139 ) 140 141 // Encode will encode the set of options in the format that 142 // is expected for the configuration environment variable. 143 func Encode(options Options) (string, error) { 144 encoded, err := json.Marshal(options) 145 return string(encoded), err 146 }