Skip to content

Commit 0e1e089

Browse files
awgreenestevekuznetsov
authored andcommitted
Update CatalogSource Pod Hash Logic
Problem: Commit 95405d81e4c87c8113ccd7a95ba4d088b200a42ai updated the catalog operator's logic so it does not delete the pod associated with a catalogSource while it is in a Pending state. Unfortunately, there is a race condition in which the pod may be admitted to the cluster without the imagePullSecrets specified for it's serviceAccount by the admission controller, preventing the pod from pulling its image from registries that require authentication and causing the pod to never reach a successful state. Solution: Update the catalog operator to detect when a pod is missing the imagePullSecrets granted to its serviceAccount. Signed-off-by: Alexander Greene <[email protected]>
1 parent 17b9103 commit 0e1e089

File tree

7 files changed

+136
-40
lines changed

7 files changed

+136
-40
lines changed

pkg/controller/operators/catalog/operator_test.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,13 @@ func toManifest(t *testing.T, obj runtime.Object) string {
21202120
}
21212121

21222122
func pod(s v1alpha1.CatalogSource) *corev1.Pod {
2123-
pod := reconciler.Pod(&s, "registry-server", "central-opm", "central-util", s.Spec.Image, s.GetName(), s.GetLabels(), s.GetAnnotations(), 5, 10, 1001)
2123+
serviceAccount := &corev1.ServiceAccount{
2124+
ObjectMeta: metav1.ObjectMeta{
2125+
Namespace: s.GetNamespace(),
2126+
Name: s.GetName(),
2127+
},
2128+
}
2129+
pod := reconciler.Pod(&s, "registry-server", "central-opm", "central-util", s.Spec.Image, serviceAccount, s.GetLabels(), s.GetAnnotations(), 5, 10, 1001)
21242130
ownerutil.AddOwner(pod, &s, false, true)
21252131
return pod
21262132
}

pkg/controller/registry/reconciler/configmap.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (s *configMapCatalogSourceDecorator) Service() *corev1.Service {
106106
}
107107

108108
func (s *configMapCatalogSourceDecorator) Pod(image string) *corev1.Pod {
109-
pod := Pod(s.CatalogSource, "configmap-registry-server", "", "", image, "", s.Labels(), s.Annotations(), 5, 5, s.runAsUser)
109+
pod := Pod(s.CatalogSource, "configmap-registry-server", "", "", image, nil, s.Labels(), s.Annotations(), 5, 5, s.runAsUser)
110110
pod.Spec.ServiceAccountName = s.GetName() + ConfigMapServerPostfix
111111
pod.Spec.Containers[0].Command = []string{"configmap-server", "-c", s.Spec.ConfigMap, "-n", s.GetNamespace()}
112112
ownerutil.AddOwner(pod, s.CatalogSource, false, true)

pkg/controller/registry/reconciler/configmap_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,11 @@ func objectsForCatalogSource(catsrc *v1alpha1.CatalogSource) []runtime.Object {
199199
case v1alpha1.SourceTypeGrpc:
200200
if catsrc.Spec.Image != "" {
201201
decorated := grpcCatalogSourceDecorator{CatalogSource: catsrc, createPodAsUser: runAsUser, opmImage: ""}
202+
serviceAccount := decorated.ServiceAccount()
202203
objs = clientfake.AddSimpleGeneratedNames(
203-
decorated.Pod(catsrc.GetName()),
204+
decorated.Pod(serviceAccount),
204205
decorated.Service(),
205-
decorated.ServiceAccount(),
206+
serviceAccount,
206207
)
207208
}
208209
}

pkg/controller/registry/reconciler/grpc.go

+43-25
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ func (s *grpcCatalogSourceDecorator) ServiceAccount() *corev1.ServiceAccount {
129129
}
130130
}
131131

132-
func (s *grpcCatalogSourceDecorator) Pod(saName string) *corev1.Pod {
133-
pod := Pod(s.CatalogSource, "registry-server", s.opmImage, s.utilImage, s.Spec.Image, saName, s.Labels(), s.Annotations(), 5, 10, s.createPodAsUser)
132+
func (s *grpcCatalogSourceDecorator) Pod(serviceAccount *corev1.ServiceAccount) *corev1.Pod {
133+
pod := Pod(s.CatalogSource, "registry-server", s.opmImage, s.utilImage, s.Spec.Image, serviceAccount, s.Labels(), s.Annotations(), 5, 10, s.createPodAsUser)
134134
ownerutil.AddOwner(pod, s.CatalogSource, false, true)
135135
return pod
136136
}
@@ -191,14 +191,14 @@ func (c *GrpcRegistryReconciler) currentUpdatePods(source grpcCatalogSourceDecor
191191
return pods
192192
}
193193

194-
func (c *GrpcRegistryReconciler) currentPodsWithCorrectImageAndSpec(source grpcCatalogSourceDecorator, saName string) []*corev1.Pod {
194+
func (c *GrpcRegistryReconciler) currentPodsWithCorrectImageAndSpec(source grpcCatalogSourceDecorator, serviceAccount *corev1.ServiceAccount) []*corev1.Pod {
195195
pods, err := c.Lister.CoreV1().PodLister().Pods(source.GetNamespace()).List(labels.SelectorFromValidatedSet(source.Labels()))
196196
if err != nil {
197197
logrus.WithError(err).Warn("couldn't find pod in cache")
198198
return nil
199199
}
200200
found := []*corev1.Pod{}
201-
newPod := source.Pod(saName)
201+
newPod := source.Pod(serviceAccount)
202202
for _, p := range pods {
203203
if correctImages(source, p) && podHashMatch(p, newPod) {
204204
found = append(found, p)
@@ -231,20 +231,26 @@ func (c *GrpcRegistryReconciler) EnsureRegistryServer(catalogSource *v1alpha1.Ca
231231

232232
//TODO: if any of these error out, we should write a status back (possibly set RegistryServiceStatus to nil so they get recreated)
233233
sa, err := c.ensureSA(source)
234-
// recreate the pod if no existing pod is serving the latest image or correct spec
235-
overwritePod := overwrite || len(c.currentPodsWithCorrectImageAndSpec(source, sa.GetName())) == 0
236-
237234
if err != nil && !apierrors.IsAlreadyExists(err) {
238235
return errors.Wrapf(err, "error ensuring service account: %s", source.GetName())
239236
}
240-
if err := c.ensurePod(source, sa.GetName(), overwritePod); err != nil {
241-
return errors.Wrapf(err, "error ensuring pod: %s", source.Pod(sa.Name).GetName())
237+
238+
sa, err = c.OpClient.GetServiceAccount(sa.GetNamespace(), sa.GetName())
239+
if err != nil {
240+
return err
242241
}
243-
if err := c.ensureUpdatePod(source, sa.Name); err != nil {
242+
243+
// recreate the pod if no existing pod is serving the latest image or correct spec
244+
overwritePod := overwrite || len(c.currentPodsWithCorrectImageAndSpec(source, sa)) == 0
245+
246+
if err := c.ensurePod(source, sa, overwritePod); err != nil {
247+
return errors.Wrapf(err, "error ensuring pod: %s", source.Pod(sa).GetName())
248+
}
249+
if err := c.ensureUpdatePod(source, sa); err != nil {
244250
if _, ok := err.(UpdateNotReadyErr); ok {
245251
return err
246252
}
247-
return errors.Wrapf(err, "error ensuring updated catalog source pod: %s", source.Pod(sa.Name).GetName())
253+
return errors.Wrapf(err, "error ensuring updated catalog source pod: %s", source.Pod(sa).GetName())
248254
}
249255
if err := c.ensureService(source, overwrite); err != nil {
250256
return errors.Wrapf(err, "error ensuring service: %s", source.Service().GetName())
@@ -279,7 +285,7 @@ func isRegistryServiceStatusValid(source *grpcCatalogSourceDecorator) bool {
279285
return true
280286
}
281287

282-
func (c *GrpcRegistryReconciler) ensurePod(source grpcCatalogSourceDecorator, saName string, overwrite bool) error {
288+
func (c *GrpcRegistryReconciler) ensurePod(source grpcCatalogSourceDecorator, serviceAccount *corev1.ServiceAccount, overwrite bool) error {
283289
// currentLivePods refers to the currently live instances of the catalog source
284290
currentLivePods := c.currentPods(source)
285291
if len(currentLivePods) > 0 {
@@ -292,16 +298,17 @@ func (c *GrpcRegistryReconciler) ensurePod(source grpcCatalogSourceDecorator, sa
292298
}
293299
}
294300
}
295-
_, err := c.OpClient.KubernetesInterface().CoreV1().Pods(source.GetNamespace()).Create(context.TODO(), source.Pod(saName), metav1.CreateOptions{})
301+
desiredPod := source.Pod(serviceAccount)
302+
_, err := c.OpClient.KubernetesInterface().CoreV1().Pods(source.GetNamespace()).Create(context.TODO(), desiredPod, metav1.CreateOptions{})
296303
if err != nil {
297-
return errors.Wrapf(err, "error creating new pod: %s", source.Pod(saName).GetGenerateName())
304+
return errors.Wrapf(err, "error creating new pod: %s", desiredPod.GetGenerateName())
298305
}
299306

300307
return nil
301308
}
302309

303310
// ensureUpdatePod checks that for the same catalog source version the same container imageID is running
304-
func (c *GrpcRegistryReconciler) ensureUpdatePod(source grpcCatalogSourceDecorator, saName string) error {
311+
func (c *GrpcRegistryReconciler) ensureUpdatePod(source grpcCatalogSourceDecorator, serviceAccount *corev1.ServiceAccount) error {
305312
if !source.Poll() {
306313
return nil
307314
}
@@ -311,7 +318,7 @@ func (c *GrpcRegistryReconciler) ensureUpdatePod(source grpcCatalogSourceDecorat
311318

312319
if source.Update() && len(currentUpdatePods) == 0 {
313320
logrus.WithField("CatalogSource", source.GetName()).Debugf("catalog update required at %s", time.Now().String())
314-
pod, err := c.createUpdatePod(source, saName)
321+
pod, err := c.createUpdatePod(source, serviceAccount)
315322
if err != nil {
316323
return errors.Wrapf(err, "creating update catalog source pod")
317324
}
@@ -419,14 +426,14 @@ func HashServiceSpec(spec corev1.ServiceSpec) string {
419426
}
420427

421428
// createUpdatePod is an internal method that creates a pod using the latest catalog source.
422-
func (c *GrpcRegistryReconciler) createUpdatePod(source grpcCatalogSourceDecorator, saName string) (*corev1.Pod, error) {
429+
func (c *GrpcRegistryReconciler) createUpdatePod(source grpcCatalogSourceDecorator, serviceAccount *corev1.ServiceAccount) (*corev1.Pod, error) {
423430
// remove label from pod to ensure service does not accidentally route traffic to the pod
424-
p := source.Pod(saName)
431+
p := source.Pod(serviceAccount)
425432
p = swapLabels(p, "", source.Name)
426433

427434
pod, err := c.OpClient.KubernetesInterface().CoreV1().Pods(source.GetNamespace()).Create(context.TODO(), p, metav1.CreateOptions{})
428435
if err != nil {
429-
logrus.WithField("pod", source.Pod(saName).GetName()).Warn("couldn't create new catalogsource pod")
436+
logrus.WithField("pod", source.Pod(serviceAccount).GetName()).Warn("couldn't create new catalogsource pod")
430437
return nil, err
431438
}
432439

@@ -476,18 +483,29 @@ func (c *GrpcRegistryReconciler) removePods(pods []*corev1.Pod, namespace string
476483
}
477484

478485
// CheckRegistryServer returns true if the given CatalogSource is considered healthy; false otherwise.
479-
func (c *GrpcRegistryReconciler) CheckRegistryServer(catalogSource *v1alpha1.CatalogSource) (healthy bool, err error) {
486+
func (c *GrpcRegistryReconciler) CheckRegistryServer(catalogSource *v1alpha1.CatalogSource) (bool, error) {
480487
source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage, utilImage: c.utilImage}
488+
489+
// The CheckRegistryServer function is called by the CatalogSoruce controller before the registry resources are created,
490+
// returning a IsNotFound error will cause the controller to exit and never create the resources, so we should
491+
// only return an error if it is something other than a NotFound error.
492+
serviceAccount := source.ServiceAccount()
493+
serviceAccount, err := c.OpClient.GetServiceAccount(serviceAccount.GetNamespace(), serviceAccount.GetName())
494+
if err != nil {
495+
if !apierrors.IsNotFound(err) {
496+
return false, err
497+
}
498+
return false, nil
499+
}
500+
481501
// Check on registry resources
482502
// TODO: add gRPC health check
483-
if len(c.currentPodsWithCorrectImageAndSpec(source, source.ServiceAccount().GetName())) < 1 ||
503+
if len(c.currentPodsWithCorrectImageAndSpec(source, serviceAccount)) < 1 ||
484504
c.currentService(source) == nil || c.currentServiceAccount(source) == nil {
485-
healthy = false
486-
return
505+
return false, nil
487506
}
488507

489-
healthy = true
490-
return
508+
return true, nil
491509
}
492510

493511
// promoteCatalog swaps the labels on the update pod so that the update pod is now reachable by the catalog service.

pkg/controller/registry/reconciler/grpc_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,9 @@ func TestGrpcRegistryReconciler(t *testing.T) {
358358

359359
// Check for resource existence
360360
decorated := grpcCatalogSourceDecorator{CatalogSource: tt.in.catsrc, createPodAsUser: runAsUser}
361-
pod := decorated.Pod(tt.in.catsrc.GetName())
362-
service := decorated.Service()
363361
sa := decorated.ServiceAccount()
362+
pod := decorated.Pod(sa)
363+
service := decorated.Service()
364364
listOptions := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{CatalogSourceLabelKey: tt.in.catsrc.GetName()}).String()}
365365
outPods, podErr := client.KubernetesInterface().CoreV1().Pods(pod.GetNamespace()).List(context.TODO(), listOptions)
366366
outService, serviceErr := client.KubernetesInterface().CoreV1().Services(service.GetNamespace()).Get(context.TODO(), service.GetName(), metav1.GetOptions{})
@@ -451,7 +451,7 @@ func TestRegistryPodPriorityClass(t *testing.T) {
451451

452452
// Check for resource existence
453453
decorated := grpcCatalogSourceDecorator{CatalogSource: tt.in.catsrc, createPodAsUser: runAsUser}
454-
pod := decorated.Pod(tt.in.catsrc.GetName())
454+
pod := decorated.Pod(serviceAccount(tt.in.catsrc.Namespace, tt.in.catsrc.Name))
455455
listOptions := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{CatalogSourceLabelKey: tt.in.catsrc.GetName()}).String()}
456456
outPods, podErr := client.KubernetesInterface().CoreV1().Pods(pod.GetNamespace()).List(context.TODO(), listOptions)
457457
require.NoError(t, podErr)

pkg/controller/registry/reconciler/reconciler.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func NewRegistryReconcilerFactory(lister operatorlister.OperatorLister, opClient
115115
}
116116
}
117117

118-
func Pod(source *operatorsv1alpha1.CatalogSource, name, opmImg, utilImage, img, saName string, labels, annotations map[string]string, readinessDelay, livenessDelay int32, runAsUser int64) *corev1.Pod {
118+
func Pod(source *operatorsv1alpha1.CatalogSource, name, opmImg, utilImage, img string, serviceAccount *corev1.ServiceAccount, labels, annotations map[string]string, readinessDelay, livenessDelay int32, runAsUser int64) *corev1.Pod {
119119
// make a copy of the labels and annotations to avoid mutating the input parameters
120120
podLabels := make(map[string]string)
121121
podAnnotations := make(map[string]string)
@@ -129,6 +129,15 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name, opmImg, utilImage, img,
129129
podAnnotations[key] = value
130130
}
131131

132+
// Default case for nil serviceAccount
133+
var saName string
134+
var saImagePullSecrets []corev1.LocalObjectReference
135+
// If the serviceAccount is not nil, set the fields that should appear on the pod
136+
if serviceAccount != nil {
137+
saName = serviceAccount.GetName()
138+
saImagePullSecrets = serviceAccount.ImagePullSecrets
139+
}
140+
132141
pod := &corev1.Pod{
133142
ObjectMeta: metav1.ObjectMeta{
134143
GenerateName: source.GetName() + "-",
@@ -192,6 +201,9 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name, opmImg, utilImage, img,
192201
"kubernetes.io/os": "linux",
193202
},
194203
ServiceAccountName: saName,
204+
// If this field is not set, there that the is a chance that pod will be created without the imagePullSecret
205+
// defined by the serviceAccount
206+
ImagePullSecrets: saImagePullSecrets,
195207
},
196208
}
197209

pkg/controller/registry/reconciler/reconciler_test.go

+66-7
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,22 @@ func TestPodMemoryTarget(t *testing.T) {
167167
}
168168

169169
for _, testCase := range testCases {
170-
pod := Pod(testCase.input, "name", "opmImage", "utilImage", "image", "service-account", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
170+
pod := Pod(testCase.input, "name", "opmImage", "utilImage", "image", serviceAccount("", "service-account"), map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
171171
if diff := cmp.Diff(pod, testCase.expected); diff != "" {
172172
t.Errorf("got incorrect pod: %v", diff)
173173
}
174174
}
175175
}
176176

177+
func serviceAccount(namespace, name string) *corev1.ServiceAccount {
178+
return &corev1.ServiceAccount{
179+
ObjectMeta: metav1.ObjectMeta{
180+
Namespace: namespace,
181+
Name: name,
182+
},
183+
}
184+
}
185+
177186
func TestPodExtractContent(t *testing.T) {
178187
var testCases = []struct {
179188
name string
@@ -362,13 +371,63 @@ func TestPodExtractContent(t *testing.T) {
362371
}
363372

364373
for _, testCase := range testCases {
365-
pod := Pod(testCase.input, "name", "opmImage", "utilImage", "image", "service-account", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
374+
pod := Pod(testCase.input, "name", "opmImage", "utilImage", "image", serviceAccount("", "service-account"), map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
366375
if diff := cmp.Diff(pod, testCase.expected); diff != "" {
367376
t.Errorf("got incorrect pod: %v", diff)
368377
}
369378
}
370379
}
371380

381+
func TestPodServiceAccountImagePullSecrets(t *testing.T) {
382+
var testCases = []struct {
383+
name string
384+
catalogSource *v1alpha1.CatalogSource
385+
serviceAccount *corev1.ServiceAccount
386+
}{
387+
{
388+
name: "ServiceAccount has no imagePullSecret",
389+
serviceAccount: &corev1.ServiceAccount{
390+
ObjectMeta: metav1.ObjectMeta{
391+
Namespace: "",
392+
Name: "service-account",
393+
},
394+
},
395+
},
396+
{
397+
name: "ServiceAccount has one imagePullSecret",
398+
serviceAccount: &corev1.ServiceAccount{
399+
ObjectMeta: metav1.ObjectMeta{
400+
Namespace: "",
401+
Name: "service-account",
402+
},
403+
ImagePullSecrets: []corev1.LocalObjectReference{{Name: "foo"}},
404+
},
405+
},
406+
}
407+
408+
catalogSource := &v1alpha1.CatalogSource{
409+
ObjectMeta: metav1.ObjectMeta{
410+
Name: "test",
411+
Namespace: "testns",
412+
},
413+
Spec: v1alpha1.CatalogSourceSpec{
414+
GrpcPodConfig: &v1alpha1.GrpcPodConfig{
415+
ExtractContent: &v1alpha1.ExtractContentConfig{
416+
CacheDir: "/tmp/cache",
417+
CatalogDir: "/catalog",
418+
},
419+
},
420+
},
421+
}
422+
423+
for _, testCase := range testCases {
424+
pod := Pod(catalogSource, "name", "opmImage", "utilImage", "image", testCase.serviceAccount, map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
425+
if diff := cmp.Diff(testCase.serviceAccount.ImagePullSecrets, pod.Spec.ImagePullSecrets); diff != "" {
426+
t.Errorf("got incorrect pod: %v", diff)
427+
}
428+
}
429+
}
430+
372431
func TestPodNodeSelector(t *testing.T) {
373432
catsrc := &v1alpha1.CatalogSource{
374433
ObjectMeta: metav1.ObjectMeta{
@@ -380,7 +439,7 @@ func TestPodNodeSelector(t *testing.T) {
380439
key := "kubernetes.io/os"
381440
value := "linux"
382441

383-
gotCatSrcPod := Pod(catsrc, "hello", "utilImage", "opmImage", "busybox", "", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
442+
gotCatSrcPod := Pod(catsrc, "hello", "utilImage", "opmImage", "busybox", serviceAccount("", "service-account"), map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
384443
gotCatSrcPodSelector := gotCatSrcPod.Spec.NodeSelector
385444

386445
if gotCatSrcPodSelector[key] != value {
@@ -428,7 +487,7 @@ func TestPullPolicy(t *testing.T) {
428487
}
429488

430489
for _, tt := range table {
431-
p := Pod(source, "catalog", "opmImage", "utilImage", tt.image, "", nil, nil, int32(0), int32(0), int64(workloadUserID))
490+
p := Pod(source, "catalog", "opmImage", "utilImage", tt.image, serviceAccount("", "service-account"), nil, nil, int32(0), int32(0), int64(workloadUserID))
432491
policy := p.Spec.Containers[0].ImagePullPolicy
433492
if policy != tt.policy {
434493
t.Fatalf("expected pull policy %s for image %s", tt.policy, tt.image)
@@ -540,7 +599,7 @@ func TestPodContainerSecurityContext(t *testing.T) {
540599
},
541600
}
542601
for _, testcase := range testcases {
543-
outputPod := Pod(testcase.inputCatsrc, "hello", "utilImage", "opmImage", "busybox", "", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
602+
outputPod := Pod(testcase.inputCatsrc, "hello", "utilImage", "opmImage", "busybox", serviceAccount("", "service-account"), map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID))
544603
if testcase.expectedSecurityContext != nil {
545604
require.Equal(t, testcase.expectedSecurityContext, outputPod.Spec.SecurityContext)
546605
}
@@ -570,7 +629,7 @@ func TestPodAvoidsConcurrentWrite(t *testing.T) {
570629
"annotation": "somethingelse",
571630
}
572631

573-
gotPod := Pod(catsrc, "hello", "opmImage", "utilImage", "busybox", "", labels, annotations, int32(0), int32(0), int64(workloadUserID))
632+
gotPod := Pod(catsrc, "hello", "opmImage", "utilImage", "busybox", serviceAccount("", "service-account"), labels, annotations, int32(0), int32(0), int64(workloadUserID))
574633

575634
// check labels and annotations point to different addresses between parameters and what's in the pod
576635
require.NotEqual(t, &labels, &gotPod.Labels)
@@ -799,7 +858,7 @@ func TestPodSchedulingOverrides(t *testing.T) {
799858
}
800859

801860
for _, testCase := range testCases {
802-
pod := Pod(testCase.catalogSource, "hello", "opmImage", "utilImage", "busybox", "", map[string]string{}, testCase.annotations, int32(0), int32(0), int64(workloadUserID))
861+
pod := Pod(testCase.catalogSource, "hello", "opmImage", "utilImage", "busybox", serviceAccount("", "service-account"), map[string]string{}, testCase.annotations, int32(0), int32(0), int64(workloadUserID))
803862
require.Equal(t, testCase.expectedNodeSelectors, pod.Spec.NodeSelector)
804863
require.Equal(t, testCase.expectedPriorityClassName, pod.Spec.PriorityClassName)
805864
require.Equal(t, testCase.expectedTolerations, pod.Spec.Tolerations)

0 commit comments

Comments
 (0)