Skip to content

(go/v4) kubebuilder edit silently reverts a namespaced project to cluster-scoped when --namespaced is omitted #5752

Description

@camilamacedo86

What broke? What's expected?

In editScaffolder.Scaffold (pkg/plugins/golang/v4/scaffolds/edit.go),
both toggles are applied unconditionally:

if s.namespaced {
    _ = s.config.SetNamespaced()
} else {
    _ = s.config.ClearNamespaced()
}
// same pattern for multigroup

The flags default to false, so any kubebuilder edit invocation that
omits --namespaced is treated as an explicit request to disable it.
On a namespaced project this clears namespaced: true from the PROJECT
file, and the !s.namespaced && wasNamespaced transition then scaffolds
ClusterRole and ClusterRoleBinding, overwriting config/rbac/role.yaml
and config/rbac/role_binding.yaml (those templates hardcode
OverwriteFile). In short: running kubebuilder edit --multigroup on a
namespaced project converts it back to cluster-scoped without being
asked. Since edit has also gained --license and --owner flags on
master, even kubebuilder edit --license apache2 now flips the scope.

This bites the alpha generate flow directly. getInitArgs correctly
passes --namespaced to init, but kubebuilderEdit then runs
kubebuilder edit --multigroup for multigroup projects. So regenerating
a project that is both multigroup and namespaced produces an
inconsistent result: cmd/main.go and config/manager/manager.yaml
keep the WATCH_NAMESPACE code (scaffolded by init), but the PROJECT file
loses namespaced: true, RBAC reverts to ClusterRole, and controllers
created afterwards get markers without namespace=.

The tests in pkg/cli/alpha/internal/generate_test.go do not catch
this. The "both multigroup and namespaced" test only asserts that the
init args contain --namespaced and that kubebuilderEdit returns no
error. The namespaced-only edit test is vacuous because no command runs
at all (only multigroup triggers an edit), and nothing asserts that the
edit step preserves the namespaced setting, which is exactly where the
regression happens.

Expected: an omitted flag means "leave as is". Only a flag the user
actually passed should toggle project state, and alpha generate should
preserve the namespaced setting through the edit step.

How to reproduce

Scenario 1, plain edit flips the scope:

kubebuilder init --domain example.com --namespaced
kubebuilder create api --group app --version v1 --kind Foo --resource --controller
grep namespaced PROJECT          # shows namespaced: true
kubebuilder edit --multigroup
grep namespaced PROJECT          # gone, project is cluster-scoped again
head config/rbac/role.yaml       # now kind: ClusterRole

Scenario 2, alpha generate breaks multigroup plus namespaced projects:

# on a project that has both multigroup: true and namespaced: true
kubebuilder alpha generate
# the regenerated project has WATCH_NAMESPACE in main.go and manager.yaml,
# but PROJECT lost namespaced: true and RBAC is ClusterRole

Suggested fix

Master already stores the flag set on the subcommand (p.fs = fs in
BindFlags), so the scaffolder can ask whether a flag was actually
provided. Gate each toggle on fs.Changed("namespaced") and
fs.Changed("multigroup") so that omitted flags leave the current
configuration untouched. In addition, make kubebuilderEdit in
pkg/cli/alpha/internal/generate.go pass --namespaced when the stored
config has it, so alpha generate round-trips the setting.

Add tests that cover the real scenario: a namespaced project where
edit runs without --namespaced must keep namespaced: true, and the
alpha generate flow for a multigroup plus namespaced project must end
with both settings present in the PROJECT file.

KubeBuilder (CLI) Version

master (introduced by #5411)

Metadata

Metadata

Assignees

Labels

kind/bugCategorizes issue or PR as related to a bug.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions