diff --git a/internal/operator-controller/applier/helm_test.go b/internal/operator-controller/applier/helm_test.go index 21fbdb4a4..faaa41783 100644 --- a/internal/operator-controller/applier/helm_test.go +++ b/internal/operator-controller/applier/helm_test.go @@ -447,7 +447,7 @@ func TestApply_Upgrade(t *testing.T) { func TestApply_InstallationWithSingleOwnNamespaceInstallSupportEnabled(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.SingleOwnNamespaceInstallSupport, true) - t.Run("generates bundle resources in SingleNamespace install mode when watch namespace is configured", func(t *testing.T) { + t.Run("generates bundle resources using the configured watch namespace", func(t *testing.T) { var expectedWatchNamespace = "watch-namespace" helmApplier := applier.Helm{ @@ -464,7 +464,7 @@ func TestApply_InstallationWithSingleOwnNamespaceInstallSupportEnabled(t *testin }, } - testExt := &v1.ClusterExtension{ + testExt := &ocv1.ClusterExtension{ ObjectMeta: metav1.ObjectMeta{ Name: "testExt", Annotations: map[string]string{ diff --git a/internal/operator-controller/applier/watchnamespace_test.go b/internal/operator-controller/applier/watchnamespace_test.go index 6f6e341e8..90e018dc7 100644 --- a/internal/operator-controller/applier/watchnamespace_test.go +++ b/internal/operator-controller/applier/watchnamespace_test.go @@ -13,6 +13,21 @@ import ( "github.com/operator-framework/operator-controller/internal/operator-controller/features" ) +func TestGetWatchNamespacesWhenFeatureGateIsDisabled(t *testing.T) { + watchNamespace, err := applier.GetWatchNamespace(&v1.ClusterExtension{ + ObjectMeta: metav1.ObjectMeta{ + Name: "extension", + Annotations: map[string]string{ + "olm.operatorframework.io/watch-namespace": "watch-namespace", + }, + }, + Spec: v1.ClusterExtensionSpec{}, + }) + require.NoError(t, err) + t.Log("Check watchNamespace is '' even if the annotation is set") + require.Equal(t, corev1.NamespaceAll, watchNamespace) +} + func TestGetWatchNamespace(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.SingleOwnNamespaceInstallSupport, true) diff --git a/internal/operator-controller/rukpak/convert/registryv1_test.go b/internal/operator-controller/rukpak/convert/registryv1_test.go index a79e4624f..20ea7fc88 100644 --- a/internal/operator-controller/rukpak/convert/registryv1_test.go +++ b/internal/operator-controller/rukpak/convert/registryv1_test.go @@ -379,81 +379,102 @@ func TestRegistryV1SuiteGenerateOwnNamespace(t *testing.T) { require.Equal(t, strings.Join(watchNamespaces, ","), dep.(*appsv1.Deployment).Spec.Template.Annotations[olmNamespaces]) } -func TestRegistryV1SuiteGenerateErrorMultiNamespaceEmpty(t *testing.T) { - t.Log("RegistryV1 Suite Convert") - t.Log("It should generate objects successfully based on target namespaces") - - t.Log("It should error when multinamespace mode is supported with an empty string in target namespaces") - baseCSV, svc := getBaseCsvAndService() - csv := baseCSV.DeepCopy() - csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}} - - t.Log("By creating a registry v1 bundle") - watchNamespaces := []string{"testWatchNs1", ""} - unstructuredSvc := convertToUnstructured(t, svc) - registryv1Bundle := convert.RegistryV1{ - PackageName: "testPkg", - CSV: *csv, - Others: []unstructured.Unstructured{unstructuredSvc}, - } - - t.Log("By converting to plain") - plainBundle, err := convert.Convert(registryv1Bundle, installNamespace, watchNamespaces) - require.Error(t, err) - require.Nil(t, plainBundle) -} - -func TestRegistryV1SuiteGenerateErrorSingleNamespaceDisabled(t *testing.T) { - t.Log("RegistryV1 Suite Convert") - t.Log("It should generate objects successfully based on target namespaces") - - t.Log("It should error when single namespace mode is disabled with more than one target namespaces") - baseCSV, svc := getBaseCsvAndService() - csv := baseCSV.DeepCopy() - csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}} - - t.Log("By creating a registry v1 bundle") - watchNamespaces := []string{"testWatchNs1", "testWatchNs2"} - unstructuredSvc := convertToUnstructured(t, svc) - registryv1Bundle := convert.RegistryV1{ - PackageName: "testPkg", - CSV: *csv, - Others: []unstructured.Unstructured{unstructuredSvc}, - } - - t.Log("By converting to plain") - plainBundle, err := convert.Convert(registryv1Bundle, installNamespace, watchNamespaces) - require.Error(t, err) - require.Nil(t, plainBundle) -} - -func TestRegistryV1SuiteGenerateErrorAllNamespaceDisabled(t *testing.T) { - t.Log("RegistryV1 Suite Convert") - t.Log("It should generate objects successfully based on target namespaces") - - t.Log("It should error when all namespace mode is disabled with target namespace containing an empty string") - baseCSV, svc := getBaseCsvAndService() - csv := baseCSV.DeepCopy() - csv.Spec.InstallModes = []v1alpha1.InstallMode{ - {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: false}, - {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}, - {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true}, - {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}, - } +func TestConvertInstallModeValidation(t *testing.T) { + for _, tc := range []struct { + description string + installModes []v1alpha1.InstallMode + installNamespace string + watchNamespaces []string + }{ + { + description: "fails on AllNamespaces install mode when CSV does not support it", + installNamespace: "install-namespace", + watchNamespaces: []string{corev1.NamespaceAll}, + installModes: []v1alpha1.InstallMode{ + {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: false}, + {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}, + {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true}, + {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}, + }, + }, { + description: "fails on SingleNamespace install mode when CSV does not support it", + installNamespace: "install-namespace", + watchNamespaces: []string{"watch-namespace"}, + installModes: []v1alpha1.InstallMode{ + {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true}, + {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}, + {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}, + {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}, + }, + }, { + description: "fails on OwnNamespace install mode when CSV does not support it and watch namespace is not install namespace", + installNamespace: "install-namespace", + watchNamespaces: []string{"watch-namespace"}, + installModes: []v1alpha1.InstallMode{ + {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true}, + {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}, + {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}, + {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}, + }, + }, { + description: "fails on MultiNamespace install mode when CSV does not support it", + installNamespace: "install-namespace", + watchNamespaces: []string{"watch-namespace-one", "watch-namespace-two", "watch-namespace-three"}, + installModes: []v1alpha1.InstallMode{ + {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true}, + {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}, + {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true}, + {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: false}, + }, + }, { + description: "fails on MultiNamespace install mode when CSV supports it but watchNamespaces is empty", + installNamespace: "install-namespace", + watchNamespaces: []string{}, + installModes: []v1alpha1.InstallMode{ + // because install mode is inferred by the watchNamespaces parameter + // force MultiNamespace install by disabling other modes + {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: false}, + {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: false}, + {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}, + {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}, + }, + }, { + description: "fails on MultiNamespace install mode when CSV supports it but watchNamespaces is nil", + installNamespace: "install-namespace", + watchNamespaces: nil, + installModes: []v1alpha1.InstallMode{ + // because install mode is inferred by the watchNamespaces parameter + // force MultiNamespace install by disabling other modes + {Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: false}, + {Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: false}, + {Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}, + {Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}, + }, + }, + } { + t.Run(tc.description, func(t *testing.T) { + t.Log("RegistryV1 Suite Convert") + t.Log("It should generate objects successfully based on target namespaces") + + t.Log("It should error when all namespace mode is disabled with target namespace containing an empty string") + baseCSV, svc := getBaseCsvAndService() + csv := baseCSV.DeepCopy() + csv.Spec.InstallModes = tc.installModes + + t.Log("By creating a registry v1 bundle") + unstructuredSvc := convertToUnstructured(t, svc) + registryv1Bundle := convert.RegistryV1{ + PackageName: "testPkg", + CSV: *csv, + Others: []unstructured.Unstructured{unstructuredSvc}, + } - t.Log("By creating a registry v1 bundle") - watchNamespaces := []string{""} - unstructuredSvc := convertToUnstructured(t, svc) - registryv1Bundle := convert.RegistryV1{ - PackageName: "testPkg", - CSV: *csv, - Others: []unstructured.Unstructured{unstructuredSvc}, + t.Log("By converting to plain") + plainBundle, err := convert.Convert(registryv1Bundle, tc.installNamespace, tc.watchNamespaces) + require.Error(t, err) + require.Nil(t, plainBundle) + }) } - - t.Log("By converting to plain") - plainBundle, err := convert.Convert(registryv1Bundle, installNamespace, watchNamespaces) - require.Error(t, err) - require.Nil(t, plainBundle) } func TestRegistryV1SuiteReadBundleFileSystem(t *testing.T) {