Skip to content

Commit d1c78ee

Browse files
committed
test(catalog): add registry pod delete e2e test
1 parent ddefc0e commit d1c78ee

File tree

2 files changed

+146
-16
lines changed

2 files changed

+146
-16
lines changed

test/e2e/catalog_e2e_test.go

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,15 @@ func TestConfigMapUpdateTriggersRegistryPodRollout(t *testing.T) {
184184
require.Equal(t, updatedConfigMap.GetResourceVersion(), fetchedUpdatedCatalog.Status.ConfigMapResource.ResourceVersion)
185185

186186
// Await 1 CatalogSource registry pod matching the updated labels
187+
singlePod := podCount(1)
187188
selector := labels.SelectorFromSet(map[string]string{"olm.catalogSource": mainCatalogName, "olm.configMapResourceVersion": updatedConfigMap.GetResourceVersion()})
188-
podList, err := awaitPods(t, c, selector.String(), 1)
189+
podList, err := awaitPods(t, c, testNamespace, selector.String(), singlePod)
189190
require.NoError(t, err)
190191
require.Equal(t, 1, len(podList.Items), "expected pod list not of length 1")
191192

192193
// Await 1 CatalogSource registry pod matching the updated labels
193194
selector = labels.SelectorFromSet(map[string]string{"olm.catalogSource": mainCatalogName})
194-
podList, err = awaitPods(t, c, selector.String(), 1)
195+
podList, err = awaitPods(t, c, testNamespace, selector.String(), singlePod)
195196
require.NoError(t, err)
196197
require.Equal(t, 1, len(podList.Items), "expected pod list not of length 1")
197198

@@ -377,9 +378,9 @@ func TestGrpcAddressCatalogSource(t *testing.T) {
377378

378379
// Replicate catalog pods with no OwnerReferences
379380
mainCopy := replicateCatalogPod(t, c, crc, mainSource)
380-
mainCopy = awaitPod(t, c, mainCopy.GetNamespace(), mainCopy.GetName(), HasPodIP)
381+
mainCopy = awaitPod(t, c, mainCopy.GetNamespace(), mainCopy.GetName(), hasPodIP)
381382
replacementCopy := replicateCatalogPod(t, c, crc, replacementSource)
382-
replacementCopy = awaitPod(t, c, replacementCopy.GetNamespace(), replacementCopy.GetName(), HasPodIP)
383+
replacementCopy = awaitPod(t, c, replacementCopy.GetNamespace(), replacementCopy.GetName(), hasPodIP)
383384

384385
addressSourceName := genName("address-catalog-")
385386

@@ -435,6 +436,86 @@ func TestGrpcAddressCatalogSource(t *testing.T) {
435436
require.NoError(t, err)
436437
}
437438

439+
func TestDeleteRegistryPodTriggersRecreation(t *testing.T) {
440+
// Create internal CatalogSource containing csv in package
441+
// Wait for a registry pod to be created
442+
// Create a Subscription for package
443+
// Wait for the Subscription to succeed
444+
// Wait for csv to succeed
445+
// Delete the registry pod
446+
// Wait for a new registry pod to be created
447+
448+
defer cleaner.NotifyTestComplete(t, true)
449+
450+
// Create internal CatalogSource containing csv in package
451+
packageName := genName("nginx-")
452+
packageStable := fmt.Sprintf("%s-stable", packageName)
453+
stableChannel := "stable"
454+
namedStrategy := newNginxInstallStrategy(genName("dep-"), nil, nil)
455+
catalogName := genName("catsrc-")
456+
crd := newCRD(genName("ins-"))
457+
csv := newCSV(packageStable, testNamespace, "", *semver.New("0.1.0"), []apiextensions.CustomResourceDefinition{crd}, nil, namedStrategy)
458+
manifests := []registry.PackageManifest{
459+
{
460+
PackageName: packageName,
461+
Channels: []registry.PackageChannel{
462+
{Name: stableChannel, CurrentCSVName: packageStable},
463+
},
464+
DefaultChannelName: stableChannel,
465+
},
466+
}
467+
468+
c := newKubeClient(t)
469+
crc := newCRClient(t)
470+
_, cleanupCatalog := createInternalCatalogSource(t, c, crc, catalogName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csv})
471+
defer cleanupCatalog()
472+
473+
// Wait for a new registry pod to be created
474+
selector := labels.SelectorFromSet(map[string]string{"olm.catalogSource": catalogName})
475+
singlePod := podCount(1)
476+
registryPods, err := awaitPods(t, c, testNamespace, selector.String(), singlePod)
477+
require.NoError(t, err, "error awaiting registry pod")
478+
require.NotNil(t, registryPods, "nil registry pods")
479+
require.Equal(t, 1, len(registryPods.Items), "unexpected number of registry pods found")
480+
481+
// Store the UID for later comparison
482+
uid := registryPods.Items[0].GetUID()
483+
name := registryPods.Items[0].GetName()
484+
485+
// Create a Subscription for package
486+
subscriptionName := genName("sub-")
487+
cleanupSubscription := createSubscriptionForCatalog(t, crc, testNamespace, subscriptionName, catalogName, packageName, stableChannel, "", v1alpha1.ApprovalAutomatic)
488+
defer cleanupSubscription()
489+
490+
// Wait for the Subscription to succeed
491+
subscription, err := fetchSubscription(t, crc, testNamespace, subscriptionName, subscriptionStateAtLatestChecker)
492+
require.NoError(t, err)
493+
require.NotNil(t, subscription)
494+
495+
// Wait for csv to succeed
496+
_, err = fetchCSV(t, crc, subscription.Status.CurrentCSV, testNamespace, csvSucceededChecker)
497+
require.NoError(t, err)
498+
499+
// Delete the registry pod
500+
err = c.KubernetesInterface().CoreV1().Pods(testNamespace).Delete(name, &metav1.DeleteOptions{})
501+
require.NoError(t, err)
502+
503+
// Wait for a new registry pod to be created
504+
notUID := func(pods *corev1.PodList) bool {
505+
for _, pod := range pods.Items {
506+
if pod.GetUID() == uid {
507+
return false
508+
}
509+
}
510+
511+
return true
512+
}
513+
registryPods, err = awaitPods(t, c, testNamespace, selector.String(), unionPodsCheck(singlePod, notUID))
514+
require.NoError(t, err, "error waiting for replacement registry pod")
515+
require.NotNil(t, registryPods, "nil replacement registry pods")
516+
require.Equal(t, 1, len(registryPods.Items), "unexpected number of replacement registry pods found")
517+
}
518+
438519
func getOperatorDeployment(c operatorclient.ClientInterface, namespace string, operatorLabels labels.Set) (*appsv1.Deployment, error) {
439520
deployments, err := c.ListDeploymentsWithLabels(namespace, operatorLabels)
440521
if err != nil || deployments == nil || len(deployments.Items) != 1 {

test/e2e/util_test.go

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,47 +115,96 @@ func newPMClient(t *testing.T) pmversioned.Interface {
115115
}
116116

117117
// awaitPods waits for a set of pods to exist in the cluster
118-
func awaitPods(t *testing.T, c operatorclient.ClientInterface, selector string, expectedCount int) (*corev1.PodList, error) {
118+
func awaitPods(t *testing.T, c operatorclient.ClientInterface, namespace, selector string, checkPods podsCheckFunc) (*corev1.PodList, error) {
119119
var fetchedPodList *corev1.PodList
120120
var err error
121121

122122
err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
123-
fetchedPodList, err = c.KubernetesInterface().CoreV1().Pods(testNamespace).List(metav1.ListOptions{
123+
fetchedPodList, err = c.KubernetesInterface().CoreV1().Pods(namespace).List(metav1.ListOptions{
124124
LabelSelector: selector,
125125
})
126126

127127
if err != nil {
128128
return false, err
129129
}
130130

131-
t.Logf("Waiting for %d nodes matching %s selector, %d present", expectedCount, selector, len(fetchedPodList.Items))
131+
t.Logf("Waiting for pods matching selector %s to match given conditions", selector)
132132

133-
if len(fetchedPodList.Items) < expectedCount {
134-
return false, nil
135-
}
136-
137-
return true, nil
133+
return checkPods(fetchedPodList), nil
138134
})
139135

140136
require.NoError(t, err)
141137
return fetchedPodList, err
142138
}
143139

144-
type PodCheckFunc func(pod *corev1.Pod) bool
140+
// podsCheckFunc describes a function that true if the given PodList meets some criteria; false otherwise.
141+
type podsCheckFunc func(pods *corev1.PodList) bool
142+
143+
// unionPodsCheck returns a podsCheckFunc that represents the union of the given podsCheckFuncs.
144+
func unionPodsCheck(checks ...podsCheckFunc) podsCheckFunc {
145+
return func(pods *corev1.PodList) bool {
146+
for _, check := range checks {
147+
if !check(pods) {
148+
return false
149+
}
150+
}
151+
152+
return true
153+
}
154+
}
155+
156+
// podCount returns a podsCheckFunc that returns true if a PodList is of length count; false otherwise.
157+
func podCount(count int) podsCheckFunc {
158+
return func(pods *corev1.PodList) bool {
159+
return len(pods.Items) == count
160+
}
161+
}
145162

146-
func HasPodIP(pod *corev1.Pod) bool {
163+
// podsReady returns true if all of the pods in the given PodList have a ready condition with ConditionStatus "True"; false otherwise.
164+
func podsReady(pods *corev1.PodList) bool {
165+
for _, pod := range pods.Items {
166+
if !podReady(&pod) {
167+
return false
168+
}
169+
}
170+
171+
return true
172+
}
173+
174+
// podCheckFunc describes a function that returns true if the given Pod meets some criteria; false otherwise.
175+
type podCheckFunc func(pod *corev1.Pod) bool
176+
177+
// hasPodIP returns true if the given Pod has a PodIP.
178+
func hasPodIP(pod *corev1.Pod) bool {
147179
return pod.Status.PodIP != ""
148180
}
149181

150-
func awaitPod(t *testing.T, c operatorclient.ClientInterface, namespace, name string, check PodCheckFunc) *corev1.Pod {
182+
// podReady returns true if the given Pod has a ready condition with ConditionStatus "True"; false otherwise.
183+
func podReady(pod *corev1.Pod) bool {
184+
var status corev1.ConditionStatus
185+
for _, condition := range pod.Status.Conditions {
186+
if condition.Type != corev1.PodReady {
187+
// Ignore all condition other than PodReady
188+
continue
189+
}
190+
191+
// Found PodReady condition
192+
status = condition.Status
193+
break
194+
}
195+
196+
return status == corev1.ConditionTrue
197+
}
198+
199+
func awaitPod(t *testing.T, c operatorclient.ClientInterface, namespace, name string, checkPod podCheckFunc) *corev1.Pod {
151200
var pod *corev1.Pod
152201
err := wait.Poll(pollInterval, pollDuration, func() (bool, error) {
153202
p, err := c.KubernetesInterface().CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
154203
if err != nil {
155204
return false, err
156205
}
157206
pod = p
158-
return check(pod), nil
207+
return checkPod(pod), nil
159208
})
160209
require.NoError(t, err)
161210

0 commit comments

Comments
 (0)