Summary
When spec.gitSpec.tokenSecret is set, the patterns-operator copies the bootstrap git credentials twice:
- Into the real ArgoCD namespace (
vp-gitops / getClusterWideArgoNamespace()) as vp-private-repo-credentials — correct.
- Into a namespace named
{pattern}-{clusterGroupName} via applicationName(pattern) — incorrect under single ArgoCD.
Under global.singleArgoCD: true, that string is only the ClusterGroup Application name (e.g. rhoso-gitops-standalone). The Application lives in vp-gitops; the namespace rhoso-gitops-standalone does not exist by default. Reconcile fails with:
Reconcile step "copying clusterwide git auth secret to namespaced argo" failed:
namespaces "rhoso-gitops-standalone" not found
until an empty namespace with that name is created by hand.
This looks like a leftover from the legacy per-pattern ArgoCD layout (namespace == application name), not updated for single-ArgoCD.
Environment
- patterns-operator: v0.0.80 (community-operators
fast)
- Pattern:
rhoso-gitops in patterns-operator
spec.clusterGroupName: standalone
global.singleArgoCD: true (pattern values)
- ArgoCD instance:
vp-gitops / namespace vp-gitops
- ClusterGroup Application:
rhoso-gitops-standalone in namespace vp-gitops (name ≠ namespace)
- Git auth: SSH (
git@…) via Argo-shaped Secret + tokenSecret / tokenSecretNamespace
Steps to reproduce
-
Deploy a pattern with singleArgoCD: true.
-
Provide git credentials via Secret (e.g. openshift-operators/private-repo with sshPrivateKey / url / type=git and label argocd.argoproj.io/secret-type: repository).
-
Set on the Pattern CR:
spec:
clusterGroupName: standalone
gitSpec:
targetRepo: git@… # or https
tokenSecret: private-repo
tokenSecretNamespace: openshift-operators
-
Do not pre-create namespace rhoso-gitops-standalone.
-
Watch Pattern status / operator logs.
Actual behavior
-
Operator successfully clones with the secret (SSH/HTTPS auth for local checkout works).
-
First copy of credentials into vp-gitops as vp-private-repo-credentials succeeds.
-
Second copy targets namespace rhoso-gitops-standalone and fails:
namespaces "rhoso-gitops-standalone" not found
lastStep: copying clusterwide git auth secret to namespaced argo
-
Reconcile loops until that namespace exists.
-
Creating an empty Namespace/rhoso-gitops-standalone unblocks reconcile (lastStep: reconcile complete), but leaves a useless namespace that is not the ArgoCD instance namespace.
Expected behavior
Under single ArgoCD (vp-gitops):
- Git auth secret should be copied only into the ArgoCD namespace (
getClusterWideArgoNamespace() → vp-gitops), not into a namespace derived from applicationName().
- Reconcile should complete without requiring a namespace whose name happens to equal the ClusterGroup Application name.
- Optionally: if a second copy remains for legacy multi-Argo mode, it should only run when a namespaced Argo instance actually exists in
{pattern}-{clusterGroup}.
Code references
applicationName is pattern + clusterGroup (Application name):
// internal/controller/argo.go
func applicationName(p *api.Pattern) string {
return fmt.Sprintf("%s-%s", p.Name, p.Spec.ClusterGroupName)
}
Two copy sites in reconcile (internal/controller/pattern_controller.go):
// 1) Correct for single ArgoCD — destination = Argo namespace (vp-gitops)
r.copyAuthGitSecret(
qualifiedInstance.Spec.GitConfig.TokenSecretNamespace,
qualifiedInstance.Spec.GitConfig.TokenSecret,
getClusterWideArgoNamespace(),
"vp-private-repo-credentials")
// … later, after reconcileApplication …
// 2) Bug under single ArgoCD — destination = Application *name* used as *namespace*
r.copyAuthGitSecret(
qualifiedInstance.Spec.GitConfig.TokenSecretNamespace,
qualifiedInstance.Spec.GitConfig.TokenSecret,
applicationName(qualifiedInstance), // e.g. "rhoso-gitops-standalone"
"vp-private-repo-credentials")
copyAuthGitSecret treats the third argument as destNamespace and Create/Update’s the Secret there (pattern_controller.go).
Lab confirmation:
- Pattern:
clusterGroupName=standalone → applicationName = rhoso-gitops-standalone
- Application object:
name=rhoso-gitops-standalone, namespace=vp-gitops
- No Pattern CR field redirects the second copy destination (
tokenSecret / tokenSecretNamespace only control the source).
Workaround
oc create namespace rhoso-gitops-standalone # or {pattern}-{clusterGroupName}
Reconcile then completes; Argo still uses credentials in vp-gitops.
Suggested fix
- Prefer: second
copyAuthGitSecret should also use getClusterWideArgoNamespace() when single-ArgoCD / cluster-wide instance is active; or drop the second copy if redundant with the first.
- Legacy path: only copy into
applicationName(p) if that namespace hosts a namespaced ArgoCD instance (multi-Argo mode).
- Add a regression test: Pattern with
tokenSecret + single ArgoCD in vp-gitops, Application named {pattern}-{clusterGroup} in vp-gitops, no namespace {pattern}-{clusterGroup} → reconcile succeeds and Secret exists in vp-gitops only.
Impact
- Blocks Pattern reconcile whenever
tokenSecret is used with single ArgoCD until a dummy namespace is created.
- Affects private-repo / SSH / HTTPS token bootstrap flows documented for Validated Patterns (
TOKEN_SECRET / tokenSecret).
- Easy to misdiagnose as a secrets or Argo config problem.
Summary
When
spec.gitSpec.tokenSecretis set, the patterns-operator copies the bootstrap git credentials twice:vp-gitops/getClusterWideArgoNamespace()) asvp-private-repo-credentials— correct.{pattern}-{clusterGroupName}viaapplicationName(pattern)— incorrect under single ArgoCD.Under
global.singleArgoCD: true, that string is only the ClusterGroup Application name (e.g.rhoso-gitops-standalone). The Application lives invp-gitops; the namespacerhoso-gitops-standalonedoes not exist by default. Reconcile fails with:until an empty namespace with that name is created by hand.
This looks like a leftover from the legacy per-pattern ArgoCD layout (namespace == application name), not updated for single-ArgoCD.
Environment
fast)rhoso-gitopsinpatterns-operatorspec.clusterGroupName: standaloneglobal.singleArgoCD: true(pattern values)vp-gitops/ namespacevp-gitopsrhoso-gitops-standalonein namespacevp-gitops(name ≠ namespace)git@…) via Argo-shaped Secret +tokenSecret/tokenSecretNamespaceSteps to reproduce
Deploy a pattern with
singleArgoCD: true.Provide git credentials via Secret (e.g.
openshift-operators/private-repowithsshPrivateKey/url/type=gitand labelargocd.argoproj.io/secret-type: repository).Set on the Pattern CR:
Do not pre-create namespace
rhoso-gitops-standalone.Watch Pattern status / operator logs.
Actual behavior
Operator successfully clones with the secret (SSH/HTTPS auth for local checkout works).
First copy of credentials into
vp-gitopsasvp-private-repo-credentialssucceeds.Second copy targets namespace
rhoso-gitops-standaloneand fails:Reconcile loops until that namespace exists.
Creating an empty
Namespace/rhoso-gitops-standaloneunblocks reconcile (lastStep: reconcile complete), but leaves a useless namespace that is not the ArgoCD instance namespace.Expected behavior
Under single ArgoCD (
vp-gitops):getClusterWideArgoNamespace()→vp-gitops), not into a namespace derived fromapplicationName().{pattern}-{clusterGroup}.Code references
applicationNameis pattern + clusterGroup (Application name):Two copy sites in reconcile (
internal/controller/pattern_controller.go):copyAuthGitSecrettreats the third argument asdestNamespaceand Create/Update’s the Secret there (pattern_controller.go).Lab confirmation:
clusterGroupName=standalone→applicationName=rhoso-gitops-standalonename=rhoso-gitops-standalone,namespace=vp-gitopstokenSecret/tokenSecretNamespaceonly control the source).Workaround
oc create namespace rhoso-gitops-standalone # or {pattern}-{clusterGroupName}Reconcile then completes; Argo still uses credentials in
vp-gitops.Suggested fix
copyAuthGitSecretshould also usegetClusterWideArgoNamespace()when single-ArgoCD / cluster-wide instance is active; or drop the second copy if redundant with the first.applicationName(p)if that namespace hosts a namespaced ArgoCD instance (multi-Argo mode).tokenSecret+ single ArgoCD invp-gitops, Application named{pattern}-{clusterGroup}invp-gitops, no namespace{pattern}-{clusterGroup}→ reconcile succeeds and Secret exists invp-gitopsonly.Impact
tokenSecretis used with single ArgoCD until a dummy namespace is created.TOKEN_SECRET/tokenSecret).