fix(action): do not mutate shared Configuration in client-only install

When Install.Run runs with DryRunStrategy=DryRunClient (client-only),
it previously replaced cfg.KubeClient, cfg.Releases, and cfg.Capabilities
on the shared Configuration pointer. Subsequent actions reusing that
cfg then silently used the fake client / in-memory storage.

Copy the Configuration for the client-only path so mocks stay local to
the run, matching the scenario in #11463.

Fixes #11463

Signed-off-by: Dean Chen <862469039@qq.com>
pull/32431/head
Dean Chen 2 months ago
parent 3f1f55c4c8
commit 4458a191b3
No known key found for this signature in database
GPG Key ID: 03656C0AA9B7E279

@ -327,6 +327,16 @@ func (i *Install) RunWithContext(ctx context.Context, ch ci.Charter, vals map[st
}
if !interactWithServer(i.DryRunStrategy) {
// Work on a local copy of the Configuration so client-only mocks
// (fake KubeClient, in-memory Releases, default Capabilities) do
// not mutate the shared *Configuration passed to NewInstall.
// Callers that reuse the same cfg for a later real install must
// still observe the original client and storage. See #11463.
origCfg := i.cfg
cfgCopy := *i.cfg
i.cfg = &cfgCopy
defer func() { i.cfg = origCfg }()
// Add mock objects in here so it doesn't use Kube API server
// NOTE(bacongobbler): used for `helm template`
i.cfg.Capabilities = common.DefaultCapabilities.Copy()

@ -1316,3 +1316,39 @@ func TestInstallRelease_WaitOptionsPassedDownstream(t *testing.T) {
// Verify that WaitOptions were passed to GetWaiter
is.NotEmpty(failer.RecordedWaitOptions, "WaitOptions should be passed to GetWaiter")
}
// TestInstallDryRunClientDoesNotMutateSharedConfiguration ensures that a
// client-only install does not permanently replace the shared Configuration's
// KubeClient, Releases, or Capabilities (issue #11463).
func TestInstallDryRunClientDoesNotMutateSharedConfiguration(t *testing.T) {
req := require.New(t)
config := actionConfigFixture(t)
originalKubeClient := config.KubeClient
originalCapabilities := config.Capabilities
originalReleases := config.Releases
clientOnly := NewInstall(config)
clientOnly.DryRunStrategy = DryRunClient
clientOnly.ReleaseName = "test-client-only"
clientOnly.Namespace = "spaced"
_, err := clientOnly.Run(buildChart(), nil)
req.NoError(err)
req.Same(originalKubeClient, config.KubeClient, "KubeClient must not be replaced by client-only install")
req.Same(originalCapabilities, config.Capabilities, "Capabilities must not be replaced by client-only install")
req.Same(originalReleases, config.Releases, "Releases must not be replaced by client-only install")
// A subsequent real install sharing the same Configuration must still work.
realInstall := NewInstall(config)
realInstall.DryRunStrategy = DryRunNone
realInstall.ReleaseName = "test-real-install"
realInstall.Namespace = "spaced"
_, err = realInstall.Run(buildChart(), nil)
req.NoError(err)
req.Same(originalKubeClient, config.KubeClient, "KubeClient must still be original after real install")
req.Same(originalReleases, config.Releases, "Releases must still be original after real install")
}

Loading…
Cancel
Save