pull/31195/merge
Matt Farina 2 weeks ago committed by GitHub
commit e2ccacf2dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -94,7 +94,6 @@ type Install struct {
DisableHooks bool DisableHooks bool
Replace bool Replace bool
WaitStrategy kube.WaitStrategy WaitStrategy kube.WaitStrategy
WaitForJobs bool
Devel bool Devel bool
DependencyUpdate bool DependencyUpdate bool
Timeout time.Duration Timeout time.Duration
@ -512,11 +511,7 @@ func (i *Install) performInstall(rel *release.Release, toBeAdopted kube.Resource
return rel, fmt.Errorf("failed to get waiter: %w", err) return rel, fmt.Errorf("failed to get waiter: %w", err)
} }
if i.WaitForJobs { err = waiter.Wait(resources, i.Timeout)
err = waiter.WaitWithJobs(resources, i.Timeout)
} else {
err = waiter.Wait(resources, i.Timeout)
}
if err != nil { if err != nil {
return rel, err return rel, err
} }

@ -569,22 +569,6 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
time.Sleep(10 * time.Second) // wait for goroutine to finish time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, instAction.getGoroutineCount()) is.Equal(goroutines, instAction.getGoroutineCount())
} }
func TestInstallRelease_WaitForJobs(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
instAction.cfg.KubeClient = failer
instAction.WaitStrategy = kube.StatusWatcherStrategy
instAction.WaitForJobs = true
vals := map[string]interface{}{}
res, err := instAction.Run(buildChart(), vals)
is.Error(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed)
}
func TestInstallRelease_RollbackOnFailure(t *testing.T) { func TestInstallRelease_RollbackOnFailure(t *testing.T) {
is := assert.New(t) is := assert.New(t)

@ -38,7 +38,6 @@ type Rollback struct {
Version int Version int
Timeout time.Duration Timeout time.Duration
WaitStrategy kube.WaitStrategy WaitStrategy kube.WaitStrategy
WaitForJobs bool
DisableHooks bool DisableHooks bool
DryRun bool DryRun bool
// ForceReplace will, if set to `true`, ignore certain warnings and perform the rollback anyway. // ForceReplace will, if set to `true`, ignore certain warnings and perform the rollback anyway.
@ -238,20 +237,12 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to set metadata visitor from target release: %w", err) return nil, fmt.Errorf("unable to set metadata visitor from target release: %w", err)
} }
if r.WaitForJobs {
if err := waiter.WaitWithJobs(target, r.Timeout); err != nil { if err := waiter.Wait(target, r.Timeout); err != nil {
targetRelease.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", targetRelease.Name, err.Error())) targetRelease.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", targetRelease.Name, err.Error()))
r.cfg.recordRelease(currentRelease) r.cfg.recordRelease(currentRelease)
r.cfg.recordRelease(targetRelease) r.cfg.recordRelease(targetRelease)
return targetRelease, fmt.Errorf("release %s failed: %w", targetRelease.Name, err) return targetRelease, fmt.Errorf("release %s failed: %w", targetRelease.Name, err)
}
} else {
if err := waiter.Wait(target, r.Timeout); err != nil {
targetRelease.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", targetRelease.Name, err.Error()))
r.cfg.recordRelease(currentRelease)
r.cfg.recordRelease(targetRelease)
return targetRelease, fmt.Errorf("release %s failed: %w", targetRelease.Name, err)
}
} }
// post-rollback hooks // post-rollback hooks

@ -68,8 +68,6 @@ type Upgrade struct {
Timeout time.Duration Timeout time.Duration
// WaitStrategy determines what type of waiting should be done // WaitStrategy determines what type of waiting should be done
WaitStrategy kube.WaitStrategy WaitStrategy kube.WaitStrategy
// WaitForJobs determines whether the wait operation for the Jobs should be performed after the upgrade is requested.
WaitForJobs bool
// DisableHooks disables hook processing if set to true. // DisableHooks disables hook processing if set to true.
DisableHooks bool DisableHooks bool
// DryRun controls whether the operation is prepared, but not executed. // DryRun controls whether the operation is prepared, but not executed.
@ -470,18 +468,10 @@ func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *rele
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err) u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
return return
} }
if u.WaitForJobs { if err := waiter.Wait(target, u.Timeout); err != nil {
if err := waiter.WaitWithJobs(target, u.Timeout); err != nil { u.cfg.recordRelease(originalRelease)
u.cfg.recordRelease(originalRelease) u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err) return
return
}
} else {
if err := waiter.Wait(target, u.Timeout); err != nil {
u.cfg.recordRelease(originalRelease)
u.reportToPerformUpgrade(c, upgradedRelease, results.Created, err)
return
}
} }
// post-upgrade hooks // post-upgrade hooks
@ -555,7 +545,6 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
if u.WaitStrategy == kube.HookOnlyStrategy { if u.WaitStrategy == kube.HookOnlyStrategy {
rollin.WaitStrategy = kube.StatusWatcherStrategy rollin.WaitStrategy = kube.StatusWatcherStrategy
} }
rollin.WaitForJobs = u.WaitForJobs
rollin.DisableHooks = u.DisableHooks rollin.DisableHooks = u.DisableHooks
rollin.ForceReplace = u.ForceReplace rollin.ForceReplace = u.ForceReplace
rollin.ForceConflicts = u.ForceConflicts rollin.ForceConflicts = u.ForceConflicts

@ -93,29 +93,6 @@ func TestUpgradeRelease_Wait(t *testing.T) {
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(res.Info.Status, release.StatusFailed)
} }
func TestUpgradeRelease_WaitForJobs(t *testing.T) {
is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
rel.Name = "come-fail-away"
rel.Info.Status = release.StatusDeployed
upAction.cfg.Releases.Create(rel)
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
upAction.cfg.KubeClient = failer
upAction.WaitStrategy = kube.StatusWatcherStrategy
upAction.WaitForJobs = true
vals := map[string]interface{}{}
res, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err)
is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed)
}
func TestUpgradeRelease_CleanupOnFail(t *testing.T) { func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t) req := require.New(t)

@ -201,7 +201,6 @@ func addInstallFlags(cmd *cobra.Command, f *pflag.FlagSet, client *action.Instal
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install") f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during install")
f.BoolVar(&client.Replace, "replace", false, "reuse the given name, only if that name is a deleted release which remains in the history. This is unsafe in production") f.BoolVar(&client.Replace, "replace", false, "reuse the given name, only if that name is a deleted release which remains in the history. This is unsafe in production")
f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)") f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&client.WaitForJobs, "wait-for-jobs", false, "if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout")
f.BoolVarP(&client.GenerateName, "generate-name", "g", false, "generate the name (and omit the NAME parameter)") f.BoolVarP(&client.GenerateName, "generate-name", "g", false, "generate the name (and omit the NAME parameter)")
f.StringVar(&client.NameTemplate, "name-template", "", "specify template used to name the release") f.StringVar(&client.NameTemplate, "name-template", "", "specify template used to name the release")
f.StringVar(&client.Description, "description", "", "add a custom description") f.StringVar(&client.Description, "description", "", "add a custom description")

@ -114,12 +114,6 @@ func TestInstall(t *testing.T) {
cmd: "install apollo testdata/testcharts/empty --wait", cmd: "install apollo testdata/testcharts/empty --wait",
golden: "output/install-with-wait.txt", golden: "output/install-with-wait.txt",
}, },
// Install, with wait-for-jobs
{
name: "install with wait-for-jobs",
cmd: "install apollo testdata/testcharts/empty --wait --wait-for-jobs",
golden: "output/install-with-wait-for-jobs.txt",
},
// Install, using the name-template // Install, using the name-template
{ {
name: "install with name-template", name: "install with name-template",

@ -84,7 +84,6 @@ func newRollbackCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.StringVar(&client.ServerSideApply, "server-side", "auto", "must be \"true\", \"false\" or \"auto\". Object updates run in the server instead of the client (\"auto\" defaults the value from the previous chart release's method)") f.StringVar(&client.ServerSideApply, "server-side", "auto", "must be \"true\", \"false\" or \"auto\". Object updates run in the server instead of the client (\"auto\" defaults the value from the previous chart release's method)")
f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during rollback") f.BoolVar(&client.DisableHooks, "no-hooks", false, "prevent hooks from running during rollback")
f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)") f.DurationVar(&client.Timeout, "timeout", 300*time.Second, "time to wait for any individual Kubernetes operation (like Jobs for hooks)")
f.BoolVar(&client.WaitForJobs, "wait-for-jobs", false, "if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&client.CleanupOnFail, "cleanup-on-fail", false, "allow deletion of new resources created in this rollback when rollback fails") f.BoolVar(&client.CleanupOnFail, "cleanup-on-fail", false, "allow deletion of new resources created in this rollback when rollback fails")
f.IntVar(&client.MaxHistory, "history-max", settings.MaxHistory, "limit the maximum number of revisions saved per release. Use 0 for no limit") f.IntVar(&client.MaxHistory, "history-max", settings.MaxHistory, "limit the maximum number of revisions saved per release. Use 0 for no limit")
AddWaitFlag(cmd, &client.WaitStrategy) AddWaitFlag(cmd, &client.WaitStrategy)

@ -56,11 +56,6 @@ func TestRollbackCmd(t *testing.T) {
cmd: "rollback funny-honey 1 --wait", cmd: "rollback funny-honey 1 --wait",
golden: "output/rollback-wait.txt", golden: "output/rollback-wait.txt",
rels: rels, rels: rels,
}, {
name: "rollback a release with wait-for-jobs",
cmd: "rollback funny-honey 1 --wait --wait-for-jobs",
golden: "output/rollback-wait-for-jobs.txt",
rels: rels,
}, { }, {
name: "rollback a release without revision", name: "rollback a release without revision",
cmd: "rollback funny-honey", cmd: "rollback funny-honey",

@ -1,7 +0,0 @@
NAME: apollo
LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None

@ -1 +0,0 @@
Rollback was a success! Happy Helming!

@ -1,8 +0,0 @@
Release "crazy-bunny" has been upgraded. Happy Helming!
NAME: crazy-bunny
LAST DEPLOYED: Fri Sep 2 22:04:05 1977
NAMESPACE: default
STATUS: deployed
REVISION: 3
DESCRIPTION: Upgrade complete
TEST SUITE: None

@ -137,7 +137,6 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
instClient.SkipCRDs = client.SkipCRDs instClient.SkipCRDs = client.SkipCRDs
instClient.Timeout = client.Timeout instClient.Timeout = client.Timeout
instClient.WaitStrategy = client.WaitStrategy instClient.WaitStrategy = client.WaitStrategy
instClient.WaitForJobs = client.WaitForJobs
instClient.Devel = client.Devel instClient.Devel = client.Devel
instClient.Namespace = client.Namespace instClient.Namespace = client.Namespace
instClient.RollbackOnFailure = client.RollbackOnFailure instClient.RollbackOnFailure = client.RollbackOnFailure
@ -283,7 +282,6 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.BoolVar(&client.ResetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart") f.BoolVar(&client.ResetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
f.BoolVar(&client.ReuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored") f.BoolVar(&client.ReuseValues, "reuse-values", false, "when upgrading, reuse the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' is specified, this is ignored")
f.BoolVar(&client.ResetThenReuseValues, "reset-then-reuse-values", false, "when upgrading, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' or '--reuse-values' is specified, this is ignored") f.BoolVar(&client.ResetThenReuseValues, "reset-then-reuse-values", false, "when upgrading, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from the command line via --set and -f. If '--reset-values' or '--reuse-values' is specified, this is ignored")
f.BoolVar(&client.WaitForJobs, "wait-for-jobs", false, "if set and --wait enabled, will wait until all Jobs have been completed before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&client.RollbackOnFailure, "rollback-on-failure", false, "if set, Helm will rollback the upgrade to previous success release upon failure. The --wait flag will be defaulted to \"watcher\" if --rollback-on-failure is set") f.BoolVar(&client.RollbackOnFailure, "rollback-on-failure", false, "if set, Helm will rollback the upgrade to previous success release upon failure. The --wait flag will be defaulted to \"watcher\" if --rollback-on-failure is set")
f.BoolVar(&client.RollbackOnFailure, "atomic", false, "deprecated") f.BoolVar(&client.RollbackOnFailure, "atomic", false, "deprecated")
f.MarkDeprecated("atomic", "use --rollback-on-failure instead") f.MarkDeprecated("atomic", "use --rollback-on-failure instead")

@ -139,12 +139,6 @@ func TestUpgradeCmd(t *testing.T) {
golden: "output/upgrade-with-wait.txt", golden: "output/upgrade-with-wait.txt",
rels: []*release.Release{relMock("crazy-bunny", 2, ch2)}, rels: []*release.Release{relMock("crazy-bunny", 2, ch2)},
}, },
{
name: "upgrade a release with wait-for-jobs",
cmd: fmt.Sprintf("upgrade crazy-bunny --wait --wait-for-jobs '%s'", chartPath),
golden: "output/upgrade-with-wait-for-jobs.txt",
rels: []*release.Release{relMock("crazy-bunny", 2, ch2)},
},
{ {
name: "upgrade a release with missing dependencies", name: "upgrade a release with missing dependencies",
cmd: fmt.Sprintf("upgrade bonkers-bunny %s", missingDepsPath), cmd: fmt.Sprintf("upgrade bonkers-bunny %s", missingDepsPath),

@ -756,7 +756,7 @@ func TestWaitJob(t *testing.T) {
t.Errorf("expected 1 resource created, got %d", len(result.Created)) t.Errorf("expected 1 resource created, got %d", len(result.Created))
} }
if err := c.WaitWithJobs(resources, time.Second*30); err != nil { if err := c.Wait(resources, time.Second*30); err != nil {
t.Errorf("expected wait without error, got %s", err) t.Errorf("expected wait without error, got %s", err)
} }

@ -84,14 +84,6 @@ func (f *FailingKubeWaiter) Wait(resources kube.ResourceList, d time.Duration) e
return f.PrintingKubeWaiter.Wait(resources, d) return f.PrintingKubeWaiter.Wait(resources, d)
} }
// WaitWithJobs returns the configured error if set or prints
func (f *FailingKubeWaiter) WaitWithJobs(resources kube.ResourceList, d time.Duration) error {
if f.waitError != nil {
return f.waitError
}
return f.PrintingKubeWaiter.WaitWithJobs(resources, d)
}
// WaitForDelete returns the configured error if set or prints // WaitForDelete returns the configured error if set or prints
func (f *FailingKubeWaiter) WaitForDelete(resources kube.ResourceList, d time.Duration) error { func (f *FailingKubeWaiter) WaitForDelete(resources kube.ResourceList, d time.Duration) error {
if f.waitForDeleteError != nil { if f.waitForDeleteError != nil {

@ -70,11 +70,6 @@ func (p *PrintingKubeWaiter) Wait(resources kube.ResourceList, _ time.Duration)
return err return err
} }
func (p *PrintingKubeWaiter) WaitWithJobs(resources kube.ResourceList, _ time.Duration) error {
_, err := io.Copy(p.Out, bufferize(resources))
return err
}
func (p *PrintingKubeWaiter) WaitForDelete(resources kube.ResourceList, _ time.Duration) error { func (p *PrintingKubeWaiter) WaitForDelete(resources kube.ResourceList, _ time.Duration) error {
_, err := io.Copy(p.Out, bufferize(resources)) _, err := io.Copy(p.Out, bufferize(resources))
return err return err

@ -58,9 +58,6 @@ type Waiter interface {
// Wait waits up to the given timeout for the specified resources to be ready. // Wait waits up to the given timeout for the specified resources to be ready.
Wait(resources ResourceList, timeout time.Duration) error Wait(resources ResourceList, timeout time.Duration) error
// WaitWithJobs wait up to the given timeout for the specified resources to be ready, including jobs.
WaitWithJobs(resources ResourceList, timeout time.Duration) error
// WaitForDelete wait up to the given timeout for the specified resources to be deleted. // WaitForDelete wait up to the given timeout for the specified resources to be deleted.
WaitForDelete(resources ResourceList, timeout time.Duration) error WaitForDelete(resources ResourceList, timeout time.Duration) error

@ -74,14 +74,6 @@ func (w *statusWaiter) WatchUntilReady(resourceList ResourceList, timeout time.D
} }
func (w *statusWaiter) Wait(resourceList ResourceList, timeout time.Duration) error { func (w *statusWaiter) Wait(resourceList ResourceList, timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel()
slog.Debug("waiting for resources", "count", len(resourceList), "timeout", timeout)
sw := watcher.NewDefaultStatusWatcher(w.client, w.restMapper)
return w.wait(ctx, resourceList, sw)
}
func (w *statusWaiter) WaitWithJobs(resourceList ResourceList, timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.TODO(), timeout) ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel() defer cancel()
slog.Debug("waiting for resources", "count", len(resourceList), "timeout", timeout) slog.Debug("waiting for resources", "count", len(resourceList), "timeout", timeout)
@ -226,10 +218,6 @@ func (w *hookOnlyWaiter) Wait(_ ResourceList, _ time.Duration) error {
return nil return nil
} }
func (w *hookOnlyWaiter) WaitWithJobs(_ ResourceList, _ time.Duration) error {
return nil
}
func (w *hookOnlyWaiter) WaitForDelete(_ ResourceList, _ time.Duration) error { func (w *hookOnlyWaiter) WaitForDelete(_ ResourceList, _ time.Duration) error {
return nil return nil
} }

@ -274,19 +274,11 @@ func TestStatusWait(t *testing.T) {
name string name string
objManifests []string objManifests []string
expectErrs []error expectErrs []error
waitForJobs bool
}{ }{
{ {
name: "Job is not complete", name: "Job is not complete",
objManifests: []string{jobNoStatusManifest}, objManifests: []string{jobNoStatusManifest},
expectErrs: []error{errors.New("resource not ready, name: test, kind: Job, status: InProgress"), errors.New("context deadline exceeded")}, expectErrs: []error{errors.New("resource not ready, name: test, kind: Job, status: InProgress"), errors.New("context deadline exceeded")},
waitForJobs: true,
},
{
name: "Job is ready but not complete",
objManifests: []string{jobReadyManifest},
expectErrs: nil,
waitForJobs: false,
}, },
{ {
name: "Pod is ready", name: "Pod is ready",
@ -380,7 +372,7 @@ func TestWaitForJobComplete(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
} }
resourceList := getResourceListFromRuntimeObjs(t, c, objs) resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WaitWithJobs(resourceList, time.Second*3) err := statusWaiter.Wait(resourceList, time.Second*3)
if tt.expectErrs != nil { if tt.expectErrs != nil {
assert.EqualError(t, err, errors.Join(tt.expectErrs...).Error()) assert.EqualError(t, err, errors.Join(tt.expectErrs...).Error())
return return

@ -52,11 +52,6 @@ type legacyWaiter struct {
} }
func (hw *legacyWaiter) Wait(resources ResourceList, timeout time.Duration) error { func (hw *legacyWaiter) Wait(resources ResourceList, timeout time.Duration) error {
hw.c = NewReadyChecker(hw.kubeClient, PausedAsReady(true))
return hw.waitForResources(resources, timeout)
}
func (hw *legacyWaiter) WaitWithJobs(resources ResourceList, timeout time.Duration) error {
hw.c = NewReadyChecker(hw.kubeClient, PausedAsReady(true), CheckJobs(true)) hw.c = NewReadyChecker(hw.kubeClient, PausedAsReady(true), CheckJobs(true))
return hw.waitForResources(resources, timeout) return hw.waitForResources(resources, timeout)
} }

Loading…
Cancel
Save