github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/gcsupload/run.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  	"context"
    21  	"fmt"
    22  	"os"
    23  	"path"
    24  	"path/filepath"
    25  	"strings"
    26  
    27  	"cloud.google.com/go/storage"
    28  	"github.com/sirupsen/logrus"
    29  	"google.golang.org/api/option"
    30  	"k8s.io/test-infra/prow/kube"
    31  	"k8s.io/test-infra/prow/pod-utils/downwardapi"
    32  	"k8s.io/test-infra/prow/pod-utils/gcs"
    33  )
    34  
    35  // Run will upload files to GCS as prescribed by
    36  // the options. Any extra files can be passed as
    37  // a parameter and will have the prefix prepended
    38  // to their destination in GCS, so the caller can
    39  // operate relative to the base of the GCS dir.
    40  func (o Options) Run(spec *downwardapi.JobSpec, extra map[string]gcs.UploadFunc) error {
    41  	uploadTargets := o.assembleTargets(spec, extra)
    42  
    43  	if !o.DryRun {
    44  		ctx := context.Background()
    45  		gcsClient, err := storage.NewClient(ctx, option.WithCredentialsFile(o.GcsCredentialsFile))
    46  		if err != nil {
    47  			return fmt.Errorf("could not connect to GCS: %v", err)
    48  		}
    49  
    50  		if err := gcs.Upload(gcsClient.Bucket(o.Bucket), uploadTargets); err != nil {
    51  			return fmt.Errorf("failed to upload to GCS: %v", err)
    52  		}
    53  	} else {
    54  		for destination := range uploadTargets {
    55  			logrus.WithField("dest", destination).Info("Would upload")
    56  		}
    57  	}
    58  
    59  	logrus.Info("Finished upload to GCS")
    60  	return nil
    61  }
    62  
    63  func (o Options) assembleTargets(spec *downwardapi.JobSpec, extra map[string]gcs.UploadFunc) map[string]gcs.UploadFunc {
    64  	builder := builderForStrategy(o.PathStrategy, o.DefaultOrg, o.DefaultRepo)
    65  	jobBasePath := gcs.PathForSpec(spec, builder)
    66  	if o.PathPrefix != "" {
    67  		jobBasePath = path.Join(o.PathPrefix, jobBasePath)
    68  	}
    69  	var gcsPath string
    70  	if o.SubDir == "" {
    71  		gcsPath = jobBasePath
    72  	} else {
    73  		gcsPath = path.Join(jobBasePath, o.SubDir)
    74  	}
    75  
    76  	uploadTargets := map[string]gcs.UploadFunc{}
    77  
    78  	// ensure that an alias exists for any
    79  	// job we're uploading artifacts for
    80  	if alias := gcs.AliasForSpec(spec); alias != "" {
    81  		fullBasePath := "gs://" + path.Join(o.Bucket, jobBasePath)
    82  		uploadTargets[alias] = gcs.DataUpload(strings.NewReader(fullBasePath))
    83  	}
    84  
    85  	if latestBuilds := gcs.LatestBuildForSpec(spec, builder); len(latestBuilds) > 0 {
    86  		for _, latestBuild := range latestBuilds {
    87  			uploadTargets[latestBuild] = gcs.DataUpload(strings.NewReader(spec.BuildID))
    88  		}
    89  	}
    90  
    91  	for _, item := range o.Items {
    92  		info, err := os.Stat(item)
    93  		if err != nil {
    94  			logrus.Warnf("Encountered error in resolving items to upload for %s: %v", item, err)
    95  			continue
    96  		}
    97  		if info.IsDir() {
    98  			gatherArtifacts(item, gcsPath, info.Name(), uploadTargets)
    99  		} else {
   100  			destination := path.Join(gcsPath, info.Name())
   101  			if _, exists := uploadTargets[destination]; exists {
   102  				logrus.Warnf("Encountered duplicate upload of %s, skipping...", destination)
   103  				continue
   104  			}
   105  			uploadTargets[destination] = gcs.FileUpload(item)
   106  		}
   107  	}
   108  
   109  	for destination, upload := range extra {
   110  		uploadTargets[path.Join(gcsPath, destination)] = upload
   111  	}
   112  
   113  	return uploadTargets
   114  }
   115  
   116  func builderForStrategy(strategy, defaultOrg, defaultRepo string) gcs.RepoPathBuilder {
   117  	var builder gcs.RepoPathBuilder
   118  	switch strategy {
   119  	case kube.PathStrategyExplicit:
   120  		builder = gcs.NewExplicitRepoPathBuilder()
   121  	case kube.PathStrategyLegacy:
   122  		builder = gcs.NewLegacyRepoPathBuilder(defaultOrg, defaultRepo)
   123  	case kube.PathStrategySingle:
   124  		builder = gcs.NewSingleDefaultRepoPathBuilder(defaultOrg, defaultRepo)
   125  	}
   126  
   127  	return builder
   128  }
   129  
   130  func gatherArtifacts(artifactDir, gcsPath, subDir string, uploadTargets map[string]gcs.UploadFunc) {
   131  	logrus.Printf("Gathering artifacts from artifact directory: %s", artifactDir)
   132  	filepath.Walk(artifactDir, func(fspath string, info os.FileInfo, err error) error {
   133  		if info == nil || info.IsDir() {
   134  			return nil
   135  		}
   136  
   137  		// we know path will be below artifactDir, but we can't
   138  		// communicate that to the filepath module. We can ignore
   139  		// this error as we can be certain it won't occur and best-
   140  		// effort upload is OK in any case
   141  		if relPath, err := filepath.Rel(artifactDir, fspath); err == nil {
   142  			destination := path.Join(gcsPath, subDir, relPath)
   143  			if _, exists := uploadTargets[destination]; exists {
   144  				logrus.Warnf("Encountered duplicate upload of %s, skipping...", destination)
   145  				return nil
   146  			}
   147  			logrus.Printf("Found %s in artifact directory. Uploading as %s\n", fspath, destination)
   148  			uploadTargets[destination] = gcs.FileUpload(fspath)
   149  		} else {
   150  			logrus.Warnf("Encountered error in relative path calculation for %s under %s: %v", fspath, artifactDir, err)
   151  		}
   152  		return nil
   153  	})
   154  }