github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/prow/pod-utils/decorate/podspec_test.go (about)

     1  /*
     2  Copyright 2018 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 decorate
    18  
    19  import (
    20  	"strconv"
    21  	"testing"
    22  	"time"
    23  
    24  	"k8s.io/api/core/v1"
    25  	"k8s.io/apimachinery/pkg/api/equality"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/util/diff"
    28  
    29  	"k8s.io/test-infra/prow/clonerefs"
    30  	"k8s.io/test-infra/prow/kube"
    31  )
    32  
    33  func cookieVolumeOnly(secret string) kube.Volume {
    34  	v, _, _ := cookiefileVolume(secret)
    35  	return v
    36  }
    37  
    38  func cookieMountOnly(secret string) kube.VolumeMount {
    39  	_, vm, _ := cookiefileVolume(secret)
    40  	return vm
    41  }
    42  func cookiePathOnly(secret string) string {
    43  	_, _, vp := cookiefileVolume(secret)
    44  	return vp
    45  }
    46  
    47  func TestCloneRefs(t *testing.T) {
    48  	truth := true
    49  	logMount := kube.VolumeMount{
    50  		Name:      "log",
    51  		MountPath: "/log-mount",
    52  	}
    53  	codeMount := kube.VolumeMount{
    54  		Name:      "code",
    55  		MountPath: "/code-mount",
    56  	}
    57  	envOrDie := func(opt clonerefs.Options) []v1.EnvVar {
    58  		e, err := cloneEnv(opt)
    59  		if err != nil {
    60  			t.Fatal(err)
    61  		}
    62  		return e
    63  	}
    64  	sshVolumeOnly := func(secret string) kube.Volume {
    65  		v, _ := sshVolume(secret)
    66  		return v
    67  	}
    68  
    69  	sshMountOnly := func(secret string) kube.VolumeMount {
    70  		_, vm := sshVolume(secret)
    71  		return vm
    72  	}
    73  
    74  	cases := []struct {
    75  		name              string
    76  		pj                kube.ProwJob
    77  		codeMountOverride *kube.VolumeMount
    78  		logMountOverride  *kube.VolumeMount
    79  		expected          *kube.Container
    80  		volumes           []kube.Volume
    81  		err               bool
    82  	}{
    83  		{
    84  			name: "empty returns nil",
    85  		},
    86  		{
    87  			name: "nil refs and extrarefs returns nil",
    88  			pj: kube.ProwJob{
    89  				Spec: kube.ProwJobSpec{
    90  					DecorationConfig: &kube.DecorationConfig{},
    91  				},
    92  			},
    93  		},
    94  		{
    95  			name: "nil DecorationConfig returns nil",
    96  			pj: kube.ProwJob{
    97  				Spec: kube.ProwJobSpec{
    98  					Refs: &kube.Refs{},
    99  				},
   100  			},
   101  		},
   102  		{
   103  			name: "SkipCloning returns nil",
   104  			pj: kube.ProwJob{
   105  				Spec: kube.ProwJobSpec{
   106  					Refs: &kube.Refs{},
   107  					DecorationConfig: &kube.DecorationConfig{
   108  						SkipCloning: &truth,
   109  					},
   110  				},
   111  			},
   112  		},
   113  		{
   114  			name: "reject empty code mount name",
   115  			pj: kube.ProwJob{
   116  				Spec: kube.ProwJobSpec{
   117  					DecorationConfig: &kube.DecorationConfig{},
   118  					Refs:             &kube.Refs{},
   119  				},
   120  			},
   121  			codeMountOverride: &kube.VolumeMount{
   122  				MountPath: "/whatever",
   123  			},
   124  			err: true,
   125  		},
   126  		{
   127  			name: "reject empty code mountpath",
   128  			pj: kube.ProwJob{
   129  				Spec: kube.ProwJobSpec{
   130  					DecorationConfig: &kube.DecorationConfig{},
   131  					Refs:             &kube.Refs{},
   132  				},
   133  			},
   134  			codeMountOverride: &kube.VolumeMount{
   135  				Name: "wee",
   136  			},
   137  			err: true,
   138  		},
   139  		{
   140  			name: "reject empty log mount name",
   141  			pj: kube.ProwJob{
   142  				Spec: kube.ProwJobSpec{
   143  					DecorationConfig: &kube.DecorationConfig{},
   144  					Refs:             &kube.Refs{},
   145  				},
   146  			},
   147  			logMountOverride: &kube.VolumeMount{
   148  				MountPath: "/whatever",
   149  			},
   150  			err: true,
   151  		},
   152  		{
   153  			name: "reject empty log mountpath",
   154  			pj: kube.ProwJob{
   155  				Spec: kube.ProwJobSpec{
   156  					DecorationConfig: &kube.DecorationConfig{},
   157  					Refs:             &kube.Refs{},
   158  				},
   159  			},
   160  			logMountOverride: &kube.VolumeMount{
   161  				Name: "wee",
   162  			},
   163  			err: true,
   164  		},
   165  		{
   166  			name: "create clonerefs container when refs are set",
   167  			pj: kube.ProwJob{
   168  				Spec: kube.ProwJobSpec{
   169  					Refs: &kube.Refs{},
   170  					DecorationConfig: &kube.DecorationConfig{
   171  						UtilityImages: &kube.UtilityImages{},
   172  					},
   173  				},
   174  			},
   175  			expected: &kube.Container{
   176  				Name:    cloneRefsName,
   177  				Command: []string{cloneRefsCommand},
   178  				Env: envOrDie(clonerefs.Options{
   179  					GitRefs:      []kube.Refs{{}},
   180  					GitUserEmail: clonerefs.DefaultGitUserEmail,
   181  					GitUserName:  clonerefs.DefaultGitUserName,
   182  					SrcRoot:      codeMount.MountPath,
   183  					Log:          CloneLogPath(logMount),
   184  				}),
   185  				VolumeMounts: []kube.VolumeMount{logMount, codeMount},
   186  			},
   187  		},
   188  		{
   189  			name: "create clonerefs containers when extrarefs are set",
   190  			pj: kube.ProwJob{
   191  				Spec: kube.ProwJobSpec{
   192  					ExtraRefs: []kube.Refs{{}},
   193  					DecorationConfig: &kube.DecorationConfig{
   194  						UtilityImages: &kube.UtilityImages{},
   195  					},
   196  				},
   197  			},
   198  			expected: &kube.Container{
   199  				Name:    cloneRefsName,
   200  				Command: []string{cloneRefsCommand},
   201  				Env: envOrDie(clonerefs.Options{
   202  					GitRefs:      []kube.Refs{{}},
   203  					GitUserEmail: clonerefs.DefaultGitUserEmail,
   204  					GitUserName:  clonerefs.DefaultGitUserName,
   205  					SrcRoot:      codeMount.MountPath,
   206  					Log:          CloneLogPath(logMount),
   207  				}),
   208  				VolumeMounts: []kube.VolumeMount{logMount, codeMount},
   209  			},
   210  		},
   211  		{
   212  			name: "append extrarefs after refs",
   213  			pj: kube.ProwJob{
   214  				Spec: kube.ProwJobSpec{
   215  					Refs:      &kube.Refs{Org: "first"},
   216  					ExtraRefs: []kube.Refs{{Org: "second"}, {Org: "third"}},
   217  					DecorationConfig: &kube.DecorationConfig{
   218  						UtilityImages: &kube.UtilityImages{},
   219  					},
   220  				},
   221  			},
   222  			expected: &kube.Container{
   223  				Name:    cloneRefsName,
   224  				Command: []string{cloneRefsCommand},
   225  				Env: envOrDie(clonerefs.Options{
   226  					GitRefs:      []kube.Refs{{Org: "first"}, {Org: "second"}, {Org: "third"}},
   227  					GitUserEmail: clonerefs.DefaultGitUserEmail,
   228  					GitUserName:  clonerefs.DefaultGitUserName,
   229  					SrcRoot:      codeMount.MountPath,
   230  					Log:          CloneLogPath(logMount),
   231  				}),
   232  				VolumeMounts: []kube.VolumeMount{logMount, codeMount},
   233  			},
   234  		},
   235  		{
   236  			name: "append ssh secrets when set",
   237  			pj: kube.ProwJob{
   238  				Spec: kube.ProwJobSpec{
   239  					Refs: &kube.Refs{},
   240  					DecorationConfig: &kube.DecorationConfig{
   241  						UtilityImages: &kube.UtilityImages{},
   242  						SSHKeySecrets: []string{"super", "secret"},
   243  					},
   244  				},
   245  			},
   246  			expected: &kube.Container{
   247  				Name:    cloneRefsName,
   248  				Command: []string{cloneRefsCommand},
   249  				Env: envOrDie(clonerefs.Options{
   250  					GitRefs:      []kube.Refs{{}},
   251  					GitUserEmail: clonerefs.DefaultGitUserEmail,
   252  					GitUserName:  clonerefs.DefaultGitUserName,
   253  					KeyFiles:     []string{sshMountOnly("super").MountPath, sshMountOnly("secret").MountPath},
   254  					SrcRoot:      codeMount.MountPath,
   255  					Log:          CloneLogPath(logMount),
   256  				}),
   257  				VolumeMounts: []kube.VolumeMount{
   258  					logMount,
   259  					codeMount,
   260  					sshMountOnly("super"),
   261  					sshMountOnly("secret"),
   262  				},
   263  			},
   264  			volumes: []kube.Volume{sshVolumeOnly("super"), sshVolumeOnly("secret")},
   265  		},
   266  		{
   267  			name: "include ssh host fingerprints when set",
   268  			pj: kube.ProwJob{
   269  				Spec: kube.ProwJobSpec{
   270  					ExtraRefs: []kube.Refs{{}},
   271  					DecorationConfig: &kube.DecorationConfig{
   272  						UtilityImages:       &kube.UtilityImages{},
   273  						SSHHostFingerprints: []string{"thumb", "pinky"},
   274  					},
   275  				},
   276  			},
   277  			expected: &kube.Container{
   278  				Name:    cloneRefsName,
   279  				Command: []string{cloneRefsCommand},
   280  				Env: envOrDie(clonerefs.Options{
   281  					GitRefs:          []kube.Refs{{}},
   282  					GitUserEmail:     clonerefs.DefaultGitUserEmail,
   283  					GitUserName:      clonerefs.DefaultGitUserName,
   284  					SrcRoot:          codeMount.MountPath,
   285  					HostFingerprints: []string{"thumb", "pinky"},
   286  					Log:              CloneLogPath(logMount),
   287  				}),
   288  				VolumeMounts: []kube.VolumeMount{logMount, codeMount},
   289  			},
   290  		},
   291  		{
   292  			name: "include cookiefile secrets when set",
   293  			pj: kube.ProwJob{
   294  				Spec: kube.ProwJobSpec{
   295  					ExtraRefs: []kube.Refs{{}},
   296  					DecorationConfig: &kube.DecorationConfig{
   297  						UtilityImages:    &kube.UtilityImages{},
   298  						CookiefileSecret: "oatmeal",
   299  					},
   300  				},
   301  			},
   302  			expected: &kube.Container{
   303  				Name:    cloneRefsName,
   304  				Command: []string{cloneRefsCommand},
   305  				Args:    []string{"--cookiefile=" + cookiePathOnly("oatmeal")},
   306  				Env: envOrDie(clonerefs.Options{
   307  					CookiePath:   cookiePathOnly("oatmeal"),
   308  					GitRefs:      []kube.Refs{{}},
   309  					GitUserEmail: clonerefs.DefaultGitUserEmail,
   310  					GitUserName:  clonerefs.DefaultGitUserName,
   311  					SrcRoot:      codeMount.MountPath,
   312  					Log:          CloneLogPath(logMount),
   313  				}),
   314  				VolumeMounts: []kube.VolumeMount{logMount, codeMount, cookieMountOnly("oatmeal")},
   315  			},
   316  			volumes: []kube.Volume{cookieVolumeOnly("oatmeal")},
   317  		},
   318  	}
   319  
   320  	for _, tc := range cases {
   321  		t.Run(tc.name, func(t *testing.T) {
   322  			lm := logMount
   323  			if tc.logMountOverride != nil {
   324  				lm = *tc.logMountOverride
   325  			}
   326  			cm := codeMount
   327  			if tc.codeMountOverride != nil {
   328  				cm = *tc.codeMountOverride
   329  			}
   330  			actual, refs, volumes, err := CloneRefs(tc.pj, cm, lm)
   331  			switch {
   332  			case err != nil:
   333  				if !tc.err {
   334  					t.Errorf("unexpected error: %v", err)
   335  				}
   336  			case tc.err:
   337  				t.Error("failed to receive expected exception")
   338  			case !equality.Semantic.DeepEqual(tc.expected, actual):
   339  				t.Errorf("unexpected container:\n%s", diff.ObjectReflectDiff(tc.expected, actual))
   340  			case !equality.Semantic.DeepEqual(tc.volumes, volumes):
   341  				t.Errorf("unexpected volume:\n%s", diff.ObjectReflectDiff(tc.volumes, volumes))
   342  			case actual != nil:
   343  				var er []kube.Refs
   344  				if tc.pj.Spec.Refs != nil {
   345  					er = append(er, *tc.pj.Spec.Refs)
   346  				}
   347  				for _, r := range tc.pj.Spec.ExtraRefs {
   348  					er = append(er, r)
   349  				}
   350  				if !equality.Semantic.DeepEqual(refs, er) {
   351  					t.Errorf("unexpected refs:\n%s", diff.ObjectReflectDiff(er, refs))
   352  				}
   353  			}
   354  		})
   355  	}
   356  }
   357  
   358  func TestProwJobToPod(t *testing.T) {
   359  	truth := true
   360  	falseth := false
   361  	var sshKeyMode int32 = 0400
   362  	tests := []struct {
   363  		podName string
   364  		buildID string
   365  		labels  map[string]string
   366  		pjSpec  kube.ProwJobSpec
   367  
   368  		expected *v1.Pod
   369  	}{
   370  		{
   371  			podName: "pod",
   372  			buildID: "blabla",
   373  			labels:  map[string]string{"needstobe": "inherited"},
   374  			pjSpec: kube.ProwJobSpec{
   375  				Type:  kube.PresubmitJob,
   376  				Job:   "job-name",
   377  				Agent: kube.KubernetesAgent,
   378  				Refs: &kube.Refs{
   379  					Org:     "org-name",
   380  					Repo:    "repo-name",
   381  					BaseRef: "base-ref",
   382  					BaseSHA: "base-sha",
   383  					Pulls: []kube.Pull{{
   384  						Number: 1,
   385  						Author: "author-name",
   386  						SHA:    "pull-sha",
   387  					}},
   388  				},
   389  				PodSpec: &v1.PodSpec{
   390  					Containers: []v1.Container{
   391  						{
   392  							Image: "tester",
   393  							Env: []v1.EnvVar{
   394  								{Name: "MY_ENV", Value: "rocks"},
   395  							},
   396  						},
   397  					},
   398  				},
   399  			},
   400  
   401  			expected: &v1.Pod{
   402  				ObjectMeta: metav1.ObjectMeta{
   403  					Name: "pod",
   404  					Labels: map[string]string{
   405  						kube.CreatedByProw:     "true",
   406  						kube.ProwJobTypeLabel:  "presubmit",
   407  						kube.ProwJobIDLabel:    "pod",
   408  						"needstobe":            "inherited",
   409  						kube.OrgLabel:          "org-name",
   410  						kube.RepoLabel:         "repo-name",
   411  						kube.PullLabel:         "1",
   412  						kube.ProwJobAnnotation: "job-name",
   413  					},
   414  					Annotations: map[string]string{
   415  						kube.ProwJobAnnotation: "job-name",
   416  					},
   417  				},
   418  				Spec: v1.PodSpec{
   419  					AutomountServiceAccountToken: &falseth,
   420  					RestartPolicy:                "Never",
   421  					Containers: []v1.Container{
   422  						{
   423  							Name:  "test",
   424  							Image: "tester",
   425  							Env: []v1.EnvVar{
   426  								{Name: "MY_ENV", Value: "rocks"},
   427  								{Name: "BUILD_ID", Value: "blabla"},
   428  								{Name: "BUILD_NUMBER", Value: "blabla"},
   429  								{Name: "JOB_NAME", Value: "job-name"},
   430  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}]}}`},
   431  								{Name: "JOB_TYPE", Value: "presubmit"},
   432  								{Name: "PROW_JOB_ID", Value: "pod"},
   433  								{Name: "PULL_BASE_REF", Value: "base-ref"},
   434  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
   435  								{Name: "PULL_NUMBER", Value: "1"},
   436  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
   437  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
   438  								{Name: "REPO_NAME", Value: "repo-name"},
   439  								{Name: "REPO_OWNER", Value: "org-name"},
   440  							},
   441  						},
   442  					},
   443  				},
   444  			},
   445  		},
   446  		{
   447  			podName: "pod",
   448  			buildID: "blabla",
   449  			labels:  map[string]string{"needstobe": "inherited"},
   450  			pjSpec: kube.ProwJobSpec{
   451  				Type: kube.PresubmitJob,
   452  				Job:  "job-name",
   453  				DecorationConfig: &kube.DecorationConfig{
   454  					Timeout:     120 * time.Minute,
   455  					GracePeriod: 10 * time.Second,
   456  					UtilityImages: &kube.UtilityImages{
   457  						CloneRefs:  "clonerefs:tag",
   458  						InitUpload: "initupload:tag",
   459  						Entrypoint: "entrypoint:tag",
   460  						Sidecar:    "sidecar:tag",
   461  					},
   462  					GCSConfiguration: &kube.GCSConfiguration{
   463  						Bucket:       "my-bucket",
   464  						PathStrategy: "legacy",
   465  						DefaultOrg:   "kubernetes",
   466  						DefaultRepo:  "kubernetes",
   467  					},
   468  					GCSCredentialsSecret: "secret-name",
   469  					CookiefileSecret:     "yummy/.gitcookies",
   470  				},
   471  				Agent: kube.KubernetesAgent,
   472  				Refs: &kube.Refs{
   473  					Org:     "org-name",
   474  					Repo:    "repo-name",
   475  					BaseRef: "base-ref",
   476  					BaseSHA: "base-sha",
   477  					Pulls: []kube.Pull{{
   478  						Number: 1,
   479  						Author: "author-name",
   480  						SHA:    "pull-sha",
   481  					}},
   482  					PathAlias: "somewhere/else",
   483  				},
   484  				ExtraRefs: []kube.Refs{},
   485  				PodSpec: &v1.PodSpec{
   486  					Containers: []v1.Container{
   487  						{
   488  							Image:   "tester",
   489  							Command: []string{"/bin/thing"},
   490  							Args:    []string{"some", "args"},
   491  							Env: []v1.EnvVar{
   492  								{Name: "MY_ENV", Value: "rocks"},
   493  							},
   494  						},
   495  					},
   496  				},
   497  			},
   498  			expected: &v1.Pod{
   499  				ObjectMeta: metav1.ObjectMeta{
   500  					Name: "pod",
   501  					Labels: map[string]string{
   502  						kube.CreatedByProw:     "true",
   503  						kube.ProwJobTypeLabel:  "presubmit",
   504  						kube.ProwJobIDLabel:    "pod",
   505  						"needstobe":            "inherited",
   506  						kube.OrgLabel:          "org-name",
   507  						kube.RepoLabel:         "repo-name",
   508  						kube.PullLabel:         "1",
   509  						kube.ProwJobAnnotation: "job-name",
   510  					},
   511  					Annotations: map[string]string{
   512  						kube.ProwJobAnnotation: "job-name",
   513  					},
   514  				},
   515  				Spec: v1.PodSpec{
   516  					AutomountServiceAccountToken: &falseth,
   517  					RestartPolicy:                "Never",
   518  					InitContainers: []v1.Container{
   519  						{
   520  							Name:    "clonerefs",
   521  							Image:   "clonerefs:tag",
   522  							Command: []string{"/clonerefs"},
   523  							Args:    []string{"--cookiefile=" + cookiePathOnly("yummy/.gitcookies")},
   524  							Env: []v1.EnvVar{
   525  								{Name: "CLONEREFS_OPTIONS", Value: `{"src_root":"/home/prow/go","log":"/logs/clone.json","git_user_name":"ci-robot","git_user_email":"ci-robot@k8s.io","refs":[{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}],"cookie_path":"` + cookiePathOnly("yummy/.gitcookies") + `"}`},
   526  							},
   527  							VolumeMounts: []v1.VolumeMount{
   528  								{
   529  									Name:      "logs",
   530  									MountPath: "/logs",
   531  								},
   532  								{
   533  									Name:      "code",
   534  									MountPath: "/home/prow/go",
   535  								},
   536  								cookieMountOnly("yummy/.gitcookies"),
   537  							},
   538  						},
   539  						{
   540  							Name:    "initupload",
   541  							Image:   "initupload:tag",
   542  							Command: []string{"/initupload"},
   543  							Env: []v1.EnvVar{
   544  								{Name: "INITUPLOAD_OPTIONS", Value: `{"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false,"log":"/logs/clone.json"}`},
   545  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   546  							},
   547  							VolumeMounts: []kube.VolumeMount{
   548  								{
   549  									Name:      "logs",
   550  									MountPath: "/logs",
   551  								},
   552  								{
   553  									Name:      "gcs-credentials",
   554  									MountPath: "/secrets/gcs",
   555  								},
   556  							},
   557  						},
   558  						{
   559  							Name:    "place-tools",
   560  							Image:   "entrypoint:tag",
   561  							Command: []string{"/bin/cp"},
   562  							Args: []string{
   563  								"/entrypoint",
   564  								"/tools/entrypoint",
   565  							},
   566  							VolumeMounts: []kube.VolumeMount{
   567  								{
   568  									Name:      "tools",
   569  									MountPath: "/tools",
   570  								},
   571  							},
   572  						},
   573  					},
   574  					Containers: []v1.Container{
   575  						{
   576  							Name:       "test",
   577  							Image:      "tester",
   578  							Command:    []string{"/tools/entrypoint"},
   579  							Args:       []string{},
   580  							WorkingDir: "/home/prow/go/src/somewhere/else",
   581  							Env: []v1.EnvVar{
   582  								{Name: "MY_ENV", Value: "rocks"},
   583  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
   584  								{Name: "BUILD_ID", Value: "blabla"},
   585  								{Name: "BUILD_NUMBER", Value: "blabla"},
   586  								{Name: "ENTRYPOINT_OPTIONS", Value: `{"args":["/bin/thing","some","args"],"timeout":7200000000000,"grace_period":10000000000,"artifact_dir":"/logs/artifacts","process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}`},
   587  								{Name: "GOPATH", Value: "/home/prow/go"},
   588  								{Name: "JOB_NAME", Value: "job-name"},
   589  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   590  								{Name: "JOB_TYPE", Value: "presubmit"},
   591  								{Name: "PROW_JOB_ID", Value: "pod"},
   592  								{Name: "PULL_BASE_REF", Value: "base-ref"},
   593  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
   594  								{Name: "PULL_NUMBER", Value: "1"},
   595  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
   596  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
   597  								{Name: "REPO_NAME", Value: "repo-name"},
   598  								{Name: "REPO_OWNER", Value: "org-name"},
   599  							},
   600  							VolumeMounts: []v1.VolumeMount{
   601  								{
   602  									Name:      "logs",
   603  									MountPath: "/logs",
   604  								},
   605  								{
   606  									Name:      "tools",
   607  									MountPath: "/tools",
   608  								},
   609  								{
   610  									Name:      "code",
   611  									MountPath: "/home/prow/go",
   612  								},
   613  							},
   614  						},
   615  						{
   616  							Name:    "sidecar",
   617  							Image:   "sidecar:tag",
   618  							Command: []string{"/sidecar"},
   619  							Env: []v1.EnvVar{
   620  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   621  								{Name: "SIDECAR_OPTIONS", Value: `{"gcs_options":{"items":["/logs/artifacts"],"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false},"wrapper_options":{"process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}}`},
   622  							},
   623  							VolumeMounts: []v1.VolumeMount{
   624  								{
   625  									Name:      "logs",
   626  									MountPath: "/logs",
   627  								},
   628  								{
   629  									Name:      "gcs-credentials",
   630  									MountPath: "/secrets/gcs",
   631  								},
   632  							},
   633  						},
   634  					},
   635  					Volumes: []v1.Volume{
   636  						{
   637  							Name: "logs",
   638  							VolumeSource: v1.VolumeSource{
   639  								EmptyDir: &v1.EmptyDirVolumeSource{},
   640  							},
   641  						},
   642  						{
   643  							Name: "tools",
   644  							VolumeSource: v1.VolumeSource{
   645  								EmptyDir: &v1.EmptyDirVolumeSource{},
   646  							},
   647  						},
   648  						{
   649  							Name: "gcs-credentials",
   650  							VolumeSource: v1.VolumeSource{
   651  								Secret: &v1.SecretVolumeSource{
   652  									SecretName: "secret-name",
   653  								},
   654  							},
   655  						},
   656  						cookieVolumeOnly("yummy/.gitcookies"),
   657  						{
   658  							Name: "code",
   659  							VolumeSource: v1.VolumeSource{
   660  								EmptyDir: &v1.EmptyDirVolumeSource{},
   661  							},
   662  						},
   663  					},
   664  				},
   665  			},
   666  		},
   667  		{
   668  			podName: "pod",
   669  			buildID: "blabla",
   670  			labels:  map[string]string{"needstobe": "inherited"},
   671  			pjSpec: kube.ProwJobSpec{
   672  				Type: kube.PresubmitJob,
   673  				Job:  "job-name",
   674  				DecorationConfig: &kube.DecorationConfig{
   675  					Timeout:     120 * time.Minute,
   676  					GracePeriod: 10 * time.Second,
   677  					UtilityImages: &kube.UtilityImages{
   678  						CloneRefs:  "clonerefs:tag",
   679  						InitUpload: "initupload:tag",
   680  						Entrypoint: "entrypoint:tag",
   681  						Sidecar:    "sidecar:tag",
   682  					},
   683  					GCSConfiguration: &kube.GCSConfiguration{
   684  						Bucket:       "my-bucket",
   685  						PathStrategy: "legacy",
   686  						DefaultOrg:   "kubernetes",
   687  						DefaultRepo:  "kubernetes",
   688  					},
   689  					GCSCredentialsSecret: "secret-name",
   690  					CookiefileSecret:     "yummy",
   691  				},
   692  				Agent: kube.KubernetesAgent,
   693  				Refs: &kube.Refs{
   694  					Org:     "org-name",
   695  					Repo:    "repo-name",
   696  					BaseRef: "base-ref",
   697  					BaseSHA: "base-sha",
   698  					Pulls: []kube.Pull{{
   699  						Number: 1,
   700  						Author: "author-name",
   701  						SHA:    "pull-sha",
   702  					}},
   703  					PathAlias: "somewhere/else",
   704  				},
   705  				ExtraRefs: []kube.Refs{},
   706  				PodSpec: &v1.PodSpec{
   707  					Containers: []v1.Container{
   708  						{
   709  							Image:   "tester",
   710  							Command: []string{"/bin/thing"},
   711  							Args:    []string{"some", "args"},
   712  							Env: []v1.EnvVar{
   713  								{Name: "MY_ENV", Value: "rocks"},
   714  							},
   715  						},
   716  					},
   717  				},
   718  			},
   719  			expected: &v1.Pod{
   720  				ObjectMeta: metav1.ObjectMeta{
   721  					Name: "pod",
   722  					Labels: map[string]string{
   723  						kube.CreatedByProw:     "true",
   724  						kube.ProwJobTypeLabel:  "presubmit",
   725  						kube.ProwJobIDLabel:    "pod",
   726  						"needstobe":            "inherited",
   727  						kube.OrgLabel:          "org-name",
   728  						kube.RepoLabel:         "repo-name",
   729  						kube.PullLabel:         "1",
   730  						kube.ProwJobAnnotation: "job-name",
   731  					},
   732  					Annotations: map[string]string{
   733  						kube.ProwJobAnnotation: "job-name",
   734  					},
   735  				},
   736  				Spec: v1.PodSpec{
   737  					AutomountServiceAccountToken: &falseth,
   738  					RestartPolicy:                "Never",
   739  					InitContainers: []v1.Container{
   740  						{
   741  							Name:    "clonerefs",
   742  							Image:   "clonerefs:tag",
   743  							Command: []string{"/clonerefs"},
   744  							Args:    []string{"--cookiefile=" + cookiePathOnly("yummy")},
   745  							Env: []v1.EnvVar{
   746  								{Name: "CLONEREFS_OPTIONS", Value: `{"src_root":"/home/prow/go","log":"/logs/clone.json","git_user_name":"ci-robot","git_user_email":"ci-robot@k8s.io","refs":[{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}],"cookie_path":"` + cookiePathOnly("yummy") + `"}`},
   747  							},
   748  							VolumeMounts: []v1.VolumeMount{
   749  								{
   750  									Name:      "logs",
   751  									MountPath: "/logs",
   752  								},
   753  								{
   754  									Name:      "code",
   755  									MountPath: "/home/prow/go",
   756  								},
   757  								cookieMountOnly("yummy"),
   758  							},
   759  						},
   760  						{
   761  							Name:    "initupload",
   762  							Image:   "initupload:tag",
   763  							Command: []string{"/initupload"},
   764  							Env: []v1.EnvVar{
   765  								{Name: "INITUPLOAD_OPTIONS", Value: `{"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false,"log":"/logs/clone.json"}`},
   766  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   767  							},
   768  							VolumeMounts: []kube.VolumeMount{
   769  								{
   770  									Name:      "logs",
   771  									MountPath: "/logs",
   772  								},
   773  								{
   774  									Name:      "gcs-credentials",
   775  									MountPath: "/secrets/gcs",
   776  								},
   777  							},
   778  						},
   779  						{
   780  							Name:    "place-tools",
   781  							Image:   "entrypoint:tag",
   782  							Command: []string{"/bin/cp"},
   783  							Args: []string{
   784  								"/entrypoint",
   785  								"/tools/entrypoint",
   786  							},
   787  							VolumeMounts: []kube.VolumeMount{
   788  								{
   789  									Name:      "tools",
   790  									MountPath: "/tools",
   791  								},
   792  							},
   793  						},
   794  					},
   795  					Containers: []v1.Container{
   796  						{
   797  							Name:       "test",
   798  							Image:      "tester",
   799  							Command:    []string{"/tools/entrypoint"},
   800  							Args:       []string{},
   801  							WorkingDir: "/home/prow/go/src/somewhere/else",
   802  							Env: []v1.EnvVar{
   803  								{Name: "MY_ENV", Value: "rocks"},
   804  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
   805  								{Name: "BUILD_ID", Value: "blabla"},
   806  								{Name: "BUILD_NUMBER", Value: "blabla"},
   807  								{Name: "ENTRYPOINT_OPTIONS", Value: `{"args":["/bin/thing","some","args"],"timeout":7200000000000,"grace_period":10000000000,"artifact_dir":"/logs/artifacts","process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}`},
   808  								{Name: "GOPATH", Value: "/home/prow/go"},
   809  								{Name: "JOB_NAME", Value: "job-name"},
   810  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   811  								{Name: "JOB_TYPE", Value: "presubmit"},
   812  								{Name: "PROW_JOB_ID", Value: "pod"},
   813  								{Name: "PULL_BASE_REF", Value: "base-ref"},
   814  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
   815  								{Name: "PULL_NUMBER", Value: "1"},
   816  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
   817  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
   818  								{Name: "REPO_NAME", Value: "repo-name"},
   819  								{Name: "REPO_OWNER", Value: "org-name"},
   820  							},
   821  							VolumeMounts: []v1.VolumeMount{
   822  								{
   823  									Name:      "logs",
   824  									MountPath: "/logs",
   825  								},
   826  								{
   827  									Name:      "tools",
   828  									MountPath: "/tools",
   829  								},
   830  								{
   831  									Name:      "code",
   832  									MountPath: "/home/prow/go",
   833  								},
   834  							},
   835  						},
   836  						{
   837  							Name:    "sidecar",
   838  							Image:   "sidecar:tag",
   839  							Command: []string{"/sidecar"},
   840  							Env: []v1.EnvVar{
   841  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   842  								{Name: "SIDECAR_OPTIONS", Value: `{"gcs_options":{"items":["/logs/artifacts"],"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false},"wrapper_options":{"process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}}`},
   843  							},
   844  							VolumeMounts: []v1.VolumeMount{
   845  								{
   846  									Name:      "logs",
   847  									MountPath: "/logs",
   848  								},
   849  								{
   850  									Name:      "gcs-credentials",
   851  									MountPath: "/secrets/gcs",
   852  								},
   853  							},
   854  						},
   855  					},
   856  					Volumes: []v1.Volume{
   857  						{
   858  							Name: "logs",
   859  							VolumeSource: v1.VolumeSource{
   860  								EmptyDir: &v1.EmptyDirVolumeSource{},
   861  							},
   862  						},
   863  						{
   864  							Name: "tools",
   865  							VolumeSource: v1.VolumeSource{
   866  								EmptyDir: &v1.EmptyDirVolumeSource{},
   867  							},
   868  						},
   869  						{
   870  							Name: "gcs-credentials",
   871  							VolumeSource: v1.VolumeSource{
   872  								Secret: &v1.SecretVolumeSource{
   873  									SecretName: "secret-name",
   874  								},
   875  							},
   876  						},
   877  						cookieVolumeOnly("yummy"),
   878  						{
   879  							Name: "code",
   880  							VolumeSource: v1.VolumeSource{
   881  								EmptyDir: &v1.EmptyDirVolumeSource{},
   882  							},
   883  						},
   884  					},
   885  				},
   886  			},
   887  		},
   888  		{
   889  			podName: "pod",
   890  			buildID: "blabla",
   891  			labels:  map[string]string{"needstobe": "inherited"},
   892  			pjSpec: kube.ProwJobSpec{
   893  				Type: kube.PresubmitJob,
   894  				Job:  "job-name",
   895  				DecorationConfig: &kube.DecorationConfig{
   896  					Timeout:     120 * time.Minute,
   897  					GracePeriod: 10 * time.Second,
   898  					UtilityImages: &kube.UtilityImages{
   899  						CloneRefs:  "clonerefs:tag",
   900  						InitUpload: "initupload:tag",
   901  						Entrypoint: "entrypoint:tag",
   902  						Sidecar:    "sidecar:tag",
   903  					},
   904  					GCSConfiguration: &kube.GCSConfiguration{
   905  						Bucket:       "my-bucket",
   906  						PathStrategy: "legacy",
   907  						DefaultOrg:   "kubernetes",
   908  						DefaultRepo:  "kubernetes",
   909  					},
   910  					GCSCredentialsSecret: "secret-name",
   911  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
   912  					SSHHostFingerprints:  []string{"hello", "world"},
   913  				},
   914  				Agent: kube.KubernetesAgent,
   915  				Refs: &kube.Refs{
   916  					Org:     "org-name",
   917  					Repo:    "repo-name",
   918  					BaseRef: "base-ref",
   919  					BaseSHA: "base-sha",
   920  					Pulls: []kube.Pull{{
   921  						Number: 1,
   922  						Author: "author-name",
   923  						SHA:    "pull-sha",
   924  					}},
   925  					PathAlias: "somewhere/else",
   926  				},
   927  				ExtraRefs: []kube.Refs{},
   928  				PodSpec: &v1.PodSpec{
   929  					Containers: []v1.Container{
   930  						{
   931  							Image:   "tester",
   932  							Command: []string{"/bin/thing"},
   933  							Args:    []string{"some", "args"},
   934  							Env: []v1.EnvVar{
   935  								{Name: "MY_ENV", Value: "rocks"},
   936  							},
   937  						},
   938  					},
   939  				},
   940  			},
   941  			expected: &v1.Pod{
   942  				ObjectMeta: metav1.ObjectMeta{
   943  					Name: "pod",
   944  					Labels: map[string]string{
   945  						kube.CreatedByProw:     "true",
   946  						kube.ProwJobTypeLabel:  "presubmit",
   947  						kube.ProwJobIDLabel:    "pod",
   948  						"needstobe":            "inherited",
   949  						kube.OrgLabel:          "org-name",
   950  						kube.RepoLabel:         "repo-name",
   951  						kube.PullLabel:         "1",
   952  						kube.ProwJobAnnotation: "job-name",
   953  					},
   954  					Annotations: map[string]string{
   955  						kube.ProwJobAnnotation: "job-name",
   956  					},
   957  				},
   958  				Spec: v1.PodSpec{
   959  					AutomountServiceAccountToken: &falseth,
   960  					RestartPolicy:                "Never",
   961  					InitContainers: []v1.Container{
   962  						{
   963  							Name:    "clonerefs",
   964  							Image:   "clonerefs:tag",
   965  							Command: []string{"/clonerefs"},
   966  							Env: []v1.EnvVar{
   967  								{Name: "CLONEREFS_OPTIONS", Value: `{"src_root":"/home/prow/go","log":"/logs/clone.json","git_user_name":"ci-robot","git_user_email":"ci-robot@k8s.io","refs":[{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}],"key_files":["/secrets/ssh/ssh-1","/secrets/ssh/ssh-2"],"host_fingerprints":["hello","world"]}`},
   968  							},
   969  							VolumeMounts: []v1.VolumeMount{
   970  								{
   971  									Name:      "logs",
   972  									MountPath: "/logs",
   973  								},
   974  								{
   975  									Name:      "code",
   976  									MountPath: "/home/prow/go",
   977  								},
   978  								{
   979  									Name:      "ssh-keys-ssh-1",
   980  									MountPath: "/secrets/ssh/ssh-1",
   981  									ReadOnly:  true,
   982  								},
   983  								{
   984  									Name:      "ssh-keys-ssh-2",
   985  									MountPath: "/secrets/ssh/ssh-2",
   986  									ReadOnly:  true,
   987  								},
   988  							},
   989  						},
   990  						{
   991  							Name:    "initupload",
   992  							Image:   "initupload:tag",
   993  							Command: []string{"/initupload"},
   994  							Env: []v1.EnvVar{
   995  								{Name: "INITUPLOAD_OPTIONS", Value: `{"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false,"log":"/logs/clone.json"}`},
   996  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
   997  							},
   998  							VolumeMounts: []kube.VolumeMount{
   999  								{
  1000  									Name:      "logs",
  1001  									MountPath: "/logs",
  1002  								},
  1003  								{
  1004  									Name:      "gcs-credentials",
  1005  									MountPath: "/secrets/gcs",
  1006  								},
  1007  							},
  1008  						},
  1009  						{
  1010  							Name:    "place-tools",
  1011  							Image:   "entrypoint:tag",
  1012  							Command: []string{"/bin/cp"},
  1013  							Args: []string{
  1014  								"/entrypoint",
  1015  								"/tools/entrypoint",
  1016  							},
  1017  							VolumeMounts: []kube.VolumeMount{
  1018  								{
  1019  									Name:      "tools",
  1020  									MountPath: "/tools",
  1021  								},
  1022  							},
  1023  						},
  1024  					},
  1025  					Containers: []v1.Container{
  1026  						{
  1027  							Name:       "test",
  1028  							Image:      "tester",
  1029  							Command:    []string{"/tools/entrypoint"},
  1030  							Args:       []string{},
  1031  							WorkingDir: "/home/prow/go/src/somewhere/else",
  1032  							Env: []v1.EnvVar{
  1033  								{Name: "MY_ENV", Value: "rocks"},
  1034  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
  1035  								{Name: "BUILD_ID", Value: "blabla"},
  1036  								{Name: "BUILD_NUMBER", Value: "blabla"},
  1037  								{Name: "ENTRYPOINT_OPTIONS", Value: `{"args":["/bin/thing","some","args"],"timeout":7200000000000,"grace_period":10000000000,"artifact_dir":"/logs/artifacts","process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}`},
  1038  								{Name: "GOPATH", Value: "/home/prow/go"},
  1039  								{Name: "JOB_NAME", Value: "job-name"},
  1040  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
  1041  								{Name: "JOB_TYPE", Value: "presubmit"},
  1042  								{Name: "PROW_JOB_ID", Value: "pod"},
  1043  								{Name: "PULL_BASE_REF", Value: "base-ref"},
  1044  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
  1045  								{Name: "PULL_NUMBER", Value: "1"},
  1046  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
  1047  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
  1048  								{Name: "REPO_NAME", Value: "repo-name"},
  1049  								{Name: "REPO_OWNER", Value: "org-name"},
  1050  							},
  1051  							VolumeMounts: []v1.VolumeMount{
  1052  								{
  1053  									Name:      "logs",
  1054  									MountPath: "/logs",
  1055  								},
  1056  								{
  1057  									Name:      "tools",
  1058  									MountPath: "/tools",
  1059  								},
  1060  								{
  1061  									Name:      "code",
  1062  									MountPath: "/home/prow/go",
  1063  								},
  1064  							},
  1065  						},
  1066  						{
  1067  							Name:    "sidecar",
  1068  							Image:   "sidecar:tag",
  1069  							Command: []string{"/sidecar"},
  1070  							Env: []v1.EnvVar{
  1071  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
  1072  								{Name: "SIDECAR_OPTIONS", Value: `{"gcs_options":{"items":["/logs/artifacts"],"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false},"wrapper_options":{"process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}}`},
  1073  							},
  1074  							VolumeMounts: []v1.VolumeMount{
  1075  								{
  1076  									Name:      "logs",
  1077  									MountPath: "/logs",
  1078  								},
  1079  								{
  1080  									Name:      "gcs-credentials",
  1081  									MountPath: "/secrets/gcs",
  1082  								},
  1083  							},
  1084  						},
  1085  					},
  1086  					Volumes: []v1.Volume{
  1087  						{
  1088  							Name: "logs",
  1089  							VolumeSource: v1.VolumeSource{
  1090  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1091  							},
  1092  						},
  1093  						{
  1094  							Name: "tools",
  1095  							VolumeSource: v1.VolumeSource{
  1096  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1097  							},
  1098  						},
  1099  						{
  1100  							Name: "gcs-credentials",
  1101  							VolumeSource: v1.VolumeSource{
  1102  								Secret: &v1.SecretVolumeSource{
  1103  									SecretName: "secret-name",
  1104  								},
  1105  							},
  1106  						},
  1107  						{
  1108  							Name: "ssh-keys-ssh-1",
  1109  							VolumeSource: v1.VolumeSource{
  1110  								Secret: &v1.SecretVolumeSource{
  1111  									SecretName:  "ssh-1",
  1112  									DefaultMode: &sshKeyMode,
  1113  								},
  1114  							},
  1115  						},
  1116  						{
  1117  							Name: "ssh-keys-ssh-2",
  1118  							VolumeSource: v1.VolumeSource{
  1119  								Secret: &v1.SecretVolumeSource{
  1120  									SecretName:  "ssh-2",
  1121  									DefaultMode: &sshKeyMode,
  1122  								},
  1123  							},
  1124  						},
  1125  						{
  1126  							Name: "code",
  1127  							VolumeSource: v1.VolumeSource{
  1128  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1129  							},
  1130  						},
  1131  					},
  1132  				},
  1133  			},
  1134  		},
  1135  		{
  1136  			podName: "pod",
  1137  			buildID: "blabla",
  1138  			labels:  map[string]string{"needstobe": "inherited"},
  1139  			pjSpec: kube.ProwJobSpec{
  1140  				Type: kube.PresubmitJob,
  1141  				Job:  "job-name",
  1142  				DecorationConfig: &kube.DecorationConfig{
  1143  					Timeout:     120 * time.Minute,
  1144  					GracePeriod: 10 * time.Second,
  1145  					UtilityImages: &kube.UtilityImages{
  1146  						CloneRefs:  "clonerefs:tag",
  1147  						InitUpload: "initupload:tag",
  1148  						Entrypoint: "entrypoint:tag",
  1149  						Sidecar:    "sidecar:tag",
  1150  					},
  1151  					GCSConfiguration: &kube.GCSConfiguration{
  1152  						Bucket:       "my-bucket",
  1153  						PathStrategy: "legacy",
  1154  						DefaultOrg:   "kubernetes",
  1155  						DefaultRepo:  "kubernetes",
  1156  					},
  1157  					GCSCredentialsSecret: "secret-name",
  1158  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
  1159  				},
  1160  				Agent: kube.KubernetesAgent,
  1161  				Refs: &kube.Refs{
  1162  					Org:     "org-name",
  1163  					Repo:    "repo-name",
  1164  					BaseRef: "base-ref",
  1165  					BaseSHA: "base-sha",
  1166  					Pulls: []kube.Pull{{
  1167  						Number: 1,
  1168  						Author: "author-name",
  1169  						SHA:    "pull-sha",
  1170  					}},
  1171  					PathAlias: "somewhere/else",
  1172  				},
  1173  				ExtraRefs: []kube.Refs{},
  1174  				PodSpec: &v1.PodSpec{
  1175  					Containers: []v1.Container{
  1176  						{
  1177  							Image:   "tester",
  1178  							Command: []string{"/bin/thing"},
  1179  							Args:    []string{"some", "args"},
  1180  							Env: []v1.EnvVar{
  1181  								{Name: "MY_ENV", Value: "rocks"},
  1182  							},
  1183  						},
  1184  					},
  1185  				},
  1186  			},
  1187  			expected: &v1.Pod{
  1188  				ObjectMeta: metav1.ObjectMeta{
  1189  					Name: "pod",
  1190  					Labels: map[string]string{
  1191  						kube.CreatedByProw:     "true",
  1192  						kube.ProwJobTypeLabel:  "presubmit",
  1193  						kube.ProwJobIDLabel:    "pod",
  1194  						"needstobe":            "inherited",
  1195  						kube.OrgLabel:          "org-name",
  1196  						kube.RepoLabel:         "repo-name",
  1197  						kube.PullLabel:         "1",
  1198  						kube.ProwJobAnnotation: "job-name",
  1199  					},
  1200  					Annotations: map[string]string{
  1201  						kube.ProwJobAnnotation: "job-name",
  1202  					},
  1203  				},
  1204  				Spec: v1.PodSpec{
  1205  					AutomountServiceAccountToken: &falseth,
  1206  					RestartPolicy:                "Never",
  1207  					InitContainers: []v1.Container{
  1208  						{
  1209  							Name:    "clonerefs",
  1210  							Image:   "clonerefs:tag",
  1211  							Command: []string{"/clonerefs"},
  1212  							Env: []v1.EnvVar{
  1213  								{Name: "CLONEREFS_OPTIONS", Value: `{"src_root":"/home/prow/go","log":"/logs/clone.json","git_user_name":"ci-robot","git_user_email":"ci-robot@k8s.io","refs":[{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}],"key_files":["/secrets/ssh/ssh-1","/secrets/ssh/ssh-2"]}`},
  1214  							},
  1215  							VolumeMounts: []v1.VolumeMount{
  1216  								{
  1217  									Name:      "logs",
  1218  									MountPath: "/logs",
  1219  								},
  1220  								{
  1221  									Name:      "code",
  1222  									MountPath: "/home/prow/go",
  1223  								},
  1224  								{
  1225  									Name:      "ssh-keys-ssh-1",
  1226  									MountPath: "/secrets/ssh/ssh-1",
  1227  									ReadOnly:  true,
  1228  								},
  1229  								{
  1230  									Name:      "ssh-keys-ssh-2",
  1231  									MountPath: "/secrets/ssh/ssh-2",
  1232  									ReadOnly:  true,
  1233  								},
  1234  							},
  1235  						},
  1236  						{
  1237  							Name:    "initupload",
  1238  							Image:   "initupload:tag",
  1239  							Command: []string{"/initupload"},
  1240  							Env: []v1.EnvVar{
  1241  								{Name: "INITUPLOAD_OPTIONS", Value: `{"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false,"log":"/logs/clone.json"}`},
  1242  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
  1243  							},
  1244  							VolumeMounts: []kube.VolumeMount{
  1245  								{
  1246  									Name:      "logs",
  1247  									MountPath: "/logs",
  1248  								},
  1249  								{
  1250  									Name:      "gcs-credentials",
  1251  									MountPath: "/secrets/gcs",
  1252  								},
  1253  							},
  1254  						},
  1255  						{
  1256  							Name:    "place-tools",
  1257  							Image:   "entrypoint:tag",
  1258  							Command: []string{"/bin/cp"},
  1259  							Args: []string{
  1260  								"/entrypoint",
  1261  								"/tools/entrypoint",
  1262  							},
  1263  							VolumeMounts: []kube.VolumeMount{
  1264  								{
  1265  									Name:      "tools",
  1266  									MountPath: "/tools",
  1267  								},
  1268  							},
  1269  						},
  1270  					},
  1271  					Containers: []v1.Container{
  1272  						{
  1273  							Name:       "test",
  1274  							Image:      "tester",
  1275  							Command:    []string{"/tools/entrypoint"},
  1276  							Args:       []string{},
  1277  							WorkingDir: "/home/prow/go/src/somewhere/else",
  1278  							Env: []v1.EnvVar{
  1279  								{Name: "MY_ENV", Value: "rocks"},
  1280  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
  1281  								{Name: "BUILD_ID", Value: "blabla"},
  1282  								{Name: "BUILD_NUMBER", Value: "blabla"},
  1283  								{Name: "ENTRYPOINT_OPTIONS", Value: `{"args":["/bin/thing","some","args"],"timeout":7200000000000,"grace_period":10000000000,"artifact_dir":"/logs/artifacts","process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}`},
  1284  								{Name: "GOPATH", Value: "/home/prow/go"},
  1285  								{Name: "JOB_NAME", Value: "job-name"},
  1286  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
  1287  								{Name: "JOB_TYPE", Value: "presubmit"},
  1288  								{Name: "PROW_JOB_ID", Value: "pod"},
  1289  								{Name: "PULL_BASE_REF", Value: "base-ref"},
  1290  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
  1291  								{Name: "PULL_NUMBER", Value: "1"},
  1292  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
  1293  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
  1294  								{Name: "REPO_NAME", Value: "repo-name"},
  1295  								{Name: "REPO_OWNER", Value: "org-name"},
  1296  							},
  1297  							VolumeMounts: []v1.VolumeMount{
  1298  								{
  1299  									Name:      "logs",
  1300  									MountPath: "/logs",
  1301  								},
  1302  								{
  1303  									Name:      "tools",
  1304  									MountPath: "/tools",
  1305  								},
  1306  								{
  1307  									Name:      "code",
  1308  									MountPath: "/home/prow/go",
  1309  								},
  1310  							},
  1311  						},
  1312  						{
  1313  							Name:    "sidecar",
  1314  							Image:   "sidecar:tag",
  1315  							Command: []string{"/sidecar"},
  1316  							Env: []v1.EnvVar{
  1317  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"}}`},
  1318  								{Name: "SIDECAR_OPTIONS", Value: `{"gcs_options":{"items":["/logs/artifacts"],"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false},"wrapper_options":{"process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}}`},
  1319  							},
  1320  							VolumeMounts: []v1.VolumeMount{
  1321  								{
  1322  									Name:      "logs",
  1323  									MountPath: "/logs",
  1324  								},
  1325  								{
  1326  									Name:      "gcs-credentials",
  1327  									MountPath: "/secrets/gcs",
  1328  								},
  1329  							},
  1330  						},
  1331  					},
  1332  					Volumes: []v1.Volume{
  1333  						{
  1334  							Name: "logs",
  1335  							VolumeSource: v1.VolumeSource{
  1336  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1337  							},
  1338  						},
  1339  						{
  1340  							Name: "tools",
  1341  							VolumeSource: v1.VolumeSource{
  1342  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1343  							},
  1344  						},
  1345  						{
  1346  							Name: "gcs-credentials",
  1347  							VolumeSource: v1.VolumeSource{
  1348  								Secret: &v1.SecretVolumeSource{
  1349  									SecretName: "secret-name",
  1350  								},
  1351  							},
  1352  						},
  1353  						{
  1354  							Name: "ssh-keys-ssh-1",
  1355  							VolumeSource: v1.VolumeSource{
  1356  								Secret: &v1.SecretVolumeSource{
  1357  									SecretName:  "ssh-1",
  1358  									DefaultMode: &sshKeyMode,
  1359  								},
  1360  							},
  1361  						},
  1362  						{
  1363  							Name: "ssh-keys-ssh-2",
  1364  							VolumeSource: v1.VolumeSource{
  1365  								Secret: &v1.SecretVolumeSource{
  1366  									SecretName:  "ssh-2",
  1367  									DefaultMode: &sshKeyMode,
  1368  								},
  1369  							},
  1370  						},
  1371  						{
  1372  							Name: "code",
  1373  							VolumeSource: v1.VolumeSource{
  1374  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1375  							},
  1376  						},
  1377  					},
  1378  				},
  1379  			},
  1380  		},
  1381  		{
  1382  			podName: "pod",
  1383  			buildID: "blabla",
  1384  			labels:  map[string]string{"needstobe": "inherited"},
  1385  			pjSpec: kube.ProwJobSpec{
  1386  				Type: kube.PeriodicJob,
  1387  				Job:  "job-name",
  1388  				DecorationConfig: &kube.DecorationConfig{
  1389  					Timeout:     120 * time.Minute,
  1390  					GracePeriod: 10 * time.Second,
  1391  					UtilityImages: &kube.UtilityImages{
  1392  						CloneRefs:  "clonerefs:tag",
  1393  						InitUpload: "initupload:tag",
  1394  						Entrypoint: "entrypoint:tag",
  1395  						Sidecar:    "sidecar:tag",
  1396  					},
  1397  					GCSConfiguration: &kube.GCSConfiguration{
  1398  						Bucket:       "my-bucket",
  1399  						PathStrategy: "legacy",
  1400  						DefaultOrg:   "kubernetes",
  1401  						DefaultRepo:  "kubernetes",
  1402  					},
  1403  					GCSCredentialsSecret: "secret-name",
  1404  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
  1405  				},
  1406  				Agent: kube.KubernetesAgent,
  1407  				PodSpec: &v1.PodSpec{
  1408  					Containers: []v1.Container{
  1409  						{
  1410  							Image:   "tester",
  1411  							Command: []string{"/bin/thing"},
  1412  							Args:    []string{"some", "args"},
  1413  							Env: []v1.EnvVar{
  1414  								{Name: "MY_ENV", Value: "rocks"},
  1415  							},
  1416  						},
  1417  					},
  1418  				},
  1419  			},
  1420  			expected: &v1.Pod{
  1421  				ObjectMeta: metav1.ObjectMeta{
  1422  					Name: "pod",
  1423  					Labels: map[string]string{
  1424  						kube.CreatedByProw:     "true",
  1425  						kube.ProwJobTypeLabel:  "periodic",
  1426  						kube.ProwJobIDLabel:    "pod",
  1427  						"needstobe":            "inherited",
  1428  						kube.ProwJobAnnotation: "job-name",
  1429  					},
  1430  					Annotations: map[string]string{
  1431  						kube.ProwJobAnnotation: "job-name",
  1432  					},
  1433  				},
  1434  				Spec: v1.PodSpec{
  1435  					AutomountServiceAccountToken: &falseth,
  1436  					RestartPolicy:                "Never",
  1437  					InitContainers: []v1.Container{
  1438  						{
  1439  							Name:    "initupload",
  1440  							Image:   "initupload:tag",
  1441  							Command: []string{"/initupload"},
  1442  							Env: []v1.EnvVar{
  1443  								{Name: "INITUPLOAD_OPTIONS", Value: `{"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false}`},
  1444  								{Name: "JOB_SPEC", Value: `{"type":"periodic","job":"job-name","buildid":"blabla","prowjobid":"pod"}`},
  1445  							},
  1446  							VolumeMounts: []kube.VolumeMount{
  1447  								{
  1448  									Name:      "logs",
  1449  									MountPath: "/logs",
  1450  								},
  1451  								{
  1452  									Name:      "gcs-credentials",
  1453  									MountPath: "/secrets/gcs",
  1454  								},
  1455  							},
  1456  						},
  1457  						{
  1458  							Name:    "place-tools",
  1459  							Image:   "entrypoint:tag",
  1460  							Command: []string{"/bin/cp"},
  1461  							Args: []string{
  1462  								"/entrypoint",
  1463  								"/tools/entrypoint",
  1464  							},
  1465  							VolumeMounts: []kube.VolumeMount{
  1466  								{
  1467  									Name:      "tools",
  1468  									MountPath: "/tools",
  1469  								},
  1470  							},
  1471  						},
  1472  					},
  1473  					Containers: []v1.Container{
  1474  						{
  1475  							Name:    "test",
  1476  							Image:   "tester",
  1477  							Command: []string{"/tools/entrypoint"},
  1478  							Args:    []string{},
  1479  							Env: []v1.EnvVar{
  1480  								{Name: "MY_ENV", Value: "rocks"},
  1481  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
  1482  								{Name: "BUILD_ID", Value: "blabla"},
  1483  								{Name: "BUILD_NUMBER", Value: "blabla"},
  1484  								{Name: "ENTRYPOINT_OPTIONS", Value: `{"args":["/bin/thing","some","args"],"timeout":7200000000000,"grace_period":10000000000,"artifact_dir":"/logs/artifacts","process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}`},
  1485  								{Name: "GOPATH", Value: "/home/prow/go"},
  1486  								{Name: "JOB_NAME", Value: "job-name"},
  1487  								{Name: "JOB_SPEC", Value: `{"type":"periodic","job":"job-name","buildid":"blabla","prowjobid":"pod"}`},
  1488  								{Name: "JOB_TYPE", Value: "periodic"},
  1489  								{Name: "PROW_JOB_ID", Value: "pod"},
  1490  							},
  1491  							VolumeMounts: []v1.VolumeMount{
  1492  								{
  1493  									Name:      "logs",
  1494  									MountPath: "/logs",
  1495  								},
  1496  								{
  1497  									Name:      "tools",
  1498  									MountPath: "/tools",
  1499  								},
  1500  							},
  1501  						},
  1502  						{
  1503  							Name:    "sidecar",
  1504  							Image:   "sidecar:tag",
  1505  							Command: []string{"/sidecar"},
  1506  							Env: []v1.EnvVar{
  1507  								{Name: "JOB_SPEC", Value: `{"type":"periodic","job":"job-name","buildid":"blabla","prowjobid":"pod"}`},
  1508  								{Name: "SIDECAR_OPTIONS", Value: `{"gcs_options":{"items":["/logs/artifacts"],"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false},"wrapper_options":{"process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}}`},
  1509  							},
  1510  							VolumeMounts: []v1.VolumeMount{
  1511  								{
  1512  									Name:      "logs",
  1513  									MountPath: "/logs",
  1514  								},
  1515  								{
  1516  									Name:      "gcs-credentials",
  1517  									MountPath: "/secrets/gcs",
  1518  								},
  1519  							},
  1520  						},
  1521  					},
  1522  					Volumes: []v1.Volume{
  1523  						{
  1524  							Name: "logs",
  1525  							VolumeSource: v1.VolumeSource{
  1526  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1527  							},
  1528  						},
  1529  						{
  1530  							Name: "tools",
  1531  							VolumeSource: v1.VolumeSource{
  1532  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1533  							},
  1534  						},
  1535  						{
  1536  							Name: "gcs-credentials",
  1537  							VolumeSource: v1.VolumeSource{
  1538  								Secret: &v1.SecretVolumeSource{
  1539  									SecretName: "secret-name",
  1540  								},
  1541  							},
  1542  						},
  1543  					},
  1544  				},
  1545  			},
  1546  		},
  1547  		{
  1548  			podName: "pod",
  1549  			buildID: "blabla",
  1550  			labels:  map[string]string{"needstobe": "inherited"},
  1551  			pjSpec: kube.ProwJobSpec{
  1552  				Type: kube.PresubmitJob,
  1553  				Job:  "job-name",
  1554  				DecorationConfig: &kube.DecorationConfig{
  1555  					Timeout:     120 * time.Minute,
  1556  					GracePeriod: 10 * time.Second,
  1557  					UtilityImages: &kube.UtilityImages{
  1558  						CloneRefs:  "clonerefs:tag",
  1559  						InitUpload: "initupload:tag",
  1560  						Entrypoint: "entrypoint:tag",
  1561  						Sidecar:    "sidecar:tag",
  1562  					},
  1563  					GCSConfiguration: &kube.GCSConfiguration{
  1564  						Bucket:       "my-bucket",
  1565  						PathStrategy: "legacy",
  1566  						DefaultOrg:   "kubernetes",
  1567  						DefaultRepo:  "kubernetes",
  1568  					},
  1569  					GCSCredentialsSecret: "secret-name",
  1570  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
  1571  					SkipCloning:          &truth,
  1572  				},
  1573  				Agent: kube.KubernetesAgent,
  1574  				Refs: &kube.Refs{
  1575  					Org:     "org-name",
  1576  					Repo:    "repo-name",
  1577  					BaseRef: "base-ref",
  1578  					BaseSHA: "base-sha",
  1579  					Pulls: []kube.Pull{{
  1580  						Number: 1,
  1581  						Author: "author-name",
  1582  						SHA:    "pull-sha",
  1583  					}},
  1584  					PathAlias: "somewhere/else",
  1585  				},
  1586  				ExtraRefs: []kube.Refs{
  1587  					{
  1588  						Org:  "extra-org",
  1589  						Repo: "extra-repo",
  1590  					},
  1591  				},
  1592  				PodSpec: &v1.PodSpec{
  1593  					Containers: []v1.Container{
  1594  						{
  1595  							Image:   "tester",
  1596  							Command: []string{"/bin/thing"},
  1597  							Args:    []string{"some", "args"},
  1598  							Env: []v1.EnvVar{
  1599  								{Name: "MY_ENV", Value: "rocks"},
  1600  							},
  1601  						},
  1602  					},
  1603  				},
  1604  			},
  1605  			expected: &v1.Pod{
  1606  				ObjectMeta: metav1.ObjectMeta{
  1607  					Name: "pod",
  1608  					Labels: map[string]string{
  1609  						kube.CreatedByProw:     "true",
  1610  						kube.ProwJobTypeLabel:  "presubmit",
  1611  						kube.ProwJobIDLabel:    "pod",
  1612  						"needstobe":            "inherited",
  1613  						kube.OrgLabel:          "org-name",
  1614  						kube.RepoLabel:         "repo-name",
  1615  						kube.PullLabel:         "1",
  1616  						kube.ProwJobAnnotation: "job-name",
  1617  					},
  1618  					Annotations: map[string]string{
  1619  						kube.ProwJobAnnotation: "job-name",
  1620  					},
  1621  				},
  1622  				Spec: v1.PodSpec{
  1623  					AutomountServiceAccountToken: &falseth,
  1624  					RestartPolicy:                "Never",
  1625  					InitContainers: []v1.Container{
  1626  						{
  1627  							Name:    "initupload",
  1628  							Image:   "initupload:tag",
  1629  							Command: []string{"/initupload"},
  1630  							Env: []v1.EnvVar{
  1631  								{Name: "INITUPLOAD_OPTIONS", Value: `{"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false}`},
  1632  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"},"extra_refs":[{"org":"extra-org","repo":"extra-repo"}]}`},
  1633  							},
  1634  							VolumeMounts: []kube.VolumeMount{
  1635  								{
  1636  									Name:      "logs",
  1637  									MountPath: "/logs",
  1638  								},
  1639  								{
  1640  									Name:      "gcs-credentials",
  1641  									MountPath: "/secrets/gcs",
  1642  								},
  1643  							},
  1644  						},
  1645  						{
  1646  							Name:    "place-tools",
  1647  							Image:   "entrypoint:tag",
  1648  							Command: []string{"/bin/cp"},
  1649  							Args: []string{
  1650  								"/entrypoint",
  1651  								"/tools/entrypoint",
  1652  							},
  1653  							VolumeMounts: []kube.VolumeMount{
  1654  								{
  1655  									Name:      "tools",
  1656  									MountPath: "/tools",
  1657  								},
  1658  							},
  1659  						},
  1660  					},
  1661  					Containers: []v1.Container{
  1662  						{
  1663  							Name:    "test",
  1664  							Image:   "tester",
  1665  							Command: []string{"/tools/entrypoint"},
  1666  							Args:    []string{},
  1667  							Env: []v1.EnvVar{
  1668  								{Name: "MY_ENV", Value: "rocks"},
  1669  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
  1670  								{Name: "BUILD_ID", Value: "blabla"},
  1671  								{Name: "BUILD_NUMBER", Value: "blabla"},
  1672  								{Name: "ENTRYPOINT_OPTIONS", Value: `{"args":["/bin/thing","some","args"],"timeout":7200000000000,"grace_period":10000000000,"artifact_dir":"/logs/artifacts","process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}`},
  1673  								{Name: "GOPATH", Value: "/home/prow/go"},
  1674  								{Name: "JOB_NAME", Value: "job-name"},
  1675  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"},"extra_refs":[{"org":"extra-org","repo":"extra-repo"}]}`},
  1676  								{Name: "JOB_TYPE", Value: "presubmit"},
  1677  								{Name: "PROW_JOB_ID", Value: "pod"},
  1678  								{Name: "PULL_BASE_REF", Value: "base-ref"},
  1679  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
  1680  								{Name: "PULL_NUMBER", Value: "1"},
  1681  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
  1682  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
  1683  								{Name: "REPO_NAME", Value: "repo-name"},
  1684  								{Name: "REPO_OWNER", Value: "org-name"},
  1685  							},
  1686  							VolumeMounts: []v1.VolumeMount{
  1687  								{
  1688  									Name:      "logs",
  1689  									MountPath: "/logs",
  1690  								},
  1691  								{
  1692  									Name:      "tools",
  1693  									MountPath: "/tools",
  1694  								},
  1695  							},
  1696  						},
  1697  						{
  1698  							Name:    "sidecar",
  1699  							Image:   "sidecar:tag",
  1700  							Command: []string{"/sidecar"},
  1701  							Env: []v1.EnvVar{
  1702  								{Name: "JOB_SPEC", Value: `{"type":"presubmit","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{"org":"org-name","repo":"repo-name","base_ref":"base-ref","base_sha":"base-sha","pulls":[{"number":1,"author":"author-name","sha":"pull-sha"}],"path_alias":"somewhere/else"},"extra_refs":[{"org":"extra-org","repo":"extra-repo"}]}`},
  1703  								{Name: "SIDECAR_OPTIONS", Value: `{"gcs_options":{"items":["/logs/artifacts"],"bucket":"my-bucket","path_strategy":"legacy","default_org":"kubernetes","default_repo":"kubernetes","gcs_credentials_file":"/secrets/gcs/service-account.json","dry_run":false},"wrapper_options":{"process_log":"/logs/process-log.txt","marker_file":"/logs/marker-file.txt","metadata_file":"/logs/artifacts/metadata.json"}}`},
  1704  							},
  1705  							VolumeMounts: []v1.VolumeMount{
  1706  								{
  1707  									Name:      "logs",
  1708  									MountPath: "/logs",
  1709  								},
  1710  								{
  1711  									Name:      "gcs-credentials",
  1712  									MountPath: "/secrets/gcs",
  1713  								},
  1714  							},
  1715  						},
  1716  					},
  1717  					Volumes: []v1.Volume{
  1718  						{
  1719  							Name: "logs",
  1720  							VolumeSource: v1.VolumeSource{
  1721  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1722  							},
  1723  						},
  1724  						{
  1725  							Name: "tools",
  1726  							VolumeSource: v1.VolumeSource{
  1727  								EmptyDir: &v1.EmptyDirVolumeSource{},
  1728  							},
  1729  						},
  1730  						{
  1731  							Name: "gcs-credentials",
  1732  							VolumeSource: v1.VolumeSource{
  1733  								Secret: &v1.SecretVolumeSource{
  1734  									SecretName: "secret-name",
  1735  								},
  1736  							},
  1737  						},
  1738  					},
  1739  				},
  1740  			},
  1741  		},
  1742  	}
  1743  
  1744  	for i, test := range tests {
  1745  		t.Run(strconv.Itoa(i), func(t *testing.T) {
  1746  			pj := kube.ProwJob{ObjectMeta: metav1.ObjectMeta{Name: test.podName, Labels: test.labels}, Spec: test.pjSpec}
  1747  			got, err := ProwJobToPod(pj, test.buildID)
  1748  			if err != nil {
  1749  				t.Errorf("unexpected error: %v", err)
  1750  			}
  1751  			if !equality.Semantic.DeepEqual(got, test.expected) {
  1752  				t.Errorf("unexpected pod diff:\n%s", diff.ObjectReflectDiff(test.expected, got))
  1753  			}
  1754  		})
  1755  	}
  1756  }