github.com/abayer/test-infra@v0.0.5/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  	"testing"
    21  	"time"
    22  
    23  	"k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/api/equality"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/util/diff"
    27  
    28  	"k8s.io/test-infra/prow/kube"
    29  )
    30  
    31  func TestProwJobToPod(t *testing.T) {
    32  	var sshKeyMode int32 = 0400
    33  	tests := []struct {
    34  		podName string
    35  		buildID string
    36  		labels  map[string]string
    37  		pjSpec  kube.ProwJobSpec
    38  
    39  		expected *v1.Pod
    40  	}{
    41  		{
    42  			podName: "pod",
    43  			buildID: "blabla",
    44  			labels:  map[string]string{"needstobe": "inherited"},
    45  			pjSpec: kube.ProwJobSpec{
    46  				Type:  kube.PresubmitJob,
    47  				Job:   "job-name",
    48  				Agent: kube.KubernetesAgent,
    49  				Refs: &kube.Refs{
    50  					Org:     "org-name",
    51  					Repo:    "repo-name",
    52  					BaseRef: "base-ref",
    53  					BaseSHA: "base-sha",
    54  					Pulls: []kube.Pull{{
    55  						Number: 1,
    56  						Author: "author-name",
    57  						SHA:    "pull-sha",
    58  					}},
    59  				},
    60  				PodSpec: &v1.PodSpec{
    61  					Containers: []v1.Container{
    62  						{
    63  							Image: "tester",
    64  							Env: []v1.EnvVar{
    65  								{Name: "MY_ENV", Value: "rocks"},
    66  							},
    67  						},
    68  					},
    69  				},
    70  			},
    71  
    72  			expected: &v1.Pod{
    73  				ObjectMeta: metav1.ObjectMeta{
    74  					Name: "pod",
    75  					Labels: map[string]string{
    76  						kube.CreatedByProw:    "true",
    77  						kube.ProwJobTypeLabel: "presubmit",
    78  						kube.ProwJobIDLabel:   "pod",
    79  						"needstobe":           "inherited",
    80  					},
    81  					Annotations: map[string]string{
    82  						kube.ProwJobAnnotation: "job-name",
    83  					},
    84  				},
    85  				Spec: v1.PodSpec{
    86  					RestartPolicy: "Never",
    87  					Containers: []v1.Container{
    88  						{
    89  							Name:  "test",
    90  							Image: "tester",
    91  							Env: []v1.EnvVar{
    92  								{Name: "MY_ENV", Value: "rocks"},
    93  								{Name: "BUILD_ID", Value: "blabla"},
    94  								{Name: "BUILD_NUMBER", Value: "blabla"},
    95  								{Name: "JOB_NAME", Value: "job-name"},
    96  								{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"}]}}`},
    97  								{Name: "JOB_TYPE", Value: "presubmit"},
    98  								{Name: "PROW_JOB_ID", Value: "pod"},
    99  								{Name: "PULL_BASE_REF", Value: "base-ref"},
   100  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
   101  								{Name: "PULL_NUMBER", Value: "1"},
   102  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
   103  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
   104  								{Name: "REPO_NAME", Value: "repo-name"},
   105  								{Name: "REPO_OWNER", Value: "org-name"},
   106  							},
   107  						},
   108  					},
   109  				},
   110  			},
   111  		},
   112  		{
   113  			podName: "pod",
   114  			buildID: "blabla",
   115  			labels:  map[string]string{"needstobe": "inherited"},
   116  			pjSpec: kube.ProwJobSpec{
   117  				Type: kube.PresubmitJob,
   118  				Job:  "job-name",
   119  				DecorationConfig: &kube.DecorationConfig{
   120  					Timeout:     120 * time.Minute,
   121  					GracePeriod: 10 * time.Second,
   122  					UtilityImages: &kube.UtilityImages{
   123  						CloneRefs:  "clonerefs:tag",
   124  						InitUpload: "initupload:tag",
   125  						Entrypoint: "entrypoint:tag",
   126  						Sidecar:    "sidecar:tag",
   127  					},
   128  					GCSConfiguration: &kube.GCSConfiguration{
   129  						Bucket:       "my-bucket",
   130  						PathStrategy: "legacy",
   131  						DefaultOrg:   "kubernetes",
   132  						DefaultRepo:  "kubernetes",
   133  					},
   134  					GCSCredentialsSecret: "secret-name",
   135  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
   136  				},
   137  				Agent: kube.KubernetesAgent,
   138  				Refs: &kube.Refs{
   139  					Org:     "org-name",
   140  					Repo:    "repo-name",
   141  					BaseRef: "base-ref",
   142  					BaseSHA: "base-sha",
   143  					Pulls: []kube.Pull{{
   144  						Number: 1,
   145  						Author: "author-name",
   146  						SHA:    "pull-sha",
   147  					}},
   148  					PathAlias: "somewhere/else",
   149  				},
   150  				ExtraRefs: []*kube.Refs{},
   151  				PodSpec: &v1.PodSpec{
   152  					Containers: []v1.Container{
   153  						{
   154  							Image:   "tester",
   155  							Command: []string{"/bin/thing"},
   156  							Args:    []string{"some", "args"},
   157  							Env: []v1.EnvVar{
   158  								{Name: "MY_ENV", Value: "rocks"},
   159  							},
   160  						},
   161  					},
   162  				},
   163  			},
   164  			expected: &v1.Pod{
   165  				ObjectMeta: metav1.ObjectMeta{
   166  					Name: "pod",
   167  					Labels: map[string]string{
   168  						kube.CreatedByProw:    "true",
   169  						kube.ProwJobTypeLabel: "presubmit",
   170  						kube.ProwJobIDLabel:   "pod",
   171  						"needstobe":           "inherited",
   172  					},
   173  					Annotations: map[string]string{
   174  						kube.ProwJobAnnotation: "job-name",
   175  					},
   176  				},
   177  				Spec: v1.PodSpec{
   178  					RestartPolicy: "Never",
   179  					InitContainers: []v1.Container{
   180  						{
   181  							Name:    "clonerefs",
   182  							Image:   "clonerefs:tag",
   183  							Command: []string{"/clonerefs"},
   184  							Env: []v1.EnvVar{
   185  								{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"]}`},
   186  							},
   187  							VolumeMounts: []v1.VolumeMount{
   188  								{
   189  									Name:      "logs",
   190  									MountPath: "/logs",
   191  								},
   192  								{
   193  									Name:      "code",
   194  									MountPath: "/home/prow/go",
   195  								},
   196  								{
   197  									Name:      "ssh-keys-ssh-1",
   198  									MountPath: "/secrets/ssh/ssh-1",
   199  									ReadOnly:  true,
   200  								},
   201  								{
   202  									Name:      "ssh-keys-ssh-2",
   203  									MountPath: "/secrets/ssh/ssh-2",
   204  									ReadOnly:  true,
   205  								},
   206  							},
   207  						},
   208  						{
   209  							Name:    "initupload",
   210  							Image:   "initupload:tag",
   211  							Command: []string{"/initupload"},
   212  							Env: []v1.EnvVar{
   213  								{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"}`},
   214  								{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"}}`},
   215  							},
   216  							VolumeMounts: []kube.VolumeMount{
   217  								{
   218  									Name:      "logs",
   219  									MountPath: "/logs",
   220  								},
   221  								{
   222  									Name:      "gcs-credentials",
   223  									MountPath: "/secrets/gcs",
   224  								},
   225  							},
   226  						},
   227  						{
   228  							Name:    "place-tools",
   229  							Image:   "entrypoint:tag",
   230  							Command: []string{"/bin/cp"},
   231  							Args: []string{
   232  								"/entrypoint",
   233  								"/tools/entrypoint",
   234  							},
   235  							VolumeMounts: []kube.VolumeMount{
   236  								{
   237  									Name:      "tools",
   238  									MountPath: "/tools",
   239  								},
   240  							},
   241  						},
   242  					},
   243  					Containers: []v1.Container{
   244  						{
   245  							Name:       "test",
   246  							Image:      "tester",
   247  							Command:    []string{"/tools/entrypoint"},
   248  							Args:       []string{},
   249  							WorkingDir: "/home/prow/go/src/somewhere/else",
   250  							Env: []v1.EnvVar{
   251  								{Name: "MY_ENV", Value: "rocks"},
   252  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
   253  								{Name: "BUILD_ID", Value: "blabla"},
   254  								{Name: "BUILD_NUMBER", Value: "blabla"},
   255  								{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"}`},
   256  								{Name: "GOPATH", Value: "/home/prow/go"},
   257  								{Name: "JOB_NAME", Value: "job-name"},
   258  								{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"}}`},
   259  								{Name: "JOB_TYPE", Value: "presubmit"},
   260  								{Name: "PROW_JOB_ID", Value: "pod"},
   261  								{Name: "PULL_BASE_REF", Value: "base-ref"},
   262  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
   263  								{Name: "PULL_NUMBER", Value: "1"},
   264  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
   265  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
   266  								{Name: "REPO_NAME", Value: "repo-name"},
   267  								{Name: "REPO_OWNER", Value: "org-name"},
   268  							},
   269  							VolumeMounts: []v1.VolumeMount{
   270  								{
   271  									Name:      "logs",
   272  									MountPath: "/logs",
   273  								},
   274  								{
   275  									Name:      "tools",
   276  									MountPath: "/tools",
   277  								},
   278  								{
   279  									Name:      "code",
   280  									MountPath: "/home/prow/go",
   281  								},
   282  							},
   283  						},
   284  						{
   285  							Name:    "sidecar",
   286  							Image:   "sidecar:tag",
   287  							Command: []string{"/sidecar"},
   288  							Env: []v1.EnvVar{
   289  								{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"}}`},
   290  								{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"}}`},
   291  							},
   292  							VolumeMounts: []v1.VolumeMount{
   293  								{
   294  									Name:      "logs",
   295  									MountPath: "/logs",
   296  								},
   297  								{
   298  									Name:      "gcs-credentials",
   299  									MountPath: "/secrets/gcs",
   300  								},
   301  							},
   302  						},
   303  					},
   304  					Volumes: []v1.Volume{
   305  						{
   306  							Name: "logs",
   307  							VolumeSource: v1.VolumeSource{
   308  								EmptyDir: &v1.EmptyDirVolumeSource{},
   309  							},
   310  						},
   311  						{
   312  							Name: "tools",
   313  							VolumeSource: v1.VolumeSource{
   314  								EmptyDir: &v1.EmptyDirVolumeSource{},
   315  							},
   316  						},
   317  						{
   318  							Name: "gcs-credentials",
   319  							VolumeSource: v1.VolumeSource{
   320  								Secret: &v1.SecretVolumeSource{
   321  									SecretName: "secret-name",
   322  								},
   323  							},
   324  						},
   325  						{
   326  							Name: "ssh-keys-ssh-1",
   327  							VolumeSource: v1.VolumeSource{
   328  								Secret: &v1.SecretVolumeSource{
   329  									SecretName:  "ssh-1",
   330  									DefaultMode: &sshKeyMode,
   331  								},
   332  							},
   333  						},
   334  						{
   335  							Name: "ssh-keys-ssh-2",
   336  							VolumeSource: v1.VolumeSource{
   337  								Secret: &v1.SecretVolumeSource{
   338  									SecretName:  "ssh-2",
   339  									DefaultMode: &sshKeyMode,
   340  								},
   341  							},
   342  						},
   343  						{
   344  							Name: "code",
   345  							VolumeSource: v1.VolumeSource{
   346  								EmptyDir: &v1.EmptyDirVolumeSource{},
   347  							},
   348  						},
   349  					},
   350  				},
   351  			},
   352  		},
   353  		{
   354  			podName: "pod",
   355  			buildID: "blabla",
   356  			labels:  map[string]string{"needstobe": "inherited"},
   357  			pjSpec: kube.ProwJobSpec{
   358  				Type: kube.PeriodicJob,
   359  				Job:  "job-name",
   360  				DecorationConfig: &kube.DecorationConfig{
   361  					Timeout:     120 * time.Minute,
   362  					GracePeriod: 10 * time.Second,
   363  					UtilityImages: &kube.UtilityImages{
   364  						CloneRefs:  "clonerefs:tag",
   365  						InitUpload: "initupload:tag",
   366  						Entrypoint: "entrypoint:tag",
   367  						Sidecar:    "sidecar:tag",
   368  					},
   369  					GCSConfiguration: &kube.GCSConfiguration{
   370  						Bucket:       "my-bucket",
   371  						PathStrategy: "legacy",
   372  						DefaultOrg:   "kubernetes",
   373  						DefaultRepo:  "kubernetes",
   374  					},
   375  					GCSCredentialsSecret: "secret-name",
   376  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
   377  				},
   378  				Agent: kube.KubernetesAgent,
   379  				PodSpec: &v1.PodSpec{
   380  					Containers: []v1.Container{
   381  						{
   382  							Image:   "tester",
   383  							Command: []string{"/bin/thing"},
   384  							Args:    []string{"some", "args"},
   385  							Env: []v1.EnvVar{
   386  								{Name: "MY_ENV", Value: "rocks"},
   387  							},
   388  						},
   389  					},
   390  				},
   391  			},
   392  			expected: &v1.Pod{
   393  				ObjectMeta: metav1.ObjectMeta{
   394  					Name: "pod",
   395  					Labels: map[string]string{
   396  						kube.CreatedByProw:    "true",
   397  						kube.ProwJobTypeLabel: "periodic",
   398  						kube.ProwJobIDLabel:   "pod",
   399  						"needstobe":           "inherited",
   400  					},
   401  					Annotations: map[string]string{
   402  						kube.ProwJobAnnotation: "job-name",
   403  					},
   404  				},
   405  				Spec: v1.PodSpec{
   406  					RestartPolicy: "Never",
   407  					InitContainers: []v1.Container{
   408  						{
   409  							Name:    "initupload",
   410  							Image:   "initupload:tag",
   411  							Command: []string{"/initupload"},
   412  							Env: []v1.EnvVar{
   413  								{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}`},
   414  								{Name: "JOB_SPEC", Value: `{"type":"periodic","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{}}`},
   415  							},
   416  							VolumeMounts: []kube.VolumeMount{
   417  								{
   418  									Name:      "logs",
   419  									MountPath: "/logs",
   420  								},
   421  								{
   422  									Name:      "gcs-credentials",
   423  									MountPath: "/secrets/gcs",
   424  								},
   425  							},
   426  						},
   427  						{
   428  							Name:    "place-tools",
   429  							Image:   "entrypoint:tag",
   430  							Command: []string{"/bin/cp"},
   431  							Args: []string{
   432  								"/entrypoint",
   433  								"/tools/entrypoint",
   434  							},
   435  							VolumeMounts: []kube.VolumeMount{
   436  								{
   437  									Name:      "tools",
   438  									MountPath: "/tools",
   439  								},
   440  							},
   441  						},
   442  					},
   443  					Containers: []v1.Container{
   444  						{
   445  							Name:    "test",
   446  							Image:   "tester",
   447  							Command: []string{"/tools/entrypoint"},
   448  							Args:    []string{},
   449  							Env: []v1.EnvVar{
   450  								{Name: "MY_ENV", Value: "rocks"},
   451  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
   452  								{Name: "BUILD_ID", Value: "blabla"},
   453  								{Name: "BUILD_NUMBER", Value: "blabla"},
   454  								{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"}`},
   455  								{Name: "GOPATH", Value: "/home/prow/go"},
   456  								{Name: "JOB_NAME", Value: "job-name"},
   457  								{Name: "JOB_SPEC", Value: `{"type":"periodic","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{}}`},
   458  								{Name: "JOB_TYPE", Value: "periodic"},
   459  								{Name: "PROW_JOB_ID", Value: "pod"},
   460  							},
   461  							VolumeMounts: []v1.VolumeMount{
   462  								{
   463  									Name:      "logs",
   464  									MountPath: "/logs",
   465  								},
   466  								{
   467  									Name:      "tools",
   468  									MountPath: "/tools",
   469  								},
   470  							},
   471  						},
   472  						{
   473  							Name:    "sidecar",
   474  							Image:   "sidecar:tag",
   475  							Command: []string{"/sidecar"},
   476  							Env: []v1.EnvVar{
   477  								{Name: "JOB_SPEC", Value: `{"type":"periodic","job":"job-name","buildid":"blabla","prowjobid":"pod","refs":{}}`},
   478  								{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"}}`},
   479  							},
   480  							VolumeMounts: []v1.VolumeMount{
   481  								{
   482  									Name:      "logs",
   483  									MountPath: "/logs",
   484  								},
   485  								{
   486  									Name:      "gcs-credentials",
   487  									MountPath: "/secrets/gcs",
   488  								},
   489  							},
   490  						},
   491  					},
   492  					Volumes: []v1.Volume{
   493  						{
   494  							Name: "logs",
   495  							VolumeSource: v1.VolumeSource{
   496  								EmptyDir: &v1.EmptyDirVolumeSource{},
   497  							},
   498  						},
   499  						{
   500  							Name: "tools",
   501  							VolumeSource: v1.VolumeSource{
   502  								EmptyDir: &v1.EmptyDirVolumeSource{},
   503  							},
   504  						},
   505  						{
   506  							Name: "gcs-credentials",
   507  							VolumeSource: v1.VolumeSource{
   508  								Secret: &v1.SecretVolumeSource{
   509  									SecretName: "secret-name",
   510  								},
   511  							},
   512  						},
   513  					},
   514  				},
   515  			},
   516  		},
   517  		{
   518  			podName: "pod",
   519  			buildID: "blabla",
   520  			labels:  map[string]string{"needstobe": "inherited"},
   521  			pjSpec: kube.ProwJobSpec{
   522  				Type: kube.PresubmitJob,
   523  				Job:  "job-name",
   524  				DecorationConfig: &kube.DecorationConfig{
   525  					Timeout:     120 * time.Minute,
   526  					GracePeriod: 10 * time.Second,
   527  					UtilityImages: &kube.UtilityImages{
   528  						CloneRefs:  "clonerefs:tag",
   529  						InitUpload: "initupload:tag",
   530  						Entrypoint: "entrypoint:tag",
   531  						Sidecar:    "sidecar:tag",
   532  					},
   533  					GCSConfiguration: &kube.GCSConfiguration{
   534  						Bucket:       "my-bucket",
   535  						PathStrategy: "legacy",
   536  						DefaultOrg:   "kubernetes",
   537  						DefaultRepo:  "kubernetes",
   538  					},
   539  					GCSCredentialsSecret: "secret-name",
   540  					SSHKeySecrets:        []string{"ssh-1", "ssh-2"},
   541  					SkipCloning:          true,
   542  				},
   543  				Agent: kube.KubernetesAgent,
   544  				Refs: &kube.Refs{
   545  					Org:     "org-name",
   546  					Repo:    "repo-name",
   547  					BaseRef: "base-ref",
   548  					BaseSHA: "base-sha",
   549  					Pulls: []kube.Pull{{
   550  						Number: 1,
   551  						Author: "author-name",
   552  						SHA:    "pull-sha",
   553  					}},
   554  					PathAlias: "somewhere/else",
   555  				},
   556  				ExtraRefs: []*kube.Refs{},
   557  				PodSpec: &v1.PodSpec{
   558  					Containers: []v1.Container{
   559  						{
   560  							Image:   "tester",
   561  							Command: []string{"/bin/thing"},
   562  							Args:    []string{"some", "args"},
   563  							Env: []v1.EnvVar{
   564  								{Name: "MY_ENV", Value: "rocks"},
   565  							},
   566  						},
   567  					},
   568  				},
   569  			},
   570  			expected: &v1.Pod{
   571  				ObjectMeta: metav1.ObjectMeta{
   572  					Name: "pod",
   573  					Labels: map[string]string{
   574  						kube.CreatedByProw:    "true",
   575  						kube.ProwJobTypeLabel: "presubmit",
   576  						kube.ProwJobIDLabel:   "pod",
   577  						"needstobe":           "inherited",
   578  					},
   579  					Annotations: map[string]string{
   580  						kube.ProwJobAnnotation: "job-name",
   581  					},
   582  				},
   583  				Spec: v1.PodSpec{
   584  					RestartPolicy: "Never",
   585  					InitContainers: []v1.Container{
   586  						{
   587  							Name:    "initupload",
   588  							Image:   "initupload:tag",
   589  							Command: []string{"/initupload"},
   590  							Env: []v1.EnvVar{
   591  								{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}`},
   592  								{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"}}`},
   593  							},
   594  							VolumeMounts: []kube.VolumeMount{
   595  								{
   596  									Name:      "logs",
   597  									MountPath: "/logs",
   598  								},
   599  								{
   600  									Name:      "gcs-credentials",
   601  									MountPath: "/secrets/gcs",
   602  								},
   603  							},
   604  						},
   605  						{
   606  							Name:    "place-tools",
   607  							Image:   "entrypoint:tag",
   608  							Command: []string{"/bin/cp"},
   609  							Args: []string{
   610  								"/entrypoint",
   611  								"/tools/entrypoint",
   612  							},
   613  							VolumeMounts: []kube.VolumeMount{
   614  								{
   615  									Name:      "tools",
   616  									MountPath: "/tools",
   617  								},
   618  							},
   619  						},
   620  					},
   621  					Containers: []v1.Container{
   622  						{
   623  							Name:    "test",
   624  							Image:   "tester",
   625  							Command: []string{"/tools/entrypoint"},
   626  							Args:    []string{},
   627  							Env: []v1.EnvVar{
   628  								{Name: "MY_ENV", Value: "rocks"},
   629  								{Name: "ARTIFACTS", Value: "/logs/artifacts"},
   630  								{Name: "BUILD_ID", Value: "blabla"},
   631  								{Name: "BUILD_NUMBER", Value: "blabla"},
   632  								{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"}`},
   633  								{Name: "GOPATH", Value: "/home/prow/go"},
   634  								{Name: "JOB_NAME", Value: "job-name"},
   635  								{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"}}`},
   636  								{Name: "JOB_TYPE", Value: "presubmit"},
   637  								{Name: "PROW_JOB_ID", Value: "pod"},
   638  								{Name: "PULL_BASE_REF", Value: "base-ref"},
   639  								{Name: "PULL_BASE_SHA", Value: "base-sha"},
   640  								{Name: "PULL_NUMBER", Value: "1"},
   641  								{Name: "PULL_PULL_SHA", Value: "pull-sha"},
   642  								{Name: "PULL_REFS", Value: "base-ref:base-sha,1:pull-sha"},
   643  								{Name: "REPO_NAME", Value: "repo-name"},
   644  								{Name: "REPO_OWNER", Value: "org-name"},
   645  							},
   646  							VolumeMounts: []v1.VolumeMount{
   647  								{
   648  									Name:      "logs",
   649  									MountPath: "/logs",
   650  								},
   651  								{
   652  									Name:      "tools",
   653  									MountPath: "/tools",
   654  								},
   655  							},
   656  						},
   657  						{
   658  							Name:    "sidecar",
   659  							Image:   "sidecar:tag",
   660  							Command: []string{"/sidecar"},
   661  							Env: []v1.EnvVar{
   662  								{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"}}`},
   663  								{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"}}`},
   664  							},
   665  							VolumeMounts: []v1.VolumeMount{
   666  								{
   667  									Name:      "logs",
   668  									MountPath: "/logs",
   669  								},
   670  								{
   671  									Name:      "gcs-credentials",
   672  									MountPath: "/secrets/gcs",
   673  								},
   674  							},
   675  						},
   676  					},
   677  					Volumes: []v1.Volume{
   678  						{
   679  							Name: "logs",
   680  							VolumeSource: v1.VolumeSource{
   681  								EmptyDir: &v1.EmptyDirVolumeSource{},
   682  							},
   683  						},
   684  						{
   685  							Name: "tools",
   686  							VolumeSource: v1.VolumeSource{
   687  								EmptyDir: &v1.EmptyDirVolumeSource{},
   688  							},
   689  						},
   690  						{
   691  							Name: "gcs-credentials",
   692  							VolumeSource: v1.VolumeSource{
   693  								Secret: &v1.SecretVolumeSource{
   694  									SecretName: "secret-name",
   695  								},
   696  							},
   697  						},
   698  					},
   699  				},
   700  			},
   701  		},
   702  	}
   703  
   704  	for i, test := range tests {
   705  		t.Logf("test run #%d", i)
   706  		pj := kube.ProwJob{ObjectMeta: metav1.ObjectMeta{Name: test.podName, Labels: test.labels}, Spec: test.pjSpec}
   707  		got, err := ProwJobToPod(pj, test.buildID)
   708  		if err != nil {
   709  			t.Errorf("unexpected error: %v", err)
   710  		}
   711  		if !equality.Semantic.DeepEqual(got, test.expected) {
   712  			t.Errorf("expected pod diff:\n%s", diff.ObjectReflectDiff(test.expected, got))
   713  		}
   714  	}
   715  }