sigs.k8s.io/kueue@v0.6.2/pkg/controller/admissionchecks/multikueue/admissioncheck_test.go (about) 1 /* 2 Copyright 2024 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 multikueue 18 19 import ( 20 "testing" 21 22 "github.com/google/go-cmp/cmp" 23 "github.com/google/go-cmp/cmp/cmpopts" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/types" 26 "sigs.k8s.io/controller-runtime/pkg/reconcile" 27 28 kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1" 29 kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1" 30 utiltesting "sigs.k8s.io/kueue/pkg/util/testing" 31 ) 32 33 func TestReconcile(t *testing.T) { 34 cases := map[string]struct { 35 checks []kueue.AdmissionCheck 36 clusters []kueuealpha.MultiKueueCluster 37 reconcileFor string 38 configs []kueuealpha.MultiKueueConfig 39 40 wantChecks []kueue.AdmissionCheck 41 wantError error 42 }{ 43 "missing admissioncheck": { 44 reconcileFor: "missing-ac", 45 }, 46 "missing config": { 47 reconcileFor: "ac1", 48 checks: []kueue.AdmissionCheck{ 49 *utiltesting.MakeAdmissionCheck("ac1"). 50 ControllerName(ControllerName). 51 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 52 Obj(), 53 }, 54 wantChecks: []kueue.AdmissionCheck{ 55 *utiltesting.MakeAdmissionCheck("ac1"). 56 ControllerName(ControllerName). 57 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 58 Condition(metav1.Condition{ 59 Type: kueue.AdmissionCheckActive, 60 Status: metav1.ConditionFalse, 61 Reason: "Inactive", 62 Message: `Cannot load the AdmissionChecks parameters: multikueueconfigs.kueue.x-k8s.io "config1" not found`, 63 }). 64 Obj(), 65 }, 66 }, 67 "unmanaged": { 68 reconcileFor: "ac1", 69 checks: []kueue.AdmissionCheck{ 70 *utiltesting.MakeAdmissionCheck("ac1"). 71 ControllerName("not-multikueue"). 72 Obj(), 73 }, 74 wantChecks: []kueue.AdmissionCheck{ 75 *utiltesting.MakeAdmissionCheck("ac1"). 76 ControllerName("not-multikueue"). 77 Obj(), 78 }, 79 }, 80 "missing cluster": { 81 reconcileFor: "ac1", 82 checks: []kueue.AdmissionCheck{ 83 *utiltesting.MakeAdmissionCheck("ac1"). 84 ControllerName(ControllerName). 85 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 86 Obj(), 87 }, 88 configs: []kueuealpha.MultiKueueConfig{ 89 *utiltesting.MakeMultiKueueConfig("config1").Clusters("worker1").Obj(), 90 }, 91 wantChecks: []kueue.AdmissionCheck{ 92 *utiltesting.MakeAdmissionCheck("ac1"). 93 ControllerName(ControllerName). 94 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 95 Condition(metav1.Condition{ 96 Type: kueue.AdmissionCheckActive, 97 Status: metav1.ConditionFalse, 98 Reason: "Inactive", 99 Message: "Missing clusters: [worker1]", 100 }). 101 Obj(), 102 }, 103 }, 104 "inactive cluster": { 105 reconcileFor: "ac1", 106 checks: []kueue.AdmissionCheck{ 107 *utiltesting.MakeAdmissionCheck("ac1"). 108 ControllerName(ControllerName). 109 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 110 Obj(), 111 }, 112 configs: []kueuealpha.MultiKueueConfig{ 113 *utiltesting.MakeMultiKueueConfig("config1").Clusters("worker1").Obj(), 114 }, 115 116 clusters: []kueuealpha.MultiKueueCluster{ 117 *utiltesting.MakeMultiKueueCluster("worker1").Active(metav1.ConditionFalse, "ByTest", "by test").Obj(), 118 }, 119 wantChecks: []kueue.AdmissionCheck{ 120 *utiltesting.MakeAdmissionCheck("ac1"). 121 ControllerName(ControllerName). 122 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 123 Condition(metav1.Condition{ 124 Type: kueue.AdmissionCheckActive, 125 Status: metav1.ConditionFalse, 126 Reason: "Inactive", 127 Message: "Inactive clusters: [worker1]", 128 }). 129 Obj(), 130 }, 131 }, 132 "missing and inactive cluster": { 133 reconcileFor: "ac1", 134 checks: []kueue.AdmissionCheck{ 135 *utiltesting.MakeAdmissionCheck("ac1"). 136 ControllerName(ControllerName). 137 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 138 Obj(), 139 }, 140 configs: []kueuealpha.MultiKueueConfig{ 141 *utiltesting.MakeMultiKueueConfig("config1").Clusters("worker1", "worker2", "worker3").Obj(), 142 }, 143 144 clusters: []kueuealpha.MultiKueueCluster{ 145 *utiltesting.MakeMultiKueueCluster("worker1").Active(metav1.ConditionFalse, "ByTest", "by test").Obj(), 146 *utiltesting.MakeMultiKueueCluster("worker2").Active(metav1.ConditionTrue, "ByTest", "by test").Obj(), 147 }, 148 wantChecks: []kueue.AdmissionCheck{ 149 *utiltesting.MakeAdmissionCheck("ac1"). 150 ControllerName(ControllerName). 151 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 152 Condition(metav1.Condition{ 153 Type: kueue.AdmissionCheckActive, 154 Status: metav1.ConditionFalse, 155 Reason: "Inactive", 156 Message: "Missing clusters: [worker3], Inactive clusters: [worker1]", 157 }). 158 Obj(), 159 }, 160 }, 161 "active": { 162 reconcileFor: "ac1", 163 checks: []kueue.AdmissionCheck{ 164 *utiltesting.MakeAdmissionCheck("ac1"). 165 ControllerName(ControllerName). 166 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 167 Obj(), 168 }, 169 configs: []kueuealpha.MultiKueueConfig{ 170 *utiltesting.MakeMultiKueueConfig("config1").Clusters("worker1").Obj(), 171 }, 172 clusters: []kueuealpha.MultiKueueCluster{ 173 *utiltesting.MakeMultiKueueCluster("worker1").Active(metav1.ConditionTrue, "ByTest", "by test").Obj(), 174 }, 175 wantChecks: []kueue.AdmissionCheck{ 176 *utiltesting.MakeAdmissionCheck("ac1"). 177 ControllerName(ControllerName). 178 Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1"). 179 Condition(metav1.Condition{ 180 Type: kueue.AdmissionCheckActive, 181 Status: metav1.ConditionTrue, 182 Reason: "Active", 183 Message: `The admission check is active`, 184 }). 185 Obj(), 186 }, 187 }, 188 } 189 190 for name, tc := range cases { 191 t.Run(name, func(t *testing.T) { 192 builder, ctx := getClientBuilder() 193 194 builder = builder.WithLists( 195 &kueue.AdmissionCheckList{Items: tc.checks}, 196 &kueuealpha.MultiKueueConfigList{Items: tc.configs}, 197 &kueuealpha.MultiKueueClusterList{Items: tc.clusters}, 198 ) 199 200 for _, ac := range tc.checks { 201 builder = builder.WithStatusSubresource(ac.DeepCopy()) 202 } 203 204 c := builder.Build() 205 206 helper, _ := newMultiKueueStoreHelper(c) 207 reconciler := newACReconciler(c, helper) 208 209 _, gotErr := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: tc.reconcileFor}}) 210 if diff := cmp.Diff(tc.wantError, gotErr); diff != "" { 211 t.Errorf("unexpected error (-want/+got):\n%s", diff) 212 } 213 214 checks := &kueue.AdmissionCheckList{} 215 listErr := c.List(ctx, checks) 216 217 if listErr != nil { 218 t.Errorf("unexpected list checks error: %s", listErr) 219 } 220 221 if diff := cmp.Diff(tc.wantChecks, checks.Items, cmpopts.EquateEmpty(), cmpopts.IgnoreTypes(metav1.ObjectMeta{}), cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime")); diff != "" { 222 t.Errorf("unexpected controllers (-want/+got):\n%s", diff) 223 } 224 225 }) 226 } 227 }