...

Source file src/k8s.io/kubectl/pkg/cmd/create/create_job_test.go

Documentation: k8s.io/kubectl/pkg/cmd/create

     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 create
    18  
    19  import (
    20  	"strings"
    21  	"testing"
    22  
    23  	batchv1 "k8s.io/api/batch/v1"
    24  	corev1 "k8s.io/api/core/v1"
    25  	apiequality "k8s.io/apimachinery/pkg/api/equality"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  )
    28  
    29  func TestCreateJobValidation(t *testing.T) {
    30  	tests := map[string]struct {
    31  		image    string
    32  		command  []string
    33  		from     string
    34  		expected string
    35  	}{
    36  		"empty flags": {
    37  			expected: "--image or --from must be specified",
    38  		},
    39  		"both image and from specified": {
    40  			image:    "my-image",
    41  			from:     "cronjob/xyz",
    42  			expected: "--image or --from must be specified",
    43  		},
    44  		"from and command specified": {
    45  			from:     "cronjob/xyz",
    46  			command:  []string{"test", "command"},
    47  			expected: "cannot specify --from and command",
    48  		},
    49  	}
    50  
    51  	for name, tc := range tests {
    52  		t.Run(name, func(t *testing.T) {
    53  			o := &CreateJobOptions{
    54  				Image:   tc.image,
    55  				From:    tc.from,
    56  				Command: tc.command,
    57  			}
    58  
    59  			err := o.Validate()
    60  			if err != nil && !strings.Contains(err.Error(), tc.expected) {
    61  				t.Errorf("unexpected error: %v", err)
    62  			}
    63  		})
    64  	}
    65  }
    66  
    67  func TestCreateJob(t *testing.T) {
    68  	jobName := "test-job"
    69  	tests := map[string]struct {
    70  		image    string
    71  		command  []string
    72  		expected *batchv1.Job
    73  	}{
    74  		"just image": {
    75  			image: "busybox",
    76  			expected: &batchv1.Job{
    77  				TypeMeta: metav1.TypeMeta{APIVersion: batchv1.SchemeGroupVersion.String(), Kind: "Job"},
    78  				ObjectMeta: metav1.ObjectMeta{
    79  					Name: jobName,
    80  				},
    81  				Spec: batchv1.JobSpec{
    82  					Template: corev1.PodTemplateSpec{
    83  						Spec: corev1.PodSpec{
    84  							Containers: []corev1.Container{
    85  								{
    86  									Name:  jobName,
    87  									Image: "busybox",
    88  								},
    89  							},
    90  							RestartPolicy: corev1.RestartPolicyNever,
    91  						},
    92  					},
    93  				},
    94  			},
    95  		},
    96  		"image and command": {
    97  			image:   "busybox",
    98  			command: []string{"date"},
    99  			expected: &batchv1.Job{
   100  				TypeMeta: metav1.TypeMeta{APIVersion: batchv1.SchemeGroupVersion.String(), Kind: "Job"},
   101  				ObjectMeta: metav1.ObjectMeta{
   102  					Name: jobName,
   103  				},
   104  				Spec: batchv1.JobSpec{
   105  					Template: corev1.PodTemplateSpec{
   106  						Spec: corev1.PodSpec{
   107  							Containers: []corev1.Container{
   108  								{
   109  									Name:    jobName,
   110  									Image:   "busybox",
   111  									Command: []string{"date"},
   112  								},
   113  							},
   114  							RestartPolicy: corev1.RestartPolicyNever,
   115  						},
   116  					},
   117  				},
   118  			},
   119  		},
   120  	}
   121  
   122  	for name, tc := range tests {
   123  		t.Run(name, func(t *testing.T) {
   124  			o := &CreateJobOptions{
   125  				Name:    jobName,
   126  				Image:   tc.image,
   127  				Command: tc.command,
   128  			}
   129  			job := o.createJob()
   130  			if !apiequality.Semantic.DeepEqual(job, tc.expected) {
   131  				t.Errorf("expected:\n%#v\ngot:\n%#v", tc.expected, job)
   132  			}
   133  		})
   134  	}
   135  }
   136  
   137  func TestCreateJobFromCronJob(t *testing.T) {
   138  	jobName := "test-job"
   139  	cronJob := &batchv1.CronJob{
   140  		Spec: batchv1.CronJobSpec{
   141  			JobTemplate: batchv1.JobTemplateSpec{
   142  				Spec: batchv1.JobSpec{
   143  					Template: corev1.PodTemplateSpec{
   144  						Spec: corev1.PodSpec{
   145  							Containers: []corev1.Container{
   146  								{Image: "test-image"},
   147  							},
   148  							RestartPolicy: corev1.RestartPolicyNever,
   149  						},
   150  					},
   151  				},
   152  			},
   153  		},
   154  	}
   155  	tests := map[string]struct {
   156  		from     *batchv1.CronJob
   157  		expected *batchv1.Job
   158  	}{
   159  		"from CronJob": {
   160  			from: cronJob,
   161  			expected: &batchv1.Job{
   162  				TypeMeta: metav1.TypeMeta{APIVersion: batchv1.SchemeGroupVersion.String(), Kind: "Job"},
   163  				ObjectMeta: metav1.ObjectMeta{
   164  					Name:            jobName,
   165  					Annotations:     map[string]string{"cronjob.kubernetes.io/instantiate": "manual"},
   166  					OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(cronJob, batchv1.SchemeGroupVersion.WithKind("CronJob"))},
   167  				},
   168  				Spec: batchv1.JobSpec{
   169  					Template: corev1.PodTemplateSpec{
   170  						Spec: corev1.PodSpec{
   171  							Containers: []corev1.Container{
   172  								{Image: "test-image"},
   173  							},
   174  							RestartPolicy: corev1.RestartPolicyNever,
   175  						},
   176  					},
   177  				},
   178  			},
   179  		},
   180  	}
   181  
   182  	for name, tc := range tests {
   183  		t.Run(name, func(t *testing.T) {
   184  			o := &CreateJobOptions{
   185  				Name: jobName,
   186  			}
   187  			job := o.createJobFromCronJob(tc.from)
   188  
   189  			if !apiequality.Semantic.DeepEqual(job, tc.expected) {
   190  				t.Errorf("expected:\n%#v\ngot:\n%#v", tc.expected, job)
   191  			}
   192  		})
   193  	}
   194  }
   195  

View as plain text