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 }