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