From 7816a3e886a2e5691bdf26c777e21d76310a9813 Mon Sep 17 00:00:00 2001 From: Komh Date: Fri, 24 Apr 2026 23:21:07 +0000 Subject: [PATCH 1/3] [gitops] Argo CD UI cannot delete a repository with an invalid URL --- ...delete_a_repository_with_an_invalid_URL.md | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md diff --git a/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md b/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md new file mode 100644 index 000000000..f49526269 --- /dev/null +++ b/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md @@ -0,0 +1,79 @@ +--- +kind: + - Troubleshooting +products: + - Alauda Container Platform +ProductsVersion: + - 4.1.0,4.2.x +--- +## Issue + +A repository entry in the Argo CD UI is stuck in `Failed` status because the URL was entered incorrectly — missing scheme, invalid port, malformed host, or some other syntactic problem that Argo CD cannot parse. Attempting to remove the repository through the UI has no effect: clicking **Delete** either returns an error or silently leaves the row in place. + +## Root Cause + +Argo CD stores every repository definition as a Kubernetes `Secret` in the Argo CD namespace, labelled `argocd.argoproj.io/secret-type=repository`. The UI delete path validates and re-parses the repository URL before it issues the actual delete against the API; when the stored URL is malformed it cannot parse, the validation step fails, and the subsequent delete never runs. + +This is tracked as an upstream issue in the Argo CD project — see [argo-cd#8614](https://github.com/argoproj/argo-cd/issues/8614) for the bug and the workaround. The underlying object is a plain `Secret`, so deleting it through the Kubernetes API bypasses the broken UI path completely. + +## Resolution + +On ACP the GitOps capability is provided by the `gitops` component, which is itself based on Argo CD. The namespace hosting the Argo CD control plane is typically `cpaas-system` or whichever namespace your platform has configured for the GitOps instance; adjust the commands below to match. + +1. List every repository secret in the Argo CD namespace. They all start with `repo-`: + + ```bash + kubectl -n cpaas-system get secrets | grep '^repo-' + ``` + + Example output: + + ```text + repo-3148156268 Opaque 3 19s + ``` + +2. Decode the secret to confirm it is the one you want to remove. The repository URL is base64-encoded under `.data.url`: + + ```bash + kubectl -n cpaas-system get secret repo-3148156268 -o jsonpath='{.data.url}' | base64 -d + kubectl -n cpaas-system get secret repo-3148156268 -o jsonpath='{.data.type}' | base64 -d + kubectl -n cpaas-system get secret repo-3148156268 -o jsonpath='{.data.project}' | base64 -d + ``` + +3. Delete the secret. Argo CD watches the secrets in its namespace, so the repository disappears from the UI within a few seconds: + + ```bash + kubectl -n cpaas-system delete secret repo-3148156268 + ``` + +4. Refresh the Argo CD repositories page in the UI and confirm the row is gone. + +If the repository was referenced by an `Application`, that `Application` will move to `ComparisonError` after the delete. Either fix the URL and re-add the repository, or edit the `Application` to point at a valid source. The UI will now accept both operations because it no longer has to parse a malformed URL first. + +## Diagnostic Steps + +If the secret name is not obvious from the list, match on URL content. The `data.url` field is base64-encoded but `grep` will find the right one once you decode in a loop: + +```bash +for SECRET in $(kubectl -n cpaas-system get secret -o name | grep '^secret/repo-'); do + URL=$(kubectl -n cpaas-system get "$SECRET" -o jsonpath='{.data.url}' | base64 -d) + echo "$SECRET -> $URL" +done +``` + +Inspect the argocd-repo-server logs for the original parse failure — it confirms the root cause and is useful evidence when filing a ticket with an operator: + +```bash +kubectl -n cpaas-system logs -l app.kubernetes.io/name=argocd-repo-server --tail=100 +``` + +After deletion, verify Argo CD has reconciled its in-memory cache by fetching the API directly through a port-forward to the argocd-server service — the REST response should no longer include the deleted repository: + +```bash +kubectl -n cpaas-system port-forward svc/argocd-server 8080:443 & +curl -sk https://localhost:8080/api/v1/repositories \ + -H "Authorization: Bearer " \ + | jq '.items[].repo' +``` + +An absence of the offending URL confirms the fix has propagated through the Argo CD control plane. From ccac9edd179bad8fddd0b093f13f8ee707db7607 Mon Sep 17 00:00:00 2001 From: Komh Date: Sat, 2 May 2026 12:52:04 +0000 Subject: [PATCH 2/3] [gitops] Argo CD UI cannot delete a repository with an invalid URL --- ...Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md b/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md index f49526269..b94fedfa5 100644 --- a/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md +++ b/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md @@ -6,6 +6,8 @@ products: ProductsVersion: - 4.1.0,4.2.x --- + +# Argo CD UI cannot delete a repository with an invalid URL ## Issue A repository entry in the Argo CD UI is stuck in `Failed` status because the URL was entered incorrectly — missing scheme, invalid port, malformed host, or some other syntactic problem that Argo CD cannot parse. Attempting to remove the repository through the UI has no effect: clicking **Delete** either returns an error or silently leaves the row in place. From 8d5ca54f87c1c7efbdf646201e828bc3779f2e88 Mon Sep 17 00:00:00 2001 From: Komh Date: Sun, 17 May 2026 03:28:47 +0000 Subject: [PATCH 3/3] [gitops] Removing an Argo CD repository entry by deleting its backing Secret on ACP --- ...delete_a_repository_with_an_invalid_URL.md | 81 ------------------- ...y_by_deleting_its_backing_Secret_on_ACP.md | 39 +++++++++ 2 files changed, 39 insertions(+), 81 deletions(-) delete mode 100644 docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md create mode 100644 docs/en/solutions/Removing_an_Argo_CD_repository_entry_by_deleting_its_backing_Secret_on_ACP.md diff --git a/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md b/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md deleted file mode 100644 index b94fedfa5..000000000 --- a/docs/en/solutions/Argo_CD_UI_cannot_delete_a_repository_with_an_invalid_URL.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -kind: - - Troubleshooting -products: - - Alauda Container Platform -ProductsVersion: - - 4.1.0,4.2.x ---- - -# Argo CD UI cannot delete a repository with an invalid URL -## Issue - -A repository entry in the Argo CD UI is stuck in `Failed` status because the URL was entered incorrectly — missing scheme, invalid port, malformed host, or some other syntactic problem that Argo CD cannot parse. Attempting to remove the repository through the UI has no effect: clicking **Delete** either returns an error or silently leaves the row in place. - -## Root Cause - -Argo CD stores every repository definition as a Kubernetes `Secret` in the Argo CD namespace, labelled `argocd.argoproj.io/secret-type=repository`. The UI delete path validates and re-parses the repository URL before it issues the actual delete against the API; when the stored URL is malformed it cannot parse, the validation step fails, and the subsequent delete never runs. - -This is tracked as an upstream issue in the Argo CD project — see [argo-cd#8614](https://github.com/argoproj/argo-cd/issues/8614) for the bug and the workaround. The underlying object is a plain `Secret`, so deleting it through the Kubernetes API bypasses the broken UI path completely. - -## Resolution - -On ACP the GitOps capability is provided by the `gitops` component, which is itself based on Argo CD. The namespace hosting the Argo CD control plane is typically `cpaas-system` or whichever namespace your platform has configured for the GitOps instance; adjust the commands below to match. - -1. List every repository secret in the Argo CD namespace. They all start with `repo-`: - - ```bash - kubectl -n cpaas-system get secrets | grep '^repo-' - ``` - - Example output: - - ```text - repo-3148156268 Opaque 3 19s - ``` - -2. Decode the secret to confirm it is the one you want to remove. The repository URL is base64-encoded under `.data.url`: - - ```bash - kubectl -n cpaas-system get secret repo-3148156268 -o jsonpath='{.data.url}' | base64 -d - kubectl -n cpaas-system get secret repo-3148156268 -o jsonpath='{.data.type}' | base64 -d - kubectl -n cpaas-system get secret repo-3148156268 -o jsonpath='{.data.project}' | base64 -d - ``` - -3. Delete the secret. Argo CD watches the secrets in its namespace, so the repository disappears from the UI within a few seconds: - - ```bash - kubectl -n cpaas-system delete secret repo-3148156268 - ``` - -4. Refresh the Argo CD repositories page in the UI and confirm the row is gone. - -If the repository was referenced by an `Application`, that `Application` will move to `ComparisonError` after the delete. Either fix the URL and re-add the repository, or edit the `Application` to point at a valid source. The UI will now accept both operations because it no longer has to parse a malformed URL first. - -## Diagnostic Steps - -If the secret name is not obvious from the list, match on URL content. The `data.url` field is base64-encoded but `grep` will find the right one once you decode in a loop: - -```bash -for SECRET in $(kubectl -n cpaas-system get secret -o name | grep '^secret/repo-'); do - URL=$(kubectl -n cpaas-system get "$SECRET" -o jsonpath='{.data.url}' | base64 -d) - echo "$SECRET -> $URL" -done -``` - -Inspect the argocd-repo-server logs for the original parse failure — it confirms the root cause and is useful evidence when filing a ticket with an operator: - -```bash -kubectl -n cpaas-system logs -l app.kubernetes.io/name=argocd-repo-server --tail=100 -``` - -After deletion, verify Argo CD has reconciled its in-memory cache by fetching the API directly through a port-forward to the argocd-server service — the REST response should no longer include the deleted repository: - -```bash -kubectl -n cpaas-system port-forward svc/argocd-server 8080:443 & -curl -sk https://localhost:8080/api/v1/repositories \ - -H "Authorization: Bearer " \ - | jq '.items[].repo' -``` - -An absence of the offending URL confirms the fix has propagated through the Argo CD control plane. diff --git a/docs/en/solutions/Removing_an_Argo_CD_repository_entry_by_deleting_its_backing_Secret_on_ACP.md b/docs/en/solutions/Removing_an_Argo_CD_repository_entry_by_deleting_its_backing_Secret_on_ACP.md new file mode 100644 index 000000000..dd3ee974a --- /dev/null +++ b/docs/en/solutions/Removing_an_Argo_CD_repository_entry_by_deleting_its_backing_Secret_on_ACP.md @@ -0,0 +1,39 @@ +--- +kind: + - How To +products: + - Alauda Container Platform +ProductsVersion: + - 4.1.0,4.2.x +--- + +# Removing an Argo CD repository entry by deleting its backing Secret on ACP + +## Issue + +On Alauda Container Platform, Argo CD is delivered through the `argocd-operator` bundle (argo-cd image v3.x) and the installer chart deploys an `ArgoCD` CR (`argoproj.io/v1beta1`) into the `argocd` namespace; the same upstream argo-cd binary backs the UI, so the standard Repository CR contract carries over unchanged. Because each UI-added repository is materialised as a Kubernetes Secret in that namespace, the platform-level lifecycle of a repository entry is the lifecycle of its Secret — an administrator who needs to remove a stuck or unwanted repository entry must operate on the Secret directly when the Argo CD UI is not a viable path. + +## Resolution + +Delete the underlying repository Secret in the `argocd` namespace; the entry disappears from the Argo CD UI because the UI's repository list is derived from the standard secret-based mechanism that ACP inherits from upstream argo-cd via the `argocd-operator` bundle. The Secret follows the standard upstream shape — labelled `argocd.argoproj.io/secret-type: repository` and conventionally named `repo-` — so a plain `kubectl delete secret` is sufficient and no Argo CD API call is required: + +```bash +kubectl delete secret -n argocd repo- +``` + +Substitute `repo-` with the actual Secret name discovered via the diagnostic step below. Because the same secret-based mechanism applies on ACP as upstream, no operator-side reconciliation re-creates the entry from a separate source of truth once the Secret is gone. + +## Diagnostic Steps + +Identify the Secret that backs the target repository by listing every Secret whose name starts with `repo-` in the `argocd` namespace and decoding the `.data.url` field (base64) on each candidate to find the entry whose URL matches the offending repository. The Secret carries the standard upstream `.data` shape, so a one-shot jsonpath query plus `base64 -d` returns the URL set at repository-creation time: + +```bash +kubectl get secret -n argocd \ + -l argocd.argoproj.io/secret-type=repository \ + -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.data.url}{"\n"}{end}' \ + | while IFS=$'\t' read name url; do + echo "$name -> $(echo "$url" | base64 -d)" + done +``` + +Match the decoded URL against the repository the UI shows as stuck, note the corresponding Secret name (the `repo-` value), and feed it into the deletion command in the Resolution section. The same lookup-by-label approach works for every repository entry on ACP because the Repository CR contract is unchanged from upstream argo-cd as packaged by `argocd-operator`.