Skip to content

Commit 4c0cdb5

Browse files
authored
feat: Support custom ArgoCD namespace configuration (#134)
- Add ARGOCD_NAMESPACE and ARGOCD_OPERATOR_NAMESPACE environment variables - Update GitOpsCluster controller to pass namespace config via AddOnDeploymentConfig - Refactor addon install/cleanup to use configurable namespaces instead of hardcoded values - Add e2e test for custom namespace scenarios (hub: notargocd, spoke: notargocd) - Extract cluster setup into reusable make target (setup-e2e-clusters) - Update Helm installation to use --create-namespace flag - Update GitHub Actions workflow to include custom namespace e2e test - Fix README with correct Helm installation commands Signed-off-by: Mike Ng <[email protected]>
1 parent 120ac30 commit 4c0cdb5

File tree

15 files changed

+522
-87
lines changed

15 files changed

+522
-87
lines changed

.github/workflows/e2e.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,62 @@ jobs:
136136
env:
137137
KUBECONFIG: /home/runner/.kube/config
138138
run: make test-e2e-cleanup
139+
140+
e2e-custom-namespace:
141+
name: e2e-custom-namespace
142+
runs-on: ubuntu-latest
143+
steps:
144+
- name: checkout code
145+
uses: actions/checkout@v4
146+
with:
147+
fetch-depth: 1
148+
path: go/src/open-cluster-management.io/argocd-pull-integration
149+
150+
- name: install Go
151+
uses: actions/setup-go@v5
152+
with:
153+
go-version: ${{ env.GO_VERSION }}
154+
155+
- name: Add GOPATH/bin to PATH
156+
run: echo "$GOPATH/bin" >> "$GITHUB_PATH"
157+
158+
- name: install imagebuilder
159+
run: go install github.com/openshift/imagebuilder/cmd/[email protected]
160+
161+
- name: Set up Helm
162+
uses: azure/setup-helm@v4
163+
with:
164+
version: v3.15.2
165+
166+
- name: Set up kubectl
167+
uses: azure/setup-kubectl@v4
168+
with:
169+
version: v1.29.0
170+
171+
- name: build-images
172+
run: make build-images
173+
174+
- name: setup kind (cluster1)
175+
uses: engineerd/[email protected]
176+
with:
177+
version: v0.14.0
178+
name: cluster1
179+
180+
- name: setup kind (hub)
181+
uses: engineerd/[email protected]
182+
with:
183+
version: v0.14.0
184+
name: hub
185+
186+
- name: Load image on the nodes of the hub
187+
run: |
188+
kind load docker-image --name=hub quay.io/open-cluster-management/argocd-pull-integration:latest
189+
190+
- name: Load image on the nodes of the cluster1
191+
run: |
192+
kind load docker-image --name=cluster1 quay.io/open-cluster-management/argocd-pull-integration:latest
193+
194+
- name: Run e2e custom namespace test
195+
env:
196+
KUBECONFIG: /home/runner/.kube/config
197+
run: make test-e2e-custom-namespace

Makefile

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,22 @@ E2E_IMG ?= quay.io/open-cluster-management/argocd-pull-integration:latest
6969

7070
##@ E2E Tests
7171

72+
.PHONY: setup-e2e-clusters
73+
setup-e2e-clusters: ## Setup KinD clusters, build and load controller image
74+
@echo "===== Cleaning up existing clusters ====="
75+
$(KIND) delete clusters --all || true
76+
@echo ""
77+
@echo "===== Creating KinD clusters ====="
78+
$(KIND) create cluster --name $(HUB_CLUSTER)
79+
$(KIND) create cluster --name $(SPOKE_CLUSTER)
80+
@echo ""
81+
@echo "===== Building controller image ====="
82+
$(MAKE) docker-build IMG=$(E2E_IMG)
83+
@echo ""
84+
@echo "===== Loading image to clusters ====="
85+
$(KIND) load docker-image $(E2E_IMG) --name $(HUB_CLUSTER)
86+
$(KIND) load docker-image $(E2E_IMG) --name $(SPOKE_CLUSTER)
87+
7288
.PHONY: test-e2e
7389
test-e2e: manifests generate fmt vet ## Run e2e deployment tests only (checks pods running and logs)
7490
@echo "===== Installing MetalLB ====="
@@ -79,12 +95,10 @@ test-e2e: manifests generate fmt vet ## Run e2e deployment tests only (checks po
7995
@echo ""
8096
@echo "===== Installing addon via Helm ====="
8197
$(KUBECTL) config use-context kind-$(HUB_CLUSTER)
82-
$(KUBECTL) create namespace argocd || true
83-
$(KUBECTL) label namespace argocd app.kubernetes.io/managed-by=Helm --overwrite
84-
$(KUBECTL) annotate namespace argocd meta.helm.sh/release-name=argocd-agent-addon meta.helm.sh/release-namespace=argocd --overwrite
8598
helm install argocd-agent-addon \
8699
./charts/argocd-agent-addon \
87100
--namespace argocd \
101+
--create-namespace \
88102
--set image=quay.io/open-cluster-management/argocd-pull-integration \
89103
--set tag=latest \
90104
--wait \
@@ -117,19 +131,7 @@ test-e2e-integration: ## Run full e2e integration tests including AppProject and
117131

118132
.PHONY: test-e2e-full
119133
test-e2e-full: ## Complete e2e test with kind cluster setup, build, deployment, and full integration tests
120-
@echo "===== Cleaning up existing clusters ====="
121-
$(KIND) delete clusters --all || true
122-
@echo ""
123-
@echo "===== Creating KinD clusters ====="
124-
$(KIND) create cluster --name $(HUB_CLUSTER)
125-
$(KIND) create cluster --name $(SPOKE_CLUSTER)
126-
@echo ""
127-
@echo "===== Building controller image ====="
128-
$(MAKE) docker-build IMG=$(E2E_IMG)
129-
@echo ""
130-
@echo "===== Loading image to clusters ====="
131-
$(KIND) load docker-image $(E2E_IMG) --name $(HUB_CLUSTER)
132-
$(KIND) load docker-image $(E2E_IMG) --name $(SPOKE_CLUSTER)
134+
$(MAKE) setup-e2e-clusters
133135
@echo ""
134136
@echo "===== Running deployment tests ====="
135137
$(MAKE) test-e2e
@@ -171,12 +173,10 @@ test-e2e-cleanup: manifests generate fmt vet ## Run e2e cleanup tests (checks ad
171173
@echo ""
172174
@echo "===== Installing addon via Helm ====="
173175
$(KUBECTL) config use-context kind-$(HUB_CLUSTER)
174-
$(KUBECTL) create namespace argocd || true
175-
$(KUBECTL) label namespace argocd app.kubernetes.io/managed-by=Helm --overwrite
176-
$(KUBECTL) annotate namespace argocd meta.helm.sh/release-name=argocd-agent-addon meta.helm.sh/release-namespace=argocd --overwrite
177176
helm install argocd-agent-addon \
178177
./charts/argocd-agent-addon \
179178
--namespace argocd \
179+
--create-namespace \
180180
--set image=quay.io/open-cluster-management/argocd-pull-integration \
181181
--set tag=latest \
182182
--wait \
@@ -189,19 +189,7 @@ test-e2e-cleanup: manifests generate fmt vet ## Run e2e cleanup tests (checks ad
189189

190190
.PHONY: test-e2e-cleanup-full
191191
test-e2e-cleanup-full: ## Complete e2e test with cleanup verification including Application (cluster setup + deployment + cleanup)
192-
@echo "===== Cleaning up existing clusters ====="
193-
$(KIND) delete clusters --all || true
194-
@echo ""
195-
@echo "===== Creating KinD clusters ====="
196-
$(KIND) create cluster --name $(HUB_CLUSTER)
197-
$(KIND) create cluster --name $(SPOKE_CLUSTER)
198-
@echo ""
199-
@echo "===== Building controller image ====="
200-
$(MAKE) docker-build IMG=$(E2E_IMG)
201-
@echo ""
202-
@echo "===== Loading image to clusters ====="
203-
$(KIND) load docker-image $(E2E_IMG) --name $(HUB_CLUSTER)
204-
$(KIND) load docker-image $(E2E_IMG) --name $(SPOKE_CLUSTER)
192+
$(MAKE) setup-e2e-clusters
205193
@echo ""
206194
@echo "===== Installing MetalLB ====="
207195
./test/e2e/scripts/install_metallb.sh
@@ -211,12 +199,10 @@ test-e2e-cleanup-full: ## Complete e2e test with cleanup verification including
211199
@echo ""
212200
@echo "===== Installing addon via Helm ====="
213201
$(KUBECTL) config use-context kind-$(HUB_CLUSTER)
214-
$(KUBECTL) create namespace argocd || true
215-
$(KUBECTL) label namespace argocd app.kubernetes.io/managed-by=Helm --overwrite
216-
$(KUBECTL) annotate namespace argocd meta.helm.sh/release-name=argocd-agent-addon meta.helm.sh/release-namespace=argocd --overwrite
217202
helm install argocd-agent-addon \
218203
./charts/argocd-agent-addon \
219204
--namespace argocd \
205+
--create-namespace \
220206
--set image=quay.io/open-cluster-management/argocd-pull-integration \
221207
--set tag=latest \
222208
--wait \
@@ -229,6 +215,42 @@ test-e2e-cleanup-full: ## Complete e2e test with cleanup verification including
229215
@echo "Hub context: kind-$(HUB_CLUSTER)"
230216
@echo "Spoke context: kind-$(SPOKE_CLUSTER)"
231217

218+
.PHONY: test-e2e-custom-namespace
219+
test-e2e-custom-namespace: manifests generate fmt vet ## Run e2e test with custom ArgoCD namespaces (hub: notargocd, spoke: argocdnot)
220+
@echo "===== Installing MetalLB ====="
221+
./test/e2e/scripts/install_metallb.sh
222+
@echo ""
223+
@echo "===== Setting up OCM environment ====="
224+
./test/e2e/scripts/setup_ocm_env.sh
225+
@echo ""
226+
@echo "===== Installing addon via Helm with custom namespaces ====="
227+
$(KUBECTL) config use-context kind-$(HUB_CLUSTER)
228+
helm install argocd-agent-addon \
229+
./charts/argocd-agent-addon \
230+
--namespace notargocd \
231+
--create-namespace \
232+
--set global.argoCDNamespace=notargocd \
233+
--set global.argoCDOperatorNamespace=argocd-operator-system \
234+
--set controller.namespace=notargocd \
235+
--set gitOpsCluster.namespace=notargocd \
236+
--set image=quay.io/open-cluster-management/argocd-pull-integration \
237+
--set tag=latest \
238+
--wait \
239+
--timeout 10m
240+
@echo ""
241+
@echo "===== Running e2e tests with custom namespaces ====="
242+
HUB_ARGOCD_NAMESPACE=notargocd go test -tags=e2e ./test/e2e/ -v -ginkgo.v --ginkgo.label-filter="custom-namespace"
243+
@echo ""
244+
@echo "===== E2E Custom Namespace Tests Complete ====="
245+
@echo "Hub context: kind-$(HUB_CLUSTER) (ArgoCD in notargocd namespace)"
246+
@echo "Spoke context: kind-$(SPOKE_CLUSTER) (ArgoCD in notargocd namespace)"
247+
248+
.PHONY: test-e2e-custom-namespace-full
249+
test-e2e-custom-namespace-full: ## Complete e2e test with custom namespaces (cluster setup + custom namespace deployment + tests)
250+
$(MAKE) setup-e2e-clusters
251+
@echo ""
252+
$(MAKE) test-e2e-custom-namespace
253+
232254
##@ Build
233255

234256
.PHONY: build

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ For detailed argocd-agent architecture and operational modes, see [argocd-agent
138138
helm repo add ocm https://open-cluster-management.io/helm-charts
139139
helm repo update
140140
helm search repo ocm
141-
helm install argocd-agent-addon ocm/argocd-agent-addon
141+
helm install argocd-agent-addon ocm/argocd-agent-addon --namespace argocd --create-namespace
142142
```
143143

144144
This installs the GitOpsCluster controller and creates a GitOpsCluster resource that automatically deploys argocd-agent to your managed clusters.

charts/argocd-agent-addon/templates/argocd-operator/operator.yaml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ metadata:
88
name: {{ .Values.global.argoCDOperatorNamespace }}
99
---
1010
apiVersion: v1
11-
kind: Namespace
12-
metadata:
13-
labels:
14-
control-plane: argocd-operator
15-
app.kubernetes.io/managed-by: argocd-agent-addon
16-
name: {{ .Values.global.argoCDNamespace }}
17-
---
18-
apiVersion: v1
1911
kind: ServiceAccount
2012
metadata:
2113
name: argocd-operator-controller-manager

internal/addon/addon_cleanup.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,25 @@ import (
3333
)
3434

3535
const (
36-
operatorNamespace = "argocd-operator-system"
37-
argoCDNamespace = "argocd"
3836
// PauseMarkerName is the name of the ConfigMap used to pause the addon controller
3937
PauseMarkerName = "argocd-agent-addon-pause"
4038
)
4139

40+
// getNamespaceConfig returns namespace configuration from environment variables or defaults
41+
func getNamespaceConfig() (operatorNamespace, argoCDNamespace string) {
42+
operatorNamespace = os.Getenv("ARGOCD_OPERATOR_NAMESPACE")
43+
if operatorNamespace == "" {
44+
operatorNamespace = "argocd-operator-system"
45+
}
46+
47+
argoCDNamespace = os.Getenv("ARGOCD_NAMESPACE")
48+
if argoCDNamespace == "" {
49+
argoCDNamespace = "argocd"
50+
}
51+
52+
return operatorNamespace, argoCDNamespace
53+
}
54+
4255
// uninstallArgoCDAgent uninstalls the ArgoCD agent addon in reverse order
4356
// Does NOT delete namespaces, only deletes operator after ArgoCD CR is gone
4457
func (r *ArgoCDAgentAddonReconciler) uninstallArgoCDAgent(ctx context.Context) error {
@@ -59,6 +72,10 @@ func uninstallArgoCDAgentInternal(ctx context.Context, c client.Client) error {
5972
klog.Info("Starting ArgoCD agent addon uninstall")
6073
var cleanupErrors []error
6174

75+
// Get namespace configuration from environment
76+
operatorNamespace, argoCDNamespace := getNamespaceConfig()
77+
klog.Infof("Using namespaces - operator: %s, argocd: %s", operatorNamespace, argoCDNamespace)
78+
6279
// Step 0: Create pause marker to prevent the addon controller from reconciling resources
6380
klog.Infof("Step 0: Creating pause marker in namespace: %s", operatorNamespace)
6481
if err := createPauseMarker(ctx, c, operatorNamespace); err != nil {
@@ -122,7 +139,7 @@ func uninstallArgoCDAgentInternal(ctx context.Context, c client.Client) error {
122139

123140
// Step 2: ArgoCD CR is gone (or timed out), now delete operator resources
124141
klog.Info("Step 2: Deleting operator resources from namespace: " + operatorNamespace)
125-
if err := deleteOperatorResourcesInternal(ctx, c); err != nil {
142+
if err := deleteOperatorResourcesInternal(ctx, c, operatorNamespace); err != nil {
126143
klog.Errorf("Error deleting operator resources (continuing with cleanup): %v", err)
127144
cleanupErrors = append(cleanupErrors, fmt.Errorf("failed to delete operator resources: %w", err))
128145
}
@@ -133,7 +150,7 @@ func uninstallArgoCDAgentInternal(ctx context.Context, c client.Client) error {
133150
waitDuration := getCleanupVerificationWaitDuration()
134151
if waitDuration > 0 {
135152
klog.Infof("Step 3: Waiting and re-verifying that resources stay deleted (%v)...", waitDuration)
136-
if err := waitAndVerifyCleanup(ctx, c, waitDuration); err != nil {
153+
if err := waitAndVerifyCleanup(ctx, c, waitDuration, argoCDNamespace, operatorNamespace); err != nil {
137154
klog.Errorf("Error during cleanup verification (resources may have been recreated): %v", err)
138155
cleanupErrors = append(cleanupErrors, fmt.Errorf("cleanup verification failed: %w", err))
139156
}
@@ -153,11 +170,12 @@ func uninstallArgoCDAgentInternal(ctx context.Context, c client.Client) error {
153170

154171
// deleteOperatorResources deletes operator resources (deployment, RBAC, etc.)
155172
func (r *ArgoCDAgentAddonReconciler) deleteOperatorResources(ctx context.Context) error {
156-
return deleteOperatorResourcesInternal(ctx, r.Client)
173+
_, operatorNamespace := getNamespaceConfig()
174+
return deleteOperatorResourcesInternal(ctx, r.Client, operatorNamespace)
157175
}
158176

159177
// deleteOperatorResourcesInternal deletes operator resources (deployment, RBAC, etc.)
160-
func deleteOperatorResourcesInternal(ctx context.Context, c client.Client) error {
178+
func deleteOperatorResourcesInternal(ctx context.Context, c client.Client, operatorNamespace string) error {
161179
klog.Info("Deleting operator resources")
162180

163181
// Delete resources in the operator namespace with our management label
@@ -287,7 +305,7 @@ func IsPaused(ctx context.Context, c client.Client, namespace string) bool {
287305

288306
// waitAndVerifyCleanup waits for a specified duration and periodically verifies that
289307
// resources stay deleted. If resources are recreated, it deletes them again.
290-
func waitAndVerifyCleanup(ctx context.Context, c client.Client, waitDuration time.Duration) error {
308+
func waitAndVerifyCleanup(ctx context.Context, c client.Client, waitDuration time.Duration, argoCDNamespace, operatorNamespace string) error {
291309
klog.Infof("Starting cleanup verification for %v", waitDuration)
292310

293311
checkInterval := 20 * time.Second
@@ -325,7 +343,7 @@ func waitAndVerifyCleanup(ctx context.Context, c client.Client, waitDuration tim
325343

326344
if operatorResourcesExist {
327345
klog.Warning("Resources detected in operator namespace, attempting to delete again...")
328-
if err := deleteOperatorResourcesInternal(ctx, c); err != nil {
346+
if err := deleteOperatorResourcesInternal(ctx, c, operatorNamespace); err != nil {
329347
klog.Errorf("Failed to re-delete operator resources: %v", err)
330348
}
331349
}

0 commit comments

Comments
 (0)