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  }