From 199c98d52384b9b7d13d909e7f046c07111f3fdf Mon Sep 17 00:00:00 2001 From: MrJack <36191829+biagiopietro@users.noreply.github.com> Date: Sun, 30 Aug 2026 11:22:42 +0200 Subject: [PATCH] fix(action): fix --create-namespace ordering and clean up install dry-run=server path Move server-side dry-run validation to after namespace creation so that resources inside a not-yet-existing namespace do not get a 'not found' error when --create-namespace is also set. Also: error explicitly when --dry-run=server is combined with --server-side=false (client-side paths ignore the dry-run flag); harden the ForceReplace option to false (Update rejects SSA+ForceReplace); gate UpgradeClientSideFieldManager on TakeOwnership instead of passing true unconditionally. Signed-off-by: MrJack <36191829+biagiopietro@users.noreply.github.com> --- pkg/action/install.go | 62 ++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/pkg/action/install.go b/pkg/action/install.go index 894a9d332..640312368 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -419,36 +419,8 @@ func (i *Install) RunWithContext(ctx context.Context, ch ci.Charter, vals map[st } } - // Bail out here if it is a dry run - if isDryRun(i.DryRunStrategy) { - // For server-side dry-run, validate resources against the API server. - // Force server-side apply in this path because kube dry-run semantics are - // only honored by the server-side apply create/update code paths. - if i.DryRunStrategy == DryRunServer { - serverSideDryRun := true - var err error - if len(toBeAdopted) == 0 && len(resources) > 0 { - _, err = i.cfg.KubeClient.Create( - resources, - kube.ClientCreateOptionServerSideApply(serverSideDryRun, false), - kube.ClientCreateOptionDryRun(true), - ) - } else if len(resources) > 0 { - updateThreeWayMergeForUnstructured := i.TakeOwnership && !serverSideDryRun - _, err = i.cfg.KubeClient.Update( - toBeAdopted, - resources, - kube.ClientUpdateOptionForceReplace(i.ForceReplace), - kube.ClientUpdateOptionServerSideApply(serverSideDryRun, i.ForceConflicts), - kube.ClientUpdateOptionDryRun(true), - kube.ClientUpdateOptionThreeWayMergeForUnstructured(updateThreeWayMergeForUnstructured), - kube.ClientUpdateOptionUpgradeClientSideFieldManager(true), - ) - } - if err != nil { - return rel, err - } - } + // Bail out early for client-side dry run before any cluster interaction. + if isDryRun(i.DryRunStrategy) && i.DryRunStrategy != DryRunServer { rel.Info.Description = "Dry run complete" return rel, nil } @@ -482,6 +454,36 @@ func (i *Install) RunWithContext(ctx context.Context, ch ci.Charter, vals map[st } } + // For server-side dry-run, validate resources against the API server after + // namespace creation so resources inside that namespace resolve correctly. + if i.DryRunStrategy == DryRunServer { + if !i.ServerSideApply { + return rel, errors.New("--dry-run=server requires --server-side=true") + } + var err error + if len(toBeAdopted) == 0 && len(resources) > 0 { + _, err = i.cfg.KubeClient.Create( + resources, + kube.ClientCreateOptionServerSideApply(true, i.ForceConflicts), + kube.ClientCreateOptionDryRun(true), + ) + } else if len(resources) > 0 { + _, err = i.cfg.KubeClient.Update( + toBeAdopted, + resources, + kube.ClientUpdateOptionForceReplace(false), + kube.ClientUpdateOptionServerSideApply(true, i.ForceConflicts), + kube.ClientUpdateOptionDryRun(true), + kube.ClientUpdateOptionUpgradeClientSideFieldManager(i.TakeOwnership), + ) + } + if err != nil { + return rel, err + } + rel.Info.Description = "Dry run complete" + return rel, nil + } + // If Replace is true, we need to supersede the last release. if i.Replace { if err := i.replaceRelease(rel); err != nil {