github.com/kubeflow/training-operator@v1.7.0/pkg/apis/kubeflow.org/v1/xgboost_validation_test.go (about) 1 // Copyright 2021 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 TestValidateV1XGBoostJob(t *testing.T) { 26 validXGBoostReplicaSpecs := map[ReplicaType]*ReplicaSpec{ 27 XGBoostJobReplicaTypeMaster: { 28 Replicas: pointer.Int32(1), 29 RestartPolicy: RestartPolicyNever, 30 Template: corev1.PodTemplateSpec{ 31 Spec: corev1.PodSpec{ 32 Containers: []corev1.Container{{ 33 Name: "xgboost", 34 Image: "docker.io/merlintang/xgboost-dist-iris:1.1", 35 Ports: []corev1.ContainerPort{{ 36 Name: "xgboostjob-port", 37 ContainerPort: 9991, 38 }}, 39 ImagePullPolicy: corev1.PullAlways, 40 Args: []string{ 41 "--job_type=Train", 42 "--xgboost_parameter=objective:multi:softprob,num_class:3", 43 "--n_estimators=10", 44 "--learning_rate=0.1", 45 "--model_path=/tmp/xgboost-model", 46 "--model_storage_type=local", 47 }, 48 }}, 49 }, 50 }, 51 }, 52 XGBoostJobReplicaTypeWorker: { 53 Replicas: pointer.Int32(2), 54 RestartPolicy: RestartPolicyExitCode, 55 Template: corev1.PodTemplateSpec{ 56 Spec: corev1.PodSpec{ 57 Containers: []corev1.Container{{ 58 Name: "xgboost", 59 Image: "docker.io/merlintang/xgboost-dist-iris:1.", 60 Ports: []corev1.ContainerPort{{ 61 Name: "xgboostjob-port", 62 ContainerPort: 9991, 63 }}, 64 ImagePullPolicy: corev1.PullAlways, 65 Args: []string{ 66 "--job_type=Train", 67 "--xgboost_parameter=objective:multi:softprob,num_class:3", 68 "--n_estimators=10", 69 "--learning_rate=0.1", 70 }, 71 }}, 72 }, 73 }, 74 }, 75 } 76 77 testCases := map[string]struct { 78 xgboostJob *XGBoostJob 79 wantErr bool 80 }{ 81 "valid XGBoostJob": { 82 xgboostJob: &XGBoostJob{ 83 ObjectMeta: metav1.ObjectMeta{ 84 Name: "test", 85 }, 86 Spec: XGBoostJobSpec{ 87 XGBReplicaSpecs: validXGBoostReplicaSpecs, 88 }, 89 }, 90 wantErr: false, 91 }, 92 "XGBoostJob name does not meet DNS1035": { 93 xgboostJob: &XGBoostJob{ 94 ObjectMeta: metav1.ObjectMeta{ 95 Name: "-test", 96 }, 97 Spec: XGBoostJobSpec{ 98 XGBReplicaSpecs: validXGBoostReplicaSpecs, 99 }, 100 }, 101 wantErr: true, 102 }, 103 "empty containers": { 104 xgboostJob: &XGBoostJob{ 105 ObjectMeta: metav1.ObjectMeta{ 106 Name: "test", 107 }, 108 Spec: XGBoostJobSpec{ 109 XGBReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 110 XGBoostJobReplicaTypeWorker: { 111 Template: corev1.PodTemplateSpec{ 112 Spec: corev1.PodSpec{ 113 Containers: []corev1.Container{}, 114 }, 115 }, 116 }, 117 }, 118 }, 119 }, 120 wantErr: true, 121 }, 122 "image is empty": { 123 xgboostJob: &XGBoostJob{ 124 ObjectMeta: metav1.ObjectMeta{ 125 Name: "test", 126 }, 127 Spec: XGBoostJobSpec{ 128 XGBReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 129 XGBoostJobReplicaTypeWorker: { 130 Template: corev1.PodTemplateSpec{ 131 Spec: corev1.PodSpec{ 132 Containers: []corev1.Container{{ 133 Name: "xgboost", 134 Image: "", 135 }}, 136 }, 137 }, 138 }, 139 }, 140 }, 141 }, 142 wantErr: true, 143 }, 144 "xgboostJob default container name doesn't present": { 145 xgboostJob: &XGBoostJob{ 146 ObjectMeta: metav1.ObjectMeta{ 147 Name: "test", 148 }, 149 Spec: XGBoostJobSpec{ 150 XGBReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 151 XGBoostJobReplicaTypeWorker: { 152 Template: corev1.PodTemplateSpec{ 153 Spec: corev1.PodSpec{ 154 Containers: []corev1.Container{{ 155 Name: "", 156 Image: "gcr.io/kubeflow-ci/xgboost-dist-mnist_test:1.0", 157 }}, 158 }, 159 }, 160 }, 161 }, 162 }, 163 }, 164 wantErr: true, 165 }, 166 "the number of replicas in masterReplica is other than 1": { 167 xgboostJob: &XGBoostJob{ 168 ObjectMeta: metav1.ObjectMeta{ 169 Name: "test", 170 }, 171 Spec: XGBoostJobSpec{ 172 XGBReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 173 XGBoostJobReplicaTypeMaster: { 174 Replicas: pointer.Int32(2), 175 Template: corev1.PodTemplateSpec{ 176 Spec: corev1.PodSpec{ 177 Containers: []corev1.Container{{ 178 Name: "xgboost", 179 Image: "gcr.io/kubeflow-ci/xgboost-dist-mnist_test:1.0", 180 }}, 181 }, 182 }, 183 }, 184 }, 185 }, 186 }, 187 wantErr: true, 188 }, 189 "masterReplica does not exist": { 190 xgboostJob: &XGBoostJob{ 191 ObjectMeta: metav1.ObjectMeta{ 192 Name: "test", 193 }, 194 Spec: XGBoostJobSpec{ 195 XGBReplicaSpecs: map[ReplicaType]*ReplicaSpec{ 196 XGBoostJobReplicaTypeWorker: { 197 Replicas: pointer.Int32(1), 198 Template: corev1.PodTemplateSpec{ 199 Spec: corev1.PodSpec{ 200 Containers: []corev1.Container{{ 201 Name: "xgboost", 202 Image: "gcr.io/kubeflow-ci/xgboost-dist-mnist_test:1.0", 203 }}, 204 }, 205 }, 206 }, 207 }, 208 }, 209 }, 210 wantErr: true, 211 }, 212 } 213 214 for name, tc := range testCases { 215 t.Run(name, func(t *testing.T) { 216 got := ValidateV1XGBoostJob(tc.xgboostJob) 217 if (got != nil) != tc.wantErr { 218 t.Fatalf("ValidateV1XGBoostJob() error = %v, wantErr %v", got, tc.wantErr) 219 } 220 }) 221 } 222 }