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 {