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  }