Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docs/draft/howto/single-ownnamespace-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
name: argocd
annotations:
olm.operatorframework.io/watch-namespace: argocd
spec:
namespace: argocd
serviceAccount:
Expand Down
33 changes: 32 additions & 1 deletion hack/demo/own-namespace-demo-script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
#
# Welcome to the OwnNamespace install mode demo
#
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
set -e
trap 'echo "Demo ran into error"; trap - SIGTERM && kill -- -$$; exit 1' ERR SIGINT SIGTERM EXIT

# install experimental CRDs with config field support
kubectl apply -f "$(dirname "${BASH_SOURCE[0]}")/../../manifests/experimental.yaml"

# wait for experimental CRDs to be available
kubectl wait --for condition=established --timeout=60s crd/clusterextensions.olm.operatorframework.io

# enable 'SingleOwnNamespaceInstallSupport' feature gate
kubectl patch deployment -n olmv1-system operator-controller-controller-manager --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--feature-gates=SingleOwnNamespaceInstallSupport=true"}]'
Expand Down Expand Up @@ -41,3 +48,27 @@ kubectl get deployments -n argocd-system argocd-operator-controller-manager -o j
# check service account for role binding is the same as controller service-account
rolebinding=$(kubectl get rolebindings -n argocd-system -o name | grep 'argocd-operator' | head -n 1)
kubectl get -n argocd-system $rolebinding -o jsonpath='{.subjects}' | jq .[0]

echo "Demo completed successfully!"

# cleanup resources
echo "Cleaning up demo resources..."
kubectl delete clusterextension argocd-operator --ignore-not-found=true
kubectl delete namespace argocd-system --ignore-not-found=true
kubectl delete clusterrolebinding argocd-installer-crb --ignore-not-found=true

# remove feature gate from deployment
echo "Removing feature gate from operator-controller..."
kubectl patch deployment -n olmv1-system operator-controller-controller-manager --type='json' -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/args", "value": "--feature-gates=SingleOwnNamespaceInstallSupport=true"}]' || true

# restore standard CRDs
echo "Restoring standard CRDs..."
kubectl apply -f "$(dirname "${BASH_SOURCE[0]}")/../../manifests/base.yaml"

# wait for standard CRDs to be available
kubectl wait --for condition=established --timeout=60s crd/clusterextensions.olm.operatorframework.io

# wait for operator-controller to become available with standard config
kubectl rollout status -n olmv1-system deployment/operator-controller-controller-manager

echo "Demo cleanup completed!"
3 changes: 0 additions & 3 deletions hack/demo/resources/own-namespace-demo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
name: argocd-operator
annotations:
# watch namespace is the same as intall namespace
olm.operatorframework.io/watch-namespace: argocd-system
spec:
namespace: argocd-system
serviceAccount:
Expand Down
7 changes: 4 additions & 3 deletions hack/demo/resources/single-namespace-demo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
name: argocd-operator
annotations:
# watch-namespace is different from install namespace
olm.operatorframework.io/watch-namespace: argocd
spec:
namespace: argocd-system
serviceAccount:
name: argocd-installer
config:
configType: Inline
inline:
watchNamespace: argocd
source:
sourceType: Catalog
catalog:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
#
# Welcome to the SingleNamespace install mode demo
#
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
set -e
trap 'echo "Demo ran into error"; trap - SIGTERM && kill -- -$$; exit 1' ERR SIGINT SIGTERM EXIT

# install experimental CRDs with config field support
kubectl apply -f "$(dirname "${BASH_SOURCE[0]}")/../../manifests/experimental.yaml"

# wait for experimental CRDs to be available
kubectl wait --for condition=established --timeout=60s crd/clusterextensions.olm.operatorframework.io

# enable 'SingleOwnNamespaceInstallSupport' feature gate
kubectl patch deployment -n olmv1-system operator-controller-controller-manager --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--feature-gates=SingleOwnNamespaceInstallSupport=true"}]'
Expand Down Expand Up @@ -44,3 +51,27 @@ kubectl get deployments -n argocd-system argocd-operator-controller-manager -o j
# check service account for role binding is the controller deployment service account
rolebinding=$(kubectl get rolebindings -n argocd -o name | grep 'argocd-operator' | head -n 1)
kubectl get -n argocd $rolebinding -o jsonpath='{.subjects}' | jq .[0]

echo "Demo completed successfully!"

# cleanup resources
echo "Cleaning up demo resources..."
kubectl delete clusterextension argocd-operator --ignore-not-found=true
kubectl delete namespace argocd-system argocd --ignore-not-found=true
kubectl delete clusterrolebinding argocd-installer-crb --ignore-not-found=true

# remove feature gate from deployment
echo "Removing feature gate from operator-controller..."
kubectl patch deployment -n olmv1-system operator-controller-controller-manager --type='json' -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/args", "value": "--feature-gates=SingleOwnNamespaceInstallSupport=true"}]' || true

# restore standard CRDs
echo "Restoring standard CRDs..."
kubectl apply -f "$(dirname "${BASH_SOURCE[0]}")/../../manifests/base.yaml"

# wait for standard CRDs to be available
kubectl wait --for condition=established --timeout=60s crd/clusterextensions.olm.operatorframework.io

# wait for operator-controller to become available with standard config
kubectl rollout status -n olmv1-system deployment/operator-controller-controller-manager

echo "Demo cleanup completed!"
6 changes: 0 additions & 6 deletions internal/operator-controller/applier/watchnamespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import (
"github.com/operator-framework/operator-controller/internal/operator-controller/features"
)

const (
AnnotationClusterExtensionWatchNamespace = "olm.operatorframework.io/watch-namespace"
)

// GetWatchNamespace determines the watch namespace the ClusterExtension should use
// Note: this is a temporary artifice to enable gated use of single/own namespace install modes
// for registry+v1 bundles. This will go away once the ClusterExtension API is updated to include
Expand All @@ -32,8 +28,6 @@ func GetWatchNamespace(ext *ocv1.ClusterExtension) (string, error) {
return "", fmt.Errorf("invalid bundle configuration: %w", err)
}
watchNamespace = cfg.WatchNamespace
} else if _, ok := ext.Annotations[AnnotationClusterExtensionWatchNamespace]; ok {
watchNamespace = ext.Annotations[AnnotationClusterExtensionWatchNamespace]
} else {
return "", nil
}
Expand Down
70 changes: 24 additions & 46 deletions internal/operator-controller/applier/watchnamespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ func TestGetWatchNamespace(t *testing.T) {
for _, tt := range []struct {
name string
want string
csv *ocv1.ClusterExtension
ce *ocv1.ClusterExtension
expectError bool
}{
{
name: "cluster extension does not configure a watch namespace",
name: "no watch namespace is configured in a ClusterExtension CR",
want: corev1.NamespaceAll,
csv: &ocv1.ClusterExtension{
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
Annotations: nil,
Expand All @@ -54,9 +54,9 @@ func TestGetWatchNamespace(t *testing.T) {
},
expectError: false,
}, {
name: "cluster extension configures a watch namespace",
name: "a watch namespace is configured in a ClusterExtension CR",
want: "watch-namespace",
csv: &ocv1.ClusterExtension{
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
},
Expand All @@ -71,63 +71,41 @@ func TestGetWatchNamespace(t *testing.T) {
},
expectError: false,
}, {
name: "cluster extension configures a watch namespace through annotation",
want: "watch-namespace",
csv: &ocv1.ClusterExtension{
name: "a watch namespace is configured in a ClusterExtension CR but with invalid namespace",
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
Annotations: map[string]string{
"olm.operatorframework.io/watch-namespace": "watch-namespace",
},
},
},
expectError: false,
}, {
name: "cluster extension configures a watch namespace through annotation with invalid ns",
csv: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
Annotations: map[string]string{
"olm.operatorframework.io/watch-namespace": "watch-namespace-",
},
},
},
expectError: true,
}, {
name: "cluster extension configures a watch namespace through annotation with empty ns",
csv: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
Annotations: map[string]string{
"olm.operatorframework.io/watch-namespace": "",
Spec: ocv1.ClusterExtensionSpec{
Config: &ocv1.ClusterExtensionConfig{
ConfigType: ocv1.ClusterExtensionConfigTypeInline,
Inline: &apiextensionsv1.JSON{
Raw: []byte(`{"watchNamespace":"watch-namespace-"}`),
},
},
},
},
expectError: true,
}, {
name: "cluster extension configures a watch namespace through annotation and config (take config)",
want: "watch-namespace",
csv: &ocv1.ClusterExtension{
name: "a watch namespace is configured in a ClusterExtension CR with an empty string as the namespace",
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
Annotations: map[string]string{
"olm.operatorframework.io/watch-namespace": "dont-use-this-watch-namespace",
},
},
Spec: ocv1.ClusterExtensionSpec{
Config: &ocv1.ClusterExtensionConfig{
ConfigType: ocv1.ClusterExtensionConfigTypeInline,
Inline: &apiextensionsv1.JSON{
Raw: []byte(`{"watchNamespace":"watch-namespace"}`),
Raw: []byte(`{"watchNamespace":""}`),
},
},
},
},
expectError: false,
expectError: true,
}, {
name: "cluster extension configures an invalid watchNamespace: multiple watch namespaces",
name: "an invalid watchNamespace value is configured in a ClusterExtension CR: multiple watch namespaces",
want: "",
csv: &ocv1.ClusterExtension{
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
},
Expand All @@ -142,9 +120,9 @@ func TestGetWatchNamespace(t *testing.T) {
},
expectError: true,
}, {
name: "cluster extension configures an invalid watchNamespace: invalid name",
name: "an invalid watchNamespace value is configured in a ClusterExtension CR: invalid name",
want: "",
csv: &ocv1.ClusterExtension{
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
},
Expand All @@ -159,9 +137,9 @@ func TestGetWatchNamespace(t *testing.T) {
},
expectError: true,
}, {
name: "cluster extension configures an invalid watchNamespace: invalid json",
name: "an invalid watchNamespace value is configured in a ClusterExtension CR: invalid json",
want: "",
csv: &ocv1.ClusterExtension{
ce: &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{
Name: "extension",
},
Expand All @@ -178,7 +156,7 @@ func TestGetWatchNamespace(t *testing.T) {
},
} {
t.Run(tt.name, func(t *testing.T) {
got, err := applier.GetWatchNamespace(tt.csv)
got, err := applier.GetWatchNamespace(tt.ce)
require.Equal(t, tt.want, got)
require.Equal(t, tt.expectError, err != nil)
})
Expand Down
Loading