sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/crier/reporters/gcs/util/util.go (about) 1 /* 2 Copyright 2020 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 util 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "strings" 24 25 "github.com/GoogleCloudPlatform/testgrid/metadata" 26 prowv1 "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 27 "sigs.k8s.io/prow/pkg/config" 28 "sigs.k8s.io/prow/pkg/gcsupload" 29 "sigs.k8s.io/prow/pkg/pod-utils/downwardapi" 30 ) 31 32 func GetJobDestination(cfg config.Getter, pj *prowv1.ProwJob) (bucket, dir string, err error) { 33 // We can't divine a destination for jobs that don't have a build ID, so don't try. 34 gc, err := gcsConfig(cfg, pj) 35 if err != nil { 36 return "", "", err 37 } 38 ps := downwardapi.NewJobSpec(pj.Spec, pj.Status.BuildID, pj.Name) 39 _, d, _ := gcsupload.PathsForJob(gc, &ps, "") 40 41 return gc.Bucket, d, nil 42 } 43 44 func IsGCSDestination(cfg config.Getter, pj *prowv1.ProwJob) bool { 45 gc, err := gcsConfig(cfg, pj) 46 if err != nil || gc.Bucket == "" { 47 return false 48 } 49 if strings.HasPrefix(gc.Bucket, "gs://") { 50 return true 51 } 52 // GCS is default if no other storage type is specified. 53 return !strings.Contains(gc.Bucket, "://") 54 } 55 56 func gcsConfig(cfg config.Getter, pj *prowv1.ProwJob) (*prowv1.GCSConfiguration, error) { 57 if pj.Status.BuildID == "" { 58 return nil, errors.New("cannot get job destination for job with no BuildID") 59 } 60 61 if pj.Spec.DecorationConfig != nil && pj.Spec.DecorationConfig.GCSConfiguration != nil { 62 return pj.Spec.DecorationConfig.GCSConfiguration, nil 63 } 64 65 // The decoration config is always provided for decorated jobs, but many 66 // jobs are not decorated, so we guess that we should use the default location 67 // for those jobs. This assumption is usually (but not always) correct. 68 // The TestGrid configurator uses the same assumption. 69 repo := "" 70 if pj.Spec.Refs != nil { 71 repo = pj.Spec.Refs.Org + "/" + pj.Spec.Refs.Repo 72 } else if len(pj.Spec.ExtraRefs) > 0 { 73 repo = fmt.Sprintf("%s/%s", pj.Spec.ExtraRefs[0].Org, pj.Spec.ExtraRefs[0].Repo) 74 } 75 76 ddc := cfg().Plank.GuessDefaultDecorationConfig(repo, pj.Spec.Cluster) 77 if ddc != nil && ddc.GCSConfiguration != nil { 78 return ddc.GCSConfiguration, nil 79 } 80 return nil, fmt.Errorf("couldn't figure out a GCS config for %q", pj.Spec.Job) 81 } 82 83 // MarshalProwJob marshals the ProwJob in the format written to GCS. 84 func MarshalProwJob(pj *prowv1.ProwJob) ([]byte, error) { 85 return json.MarshalIndent(pj, "", "\t") 86 } 87 88 // MarshalFinished marshals the finished.json format written to GCS. 89 func MarshalFinishedJSON(pj *prowv1.ProwJob) ([]byte, error) { 90 if !pj.Complete() { 91 return nil, errors.New("cannot report finished.json for incomplete job") 92 } 93 completion := pj.Status.CompletionTime.Unix() 94 passed := pj.Status.State == prowv1.SuccessState 95 f := metadata.Finished{ 96 Timestamp: &completion, 97 Passed: &passed, 98 Metadata: metadata.Metadata{"uploader": "crier"}, 99 Result: string(pj.Status.State), 100 } 101 return json.MarshalIndent(f, "", "\t") 102 }