Skip to content

Commit 5837a4b

Browse files
committed
test(catalog): add tests for catalog reconciliation
1 parent 0422b14 commit 5837a4b

File tree

3 files changed

+198
-58
lines changed

3 files changed

+198
-58
lines changed

pkg/controller/operators/catalog/operator_test.go

Lines changed: 196 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func TestExecutePlan(t *testing.T) {
138138
testName: "MultipleSteps",
139139
in: withSteps(installPlan("p", namespace, v1alpha1.InstallPlanPhaseInstalling, "csv"),
140140
[]*v1alpha1.Step{
141-
&v1alpha1.Step{
141+
{
142142
Resource: v1alpha1.StepResource{
143143
CatalogSource: "catalog",
144144
CatalogSourceNamespace: namespace,
@@ -150,7 +150,7 @@ func TestExecutePlan(t *testing.T) {
150150
},
151151
Status: v1alpha1.StepStatusUnknown,
152152
},
153-
&v1alpha1.Step{
153+
{
154154
Resource: v1alpha1.StepResource{
155155
CatalogSource: "catalog",
156156
CatalogSourceNamespace: namespace,
@@ -211,12 +211,39 @@ func TestExecutePlan(t *testing.T) {
211211
}
212212

213213
func TestSyncCatalogSources(t *testing.T) {
214+
nowTime := metav1.Date(2018, time.January, 26, 20, 40, 0, 0, time.UTC)
215+
timeNow = func() metav1.Time { return nowTime }
216+
217+
configmapCatalog := &v1alpha1.CatalogSource{
218+
ObjectMeta: metav1.ObjectMeta{
219+
Name: "cool-catalog",
220+
Namespace: "cool-namespace",
221+
UID: types.UID("catalog-uid"),
222+
},
223+
Spec: v1alpha1.CatalogSourceSpec{
224+
ConfigMap: "cool-configmap",
225+
SourceType: v1alpha1.SourceTypeInternal,
226+
},
227+
}
228+
grpcCatalog := &v1alpha1.CatalogSource{
229+
ObjectMeta: metav1.ObjectMeta{
230+
Name: "cool-catalog",
231+
Namespace: "cool-namespace",
232+
UID: types.UID("catalog-uid"),
233+
},
234+
Spec: v1alpha1.CatalogSourceSpec{
235+
Image: "catalog-image",
236+
SourceType: v1alpha1.SourceTypeGrpc,
237+
},
238+
}
214239
tests := []struct {
215240
testName string
216241
namespace string
217242
catalogSource *v1alpha1.CatalogSource
243+
k8sObjs []runtime.Object
218244
configMap *corev1.ConfigMap
219245
expectedStatus *v1alpha1.CatalogSourceStatus
246+
expectedObjs []runtime.Object
220247
expectedError error
221248
}{
222249
{
@@ -233,40 +260,34 @@ func TestSyncCatalogSources(t *testing.T) {
233260
SourceType: "nope",
234261
},
235262
},
236-
configMap: &corev1.ConfigMap{
237-
ObjectMeta: metav1.ObjectMeta{
238-
Name: "cool-configmap",
239-
Namespace: "cool-namespace",
240-
UID: types.UID("configmap-uid"),
241-
ResourceVersion: "resource-version",
263+
k8sObjs: []runtime.Object{
264+
&corev1.ConfigMap{
265+
ObjectMeta: metav1.ObjectMeta{
266+
Name: "cool-configmap",
267+
Namespace: "cool-namespace",
268+
UID: types.UID("configmap-uid"),
269+
ResourceVersion: "resource-version",
270+
},
271+
Data: fakeConfigMapData(),
242272
},
243-
Data: fakeConfigMapData(),
244273
},
245274
expectedStatus: nil,
246275
expectedError: fmt.Errorf("no reconciler for source type nope"),
247276
},
248277
{
249-
testName: "CatalogSourceWithBackingConfigMap",
250-
namespace: "cool-namespace",
251-
catalogSource: &v1alpha1.CatalogSource{
252-
ObjectMeta: metav1.ObjectMeta{
253-
Name: "cool-catalog",
254-
Namespace: "cool-namespace",
255-
UID: types.UID("catalog-uid"),
256-
},
257-
Spec: v1alpha1.CatalogSourceSpec{
258-
ConfigMap: "cool-configmap",
259-
SourceType: v1alpha1.SourceTypeInternal,
260-
},
261-
},
262-
configMap: &corev1.ConfigMap{
263-
ObjectMeta: metav1.ObjectMeta{
264-
Name: "cool-configmap",
265-
Namespace: "cool-namespace",
266-
UID: types.UID("configmap-uid"),
267-
ResourceVersion: "resource-version",
278+
testName: "CatalogSourceWithBackingConfigMap",
279+
namespace: "cool-namespace",
280+
catalogSource: configmapCatalog,
281+
k8sObjs: []runtime.Object{
282+
&corev1.ConfigMap{
283+
ObjectMeta: metav1.ObjectMeta{
284+
Name: "cool-configmap",
285+
Namespace: "cool-namespace",
286+
UID: types.UID("configmap-uid"),
287+
ResourceVersion: "resource-version",
288+
},
289+
Data: fakeConfigMapData(),
268290
},
269-
Data: fakeConfigMapData(),
270291
},
271292
expectedStatus: &v1alpha1.CatalogSourceStatus{
272293
ConfigMapResource: &v1alpha1.ConfigMapResourceReference{
@@ -276,6 +297,7 @@ func TestSyncCatalogSources(t *testing.T) {
276297
ResourceVersion: "resource-version",
277298
},
278299
RegistryServiceStatus: nil,
300+
LastSync: timeNow(),
279301
},
280302
expectedError: nil,
281303
},
@@ -300,16 +322,19 @@ func TestSyncCatalogSources(t *testing.T) {
300322
ResourceVersion: "resource-version",
301323
},
302324
RegistryServiceStatus: nil,
325+
LastSync: timeNow(),
303326
},
304327
},
305-
configMap: &corev1.ConfigMap{
306-
ObjectMeta: metav1.ObjectMeta{
307-
Name: "cool-configmap",
308-
Namespace: "cool-namespace",
309-
UID: types.UID("configmap-uid"),
310-
ResourceVersion: "resource-version",
328+
k8sObjs: []runtime.Object{
329+
&corev1.ConfigMap{
330+
ObjectMeta: metav1.ObjectMeta{
331+
Name: "cool-configmap",
332+
Namespace: "cool-namespace",
333+
UID: types.UID("configmap-uid"),
334+
ResourceVersion: "resource-version",
335+
},
336+
Data: fakeConfigMapData(),
311337
},
312-
Data: fakeConfigMapData(),
313338
},
314339
expectedStatus: &v1alpha1.CatalogSourceStatus{
315340
ConfigMapResource: &v1alpha1.ConfigMapResourceReference{
@@ -318,39 +343,89 @@ func TestSyncCatalogSources(t *testing.T) {
318343
UID: types.UID("configmap-uid"),
319344
ResourceVersion: "resource-version",
320345
},
321-
RegistryServiceStatus: nil,
346+
RegistryServiceStatus: &v1alpha1.RegistryServiceStatus{
347+
Protocol: "grpc",
348+
ServiceName: "cool-catalog",
349+
ServiceNamespace: "cool-namespace",
350+
Port: "50051",
351+
CreatedAt: timeNow(),
352+
},
353+
LastSync: timeNow(),
322354
},
323355
expectedError: nil,
324356
},
325357
{
326-
testName: "CatalogSourceWithMissingConfigMap",
327-
namespace: "cool-namespace",
328-
catalogSource: &v1alpha1.CatalogSource{
329-
ObjectMeta: metav1.ObjectMeta{
330-
Name: "cool-catalog",
331-
Namespace: "cool-namespace",
332-
UID: types.UID("catalog-uid"),
333-
},
334-
Spec: v1alpha1.CatalogSourceSpec{
335-
ConfigMap: "cool-configmap",
336-
SourceType: v1alpha1.SourceTypeConfigmap,
337-
},
358+
testName: "CatalogSourceWithMissingConfigMap",
359+
namespace: "cool-namespace",
360+
catalogSource: configmapCatalog,
361+
k8sObjs: []runtime.Object{
362+
&corev1.ConfigMap{},
338363
},
339-
configMap: &corev1.ConfigMap{},
340364
expectedStatus: nil,
341365
expectedError: errors.New("failed to get catalog config map cool-configmap: configmap \"cool-configmap\" not found"),
342366
},
367+
{
368+
testName: "CatalogSourceWithGrpcImage",
369+
namespace: "cool-namespace",
370+
catalogSource: grpcCatalog,
371+
expectedStatus: &v1alpha1.CatalogSourceStatus{
372+
RegistryServiceStatus: &v1alpha1.RegistryServiceStatus{
373+
Protocol: "grpc",
374+
ServiceName: "cool-catalog",
375+
ServiceNamespace: "cool-namespace",
376+
Port: "50051",
377+
CreatedAt: timeNow(),
378+
},
379+
LastSync: timeNow(),
380+
},
381+
expectedError: nil,
382+
expectedObjs: []runtime.Object{
383+
pod(*grpcCatalog),
384+
},
385+
},
386+
{
387+
testName: "CatalogSourceWithGrpcImage/EnsuresCorrectImage",
388+
namespace: "cool-namespace",
389+
catalogSource: grpcCatalog,
390+
k8sObjs: []runtime.Object{
391+
pod(v1alpha1.CatalogSource{
392+
ObjectMeta: metav1.ObjectMeta{
393+
Name: "cool-catalog",
394+
Namespace: "cool-namespace",
395+
UID: types.UID("catalog-uid"),
396+
},
397+
Spec: v1alpha1.CatalogSourceSpec{
398+
Image: "old-image",
399+
SourceType: v1alpha1.SourceTypeGrpc,
400+
},
401+
}),
402+
},
403+
expectedStatus: &v1alpha1.CatalogSourceStatus{
404+
RegistryServiceStatus: &v1alpha1.RegistryServiceStatus{
405+
Protocol: "grpc",
406+
ServiceName: "cool-catalog",
407+
ServiceNamespace: "cool-namespace",
408+
Port: "50051",
409+
CreatedAt: timeNow(),
410+
},
411+
LastSync: timeNow(),
412+
},
413+
expectedError: nil,
414+
expectedObjs: []runtime.Object{
415+
pod(*grpcCatalog),
416+
},
417+
},
343418
}
344419
for _, tt := range tests {
345420
t.Run(tt.testName, func(t *testing.T) {
346421
// Create existing objects
347422
clientObjs := []runtime.Object{tt.catalogSource}
348-
k8sObjs := []runtime.Object{tt.configMap}
349423

350424
// Create test operator
351425
stopCh := make(chan struct{})
352426
defer func() { stopCh <- struct{}{} }()
353-
op, err := NewFakeOperator(tt.namespace, []string{tt.namespace}, stopCh, withClientObjs(clientObjs...), withK8sObjs(k8sObjs...))
427+
428+
op, err := NewFakeOperator(tt.namespace, []string{tt.namespace}, stopCh, withClientObjs(clientObjs...), withK8sObjs(tt.k8sObjs...))
354429
require.NoError(t, err)
355430

356431
// Run sync
@@ -368,11 +443,27 @@ func TestSyncCatalogSources(t *testing.T) {
368443

369444
if tt.expectedStatus != nil {
370445
require.NotEmpty(t, updated.Status)
371-
require.Equal(t, *tt.expectedStatus.ConfigMapResource, *updated.Status.ConfigMapResource)
446+
require.Equal(t, *tt.expectedStatus, updated.Status)
372447

373-
configMap, err := op.OpClient.KubernetesInterface().CoreV1().ConfigMaps(tt.catalogSource.GetNamespace()).Get(tt.catalogSource.Spec.ConfigMap, metav1.GetOptions{})
374-
require.NoError(t, err)
375-
require.True(t, ownerutil.EnsureOwner(configMap, updated))
448+
if tt.catalogSource.Spec.ConfigMap != "" {
449+
configMap, err := op.OpClient.KubernetesInterface().CoreV1().ConfigMaps(tt.catalogSource.GetNamespace()).Get(tt.catalogSource.Spec.ConfigMap, metav1.GetOptions{})
450+
require.NoError(t, err)
451+
require.True(t, ownerutil.EnsureOwner(configMap, updated))
452+
}
453+
}
454+
455+
for _, o := range tt.expectedObjs {
456+
switch o.(type) {
457+
case *corev1.Pod:
458+
t.Log("verifying pod")
459+
pods, err := op.OpClient.KubernetesInterface().CoreV1().Pods(tt.catalogSource.Namespace).List(metav1.ListOptions{})
460+
require.NoError(t, err)
461+
require.Len(t, pods.Items, 1)
462+
463+
// set the name to the generated name
464+
o.(*corev1.Pod).SetName(pods.Items[0].GetName())
465+
require.EqualValues(t, o, &pods.Items[0])
466+
}
376467
}
377468
})
378469
}
@@ -670,3 +761,52 @@ func toManifest(obj runtime.Object) string {
670761
raw, _ := json.Marshal(obj)
671762
return string(raw)
672763
}
764+
765+
func pod(s v1alpha1.CatalogSource) *corev1.Pod {
766+
pod := &corev1.Pod{
767+
ObjectMeta: metav1.ObjectMeta{
768+
GenerateName: s.GetName() + "-",
769+
Namespace: s.GetNamespace(),
770+
Labels: map[string]string{
771+
"olm.catalogSource": s.GetName(),
772+
},
773+
},
774+
Spec: corev1.PodSpec{
775+
Containers: []corev1.Container{
776+
{
777+
Name: "registry-server",
778+
Image: s.Spec.Image,
779+
Ports: []corev1.ContainerPort{
780+
{
781+
Name: "grpc",
782+
ContainerPort: 50051,
783+
},
784+
},
785+
ReadinessProbe: &corev1.Probe{
786+
Handler: corev1.Handler{
787+
Exec: &corev1.ExecAction{
788+
Command: []string{"grpc_health_probe", "-addr=localhost:50051"},
789+
},
790+
},
791+
InitialDelaySeconds: 5,
792+
},
793+
LivenessProbe: &corev1.Probe{
794+
Handler: corev1.Handler{
795+
Exec: &corev1.ExecAction{
796+
Command: []string{"grpc_health_probe", "-addr=localhost:50051"},
797+
},
798+
},
799+
InitialDelaySeconds: 10,
800+
},
801+
},
802+
},
803+
Tolerations: []corev1.Toleration{
804+
{
805+
Operator: corev1.TolerationOpExists,
806+
},
807+
},
808+
},
809+
}
810+
ownerutil.AddOwner(pod, &s, false, false)
811+
return pod
812+
}

pkg/controller/operators/olm/operator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
11131113
case v1alpha1.CSVPhaseDeleting:
11141114
var immediate int64 = 0
11151115

1116-
if err := a.csvQueueSet.Remove(out.GetNamespace(), out.GetName()); err != nil {
1116+
if err := a.csvQueueSet.Remove(out.GetName(), out.GetNamespace()); err != nil {
11171117
logger.WithError(err).Debug("error removing from queue")
11181118
}
11191119
syncError = a.client.OperatorsV1alpha1().ClusterServiceVersions(out.GetNamespace()).Delete(out.GetName(), &metav1.DeleteOptions{GracePeriodSeconds: &immediate})

test/e2e/installplan_e2e_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ EXPECTED:
337337
require.NoError(t, err)
338338
require.NotNil(t, dependentSubscription)
339339
require.NotNil(t, dependentSubscription.Status.InstallPlanRef)
340-
require.Equal(t, v1alpha1.SubscriptionState("AtLatestKnown"), dependentSubscription.Status.State)
340+
require.Equal(t, "AtLatestKnown", string(dependentSubscription.Status.State))
341341
require.Equal(t, dependentCSV.GetName(), dependentSubscription.Status.CurrentCSV)
342342

343343
// TODO: update dependent subscription in catalog and wait for csv to update

0 commit comments

Comments
 (0)