github.com/abayer/test-infra@v0.0.5/prow/pod-utils/downwardapi/jobspec.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 downwardapi
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"os"
    23  	"strconv"
    24  
    25  	"k8s.io/test-infra/prow/kube"
    26  )
    27  
    28  // JobSpec is the full downward API that we expose to
    29  // jobs that realize a ProwJob. We will provide this
    30  // data to jobs with environment variables in two ways:
    31  //  - the full spec, in serialized JSON in one variable
    32  //  - individual fields of the spec in their own variables
    33  type JobSpec struct {
    34  	Type      kube.ProwJobType `json:"type,omitempty"`
    35  	Job       string           `json:"job,omitempty"`
    36  	BuildID   string           `json:"buildid,omitempty"`
    37  	ProwJobID string           `json:"prowjobid,omitempty"`
    38  
    39  	Refs kube.Refs `json:"refs,omitempty"`
    40  
    41  	// we need to keep track of the agent until we
    42  	// migrate everyone away from using the $BUILD_NUMBER
    43  	// environment variable
    44  	agent kube.ProwJobAgent
    45  }
    46  
    47  // NewJobSpec converts a kube.ProwJobSpec invocation into a JobSpec
    48  func NewJobSpec(spec kube.ProwJobSpec, buildID, prowJobID string) JobSpec {
    49  	refs := kube.Refs{}
    50  	if spec.Refs != nil {
    51  		refs = *spec.Refs
    52  	}
    53  
    54  	return JobSpec{
    55  		Type:      spec.Type,
    56  		Job:       spec.Job,
    57  		BuildID:   buildID,
    58  		ProwJobID: prowJobID,
    59  		Refs:      refs,
    60  		agent:     spec.Agent,
    61  	}
    62  }
    63  
    64  // ResolveSpecFromEnv will determine the Refs being
    65  // tested in by parsing Prow environment variable contents
    66  func ResolveSpecFromEnv() (*JobSpec, error) {
    67  	specEnv, ok := os.LookupEnv(JobSpecEnv)
    68  	if !ok {
    69  		return nil, fmt.Errorf("$%s unset", JobSpecEnv)
    70  	}
    71  
    72  	spec := &JobSpec{}
    73  	if err := json.Unmarshal([]byte(specEnv), spec); err != nil {
    74  		return nil, fmt.Errorf("malformed $%s: %v", JobSpecEnv, err)
    75  	}
    76  
    77  	return spec, nil
    78  }
    79  
    80  const (
    81  	// JobSpecEnv is the name that contains JobSpec marshaled into a string.
    82  	JobSpecEnv = "JOB_SPEC"
    83  
    84  	jobNameEnv   = "JOB_NAME"
    85  	jobTypeEnv   = "JOB_TYPE"
    86  	prowJobIDEnv = "PROW_JOB_ID"
    87  
    88  	buildIDEnv        = "BUILD_ID"
    89  	prowBuildIDEnv    = "BUILD_NUMBER" // Deprecated, will be removed in the future.
    90  	jenkinsBuildIDEnv = "buildId"      // Deprecated, will be removed in the future.
    91  
    92  	repoOwnerEnv   = "REPO_OWNER"
    93  	repoNameEnv    = "REPO_NAME"
    94  	pullBaseRefEnv = "PULL_BASE_REF"
    95  	pullBaseShaEnv = "PULL_BASE_SHA"
    96  	pullRefsEnv    = "PULL_REFS"
    97  	pullNumberEnv  = "PULL_NUMBER"
    98  	pullPullShaEnv = "PULL_PULL_SHA"
    99  )
   100  
   101  // EnvForSpec returns a mapping of environment variables
   102  // to their values that should be available for a job spec
   103  func EnvForSpec(spec JobSpec) (map[string]string, error) {
   104  	env := map[string]string{
   105  		jobNameEnv:   spec.Job,
   106  		buildIDEnv:   spec.BuildID,
   107  		prowJobIDEnv: spec.ProwJobID,
   108  		jobTypeEnv:   string(spec.Type),
   109  	}
   110  
   111  	// for backwards compatibility, we provide the build ID
   112  	// in both $BUILD_ID and $BUILD_NUMBER for Prow agents
   113  	// and in both $buildId and $BUILD_NUMBER for Jenkins
   114  	if spec.agent == kube.KubernetesAgent {
   115  		env[prowBuildIDEnv] = spec.BuildID
   116  	} else if spec.agent == kube.JenkinsAgent {
   117  		env[jenkinsBuildIDEnv] = spec.BuildID
   118  	}
   119  
   120  	raw, err := json.Marshal(spec)
   121  	if err != nil {
   122  		return env, fmt.Errorf("failed to marshal job spec: %v", err)
   123  	}
   124  	env[JobSpecEnv] = string(raw)
   125  
   126  	if spec.Type == kube.PeriodicJob {
   127  		return env, nil
   128  	}
   129  	env[repoOwnerEnv] = spec.Refs.Org
   130  	env[repoNameEnv] = spec.Refs.Repo
   131  	env[pullBaseRefEnv] = spec.Refs.BaseRef
   132  	env[pullBaseShaEnv] = spec.Refs.BaseSHA
   133  	env[pullRefsEnv] = spec.Refs.String()
   134  
   135  	if spec.Type == kube.PostsubmitJob || spec.Type == kube.BatchJob {
   136  		return env, nil
   137  	}
   138  	env[pullNumberEnv] = strconv.Itoa(spec.Refs.Pulls[0].Number)
   139  	env[pullPullShaEnv] = spec.Refs.Pulls[0].SHA
   140  	return env, nil
   141  }
   142  
   143  // EnvForType returns the slice of environment variables to export for jobType
   144  func EnvForType(jobType kube.ProwJobType) []string {
   145  	baseEnv := []string{jobNameEnv, JobSpecEnv, jobTypeEnv, prowJobIDEnv, buildIDEnv, prowBuildIDEnv, jenkinsBuildIDEnv}
   146  	refsEnv := []string{repoOwnerEnv, repoNameEnv, pullBaseRefEnv, pullBaseShaEnv, pullRefsEnv}
   147  	pullEnv := []string{pullNumberEnv, pullPullShaEnv}
   148  
   149  	switch jobType {
   150  	case kube.PeriodicJob:
   151  		return baseEnv
   152  	case kube.PostsubmitJob, kube.BatchJob:
   153  		return append(baseEnv, refsEnv...)
   154  	case kube.PresubmitJob:
   155  		return append(append(baseEnv, refsEnv...), pullEnv...)
   156  	default:
   157  		return []string{}
   158  	}
   159  }