sigs.k8s.io/kueue@v0.6.2/pkg/controller/jobframework/reconciler_test.go (about) 1 /* 2 Copyright 2023 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 jobframework_test 18 19 import ( 20 "context" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 "github.com/google/go-cmp/cmp/cmpopts" 25 kubeflow "github.com/kubeflow/mpi-operator/pkg/apis/kubeflow/v2beta1" 26 batchv1 "k8s.io/api/batch/v1" 27 corev1 "k8s.io/api/core/v1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "sigs.k8s.io/controller-runtime/pkg/client" 30 31 configapi "sigs.k8s.io/kueue/apis/config/v1beta1" 32 _ "sigs.k8s.io/kueue/pkg/controller/jobs" 33 "sigs.k8s.io/kueue/pkg/util/kubeversion" 34 utiltesting "sigs.k8s.io/kueue/pkg/util/testing" 35 testingjob "sigs.k8s.io/kueue/pkg/util/testingjobs/job" 36 testingmpijob "sigs.k8s.io/kueue/pkg/util/testingjobs/mpijob" 37 38 . "sigs.k8s.io/kueue/pkg/controller/jobframework" 39 ) 40 41 func TestIsParentJobManaged(t *testing.T) { 42 parentJobName := "test-job-parent" 43 childJobName := "test-job-child" 44 jobNamespace := "default" 45 cases := map[string]struct { 46 parentJob client.Object 47 job client.Object 48 wantManaged bool 49 wantErr error 50 }{ 51 "child job doesn't have ownerReference": { 52 parentJob: testingmpijob.MakeMPIJob(parentJobName, jobNamespace). 53 UID(parentJobName). 54 Obj(), 55 job: testingjob.MakeJob(childJobName, jobNamespace). 56 Obj(), 57 wantErr: ErrChildJobOwnerNotFound, 58 }, 59 "child job has ownerReference with unknown workload owner": { 60 parentJob: testingjob.MakeJob(parentJobName, jobNamespace). 61 UID(parentJobName). 62 Obj(), 63 job: testingjob.MakeJob(childJobName, jobNamespace). 64 OwnerReference(parentJobName, batchv1.SchemeGroupVersion.WithKind("CronJob")). 65 Obj(), 66 wantErr: ErrUnknownWorkloadOwner, 67 }, 68 "child job has ownerReference with known non-existing workload owner": { 69 job: testingjob.MakeJob(childJobName, jobNamespace). 70 OwnerReference(parentJobName, kubeflow.SchemeGroupVersionKind). 71 Obj(), 72 wantErr: ErrWorkloadOwnerNotFound, 73 }, 74 "child job has ownerReference with known existing workload owner, and the parent job has queue-name label": { 75 parentJob: testingmpijob.MakeMPIJob(parentJobName, jobNamespace). 76 UID(parentJobName). 77 Queue("test-q"). 78 Obj(), 79 job: testingjob.MakeJob(childJobName, jobNamespace). 80 OwnerReference(parentJobName, kubeflow.SchemeGroupVersionKind). 81 Obj(), 82 wantManaged: true, 83 }, 84 "child job has ownerReference with known existing workload owner, and the parent job doesn't has queue-name label": { 85 parentJob: testingmpijob.MakeMPIJob(parentJobName, jobNamespace). 86 UID(parentJobName). 87 Obj(), 88 job: testingjob.MakeJob(childJobName, jobNamespace). 89 OwnerReference(parentJobName, kubeflow.SchemeGroupVersionKind). 90 Obj(), 91 }, 92 } 93 for name, tc := range cases { 94 t.Run(name, func(t *testing.T) { 95 builder := utiltesting.NewClientBuilder(kubeflow.AddToScheme) 96 if tc.parentJob != nil { 97 builder = builder.WithObjects(tc.parentJob) 98 } 99 cl := builder.Build() 100 r := NewReconciler(cl, nil) 101 got, gotErr := r.IsParentJobManaged(context.Background(), tc.job, jobNamespace) 102 if tc.wantManaged != got { 103 t.Errorf("Unexpected response from isParentManaged want: %v,got: %v", tc.wantManaged, got) 104 } 105 if diff := cmp.Diff(tc.wantErr, gotErr, cmpopts.EquateErrors()); len(diff) != 0 { 106 t.Errorf("Unexpected error (-want,+got):\n%s", diff) 107 } 108 }) 109 } 110 } 111 112 func TestProcessOptions(t *testing.T) { 113 cases := map[string]struct { 114 inputOpts []Option 115 wantOpts Options 116 }{ 117 "all options are passed": { 118 inputOpts: []Option{ 119 WithManageJobsWithoutQueueName(true), 120 WithWaitForPodsReady(&configapi.WaitForPodsReady{Enable: true}), 121 WithKubeServerVersion(&kubeversion.ServerVersionFetcher{}), 122 WithIntegrationOptions(corev1.SchemeGroupVersion.WithKind("Pod").String(), &configapi.PodIntegrationOptions{ 123 PodSelector: &metav1.LabelSelector{}, 124 }), 125 }, 126 wantOpts: Options{ 127 ManageJobsWithoutQueueName: true, 128 WaitForPodsReady: true, 129 KubeServerVersion: &kubeversion.ServerVersionFetcher{}, 130 IntegrationOptions: map[string]any{ 131 corev1.SchemeGroupVersion.WithKind("Pod").String(): &configapi.PodIntegrationOptions{ 132 PodSelector: &metav1.LabelSelector{}, 133 }, 134 }, 135 }, 136 }, 137 "a single option is passed": { 138 inputOpts: []Option{ 139 WithManageJobsWithoutQueueName(true), 140 }, 141 wantOpts: Options{ 142 ManageJobsWithoutQueueName: true, 143 WaitForPodsReady: false, 144 KubeServerVersion: nil, 145 IntegrationOptions: nil, 146 }, 147 }, 148 "no options are passed": { 149 wantOpts: Options{ 150 ManageJobsWithoutQueueName: false, 151 WaitForPodsReady: false, 152 KubeServerVersion: nil, 153 IntegrationOptions: nil, 154 }, 155 }, 156 } 157 for name, tc := range cases { 158 t.Run(name, func(t *testing.T) { 159 gotOpts := ProcessOptions(tc.inputOpts...) 160 if diff := cmp.Diff(tc.wantOpts, gotOpts, 161 cmpopts.IgnoreUnexported(kubeversion.ServerVersionFetcher{})); len(diff) != 0 { 162 t.Errorf("Unexpected error from ProcessOptions (-want,+got):\n%s", diff) 163 } 164 }) 165 } 166 }