github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/pjutil/tot.go (about) 1 /* 2 Copyright 2017 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 pjutil 18 19 import ( 20 "fmt" 21 "io" 22 "log" 23 "net/http" 24 "net/url" 25 "path" 26 "time" 27 28 prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 29 "sigs.k8s.io/prow/pkg/config" 30 "sigs.k8s.io/prow/pkg/pod-utils/downwardapi" 31 32 "github.com/bwmarrin/snowflake" 33 ) 34 35 var ( 36 node *snowflake.Node 37 sleep = time.Sleep 38 ) 39 40 func init() { 41 var err error 42 node, err = snowflake.NewNode(1) 43 if err != nil { 44 log.Fatalf("failed to register snowflake node: %v", err) 45 } 46 } 47 48 // PresubmitToJobSpec generates a downwardapi.JobSpec out of a Presubmit. 49 // Useful for figuring out GCS paths when parsing jobs out 50 // of a prow config. 51 func PresubmitToJobSpec(pre config.Presubmit) *downwardapi.JobSpec { 52 return &downwardapi.JobSpec{ 53 Type: prowapi.PresubmitJob, 54 Job: pre.Name, 55 } 56 } 57 58 // PostsubmitToJobSpec generates a downwardapi.JobSpec out of a Postsubmit. 59 // Useful for figuring out GCS paths when parsing jobs out 60 // of a prow config. 61 func PostsubmitToJobSpec(post config.Postsubmit) *downwardapi.JobSpec { 62 return &downwardapi.JobSpec{ 63 Type: prowapi.PostsubmitJob, 64 Job: post.Name, 65 } 66 } 67 68 // PeriodicToJobSpec generates a downwardapi.JobSpec out of a Periodic. 69 // Useful for figuring out GCS paths when parsing jobs out 70 // of a prow config. 71 func PeriodicToJobSpec(periodic config.Periodic) *downwardapi.JobSpec { 72 return &downwardapi.JobSpec{ 73 Type: prowapi.PeriodicJob, 74 Job: periodic.Name, 75 } 76 } 77 78 // GetBuildID calls out to `tot` in order 79 // to vend build identifier for the job 80 func GetBuildID(name, totURL string) (string, error) { 81 if totURL == "" { 82 return node.Generate().String(), nil 83 } 84 var err error 85 url, err := url.Parse(totURL) 86 if err != nil { 87 return "", fmt.Errorf("invalid tot url: %w", err) 88 } 89 url.Path = path.Join(url.Path, "vend", name) 90 sleepDuration := 100 * time.Millisecond 91 for retries := 0; retries < 10; retries++ { 92 if retries > 0 { 93 sleep(sleepDuration) 94 sleepDuration = sleepDuration * 2 95 } 96 var resp *http.Response 97 resp, err = http.Get(url.String()) 98 if err != nil { 99 continue 100 } 101 defer resp.Body.Close() 102 if resp.StatusCode != 200 { 103 err = fmt.Errorf("got unexpected response from tot: %s", resp.Status) 104 continue 105 } 106 var buf []byte 107 buf, err = io.ReadAll(resp.Body) 108 if err == nil { 109 return string(buf), nil 110 } 111 return "", err 112 } 113 return "", err 114 }