github.com/kubeflow/training-operator@v1.7.0/pkg/apis/kubeflow.org/v1/tensorflow_validation_test.go (about) 1 // Copyright 2018 The Kubeflow Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package v1 16 17 import ( 18 "testing" 19 20 corev1 "k8s.io/api/core/v1" 21 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 "k8s.io/utils/pointer" 23 ) 24 25 func TestValidateV1TFJob(t *testing.T) { 26 validTFReplicaSpecs := map[ReplicaType]*ReplicaSpec{ 27 TFJobReplicaTypeWorker: { 28 Replicas: pointer.Int32(2), 29 RestartPolicy: RestartPolicyOnFailure, 30 Template: corev1.PodTemplateSpec{ 31 Spec: corev1.PodSpec{ 32 Containers: []corev1.Container{{ 33 Name: "tensorflow", 34 Image: "kubeflow/tf-mnist-with-summaries:latest", 35 Command: []string{ 36 "python", 37 "/var/tf_mnist/mnist_with_summaries.py", 38 }, 39 }}, 40 }, 41 }, 42 }, 43 } 44 45 testCases := map[string]struct { 46 tfJob *TFJob 47 wantErr bool 48 }{ 49 "valid tfJob": { 50 tfJob: &TFJob{ 51 ObjectMeta: metav1.ObjectMeta{ 52 Name: "test", 53 }, 54 Spec: TFJobSpec{ 55 TFReplicaSpecs: validTFReplicaSpecs, 56 }, 57 }, 58 wantErr: false, 59 }, 60 "TFJob name does not meet DNS1035": { 61 tfJob: &TFJob{ 62 ObjectMeta: metav1.ObjectMeta{ 63 Name: "00test", 64 }, 65 Spec: TFJobSpec{ 66 TFReplicaSpecs: validTFReplicaSpecs, 67 }, 68 }, 69 wantErr: true, 70 }, 71 "no containers": { 72 tfJob: &TFJob{ 73 ObjectMeta: metav1.ObjectMeta{ 74 Name: "test", 75 }, 76 Spec: TFJobSpec{ 77 TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 78 TFJobReplicaTypeWorker: { 79 Template: corev1.PodTemplateSpec{ 80 Spec: corev1.PodSpec{ 81 Containers: []corev1.Container{}, 82 }, 83 }, 84 }, 85 }, 86 }, 87 }, 88 wantErr: true, 89 }, 90 "empty image": { 91 tfJob: &TFJob{ 92 ObjectMeta: metav1.ObjectMeta{ 93 Name: "test", 94 }, 95 Spec: TFJobSpec{ 96 TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 97 TFJobReplicaTypeWorker: { 98 Template: corev1.PodTemplateSpec{ 99 Spec: corev1.PodSpec{ 100 Containers: []corev1.Container{{ 101 Name: "tensorflow", 102 Image: "", 103 }}, 104 }, 105 }, 106 }, 107 }, 108 }, 109 }, 110 wantErr: true, 111 }, 112 "tfJob default container name doesn't present": { 113 tfJob: &TFJob{ 114 ObjectMeta: metav1.ObjectMeta{ 115 Name: "test", 116 }, 117 Spec: TFJobSpec{ 118 TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 119 TFJobReplicaTypeWorker: { 120 Template: corev1.PodTemplateSpec{ 121 Spec: corev1.PodSpec{ 122 Containers: []corev1.Container{{ 123 Name: "", 124 Image: "kubeflow/tf-dist-mnist-test:1.0", 125 }}, 126 }, 127 }, 128 }, 129 }, 130 }, 131 }, 132 wantErr: true, 133 }, 134 "there are more than 2 masterReplica's or ChiefReplica's": { 135 tfJob: &TFJob{ 136 ObjectMeta: metav1.ObjectMeta{ 137 Name: "test", 138 }, 139 Spec: TFJobSpec{ 140 TFReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 141 TFJobReplicaTypeChief: { 142 Template: corev1.PodTemplateSpec{ 143 Spec: corev1.PodSpec{ 144 Containers: []corev1.Container{}, 145 }, 146 }, 147 }, 148 TFJobReplicaTypeMaster: { 149 Template: corev1.PodTemplateSpec{ 150 Spec: corev1.PodSpec{ 151 Containers: []corev1.Container{}, 152 }, 153 }, 154 }, 155 }, 156 }, 157 }, 158 wantErr: true, 159 }, 160 } 161 162 for name, tc := range testCases { 163 t.Run(name, func(t *testing.T) { 164 got := ValidateV1TFJob(tc.tfJob) 165 if (got != nil) != tc.wantErr { 166 t.Fatalf("ValidateV1TFJob() error = %v, wantErr %v", got, tc.wantErr) 167 } 168 }) 169 } 170 } 171 172 func TestIsChieforMaster(t *testing.T) { 173 tc := []struct { 174 Type ReplicaType 175 Expected bool 176 }{ 177 { 178 Type: TFJobReplicaTypeChief, 179 Expected: true, 180 }, 181 { 182 Type: TFJobReplicaTypeMaster, 183 Expected: true, 184 }, 185 { 186 Type: TFJobReplicaTypeWorker, 187 Expected: false, 188 }, 189 } 190 191 for _, c := range tc { 192 actual := IsChieforMaster(c.Type) 193 if actual != c.Expected { 194 t.Errorf("Expected %v; Got %v", c.Expected, actual) 195 } 196 } 197 }