sigs.k8s.io/prow@v0.0.0-20240503223140-c5e374dc7eb1/pkg/pod-utils/gcs/target.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 gcs
    18  
    19  import (
    20  	"fmt"
    21  	"path"
    22  	"strconv"
    23  	"strings"
    24  
    25  	"github.com/sirupsen/logrus"
    26  
    27  	prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1"
    28  	gerritsource "sigs.k8s.io/prow/pkg/gerrit/source"
    29  	"sigs.k8s.io/prow/pkg/pod-utils/downwardapi"
    30  )
    31  
    32  const (
    33  	// PRLogs is the name of the directory we put PR logs in.
    34  	PRLogs = "pr-logs"
    35  	// NonPRLogs is the name of directory we put logs that are not PR logs in.
    36  	NonPRLogs = "logs"
    37  )
    38  
    39  // PathForSpec determines the GCS path prefix for files uploaded
    40  // for a specific job spec
    41  func PathForSpec(spec *downwardapi.JobSpec, pathSegment RepoPathBuilder) string {
    42  	switch spec.Type {
    43  	case prowapi.PeriodicJob, prowapi.PostsubmitJob:
    44  		return path.Join(NonPRLogs, spec.Job, spec.BuildID)
    45  	case prowapi.PresubmitJob:
    46  		return path.Join(PRLogs, "pull", pathSegment(spec.Refs.Org, spec.Refs.Repo), strconv.Itoa(spec.Refs.Pulls[0].Number), spec.Job, spec.BuildID)
    47  	case prowapi.BatchJob:
    48  		return path.Join(PRLogs, "pull", "batch", spec.Job, spec.BuildID)
    49  	default:
    50  		logrus.Fatalf("unknown job spec type: %v", spec.Type)
    51  	}
    52  	return ""
    53  }
    54  
    55  // AliasForSpec determines the GCS path aliases for a job spec
    56  func AliasForSpec(spec *downwardapi.JobSpec) string {
    57  	switch spec.Type {
    58  	case prowapi.PeriodicJob, prowapi.PostsubmitJob, prowapi.BatchJob:
    59  		return ""
    60  	case prowapi.PresubmitJob:
    61  		return path.Join(PRLogs, "directory", spec.Job, fmt.Sprintf("%s.txt", spec.BuildID))
    62  	default:
    63  		logrus.Fatalf("unknown job spec type: %v", spec.Type)
    64  	}
    65  	return ""
    66  }
    67  
    68  // LatestBuildForSpec determines the GCS path for storing the latest
    69  // build id for a job. pathSegment can be nil so callers of this
    70  // helper are not required to choose a path strategy but can still
    71  // get back a result.
    72  func LatestBuildForSpec(spec *downwardapi.JobSpec, pathSegment RepoPathBuilder) []string {
    73  	var latestBuilds []string
    74  	switch spec.Type {
    75  	case prowapi.PeriodicJob, prowapi.PostsubmitJob:
    76  		latestBuilds = append(latestBuilds, path.Join(NonPRLogs, spec.Job, "latest-build.txt"))
    77  	case prowapi.PresubmitJob:
    78  		latestBuilds = append(latestBuilds, path.Join(PRLogs, "directory", spec.Job, "latest-build.txt"))
    79  		// Gubernator expects presubmit tests to upload latest-build.txt
    80  		// under the PR-specific directory too.
    81  		if pathSegment != nil {
    82  			latestBuilds = append(latestBuilds, path.Join(PRLogs, "pull", pathSegment(spec.Refs.Org, spec.Refs.Repo), strconv.Itoa(spec.Refs.Pulls[0].Number), spec.Job, "latest-build.txt"))
    83  		}
    84  	case prowapi.BatchJob:
    85  		latestBuilds = append(latestBuilds, path.Join(PRLogs, "directory", spec.Job, "latest-build.txt"))
    86  	default:
    87  		logrus.Errorf("unknown job spec type: %v", spec.Type)
    88  		return nil
    89  	}
    90  	return latestBuilds
    91  }
    92  
    93  // RootForSpec determines the root GCS path for storing artifacts about
    94  // the provided job.
    95  func RootForSpec(spec *downwardapi.JobSpec) string {
    96  	switch spec.Type {
    97  	case prowapi.PeriodicJob, prowapi.PostsubmitJob:
    98  		return path.Join(NonPRLogs, spec.Job)
    99  	case prowapi.PresubmitJob, prowapi.BatchJob:
   100  		return path.Join(PRLogs, "directory", spec.Job)
   101  	default:
   102  		logrus.Errorf("unknown job spec type: %v", spec.Type)
   103  	}
   104  	return ""
   105  }
   106  
   107  // RepoPathBuilder builds GCS path segments and embeds defaulting behavior
   108  type RepoPathBuilder func(org, repo string) string
   109  
   110  // NewLegacyRepoPathBuilder returns a builder that handles the legacy path
   111  // encoding where a path will only contain an org or repo if they are non-default
   112  func NewLegacyRepoPathBuilder(defaultOrg, defaultRepo string) RepoPathBuilder {
   113  	return func(org, repo string) string {
   114  		if org == defaultOrg {
   115  			if repo == defaultRepo {
   116  				return ""
   117  			}
   118  			return repo
   119  		}
   120  		// handle gerrit repo
   121  		org = gerritsource.TrimHTTPSPrefix(org)
   122  		repo = strings.Replace(repo, "/", "_", -1)
   123  		return fmt.Sprintf("%s_%s", org, repo)
   124  	}
   125  }
   126  
   127  // NewSingleDefaultRepoPathBuilder returns a builder that handles the legacy path
   128  // encoding where a path will contain org and repo for all but one default repo
   129  func NewSingleDefaultRepoPathBuilder(defaultOrg, defaultRepo string) RepoPathBuilder {
   130  	return func(org, repo string) string {
   131  		if org == defaultOrg && repo == defaultRepo {
   132  			return ""
   133  		}
   134  		// handle gerrit repo
   135  		org = gerritsource.TrimHTTPSPrefix(org)
   136  		repo = strings.Replace(repo, "/", "_", -1)
   137  		return fmt.Sprintf("%s_%s", org, repo)
   138  	}
   139  }
   140  
   141  // NewExplicitRepoPathBuilder returns a builder that handles the path encoding
   142  // where a path will always have an explicit "org_repo" path segment
   143  func NewExplicitRepoPathBuilder() RepoPathBuilder {
   144  	return func(org, repo string) string {
   145  		// handle gerrit repo
   146  		org = gerritsource.TrimHTTPSPrefix(org)
   147  		repo = strings.Replace(repo, "/", "_", -1)
   148  		return fmt.Sprintf("%s_%s", org, repo)
   149  	}
   150  }