Skip to content

Commit cd117ab

Browse files
authored
Merge pull request kubernetes#107763 from smarterclayton/wait_for_kuberoot_ca
e2e: Wait for kube-root-ca.crt to be created
2 parents dee9059 + b4aa9a1 commit cd117ab

File tree

2 files changed

+45
-15
lines changed

2 files changed

+45
-15
lines changed

test/e2e/framework/framework.go

+3
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ func (f *Framework) BeforeEach() {
248248
ginkgo.By("Waiting for a default service account to be provisioned in namespace")
249249
err = WaitForDefaultServiceAccountInNamespace(f.ClientSet, namespace.Name)
250250
ExpectNoError(err)
251+
ginkgo.By("Waiting for kube-root-ca.crt to be provisioned in namespace")
252+
err = WaitForKubeRootCAInNamespace(f.ClientSet, namespace.Name)
253+
ExpectNoError(err)
251254
} else {
252255
Logf("Skipping waiting for service account")
253256
}

test/e2e/framework/util.go

+42-15
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,32 @@ func WaitForNamespacesDeleted(c clientset.Interface, namespaces []string, timeou
282282
})
283283
}
284284

285+
func waitForConfigMapInNamespace(c clientset.Interface, ns, name string, timeout time.Duration) error {
286+
fieldSelector := fields.OneTermEqualSelector("metadata.name", name).String()
287+
lw := &cache.ListWatch{
288+
ListFunc: func(options metav1.ListOptions) (object runtime.Object, e error) {
289+
options.FieldSelector = fieldSelector
290+
return c.CoreV1().ConfigMaps(ns).List(context.TODO(), options)
291+
},
292+
WatchFunc: func(options metav1.ListOptions) (i watch.Interface, e error) {
293+
options.FieldSelector = fieldSelector
294+
return c.CoreV1().ConfigMaps(ns).Watch(context.TODO(), options)
295+
},
296+
}
297+
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout)
298+
defer cancel()
299+
_, err := watchtools.UntilWithSync(ctx, lw, &v1.ConfigMap{}, nil, func(event watch.Event) (bool, error) {
300+
switch event.Type {
301+
case watch.Deleted:
302+
return false, apierrors.NewNotFound(schema.GroupResource{Resource: "configmaps"}, name)
303+
case watch.Added, watch.Modified:
304+
return true, nil
305+
}
306+
return false, nil
307+
})
308+
return err
309+
}
310+
285311
func waitForServiceAccountInNamespace(c clientset.Interface, ns, serviceAccountName string, timeout time.Duration) error {
286312
fieldSelector := fields.OneTermEqualSelector("metadata.name", serviceAccountName).String()
287313
lw := &cache.ListWatch{
@@ -296,31 +322,32 @@ func waitForServiceAccountInNamespace(c clientset.Interface, ns, serviceAccountN
296322
}
297323
ctx, cancel := watchtools.ContextWithOptionalTimeout(context.Background(), timeout)
298324
defer cancel()
299-
_, err := watchtools.UntilWithSync(ctx, lw, &v1.ServiceAccount{}, nil, serviceAccountHasSecrets)
325+
_, err := watchtools.UntilWithSync(ctx, lw, &v1.ServiceAccount{}, nil, func(event watch.Event) (bool, error) {
326+
switch event.Type {
327+
case watch.Deleted:
328+
return false, apierrors.NewNotFound(schema.GroupResource{Resource: "serviceaccounts"}, serviceAccountName)
329+
case watch.Added, watch.Modified:
330+
return true, nil
331+
}
332+
return false, nil
333+
})
300334
return err
301335
}
302336

303-
// serviceAccountHasSecrets returns true if the service account has at least one secret,
304-
// false if it does not, or an error.
305-
func serviceAccountHasSecrets(event watch.Event) (bool, error) {
306-
switch event.Type {
307-
case watch.Deleted:
308-
return false, apierrors.NewNotFound(schema.GroupResource{Resource: "serviceaccounts"}, "")
309-
}
310-
switch t := event.Object.(type) {
311-
case *v1.ServiceAccount:
312-
return len(t.Secrets) > 0, nil
313-
}
314-
return false, nil
315-
}
316-
317337
// WaitForDefaultServiceAccountInNamespace waits for the default service account to be provisioned
318338
// the default service account is what is associated with pods when they do not specify a service account
319339
// as a result, pods are not able to be provisioned in a namespace until the service account is provisioned
320340
func WaitForDefaultServiceAccountInNamespace(c clientset.Interface, namespace string) error {
321341
return waitForServiceAccountInNamespace(c, namespace, "default", ServiceAccountProvisionTimeout)
322342
}
323343

344+
// WaitForKubeRootCAInNamespace waits for the configmap kube-root-ca.crt containing the service account
345+
// CA trust bundle to be provisioned in the specified namespace so that pods do not have to retry mounting
346+
// the config map (which creates noise that hides other issues in the Kubelet).
347+
func WaitForKubeRootCAInNamespace(c clientset.Interface, namespace string) error {
348+
return waitForConfigMapInNamespace(c, namespace, "kube-root-ca.crt", ServiceAccountProvisionTimeout)
349+
}
350+
324351
// CreateTestingNS should be used by every test, note that we append a common prefix to the provided test name.
325352
// Please see NewFramework instead of using this directly.
326353
func CreateTestingNS(baseName string, c clientset.Interface, labels map[string]string) (*v1.Namespace, error) {

0 commit comments

Comments
 (0)