Skip to content

Commit

Permalink
test(catalog): add tests for catalog reconciliation
Browse files Browse the repository at this point in the history
  • Loading branch information
ecordell committed May 3, 2019
1 parent 0422b14 commit 5837a4b
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 58 deletions.
252 changes: 196 additions & 56 deletions pkg/controller/operators/catalog/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func TestExecutePlan(t *testing.T) {
testName: "MultipleSteps",
in: withSteps(installPlan("p", namespace, v1alpha1.InstallPlanPhaseInstalling, "csv"),
[]*v1alpha1.Step{
&v1alpha1.Step{
{
Resource: v1alpha1.StepResource{
CatalogSource: "catalog",
CatalogSourceNamespace: namespace,
Expand All @@ -150,7 +150,7 @@ func TestExecutePlan(t *testing.T) {
},
Status: v1alpha1.StepStatusUnknown,
},
&v1alpha1.Step{
{
Resource: v1alpha1.StepResource{
CatalogSource: "catalog",
CatalogSourceNamespace: namespace,
Expand Down Expand Up @@ -211,12 +211,39 @@ func TestExecutePlan(t *testing.T) {
}

func TestSyncCatalogSources(t *testing.T) {
nowTime := metav1.Date(2018, time.January, 26, 20, 40, 0, 0, time.UTC)
timeNow = func() metav1.Time { return nowTime }

configmapCatalog := &v1alpha1.CatalogSource{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-catalog",
Namespace: "cool-namespace",
UID: types.UID("catalog-uid"),
},
Spec: v1alpha1.CatalogSourceSpec{
ConfigMap: "cool-configmap",
SourceType: v1alpha1.SourceTypeInternal,
},
}
grpcCatalog := &v1alpha1.CatalogSource{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-catalog",
Namespace: "cool-namespace",
UID: types.UID("catalog-uid"),
},
Spec: v1alpha1.CatalogSourceSpec{
Image: "catalog-image",
SourceType: v1alpha1.SourceTypeGrpc,
},
}
tests := []struct {
testName string
namespace string
catalogSource *v1alpha1.CatalogSource
k8sObjs []runtime.Object
configMap *corev1.ConfigMap
expectedStatus *v1alpha1.CatalogSourceStatus
expectedObjs []runtime.Object
expectedError error
}{
{
Expand All @@ -233,40 +260,34 @@ func TestSyncCatalogSources(t *testing.T) {
SourceType: "nope",
},
},
configMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-configmap",
Namespace: "cool-namespace",
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
k8sObjs: []runtime.Object{
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-configmap",
Namespace: "cool-namespace",
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
},
Data: fakeConfigMapData(),
},
Data: fakeConfigMapData(),
},
expectedStatus: nil,
expectedError: fmt.Errorf("no reconciler for source type nope"),
},
{
testName: "CatalogSourceWithBackingConfigMap",
namespace: "cool-namespace",
catalogSource: &v1alpha1.CatalogSource{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-catalog",
Namespace: "cool-namespace",
UID: types.UID("catalog-uid"),
},
Spec: v1alpha1.CatalogSourceSpec{
ConfigMap: "cool-configmap",
SourceType: v1alpha1.SourceTypeInternal,
},
},
configMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-configmap",
Namespace: "cool-namespace",
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
testName: "CatalogSourceWithBackingConfigMap",
namespace: "cool-namespace",
catalogSource: configmapCatalog,
k8sObjs: []runtime.Object{
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-configmap",
Namespace: "cool-namespace",
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
},
Data: fakeConfigMapData(),
},
Data: fakeConfigMapData(),
},
expectedStatus: &v1alpha1.CatalogSourceStatus{
ConfigMapResource: &v1alpha1.ConfigMapResourceReference{
Expand All @@ -276,6 +297,7 @@ func TestSyncCatalogSources(t *testing.T) {
ResourceVersion: "resource-version",
},
RegistryServiceStatus: nil,
LastSync: timeNow(),
},
expectedError: nil,
},
Expand All @@ -300,16 +322,19 @@ func TestSyncCatalogSources(t *testing.T) {
ResourceVersion: "resource-version",
},
RegistryServiceStatus: nil,
LastSync: timeNow(),
},
},
configMap: &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-configmap",
Namespace: "cool-namespace",
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
k8sObjs: []runtime.Object{
&corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-configmap",
Namespace: "cool-namespace",
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
},
Data: fakeConfigMapData(),
},
Data: fakeConfigMapData(),
},
expectedStatus: &v1alpha1.CatalogSourceStatus{
ConfigMapResource: &v1alpha1.ConfigMapResourceReference{
Expand All @@ -318,39 +343,89 @@ func TestSyncCatalogSources(t *testing.T) {
UID: types.UID("configmap-uid"),
ResourceVersion: "resource-version",
},
RegistryServiceStatus: nil,
RegistryServiceStatus: &v1alpha1.RegistryServiceStatus{
Protocol: "grpc",
ServiceName: "cool-catalog",
ServiceNamespace: "cool-namespace",
Port: "50051",
CreatedAt: timeNow(),
},
LastSync: timeNow(),
},
expectedError: nil,
},
{
testName: "CatalogSourceWithMissingConfigMap",
namespace: "cool-namespace",
catalogSource: &v1alpha1.CatalogSource{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-catalog",
Namespace: "cool-namespace",
UID: types.UID("catalog-uid"),
},
Spec: v1alpha1.CatalogSourceSpec{
ConfigMap: "cool-configmap",
SourceType: v1alpha1.SourceTypeConfigmap,
},
testName: "CatalogSourceWithMissingConfigMap",
namespace: "cool-namespace",
catalogSource: configmapCatalog,
k8sObjs: []runtime.Object{
&corev1.ConfigMap{},
},
configMap: &corev1.ConfigMap{},
expectedStatus: nil,
expectedError: errors.New("failed to get catalog config map cool-configmap: configmap \"cool-configmap\" not found"),
},
{
testName: "CatalogSourceWithGrpcImage",
namespace: "cool-namespace",
catalogSource: grpcCatalog,
expectedStatus: &v1alpha1.CatalogSourceStatus{
RegistryServiceStatus: &v1alpha1.RegistryServiceStatus{
Protocol: "grpc",
ServiceName: "cool-catalog",
ServiceNamespace: "cool-namespace",
Port: "50051",
CreatedAt: timeNow(),
},
LastSync: timeNow(),
},
expectedError: nil,
expectedObjs: []runtime.Object{
pod(*grpcCatalog),
},
},
{
testName: "CatalogSourceWithGrpcImage/EnsuresCorrectImage",
namespace: "cool-namespace",
catalogSource: grpcCatalog,
k8sObjs: []runtime.Object{
pod(v1alpha1.CatalogSource{
ObjectMeta: metav1.ObjectMeta{
Name: "cool-catalog",
Namespace: "cool-namespace",
UID: types.UID("catalog-uid"),
},
Spec: v1alpha1.CatalogSourceSpec{
Image: "old-image",
SourceType: v1alpha1.SourceTypeGrpc,
},
}),
},
expectedStatus: &v1alpha1.CatalogSourceStatus{
RegistryServiceStatus: &v1alpha1.RegistryServiceStatus{
Protocol: "grpc",
ServiceName: "cool-catalog",
ServiceNamespace: "cool-namespace",
Port: "50051",
CreatedAt: timeNow(),
},
LastSync: timeNow(),
},
expectedError: nil,
expectedObjs: []runtime.Object{
pod(*grpcCatalog),
},
},
}
for _, tt := range tests {
t.Run(tt.testName, func(t *testing.T) {
// Create existing objects
clientObjs := []runtime.Object{tt.catalogSource}
k8sObjs := []runtime.Object{tt.configMap}

// Create test operator
stopCh := make(chan struct{})
defer func() { stopCh <- struct{}{} }()
op, err := NewFakeOperator(tt.namespace, []string{tt.namespace}, stopCh, withClientObjs(clientObjs...), withK8sObjs(k8sObjs...))

op, err := NewFakeOperator(tt.namespace, []string{tt.namespace}, stopCh, withClientObjs(clientObjs...), withK8sObjs(tt.k8sObjs...))
require.NoError(t, err)

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

if tt.expectedStatus != nil {
require.NotEmpty(t, updated.Status)
require.Equal(t, *tt.expectedStatus.ConfigMapResource, *updated.Status.ConfigMapResource)
require.Equal(t, *tt.expectedStatus, updated.Status)

configMap, err := op.OpClient.KubernetesInterface().CoreV1().ConfigMaps(tt.catalogSource.GetNamespace()).Get(tt.catalogSource.Spec.ConfigMap, metav1.GetOptions{})
require.NoError(t, err)
require.True(t, ownerutil.EnsureOwner(configMap, updated))
if tt.catalogSource.Spec.ConfigMap != "" {
configMap, err := op.OpClient.KubernetesInterface().CoreV1().ConfigMaps(tt.catalogSource.GetNamespace()).Get(tt.catalogSource.Spec.ConfigMap, metav1.GetOptions{})
require.NoError(t, err)
require.True(t, ownerutil.EnsureOwner(configMap, updated))
}
}

for _, o := range tt.expectedObjs {
switch o.(type) {
case *corev1.Pod:
t.Log("verifying pod")
pods, err := op.OpClient.KubernetesInterface().CoreV1().Pods(tt.catalogSource.Namespace).List(metav1.ListOptions{})
require.NoError(t, err)
require.Len(t, pods.Items, 1)

// set the name to the generated name
o.(*corev1.Pod).SetName(pods.Items[0].GetName())
require.EqualValues(t, o, &pods.Items[0])
}
}
})
}
Expand Down Expand Up @@ -670,3 +761,52 @@ func toManifest(obj runtime.Object) string {
raw, _ := json.Marshal(obj)
return string(raw)
}

func pod(s v1alpha1.CatalogSource) *corev1.Pod {
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
GenerateName: s.GetName() + "-",
Namespace: s.GetNamespace(),
Labels: map[string]string{
"olm.catalogSource": s.GetName(),
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "registry-server",
Image: s.Spec.Image,
Ports: []corev1.ContainerPort{
{
Name: "grpc",
ContainerPort: 50051,
},
},
ReadinessProbe: &corev1.Probe{
Handler: corev1.Handler{
Exec: &corev1.ExecAction{
Command: []string{"grpc_health_probe", "-addr=localhost:50051"},
},
},
InitialDelaySeconds: 5,
},
LivenessProbe: &corev1.Probe{
Handler: corev1.Handler{
Exec: &corev1.ExecAction{
Command: []string{"grpc_health_probe", "-addr=localhost:50051"},
},
},
InitialDelaySeconds: 10,
},
},
},
Tolerations: []corev1.Toleration{
{
Operator: corev1.TolerationOpExists,
},
},
},
}
ownerutil.AddOwner(pod, &s, false, false)
return pod
}
2 changes: 1 addition & 1 deletion pkg/controller/operators/olm/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
case v1alpha1.CSVPhaseDeleting:
var immediate int64 = 0

if err := a.csvQueueSet.Remove(out.GetNamespace(), out.GetName()); err != nil {
if err := a.csvQueueSet.Remove(out.GetName(), out.GetNamespace()); err != nil {
logger.WithError(err).Debug("error removing from queue")
}
syncError = a.client.OperatorsV1alpha1().ClusterServiceVersions(out.GetNamespace()).Delete(out.GetName(), &metav1.DeleteOptions{GracePeriodSeconds: &immediate})
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/installplan_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ EXPECTED:
require.NoError(t, err)
require.NotNil(t, dependentSubscription)
require.NotNil(t, dependentSubscription.Status.InstallPlanRef)
require.Equal(t, v1alpha1.SubscriptionState("AtLatestKnown"), dependentSubscription.Status.State)
require.Equal(t, "AtLatestKnown", string(dependentSubscription.Status.State))
require.Equal(t, dependentCSV.GetName(), dependentSubscription.Status.CurrentCSV)

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

0 comments on commit 5837a4b

Please sign in to comment.