unlock unlimited code runs for $79, limited time →
NOSSLETTER.techLIVE
back to OSSpedia
cli-designconfiguration-managementtesting-strategy

feat(cli): optionally exclude status field when using argocd admin export command

Project: argoproj/argo-cd | Language: Go | Concepts: cli-design, configuration-management, testing-strategy | Difficulty: mid
Link: https://github.com/argoproj/argo-cd/pull/29219

The problem

The argocd admin export CLI command exports Argo CD resources as YAML, but always includes the status field for each resource. This is problematic when users want a "clean" manifest set to re-apply with kubectl apply or store in git, because the status field is managed by controllers and should not be set by users. There was no way to exclude this field from the export.

Why it's non-trivial

A naive fix might simply remove the status field from some resource types, or post-process the YAML output. However, the argocd admin export command exports a variety of resources (Applications, ApplicationSets, Projects, ConfigMaps, Secrets, etc.), and only some of them have a status field. The solution needs to be generic, opt-in (to avoid breaking disaster-recovery workflows that depend on preserving status), and thoroughly tested to ensure it doesn't break existing exports or miss edge cases.

The approach

1. Add a CLI flag to control status stripping:

+	command.Flags().BoolVar(&stripStatus, "strip-status", false, "Strip status field from exported resources for a clean, re-creatable manifest set")

This adds a --strip-status boolean flag to the argocd admin export command, letting users opt in to removing the status field.

2. Thread the flag through all export calls:

All calls to the export function are updated to accept the new stripStatus argument:

-	export(writer, *acdConfigMap, namespace)
+	export(writer, *acdConfigMap, namespace, stripStatus)

This pattern is repeated for every resource type exported by the command.

3. Update the export logic to conditionally remove status:

-func export(w io.Writer, un unstructured.Unstructured, argocdNamespace string) {
+func export(w io.Writer, un unstructured.Unstructured, argocdNamespace string, stripStatus bool) {
    ...
 	unstructured.RemoveNestedField(un.Object, "metadata")
+	if stripStatus {
+		unstructured.RemoveNestedField(un.Object, "status")
+	}
    ...

The function now removes the status field from the resource's unstructured object if the flag is set.

4. Add comprehensive tests:

Table-driven tests are extended to cover the new flag and its effect on different resource types:

+		{
+			name:         "Application status should be stripped from the exported manifest when strip-status is set",
+			object:       newApplication("argocd"),
+			namespace:    "argocd",
+			stripStatus:  true,
+			expectExport: true,
+			expectedFileContent: `apiVersion: ""
+kind: Application
+metadata:
+  name: test
+spec:
+  destination:
+    namespace: default
+    server: https://kubernetes.default.svc
+  project: default
+  source:
+    repoURL: ""
+---
+`,
+		},

Similar cases are added for ApplicationSets, Projects, ConfigMaps, and Secrets, ensuring that only resources with a status field are affected.

5. Document the new behavior:

The operator manual is updated to explain the new flag and its intended use cases:

+## Exporting a clean, re-creatable manifest set
+...
+If instead you want a clean backup that can be applied directly with `kubectl apply` or re-created from scratch (for example, to seed a new cluster or store manifests in git), pass `--strip-status` to omit the `status` field from the export:
+
+```bash
+argocd admin export --strip-status > backup.yaml
+kubectl apply -f backup.yaml
+```

The CLI reference is also updated to include the new flag.

From the review thread

No notable review discussion on this PR.

Takeaways

  • Design CLI flags for opt-in behavior when changing default output could break existing workflows.
  • When exporting resources for re-creation, exclude controller-managed fields like status to avoid invalid or noisy manifests.
  • Comprehensive, table-driven tests are crucial when changing export/import logic to ensure all resource types and flag combinations are covered.