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  }