Skip to content

Add --ns-follows-kube-context global flag for using the kubeconfig context namespace#5831

Merged
matheuscscp merged 1 commit intofluxcd:mainfrom
jtyr:jtyr-context-ns
Apr 30, 2026
Merged

Add --ns-follows-kube-context global flag for using the kubeconfig context namespace#5831
matheuscscp merged 1 commit intofluxcd:mainfrom
jtyr:jtyr-context-ns

Conversation

@jtyr
Copy link
Copy Markdown
Contributor

@jtyr jtyr commented Apr 10, 2026

Problem

The flux CLI ignores the namespace set in the current kubeconfig context and always defaults to flux-system when --namespace is not explicitly provided. This means users who set a namespace via kubectl config set-context --current --namespace=... still have to pass -n on every flux command.

Fix: #3453

Fix

Resolve the namespace from the kubeconfig context when neither --namespace nor FLUX_SYSTEM_NAMESPACE is set. The flux-system default is preserved as the final fallback.

The resulting priority order (highest to lowest):

  1. --namespace / -n flag
  2. FLUX_SYSTEM_NAMESPACE environment variable
  3. Kubeconfig context namespace
  4. flux-system

The context lookup runs in PersistentPreRunE (after flag parsing), so it correctly respects --context and --kubeconfig flags when determining which context to read from.

Testing

Added unit tests covering:

  • Namespace returned from the current context
  • --context flag selecting a different context's namespace
  • Context with no namespace set (empty string)
  • Non-existent context
  • FLUX_SYSTEM_NAMESPACE taking precedence over context namespace
  • --namespace flag taking precedence over context namespace
  • Fallback to flux-system when context has no namespace

@jtyr jtyr force-pushed the jtyr-context-ns branch 2 times, most recently from 168c848 to 78b99e0 Compare April 10, 2026 07:34
@stefanprodan
Copy link
Copy Markdown
Member

stefanprodan commented Apr 10, 2026

This is a major breaking change that we can not accept. Imagine how many CI pipelines and custom scripts we are going to break with this, e.g. you have flux bootstrap in your pipeline, the default namespace in kubeconfig is to some namespace, with this change new clusters will end up with Flux in the selected namespace instead of flux-system.

@jtyr jtyr force-pushed the jtyr-context-ns branch from 78b99e0 to 642533e Compare April 10, 2026 08:00
@matheuscscp
Copy link
Copy Markdown
Member

We had lots of discussions around this over the years. This is a bug that became expected behavior at this point, so we cannot break it.


However, across discussions someone suggested an env var for opting into this behavior, which would not be a breaking change and I'd be ok with it. Env var or flag, not sure what's best, though.

@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 10, 2026

Thanks for the feedback, @stefanprodan. I understand your concern.

This behavior was discussed and classified as a bug in #3453, with the consensus being that the kubeconfig context namespace should be respected (see #3453 (comment)). That said, I understand the concern about breaking existing CI pipelines and scripts that rely on flux-system being the implicit default.

Would an opt-in approach work for now? For example, introducing a FLUX_NS_FOLLOWS_KUBE_CONTEXT environment variable that users can set to enable the context namespace resolution, while keeping the current behavior as the default. This way existing workflows remain unaffected and users who want this can explicitly opt in, with the option to make it the default in a future major version.

Or would you prefer a different approach entirely?

@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 10, 2026

Thanks for joining the discussion, @matheuscscp. How about supporting both?

  • A --ns-follows-kube-context flag, which can also be set via an alias (alias flux='/usr/bin/flux --ns-follows-kube-context')
  • A FLUX_NS_FOLLOWS_KUBE_CONTEXT environment variable (export FLUX_NS_FOLLOWS_KUBE_CONTEXT=1)

This follows the existing pattern where FLUX_SYSTEM_NAMESPACE provides an env var alternative. The flag gives per-command control, while the env var allows setting it globally in a shell profile or CI environment.

Would that be acceptable?

@matheuscscp
Copy link
Copy Markdown
Member

I have no objections to this solution

@jtyr jtyr force-pushed the jtyr-context-ns branch 3 times, most recently from e16ed58 to a1ddbb5 Compare April 10, 2026 13:22
@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 10, 2026

@matheuscscp @stefanprodan I have updated the implementation to make the context namespace resolution opt-in. It can be enabled via one of the following:

  • --ns-follows-kube-context flag (e.g. alias flux='flux --ns-follows-kube-context')
  • FLUX_NS_FOLLOWS_KUBE_CONTEXT env var (e.g. export FLUX_NS_FOLLOWS_KUBE_CONTEXT=1)

Without either of these, the existing behavior is preserved (flux-system remains the default).

Copy link
Copy Markdown
Member

@matheuscscp matheuscscp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jtyr jtyr force-pushed the jtyr-context-ns branch 2 times, most recently from bb43542 to 39e6c46 Compare April 13, 2026 07:40
Comment thread cmd/flux/main.go Outdated
// explicitly set and FLUX_SYSTEM_NAMESPACE env var is not set,
// respect the namespace from the kubeconfig context.
if (rootArgs.nsFollowsKubeContext || os.Getenv("FLUX_NS_FOLLOWS_KUBE_CONTEXT") != "") &&
!cmd.Flags().Changed("namespace") && os.Getenv("FLUX_SYSTEM_NAMESPACE") == "" {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand why FLUX_SYSTEM_NAMESPACE is checked here. I don't always care about that as my Flux resources may be scattered across multiple namespaces on the cluster. Why should this generally disregard the kubeconfig NS if FLUX_SYSTEM_NAMESPACE is set?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if FLUX_SYSTEM_NAMESPACE is not used when e.g. -n is set, then it makes no sense to be checked here, good catch!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the last commit.

Comment thread cmd/flux/main_context_ns_test.go Outdated
expectedNamespace: "context-ns",
},
{
name: "FLUX_SYSTEM_NAMESPACE takes precedence over context namespace",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this should be the expected behaviour as explained above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the last commit.

@jtyr jtyr force-pushed the jtyr-context-ns branch 2 times, most recently from 7cd113a to cde48c1 Compare April 13, 2026 17:13
@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 20, 2026

@stefanprodan Please could you review this again?

@jtyr jtyr force-pushed the jtyr-context-ns branch from cde48c1 to 33d2168 Compare April 22, 2026 13:12
@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 28, 2026

@stefanprodan @matheuscscp Any idea why the E2E test is failing?

@matheuscscp
Copy link
Copy Markdown
Member

@stefanprodan @matheuscscp Any idea why the E2E test is failing?

@jtyr I investigated this for a while with Opus 4.7 and this is how far I got:

  Failure: The Run tests step (make test --tags=unit) fails in cmd/flux with:                                                                                                                                 
  - TestTrace/* — "deployments.apps 'podinfo' not found" (and similar for HelmRelease)                                                                                                                        
  - TestTree/* — "kustomizations... 'flux-system' not found"                                                                                                                                                  
                                                            
  Root cause: the new test file cmd/flux/main_context_ns_test.go (added in the PR) leaks state into subsequent tests. I reproduced it locally:                                                                
                                                                                                                                                                                                              
  - TestTrace alone → passes                                                                                                                                                                                  
  - TestContextNamespaceOptIn alone → passes                                                                                                                                                                  
  - Both together → TestTrace fails with "not found" against the envtest API server                                                                                                                           
                                                                                                                                                                                                              
  The new TestContextNamespaceOptIn test mutates the package-global kubeconfigArgs (a *genericclioptions.ConfigFlags): swaps KubeConfig/Context pointers, calls configureDefaultNamespace(), calls            
  getKubeconfigContextNamespace() (which invokes kubeconfigArgs.ToRawKubeConfigLoader()). Even though the test's t.Cleanup restores the visible pointer fields, ConfigFlags internally caches a clientConfig  
  (see cli-runtime/pkg/genericclioptions/config_flags.go — clientConfig + clientConfigLock), and that cache is not reset. The cached loader was bound to the per-subtest temp kubeconfig (which got           
  t.TempDir-deleted), and bisecting the 6 subtests shows the failure only triggers when multiple subtests run together — consistent with cumulative cache poisoning.

  Fix direction: the new test shouldn't mutate the package-global kubeconfigArgs. Either build a local *genericclioptions.ConfigFlags for the test (e.g. genericclioptions.NewConfigFlags(false)) and refactor
   getKubeconfigContextNamespace to take it as a parameter, or have cleanup replace kubeconfigArgs with a freshly constructed instance (and then re-kubeconfigArgs.KubeConfig = &testEnv.kubeConfigPath) so
  the internal cache is discarded.

@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 28, 2026

Thanks for providing the analysis, @matheuscscp. I have refactored getKubeconfigContextNamespace to take a *genericclioptions.ConfigFlags parameter, eliminating its dependency on the package-global kubeconfigArgs. The getKubeconfigContextNamespace, called from PersistentPreRunE, now passes kubeconfigArgs explicitly. Tests now construct their own local genericclioptions.NewConfigFlags(false) instance per subtest. This means:

  • The internal clientConfig cache lives only on the local instance.
  • No mutation of kubeconfigArgs whatsoever.
  • No t.Cleanup needed for kubeconfigArgs state restoration.
  • Subsequent tests like TestTrace and TestTree see a clean global kubeconfigArgs.

Please run the tests again so we can see if it passes now.

@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 28, 2026

Cool, tests pass now. Can we merge it now? ;o)

@matheuscscp
Copy link
Copy Markdown
Member

This is a major breaking change that we can not accept. Imagine how many CI pipelines and custom scripts we are going to break with this, e.g. you have flux bootstrap in your pipeline, the default namespace in kubeconfig is to some namespace, with this change new clusters will end up with Flux in the selected namespace instead of flux-system.

@stefanprodan The implementation is no longer a breaking change, it's opt-in now. Can we merge?

@stefanprodan stefanprodan changed the title Respect kubeconfig context namespace Add --ns-follows-kube-context global flag for using the kubeconfig context namespace Apr 29, 2026
@stefanprodan stefanprodan added the enhancement New feature or request label Apr 29, 2026
@matheuscscp
Copy link
Copy Markdown
Member

@jtyr Please squash the commits into one matching the PR title and force-push so we can merge 🙏

@jtyr jtyr force-pushed the jtyr-context-ns branch from de17330 to aae7027 Compare April 29, 2026 07:30
@jtyr
Copy link
Copy Markdown
Contributor Author

jtyr commented Apr 30, 2026

@matheuscscp I have squashed the commits 👍

Signed-off-by: Jiri Tyr <jiri.tyr@gmail.com>
@jtyr jtyr force-pushed the jtyr-context-ns branch from aae7027 to c031d0c Compare April 30, 2026 07:19
@matheuscscp matheuscscp merged commit c8b4c4c into fluxcd:main Apr 30, 2026
6 checks passed
@matheuscscp
Copy link
Copy Markdown
Member

@jtyr Thanks very much! You may not realize, but this is quite a feature! Probably top 10 requested by users historically. We should do a bit of noise about it! Can you please open a PR here: https://github.com/fluxcd/website/blob/main/content/en/roadmap.md?plain=1#L108-L113

@makkes
Copy link
Copy Markdown
Member

makkes commented Apr 30, 2026

Absolutely agree that this is a feature much longed for! Thanks @jtyr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flux CLI tool doesn't respect context namespace

4 participants