Adding unit tests to timeouts of release operations

Signed-off-by: BenHesketh21 <heskethben0@gmail.com>
pull/12300/head
BenHesketh21 2 years ago
parent cc0d5d1cae
commit 2873521346

@ -64,6 +64,30 @@ metadata:
data:
name: value`
var manifestWithPreInstallHook = `kind: ConfigMap
metadata:
name: test-cm-2
annotations:
"helm.sh/hook": pre-install
data:
name: value`
var manifestWithPreUpgradeHook = `kind: ConfigMap
metadata:
name: test-cm-2
annotations:
"helm.sh/hook": pre-upgrade
data:
name: value`
var manifestWithPreDeleteHook = `kind: ConfigMap
metadata:
name: test-cm-2
annotations:
"helm.sh/hook": pre-delete
data:
name: value`
var manifestWithTestHook = `kind: Pod
metadata:
name: finding-nemo,
@ -182,6 +206,36 @@ func withMetadataDependency(dependency chart.Dependency) chartOption {
}
}
func withPreInstallHook() chartOption {
return func(opts *chartOptions) {
hookTemplates := []*chart.File{
// This adds pre-install hook.
{Name: "templates/pre-install-hook", Data: []byte(manifestWithPreInstallHook)},
}
opts.Templates = hookTemplates
}
}
func withPreUpgradeHook() chartOption {
return func(opts *chartOptions) {
hookTemplates := []*chart.File{
// This adds pre-install hook.
{Name: "templates/pre-upgrade-hook", Data: []byte(manifestWithPreUpgradeHook)},
}
opts.Templates = hookTemplates
}
}
func withPreDeleteHook() chartOption {
return func(opts *chartOptions) {
hookTemplates := []*chart.File{
// This adds pre-install hook.
{Name: "templates/pre-delete-hook", Data: []byte(manifestWithPreDeleteHook)},
}
opts.Templates = hookTemplates
}
}
func withSampleTemplates() chartOption {
return func(opts *chartOptions) {
sampleTemplates := []*chart.File{

@ -322,6 +322,27 @@ func TestInstallRelease_FailedHooks(t *testing.T) {
is.Equal(release.StatusFailed, res.Info.Status)
}
func TestInstallRelease_FailedTimeout(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "failed-timeout"
instAction.Wait = true
instAction.WaitForJobs = true
instAction.DisableHooks = true
instAction.Timeout = 5 * time.Second
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
instAction.cfg.KubeClient = failer
vals := map[string]interface{}{}
start := time.Now()
res, err := instAction.Run(buildChart(), vals)
is.Equal(instAction.Timeout, time.Since(start).Round(time.Second))
is.Error(err)
is.Contains(res.Info.Description, "failed: I timed out")
is.Equal(release.StatusFailed, res.Info.Status)
}
func TestInstallRelease_ReplaceRelease(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
@ -404,6 +425,56 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, runtime.NumGoroutine())
}
func TestInstallRelease_Wait_Interrupted_Hooks(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "interrupted-hooks-release"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("I timed out")
instAction.cfg.KubeClient = failer
instAction.Wait = true
instAction.HookTimeout = 5 * time.Second
instAction.Timeout = 3 * time.Second
vals := map[string]interface{}{}
start := time.Now()
res, err := instAction.Run(buildChart(withPreInstallHook()), vals)
executionTime := time.Since(start)
is.Equal(instAction.HookTimeout, executionTime.Round(time.Second))
is.Error(err)
is.Contains(res.Info.Description, "Release \"interrupted-hooks-release\" failed: failed pre-install: I timed out")
is.Equal(res.Info.Status, release.StatusFailed)
is.Len(res.Hooks, 1)
is.Equal(res.Hooks[0].Manifest, manifestWithPreInstallHook)
is.Equal(res.Hooks[0].Events[0], release.HookPreInstall)
}
func TestInstallRelease_Wait_TimeoutUsedWhenHookTimeoutNotSet(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)
instAction.ReleaseName = "interrupted-hooks-release"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("I timed out")
instAction.cfg.KubeClient = failer
instAction.Wait = true
instAction.Timeout = 3 * time.Second
vals := map[string]interface{}{}
start := time.Now()
res, err := instAction.Run(buildChart(withPreInstallHook()), vals)
executionTime := time.Since(start)
is.Equal(instAction.Timeout, executionTime.Round(time.Second))
is.Error(err)
is.Contains(res.Info.Description, "Release \"interrupted-hooks-release\" failed: failed pre-install: I timed out")
is.Equal(res.Info.Status, release.StatusFailed)
is.Len(res.Hooks, 1)
is.Equal(res.Hooks[0].Manifest, manifestWithPreInstallHook)
is.Equal(res.Hooks[0].Events[0], release.HookPreInstall)
}
func TestInstallRelease_WaitForJobs(t *testing.T) {
is := assert.New(t)
instAction := installAction(t)

@ -19,6 +19,7 @@ package action
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
@ -138,3 +139,50 @@ func TestUninstallRelease_Cascade(t *testing.T) {
is.Error(err)
is.Contains(err.Error(), "failed to delete release: come-fail-away")
}
func TestUninstallRelease_Wait_Interrupted_Hooks(t *testing.T) {
is := assert.New(t)
unAction := uninstallAction(t)
rel := releaseStub()
rel.Name = "interrupted-hooks-release"
rel.Info.Status = release.StatusDeployed
rel.Chart = buildChart(withPreDeleteHook())
unAction.cfg.Releases.Create(rel)
failer := unAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("I timed out")
unAction.cfg.KubeClient = failer
unAction.Wait = true
unAction.HookTimeout = 5 * time.Second
unAction.Timeout = 3 * time.Second
start := time.Now()
res, err := unAction.Run(rel.Name)
executionTime := time.Since(start)
is.Equal(unAction.HookTimeout, executionTime.Round(time.Second))
is.Error(err)
is.Contains(res.Release.Info.Description, "Deletion in progress (or silently failed)")
is.Equal(res.Release.Info.Status, release.StatusUninstalling)
}
func TestUninstallRelease_Wait_TimeoutUsedWhenHookTimeoutNotSet(t *testing.T) {
is := assert.New(t)
unAction := uninstallAction(t)
rel := releaseStub()
rel.Name = "interrupted-hooks-release"
rel.Info.Status = release.StatusDeployed
rel.Chart = buildChart(withPreDeleteHook())
unAction.cfg.Releases.Create(rel)
failer := unAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("I timed out")
unAction.cfg.KubeClient = failer
unAction.Wait = true
unAction.Timeout = 3 * time.Second
start := time.Now()
res, err := unAction.Run(rel.Name)
executionTime := time.Since(start)
is.Equal(unAction.Timeout, executionTime.Round(time.Second))
is.Error(err)
is.Contains(res.Release.Info.Description, "Deletion in progress (or silently failed)")
is.Equal(res.Release.Info.Status, release.StatusUninstalling)
}

@ -114,6 +114,30 @@ func TestUpgradeRelease_WaitForJobs(t *testing.T) {
is.Equal(res.Info.Status, release.StatusFailed)
}
func TestUpgradeRelease_FailedTimeout(t *testing.T) {
is := assert.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
rel.Name = "failed-timeout"
rel.Info.Status = release.StatusDeployed
upAction.cfg.Releases.Create(rel)
upAction.Wait = true
upAction.WaitForJobs = true
upAction.DisableHooks = true
upAction.Timeout = 5 * time.Second
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WaitError = fmt.Errorf("I timed out")
upAction.cfg.KubeClient = failer
vals := map[string]interface{}{}
start := time.Now()
res, err := upAction.Run(rel.Name, buildChart(), vals)
is.Equal(upAction.Timeout, time.Since(start).Round(time.Second))
is.Error(err)
is.Contains(res.Info.Description, "failed: I timed out")
is.Equal(release.StatusFailed, res.Info.Status)
}
func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
is := assert.New(t)
req := require.New(t)
@ -357,6 +381,61 @@ func TestUpgradeRelease_Interrupted_Wait(t *testing.T) {
}
func TestUpgradeRelease_Wait_Interrupted_Hooks(t *testing.T) {
is := assert.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
rel.Name = "interrupted-hooks-release"
rel.Info.Status = release.StatusDeployed
upAction.cfg.Releases.Create(rel)
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("I timed out")
upAction.cfg.KubeClient = failer
upAction.Wait = true
upAction.HookTimeout = 5 * time.Second
upAction.Timeout = 3 * time.Second
vals := map[string]interface{}{}
start := time.Now()
res, err := upAction.Run(rel.Name, buildChart(withPreUpgradeHook()), vals)
executionTime := time.Since(start)
is.Equal(upAction.HookTimeout, executionTime.Round(time.Second))
is.Error(err)
is.Contains(res.Info.Description, "Upgrade \"interrupted-hooks-release\" failed: pre-upgrade hooks failed: I timed out")
is.Equal(res.Info.Status, release.StatusFailed)
is.Len(res.Hooks, 1)
is.Equal(res.Hooks[0].Manifest, manifestWithPreUpgradeHook)
is.Equal(res.Hooks[0].Events[0], release.HookPreUpgrade)
}
func TestUpgradeRelease_Wait_TimeoutUsedWhenHookTimeoutNotSet(t *testing.T) {
is := assert.New(t)
upAction := upgradeAction(t)
rel := releaseStub()
rel.Name = "interrupted-hooks-release"
rel.Info.Status = release.StatusDeployed
upAction.cfg.Releases.Create(rel)
failer := upAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
failer.WatchUntilReadyError = fmt.Errorf("I timed out")
upAction.cfg.KubeClient = failer
upAction.Wait = true
upAction.Timeout = 3 * time.Second
vals := map[string]interface{}{}
start := time.Now()
res, err := upAction.Run(rel.Name, buildChart(withPreUpgradeHook()), vals)
executionTime := time.Since(start)
is.Equal(upAction.Timeout, executionTime.Round(time.Second))
is.Error(err)
is.Contains(res.Info.Description, "Upgrade \"interrupted-hooks-release\" failed: pre-upgrade hooks failed: I timed out")
is.Equal(res.Info.Status, release.StatusFailed)
is.Len(res.Hooks, 1)
is.Equal(res.Hooks[0].Manifest, manifestWithPreUpgradeHook)
is.Equal(res.Hooks[0].Events[0], release.HookPreUpgrade)
}
func TestUpgradeRelease_Interrupted_Atomic(t *testing.T) {
is := assert.New(t)

@ -67,7 +67,11 @@ func (f *FailingKubeClient) Get(resources kube.ResourceList, related bool) (map[
// Waits the amount of time defined on f.WaitDuration, then returns the configured error if set or prints.
func (f *FailingKubeClient) Wait(resources kube.ResourceList, d time.Duration) error {
time.Sleep(f.WaitDuration)
if f.WaitDuration != 0*time.Second {
time.Sleep(f.WaitDuration)
} else {
time.Sleep(d)
}
if f.WaitError != nil {
return f.WaitError
}
@ -76,6 +80,11 @@ func (f *FailingKubeClient) Wait(resources kube.ResourceList, d time.Duration) e
// WaitWithJobs returns the configured error if set or prints
func (f *FailingKubeClient) WaitWithJobs(resources kube.ResourceList, d time.Duration) error {
if f.WaitDuration != 0*time.Second {
time.Sleep(f.WaitDuration)
} else {
time.Sleep(d)
}
if f.WaitError != nil {
return f.WaitError
}
@ -98,8 +107,9 @@ func (f *FailingKubeClient) Delete(resources kube.ResourceList) (*kube.Result, [
return f.PrintingKubeClient.Delete(resources)
}
// WatchUntilReady returns the configured error if set or prints
// WatchUntilReady waits for the duration provided and returns the configured error if set or prints
func (f *FailingKubeClient) WatchUntilReady(resources kube.ResourceList, d time.Duration) error {
time.Sleep(d)
if f.WatchUntilReadyError != nil {
return f.WatchUntilReadyError
}

Loading…
Cancel
Save