rollout timeout values instantiated

rollback timeout set

rollback timeout unit tests complete

Signed-off-by: Lucas Lu <lucasludev@gmail.com>
pull/10457/head
Lucas Lu 4 years ago
parent 8ca401398d
commit ff7bc0883d

@ -81,6 +81,7 @@ func newRollbackCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f.BoolVar(&client.Force, "force", false, "force resource update through delete/recreate if needed")
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.RollbackTimeout, "rollback-timeout", 3000*time.Second, "time to wait for entire rollback operation")
f.BoolVar(&client.Wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as --timeout")
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")

@ -49,6 +49,11 @@ func TestRollbackCmd(t *testing.T) {
cmd: "rollback funny-honey 1 --timeout 120s",
golden: "output/rollback-timeout.txt",
rels: rels,
}, {
name: "rollback a release with rollback timeout",
cmd: "rollback funny-honey 1 --rollback-timeout 300s",
golden: "output/rollback-timeout.txt",
rels: rels,
}, {
name: "rollback a release with wait",
cmd: "rollback funny-honey 1 --wait",

@ -18,6 +18,7 @@ package action
import (
"bytes"
"context"
"fmt"
"strings"
"time"
@ -37,6 +38,7 @@ type Rollback struct {
Version int
Timeout time.Duration
RollbackTimeout time.Duration
Wait bool
WaitForJobs bool
DisableHooks bool
@ -54,8 +56,66 @@ func NewRollback(cfg *Configuration) *Rollback {
}
}
// TESTING ONLY
func (r *Rollback) RunTest(name string, sleep time.Duration) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
eChan := make(chan error)
go func() {
err := r.RunWithSleep(ctx, name, sleep)
eChan <- err
}()
var err error
select {
case <-time.After(r.RollbackTimeout):
cancel()
case err = <-eChan:
break
}
if err != nil {
return err
}
return nil
}
// Run executes 'helm rollback' against the given release.
func (r *Rollback) Run(name string) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
eChan := make(chan error)
go func() {
err := r.RunWithContext(ctx, name)
eChan <- err
}()
var err error
select {
case <-time.After(r.RollbackTimeout):
cancel()
case err = <-eChan:
break
}
if err != nil {
return err
}
return nil
}
// TESTING ONLY
func (r *Rollback) RunWithSleep(ctx context.Context, name string, sleep time.Duration) error {
time.Sleep(sleep)
return r.RunWithContext(ctx, name)
}
// Run executes 'helm rollback' against the given release with a given context
func (r *Rollback) RunWithContext(ctx context.Context, name string) error {
if err := r.cfg.KubeClient.IsReachable(); err != nil {
return err
}

@ -0,0 +1,109 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package action
import (
"testing"
"time"
kubefake "helm.sh/helm/v3/pkg/kube/fake"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v3/pkg/release"
)
func rollbackAction(t *testing.T) *Rollback {
config := actionConfigFixture(t)
rollAction := NewRollback(config)
rollAction.Timeout = 30 * time.Second
rollAction.RollbackTimeout = 60 * time.Second
return rollAction
}
func TestRollback_Base(t *testing.T) {
is := assert.New(t)
req := require.New(t)
rollAction := rollbackAction(t)
currentReleaseName := "rollback-base"
// Create v1 release
rel1 := releaseStub()
rel1.Name = currentReleaseName
rel1.Version = 1
rel1.Info.Status = release.StatusSuperseded
// Create v2 release
rel2 := releaseStub()
rel2.Name = currentReleaseName
rel2.Version = 2
rel2.Info.Status = release.StatusDeployed
rollAction.cfg.Releases.Create(rel1)
rollAction.cfg.Releases.Create(rel2)
fakeClient := rollAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
rollAction.cfg.KubeClient = fakeClient
rollAction.Run(currentReleaseName)
curr, err := rollAction.cfg.Releases.Last(currentReleaseName)
req.NoError(err)
is.Equal(3, curr.Version)
is.Equal(release.StatusDeployed, curr.Info.Status)
is.Equal("Rollback to 1", curr.Info.Description)
v2, err := rollAction.cfg.Releases.Get(currentReleaseName, 2)
req.NoError(err)
is.Equal(2, v2.Version)
is.Equal(release.StatusSuperseded, v2.Info.Status)
}
func TestRollback_RollbackTimeout(t *testing.T) {
is := assert.New(t)
req := require.New(t)
rollAction := rollbackAction(t)
rollAction.RollbackTimeout = 1 * time.Second
currentReleaseName := "rollback-rollback-timeout"
// Create v1 release
rel1 := releaseStub()
rel1.Name = currentReleaseName
rel1.Version = 1
rel1.Info.Status = release.StatusSuperseded
// Create v2 release
rel2 := releaseStub()
rel2.Name = currentReleaseName
rel2.Version = 2
rel2.Info.Status = release.StatusDeployed
rollAction.cfg.Releases.Create(rel1)
rollAction.cfg.Releases.Create(rel2)
fakeClient := rollAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
rollAction.cfg.KubeClient = fakeClient
rollAction.RunTest(currentReleaseName, 3*time.Second)
curr, err := rollAction.cfg.Releases.Last(currentReleaseName)
req.NoError(err)
is.Equal(2, curr.Version)
is.Equal(release.StatusDeployed, curr.Info.Status)
is.Equal("Named Release Stub", curr.Info.Description)
}

@ -61,8 +61,10 @@ type Upgrade struct {
Namespace string
// SkipCRDs skips installing CRDs when install flag is enabled during upgrade
SkipCRDs bool
// Timeout is the timeout for this operation
// Timeout is the timeout for individual hooks/kubernetes operations
Timeout time.Duration
// UpgradeTimeout is the timeout for this entire upgrade operation
UpgradeTimeout time.Duration
// Wait determines whether the wait operation should be performed after the upgrade is requested.
Wait bool
// WaitForJobs determines whether the wait operation for the Jobs should be performed after the upgrade is requested.
@ -475,6 +477,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
rollin.Recreate = u.Recreate
rollin.Force = u.Force
rollin.Timeout = u.Timeout
rollin.RollbackTimeout = u.UpgradeTimeout / 2
if rollErr := rollin.Run(rel.Name); rollErr != nil {
return rel, errors.Wrapf(rollErr, "an error occurred while rolling back the release. original upgrade error: %s", err)
}

@ -36,6 +36,7 @@ func upgradeAction(t *testing.T) *Upgrade {
config := actionConfigFixture(t)
upAction := NewUpgrade(config)
upAction.Namespace = "spaced"
upAction.UpgradeTimeout = 60 * time.Second
return upAction
}

Loading…
Cancel
Save