sigs.k8s.io/kueue@v0.6.2/pkg/controller/admissionchecks/multikueue/workload_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  	"context"
    21  	"errors"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  	"github.com/google/go-cmp/cmp/cmpopts"
    26  	batchv1 "k8s.io/api/batch/v1"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/types"
    30  	"sigs.k8s.io/controller-runtime/pkg/client"
    31  	"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
    32  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    33  
    34  	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
    35  	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
    36  	"sigs.k8s.io/kueue/pkg/controller/constants"
    37  	"sigs.k8s.io/kueue/pkg/util/slices"
    38  	utiltesting "sigs.k8s.io/kueue/pkg/util/testing"
    39  	testingjob "sigs.k8s.io/kueue/pkg/util/testingjobs/job"
    40  )
    41  
    42  var (
    43  	errFake = errors.New("fake error")
    44  )
    45  
    46  func TestWlReconcile(t *testing.T) {
    47  	objCheckOpts := []cmp.Option{
    48  		cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion"),
    49  		cmpopts.EquateEmpty(),
    50  		cmpopts.IgnoreFields(metav1.Condition{}, "LastTransitionTime"),
    51  		cmpopts.IgnoreFields(kueue.AdmissionCheckState{}, "LastTransitionTime"),
    52  		cmpopts.SortSlices(func(a, b metav1.Condition) bool { return a.Type < b.Type }),
    53  	}
    54  
    55  	baseWorkloadBuilder := utiltesting.MakeWorkload("wl1", TestNamespace)
    56  	baseJobBuilder := testingjob.MakeJob("job1", TestNamespace)
    57  
    58  	cases := map[string]struct {
    59  		reconcileFor      string
    60  		managersWorkloads []kueue.Workload
    61  		managersJobs      []batchv1.Job
    62  		worker1Workloads  []kueue.Workload
    63  		worker1Jobs       []batchv1.Job
    64  		// second worker
    65  		useSecondWorker      bool
    66  		worker2OnDeleteError error
    67  		worker2OnGetError    error
    68  		worker2OnCreateError error
    69  		worker2Workloads     []kueue.Workload
    70  		worker2Jobs          []batchv1.Job
    71  
    72  		wantError             error
    73  		wantManagersWorkloads []kueue.Workload
    74  		wantManagersJobs      []batchv1.Job
    75  		wantWorker1Workloads  []kueue.Workload
    76  		wantWorker1Jobs       []batchv1.Job
    77  
    78  		// second worker
    79  		wantWorker2Workloads []kueue.Workload
    80  		wantWorker2Jobs      []batchv1.Job
    81  	}{
    82  		"missing workload": {
    83  			reconcileFor: "missing workload",
    84  		},
    85  		"unmanaged wl (no ac) is ignored": {
    86  			reconcileFor: "wl1",
    87  			managersWorkloads: []kueue.Workload{
    88  				*baseWorkloadBuilder.Clone().Obj(),
    89  			},
    90  			wantManagersWorkloads: []kueue.Workload{
    91  				*baseWorkloadBuilder.Clone().Obj(),
    92  			},
    93  		},
    94  		"unmanaged wl (no parent) is ignored": {
    95  			reconcileFor: "wl1",
    96  			managersWorkloads: []kueue.Workload{
    97  				*baseWorkloadBuilder.Clone().
    98  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
    99  					Obj(),
   100  			},
   101  			wantManagersWorkloads: []kueue.Workload{
   102  				*baseWorkloadBuilder.Clone().
   103  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   104  					Obj(),
   105  			},
   106  		},
   107  		"failing to read from a worker": {
   108  			reconcileFor: "wl1",
   109  			managersWorkloads: []kueue.Workload{
   110  				*baseWorkloadBuilder.Clone().
   111  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   112  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   113  					Obj(),
   114  			},
   115  			useSecondWorker:   true,
   116  			worker2OnGetError: errFake,
   117  
   118  			wantManagersWorkloads: []kueue.Workload{
   119  				*baseWorkloadBuilder.Clone().
   120  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   121  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   122  					Obj(),
   123  			},
   124  			wantError: errFake,
   125  		},
   126  		"wl without reservation, clears the workload objects": {
   127  			reconcileFor: "wl1",
   128  			managersWorkloads: []kueue.Workload{
   129  				*baseWorkloadBuilder.Clone().
   130  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   131  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   132  					Obj(),
   133  			},
   134  			worker1Workloads: []kueue.Workload{
   135  				*baseWorkloadBuilder.Clone().
   136  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   137  					Obj(),
   138  			},
   139  			wantManagersWorkloads: []kueue.Workload{
   140  				*baseWorkloadBuilder.Clone().
   141  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   142  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   143  					Obj(),
   144  			},
   145  		},
   146  		"wl with reservation, creates remote workloads, worker2 fails": {
   147  			reconcileFor: "wl1",
   148  			managersWorkloads: []kueue.Workload{
   149  				*baseWorkloadBuilder.Clone().
   150  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   151  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   152  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   153  					Obj(),
   154  			},
   155  			useSecondWorker:      true,
   156  			worker2OnCreateError: errFake,
   157  
   158  			wantManagersWorkloads: []kueue.Workload{
   159  				*baseWorkloadBuilder.Clone().
   160  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   161  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   162  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   163  					Obj(),
   164  			},
   165  			wantWorker1Workloads: []kueue.Workload{
   166  				*baseWorkloadBuilder.Clone().
   167  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   168  					Obj(),
   169  			},
   170  			wantError: errFake,
   171  		},
   172  		"wl with reservation, creates missing workloads": {
   173  			reconcileFor: "wl1",
   174  			managersWorkloads: []kueue.Workload{
   175  				*baseWorkloadBuilder.Clone().
   176  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   177  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   178  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   179  					Obj(),
   180  			},
   181  			worker1Workloads: []kueue.Workload{
   182  				*baseWorkloadBuilder.Clone().
   183  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   184  					Obj(),
   185  			},
   186  			useSecondWorker: true,
   187  
   188  			wantManagersWorkloads: []kueue.Workload{
   189  				*baseWorkloadBuilder.Clone().
   190  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   191  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   192  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   193  					Obj(),
   194  			},
   195  			wantWorker1Workloads: []kueue.Workload{
   196  				*baseWorkloadBuilder.Clone().
   197  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   198  					Obj(),
   199  			},
   200  
   201  			wantWorker2Workloads: []kueue.Workload{
   202  				*baseWorkloadBuilder.Clone().
   203  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   204  					Obj(),
   205  			},
   206  		},
   207  		"remote wl with reservation, unable to delete the second worker's workload": {
   208  			reconcileFor: "wl1",
   209  			managersWorkloads: []kueue.Workload{
   210  				*baseWorkloadBuilder.Clone().
   211  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   212  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   213  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   214  					Obj(),
   215  			},
   216  
   217  			managersJobs: []batchv1.Job{
   218  				*baseJobBuilder.Clone().Obj(),
   219  			},
   220  
   221  			worker1Workloads: []kueue.Workload{
   222  				*baseWorkloadBuilder.Clone().
   223  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   224  					Obj(),
   225  			},
   226  			useSecondWorker:      true,
   227  			worker2OnDeleteError: errFake,
   228  			worker2Workloads: []kueue.Workload{
   229  				*baseWorkloadBuilder.Clone().
   230  					Obj(),
   231  			},
   232  
   233  			wantManagersWorkloads: []kueue.Workload{
   234  				*baseWorkloadBuilder.Clone().
   235  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   236  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   237  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   238  					Obj(),
   239  			},
   240  			wantManagersJobs: []batchv1.Job{
   241  				*baseJobBuilder.Clone().Obj(),
   242  			},
   243  
   244  			wantWorker1Workloads: []kueue.Workload{
   245  				*baseWorkloadBuilder.Clone().
   246  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   247  					Obj(),
   248  			},
   249  			wantWorker2Workloads: []kueue.Workload{
   250  				*baseWorkloadBuilder.Clone().
   251  					Obj(),
   252  			},
   253  			wantError: errFake,
   254  		},
   255  		"remote wl with reservation": {
   256  			reconcileFor: "wl1",
   257  			managersWorkloads: []kueue.Workload{
   258  				*baseWorkloadBuilder.Clone().
   259  					AdmissionCheck(kueue.AdmissionCheckState{Name: "ac1", State: kueue.CheckStatePending}).
   260  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   261  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   262  					Obj(),
   263  			},
   264  
   265  			managersJobs: []batchv1.Job{
   266  				*baseJobBuilder.Clone().Obj(),
   267  			},
   268  
   269  			worker1Workloads: []kueue.Workload{
   270  				*baseWorkloadBuilder.Clone().
   271  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   272  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   273  					Obj(),
   274  			},
   275  			useSecondWorker: true,
   276  			worker2Workloads: []kueue.Workload{
   277  				*baseWorkloadBuilder.Clone().
   278  					Obj(),
   279  			},
   280  
   281  			wantManagersWorkloads: []kueue.Workload{
   282  				*baseWorkloadBuilder.Clone().
   283  					AdmissionCheck(kueue.AdmissionCheckState{
   284  						Name:    "ac1",
   285  						State:   kueue.CheckStatePending,
   286  						Message: `The workload got reservation on "worker1"`,
   287  					}).
   288  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   289  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   290  					Obj(),
   291  			},
   292  			wantManagersJobs: []batchv1.Job{
   293  				*baseJobBuilder.Clone().Obj(),
   294  			},
   295  
   296  			wantWorker1Workloads: []kueue.Workload{
   297  				*baseWorkloadBuilder.Clone().
   298  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   299  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   300  					Obj(),
   301  			},
   302  			wantWorker1Jobs: []batchv1.Job{
   303  				*baseJobBuilder.Clone().
   304  					Label(constants.PrebuiltWorkloadLabel, "wl1").
   305  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   306  					Obj(),
   307  			},
   308  		},
   309  		"remote wl is finished, the local workload and Job are marked completed ": {
   310  			reconcileFor: "wl1",
   311  			managersWorkloads: []kueue.Workload{
   312  				*baseWorkloadBuilder.Clone().
   313  					AdmissionCheck(kueue.AdmissionCheckState{
   314  						Name:    "ac1",
   315  						State:   kueue.CheckStatePending,
   316  						Message: `The workload got reservation on "worker1"`,
   317  					}).
   318  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   319  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   320  					Obj(),
   321  			},
   322  
   323  			managersJobs: []batchv1.Job{
   324  				*baseJobBuilder.Clone().Obj(),
   325  			},
   326  
   327  			worker1Jobs: []batchv1.Job{
   328  				*baseJobBuilder.Clone().
   329  					Label(constants.PrebuiltWorkloadLabel, "wl1").
   330  					Condition(batchv1.JobCondition{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}).
   331  					Obj(),
   332  			},
   333  
   334  			worker1Workloads: []kueue.Workload{
   335  				*baseWorkloadBuilder.Clone().
   336  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   337  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   338  					Condition(metav1.Condition{Type: kueue.WorkloadFinished, Status: metav1.ConditionTrue, Reason: "ByTest", Message: "by test"}).
   339  					Obj(),
   340  			},
   341  			wantManagersWorkloads: []kueue.Workload{
   342  				*baseWorkloadBuilder.Clone().
   343  					AdmissionCheck(kueue.AdmissionCheckState{
   344  						Name:    "ac1",
   345  						State:   kueue.CheckStatePending,
   346  						Message: `The workload got reservation on "worker1"`,
   347  					}).
   348  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   349  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   350  					Condition(metav1.Condition{Type: kueue.WorkloadFinished, Status: metav1.ConditionTrue, Reason: "ByTest", Message: `by test`}).
   351  					Obj(),
   352  			},
   353  			wantManagersJobs: []batchv1.Job{
   354  				*baseJobBuilder.Clone().
   355  					Condition(batchv1.JobCondition{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}).
   356  					Obj(),
   357  			},
   358  
   359  			wantWorker1Workloads: []kueue.Workload{
   360  				*baseWorkloadBuilder.Clone().
   361  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   362  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   363  					Condition(metav1.Condition{Type: kueue.WorkloadFinished, Status: metav1.ConditionTrue, Reason: "ByTest", Message: "by test"}).
   364  					Obj(),
   365  			},
   366  			wantWorker1Jobs: []batchv1.Job{
   367  				*baseJobBuilder.Clone().
   368  					Label(constants.PrebuiltWorkloadLabel, "wl1").
   369  					Condition(batchv1.JobCondition{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}).
   370  					Obj(),
   371  			},
   372  		},
   373  		"the local Job is marked finished, the remote objects are removed": {
   374  			reconcileFor: "wl1",
   375  			managersWorkloads: []kueue.Workload{
   376  				*baseWorkloadBuilder.Clone().
   377  					AdmissionCheck(kueue.AdmissionCheckState{
   378  						Name:    "ac1",
   379  						State:   kueue.CheckStatePending,
   380  						Message: `The workload got reservation on "worker1"`,
   381  					}).
   382  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   383  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   384  					Condition(metav1.Condition{Type: kueue.WorkloadFinished, Status: metav1.ConditionTrue, Reason: "ByTest", Message: `by test`}).
   385  					Obj(),
   386  			},
   387  
   388  			managersJobs: []batchv1.Job{
   389  				*baseJobBuilder.Clone().
   390  					Condition(batchv1.JobCondition{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}).
   391  					Obj(),
   392  			},
   393  
   394  			worker1Jobs: []batchv1.Job{
   395  				*baseJobBuilder.Clone().
   396  					Label(constants.PrebuiltWorkloadLabel, "wl1").
   397  					Condition(batchv1.JobCondition{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}).
   398  					Obj(),
   399  			},
   400  
   401  			worker1Workloads: []kueue.Workload{
   402  				*baseWorkloadBuilder.Clone().
   403  					Label(kueuealpha.MultiKueueOriginLabel, defaultOrigin).
   404  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   405  					Condition(metav1.Condition{Type: kueue.WorkloadFinished, Status: metav1.ConditionTrue, Reason: "ByTest", Message: "by test"}).
   406  					Obj(),
   407  			},
   408  			wantManagersWorkloads: []kueue.Workload{
   409  				*baseWorkloadBuilder.Clone().
   410  					AdmissionCheck(kueue.AdmissionCheckState{
   411  						Name:    "ac1",
   412  						State:   kueue.CheckStatePending,
   413  						Message: `The workload got reservation on "worker1"`,
   414  					}).
   415  					ControllerReference(batchv1.SchemeGroupVersion.WithKind("Job"), "job1", "uid1").
   416  					ReserveQuota(utiltesting.MakeAdmission("q1").Obj()).
   417  					Condition(metav1.Condition{Type: kueue.WorkloadFinished, Status: metav1.ConditionTrue, Reason: "ByTest", Message: `by test`}).
   418  					Obj(),
   419  			},
   420  			wantManagersJobs: []batchv1.Job{
   421  				*baseJobBuilder.Clone().
   422  					Condition(batchv1.JobCondition{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}).
   423  					Obj(),
   424  			},
   425  		},
   426  	}
   427  
   428  	for name, tc := range cases {
   429  		t.Run(name, func(t *testing.T) {
   430  			manageBuilder, ctx := getClientBuilder()
   431  
   432  			workerClusters := []string{"worker1"}
   433  			if tc.useSecondWorker {
   434  				workerClusters = append(workerClusters, "worker2")
   435  			}
   436  			manageBuilder = manageBuilder.WithLists(&kueue.WorkloadList{Items: tc.managersWorkloads}, &batchv1.JobList{Items: tc.managersJobs})
   437  			manageBuilder = manageBuilder.WithStatusSubresource(slices.Map(tc.managersWorkloads, func(w *kueue.Workload) client.Object { return w })...)
   438  			manageBuilder = manageBuilder.WithStatusSubresource(slices.Map(tc.managersJobs, func(w *batchv1.Job) client.Object { return w })...)
   439  			manageBuilder = manageBuilder.WithObjects(
   440  				utiltesting.MakeMultiKueueConfig("config1").Clusters(workerClusters...).Obj(),
   441  				utiltesting.MakeAdmissionCheck("ac1").ControllerName(ControllerName).
   442  					Parameters(kueuealpha.GroupVersion.Group, "MultiKueueConfig", "config1").
   443  					Obj(),
   444  			)
   445  
   446  			managerClient := manageBuilder.Build()
   447  
   448  			cRec := newClustersReconciler(managerClient, TestNamespace, 0, defaultOrigin)
   449  
   450  			worker1Builder, _ := getClientBuilder()
   451  			worker1Builder = worker1Builder.WithLists(&kueue.WorkloadList{Items: tc.worker1Workloads}, &batchv1.JobList{Items: tc.worker1Jobs})
   452  			worker1Client := worker1Builder.Build()
   453  
   454  			w1remoteClient := newRemoteClient(managerClient, nil, nil, defaultOrigin, "")
   455  			w1remoteClient.client = worker1Client
   456  			cRec.remoteClients["worker1"] = w1remoteClient
   457  
   458  			var worker2Client client.WithWatch
   459  			if tc.useSecondWorker {
   460  				worker2Builder, _ := getClientBuilder()
   461  				worker2Builder = worker2Builder.WithLists(&kueue.WorkloadList{Items: tc.worker2Workloads}, &batchv1.JobList{Items: tc.worker2Jobs})
   462  				worker2Builder = worker2Builder.WithInterceptorFuncs(interceptor.Funcs{
   463  					Get: func(ctx context.Context, c client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
   464  						if tc.worker2OnGetError != nil {
   465  							return tc.worker2OnGetError
   466  						}
   467  						return c.Get(ctx, key, obj, opts...)
   468  					},
   469  					Create: func(ctx context.Context, c client.WithWatch, obj client.Object, opts ...client.CreateOption) error {
   470  						if tc.worker2OnCreateError != nil {
   471  							return tc.worker2OnCreateError
   472  						}
   473  						return c.Create(ctx, obj, opts...)
   474  					},
   475  					Delete: func(ctx context.Context, c client.WithWatch, obj client.Object, opts ...client.DeleteOption) error {
   476  						if tc.worker2OnDeleteError != nil {
   477  							return tc.worker2OnDeleteError
   478  						}
   479  						return c.Delete(ctx, obj, opts...)
   480  					},
   481  				})
   482  				worker2Client = worker2Builder.Build()
   483  
   484  				w2remoteClient := newRemoteClient(managerClient, nil, nil, defaultOrigin, "")
   485  				w2remoteClient.client = worker2Client
   486  				cRec.remoteClients["worker2"] = w2remoteClient
   487  
   488  			}
   489  
   490  			helper, _ := newMultiKueueStoreHelper(managerClient)
   491  			reconciler := newWlReconciler(managerClient, helper, cRec, defaultOrigin)
   492  
   493  			_, gotErr := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: tc.reconcileFor, Namespace: TestNamespace}})
   494  			if diff := cmp.Diff(tc.wantError, gotErr, cmpopts.EquateErrors()); diff != "" {
   495  				t.Errorf("unexpected error (-want/+got):\n%s", diff)
   496  			}
   497  
   498  			gotManagersWokloads := &kueue.WorkloadList{}
   499  			if err := managerClient.List(ctx, gotManagersWokloads); err != nil {
   500  				t.Errorf("unexpected list manager's workloads error: %s", err)
   501  			} else {
   502  				if diff := cmp.Diff(tc.wantManagersWorkloads, gotManagersWokloads.Items, objCheckOpts...); diff != "" {
   503  					t.Errorf("unexpected manager's workloads (-want/+got):\n%s", diff)
   504  				}
   505  			}
   506  
   507  			gotWorker1Wokloads := &kueue.WorkloadList{}
   508  			if err := worker1Client.List(ctx, gotWorker1Wokloads); err != nil {
   509  				t.Errorf("unexpected list worker's workloads error: %s", err)
   510  			} else {
   511  				if diff := cmp.Diff(tc.wantWorker1Workloads, gotWorker1Wokloads.Items, objCheckOpts...); diff != "" {
   512  					t.Errorf("unexpected worker's workloads (-want/+got):\n%s", diff)
   513  				}
   514  			}
   515  
   516  			gotManagersJobs := &batchv1.JobList{}
   517  			if err := managerClient.List(ctx, gotManagersJobs); err != nil {
   518  				t.Errorf("unexpected list manager's jobs error %s", err)
   519  			} else {
   520  				if diff := cmp.Diff(tc.wantManagersJobs, gotManagersJobs.Items, objCheckOpts...); diff != "" {
   521  					t.Errorf("unexpected manager's jobs (-want/+got):\n%s", diff)
   522  				}
   523  			}
   524  
   525  			gotWorker1Job := &batchv1.JobList{}
   526  			if err := worker1Client.List(ctx, gotWorker1Job); err != nil {
   527  				t.Error("unexpected list worker's jobs error")
   528  			} else {
   529  				if diff := cmp.Diff(tc.wantWorker1Jobs, gotWorker1Job.Items, objCheckOpts...); diff != "" {
   530  					t.Errorf("unexpected worker's jobs (-want/+got):\n%s", diff)
   531  				}
   532  			}
   533  
   534  			if tc.useSecondWorker {
   535  				gotWorker2Wokloads := &kueue.WorkloadList{}
   536  				if err := worker2Client.List(ctx, gotWorker2Wokloads); err != nil {
   537  					t.Errorf("unexpected list worker2 workloads error: %s", err)
   538  				} else {
   539  					if diff := cmp.Diff(tc.wantWorker2Workloads, gotWorker2Wokloads.Items, objCheckOpts...); diff != "" {
   540  						t.Errorf("unexpected worker2 workloads (-want/+got):\n%s", diff)
   541  					}
   542  				}
   543  
   544  				gotWorker2Job := &batchv1.JobList{}
   545  				if err := worker2Client.List(ctx, gotWorker2Job); err != nil {
   546  					t.Errorf("unexpected list worker2 jobs error: %s", err)
   547  				} else {
   548  					if diff := cmp.Diff(tc.wantWorker2Jobs, gotWorker2Job.Items, objCheckOpts...); diff != "" {
   549  						t.Errorf("unexpected worker2 jobs (-want/+got):\n%s", diff)
   550  					}
   551  				}
   552  			}
   553  		})
   554  	}
   555  }