Feature add any/all/this/in-any-case policy to hook-delete-policy

Signed-off-by: Lentil1016 <lentil1016@gmail.com>
pull/3744/head
Lentil1016 7 years ago
parent b088ee6428
commit 26a64addc2

@ -36,10 +36,15 @@ message Hook {
RELEASE_TEST_FAILURE = 10;
CRD_INSTALL = 11;
}
// SUCCEEDED represents 'this hook succeed', FAILED represents 'this hook failed'
enum DeletePolicy {
SUCCEEDED = 0;
FAILED = 1;
BEFORE_HOOK_CREATION = 2;
ALL_SUCCEED = 3;
ANY_FAILED = 4;
IN_ANY_CASE = 5;
}
string name = 1;
// Kind is the Kubernetes kind.

@ -135,7 +135,7 @@ metadata:
# job is considered part of the release.
"helm.sh/hook": post-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": hook-succeeded
"helm.sh/hook-delete-policy": all-hooks-succeeded
spec:
template:
metadata:
@ -189,14 +189,24 @@ It is also possible to define policies that determine when to delete correspondi
```
annotations:
"helm.sh/hook-delete-policy": hook-succeeded
"helm.sh/hook-delete-policy": all-hooks-succeeded
```
You can choose one or more defined annotation values:
* `"hook-succeeded"` specifies Tiller should delete the hook after the hook is successfully executed.
* `"hook-failed"` specifies Tiller should delete the hook if the hook failed during execution.
* `"before-hook-creation"` specifies Tiller should delete the previous hook before the new hook is launched.
* `"before-hook-creation"` specifies Tiller should delete the previous hook before the new hook is launched. Deletion happened before any execution.
* `"this-hook-succeeded"` specifies Tiller should delete the hook after the hook is successfully executed. Deletion happened after all hooks succeeded or any hook failed.
* `"this-hook-failed"` specifies Tiller should delete the hook if the hook failed during execution. Deletion happened after all hooks succeeded or any hook failed.
* `"all-hooks-succeeded"` specifies Tiller should delete the hook after all hook in its execution stage executed successfully. Deletion happened after all hooks succeeded.
* `"any-hook-failed"` specifies Tiller should delete the hook if any hook in its execution stage failed during execution, including when itself failed. Deletion happened after any hook failed.
* `"in-any-case"` specifies Tiller should delete the hook in any case listed above.
Notice that all these policies are effect in its execution stage. For example, the delete policy of a `pre-install` hook should effect before the `pre-install` stage finished.
### deprecated hooks
- `"hook-succeeded"` is deprecated, use `"this-hook-succeeded"` instead.
- `"hook-failed"` is deprecated, use `"this-hook-failed"` instead.
### Defining a CRD with the `crd-install` Hook
@ -248,7 +258,7 @@ annotated.
When helm release being updated it is possible, that hook resource already exists in cluster. By default helm will try to create resource and fail with `"... already exists"` error.
One might choose `"helm.sh/hook-delete-policy": "before-hook-creation"` over `"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"` because:
One might choose `"helm.sh/hook-delete-policy": "before-hook-creation"` because:
* It is convenient to keep failed hook job resource in kubernetes for example for manual debug.
* It may be necessary to keep succeeded hook resource in kubernetes for some reason.

@ -44,11 +44,20 @@ const (
CRDInstall = "crd-install"
)
// Type of deprecated policies for deleting the hook
const (
HookSucceeded = "hook-succeeded" // deprecated, use ThisHookSucceeded instead
HookFailed = "hook-failed" // deprecated, use ThisHookFailed instead
)
// Type of policy for deleting the hook
const (
HookSucceeded = "hook-succeeded"
HookFailed = "hook-failed"
BeforeHookCreation = "before-hook-creation"
ThisHookSucceeded = "this-hook-succeeded"
ThisHookFailed = "this-hook-failed"
AllHooksSucceeded = "all-hooks-succeeded"
AnyHookFailed = "any-hook-failed"
InAnyCase = "in-any-case"
)
// FilterTestHooks filters the list of hooks are returns only testing hooks.

@ -89,23 +89,33 @@ func (x Hook_Event) String() string {
}
func (Hook_Event) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
// SUCCEEDED represents 'this hook succeed', FAILED represents 'this hook failed'
type Hook_DeletePolicy int32
const (
Hook_SUCCEEDED Hook_DeletePolicy = 0
Hook_FAILED Hook_DeletePolicy = 1
Hook_BEFORE_HOOK_CREATION Hook_DeletePolicy = 2
Hook_ALL_SUCCEED Hook_DeletePolicy = 3
Hook_ANY_FAILED Hook_DeletePolicy = 4
Hook_IN_ANY_CASE Hook_DeletePolicy = 5
)
var Hook_DeletePolicy_name = map[int32]string{
0: "SUCCEEDED",
1: "FAILED",
2: "BEFORE_HOOK_CREATION",
3: "ALL_SUCCEED",
4: "ANY_FAILED",
5: "IN_ANY_CASE",
}
var Hook_DeletePolicy_value = map[string]int32{
"SUCCEEDED": 0,
"FAILED": 1,
"BEFORE_HOOK_CREATION": 2,
"ALL_SUCCEED": 3,
"ANY_FAILED": 4,
"IN_ANY_CASE": 5,
}
func (x Hook_DeletePolicy) String() string {
@ -202,34 +212,35 @@ func init() {
func init() { proto.RegisterFile("hapi/release/hook.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 453 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0x51, 0x8f, 0x9a, 0x40,
0x10, 0x80, 0x8f, 0x53, 0x41, 0x47, 0xcf, 0xdb, 0x6e, 0x9a, 0x76, 0xe3, 0xcb, 0x19, 0x9f, 0x7c,
0xc2, 0xe6, 0x9a, 0xfe, 0x00, 0x84, 0xb9, 0x6a, 0x24, 0x60, 0x16, 0x4c, 0x93, 0xbe, 0x10, 0xae,
0xee, 0x29, 0x11, 0x81, 0x08, 0xb6, 0xe9, 0x1f, 0xed, 0x3f, 0xe8, 0xff, 0x68, 0x76, 0x45, 0x7a,
0x49, 0xfb, 0x36, 0xf3, 0xcd, 0xb7, 0xb3, 0x33, 0xbb, 0xf0, 0x7e, 0x1f, 0x17, 0xc9, 0xec, 0x24,
0x52, 0x11, 0x97, 0x62, 0xb6, 0xcf, 0xf3, 0x83, 0x59, 0x9c, 0xf2, 0x2a, 0xa7, 0x03, 0x59, 0x30,
0xeb, 0xc2, 0xe8, 0x61, 0x97, 0xe7, 0xbb, 0x54, 0xcc, 0x54, 0xed, 0xf9, 0xfc, 0x32, 0xab, 0x92,
0xa3, 0x28, 0xab, 0xf8, 0x58, 0x5c, 0xf4, 0xc9, 0xaf, 0x36, 0xb4, 0x17, 0x79, 0x7e, 0xa0, 0x14,
0xda, 0x59, 0x7c, 0x14, 0x4c, 0x1b, 0x6b, 0xd3, 0x1e, 0x57, 0xb1, 0x64, 0x87, 0x24, 0xdb, 0xb2,
0xdb, 0x0b, 0x93, 0xb1, 0x64, 0x45, 0x5c, 0xed, 0x59, 0xeb, 0xc2, 0x64, 0x4c, 0x47, 0xd0, 0x3d,
0xc6, 0x59, 0xf2, 0x22, 0xca, 0x8a, 0xb5, 0x15, 0x6f, 0x72, 0xfa, 0x01, 0x74, 0xf1, 0x5d, 0x64,
0x55, 0xc9, 0x3a, 0xe3, 0xd6, 0x74, 0xf8, 0xc8, 0xcc, 0xd7, 0x03, 0x9a, 0xf2, 0x6e, 0x13, 0xa5,
0xc0, 0x6b, 0x8f, 0x7e, 0x82, 0x6e, 0x1a, 0x97, 0x55, 0x74, 0x3a, 0x67, 0x4c, 0x1f, 0x6b, 0xd3,
0xfe, 0xe3, 0xc8, 0xbc, 0xac, 0x61, 0x5e, 0xd7, 0x30, 0xc3, 0xeb, 0x1a, 0xdc, 0x90, 0x2e, 0x3f,
0x67, 0xf4, 0x1d, 0xe8, 0x3f, 0x44, 0xb2, 0xdb, 0x57, 0xcc, 0x18, 0x6b, 0xd3, 0x0e, 0xaf, 0x33,
0xba, 0x80, 0xfb, 0xad, 0x48, 0x45, 0x25, 0xa2, 0x22, 0x4f, 0x93, 0x6f, 0x89, 0x28, 0x59, 0x57,
0x4d, 0xf2, 0xf0, 0x9f, 0x49, 0x1c, 0x65, 0xae, 0xa5, 0xf8, 0x93, 0x0f, 0xb7, 0x7f, 0xb3, 0x44,
0x94, 0x93, 0xdf, 0x1a, 0x74, 0xd4, 0xa8, 0xb4, 0x0f, 0xc6, 0xc6, 0x5b, 0x79, 0xfe, 0x17, 0x8f,
0xdc, 0xd0, 0x7b, 0xe8, 0xaf, 0x39, 0x46, 0x4b, 0x2f, 0x08, 0x2d, 0xd7, 0x25, 0x1a, 0x25, 0x30,
0x58, 0xfb, 0x41, 0xd8, 0x90, 0x5b, 0x3a, 0x04, 0x90, 0x8a, 0x83, 0x2e, 0x86, 0x48, 0x5a, 0xea,
0x88, 0x34, 0x6a, 0xd0, 0xbe, 0xf6, 0xd8, 0xac, 0x3f, 0x73, 0xcb, 0x41, 0xd2, 0x69, 0x7a, 0x5c,
0x89, 0xae, 0x08, 0xc7, 0x88, 0xfb, 0xae, 0x3b, 0xb7, 0xec, 0x15, 0x31, 0xe8, 0x1b, 0xb8, 0x53,
0x4e, 0x83, 0xba, 0x94, 0xc1, 0x5b, 0x8e, 0x2e, 0x5a, 0x01, 0x46, 0x21, 0x06, 0x61, 0x14, 0x6c,
0x6c, 0x1b, 0x83, 0x80, 0xf4, 0xfe, 0xa9, 0x3c, 0x59, 0x4b, 0x77, 0xc3, 0x91, 0x80, 0xbc, 0xdb,
0xe6, 0x4e, 0x33, 0x6d, 0x7f, 0x62, 0xc3, 0xe0, 0xf5, 0x3b, 0xd0, 0x3b, 0xe8, 0xa9, 0x3e, 0xe8,
0xa0, 0x43, 0x6e, 0x28, 0x80, 0x2e, 0x0f, 0xa3, 0x43, 0x34, 0xd9, 0x75, 0x8e, 0x4f, 0x3e, 0xc7,
0x68, 0xe1, 0xfb, 0xab, 0xc8, 0xe6, 0x68, 0x85, 0x4b, 0xdf, 0x23, 0xb7, 0xf3, 0xde, 0x57, 0xa3,
0x7e, 0xd9, 0x67, 0x5d, 0x7d, 0xdb, 0xc7, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xcf, 0xed,
0xd9, 0xb4, 0x02, 0x00, 0x00,
// 478 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xc1, 0x8e, 0xda, 0x30,
0x10, 0x86, 0x37, 0x40, 0x02, 0x0c, 0x2c, 0xeb, 0x5a, 0x55, 0x6b, 0x71, 0x59, 0xc4, 0x89, 0x53,
0xa8, 0xb6, 0xea, 0x03, 0x84, 0x64, 0xb6, 0x20, 0xa2, 0x04, 0x39, 0x41, 0x55, 0x7b, 0xb1, 0xb2,
0xc5, 0x0b, 0x11, 0x90, 0x20, 0x12, 0x5a, 0xf5, 0x0d, 0xfa, 0xa2, 0x7d, 0x8f, 0xca, 0x26, 0xd0,
0x95, 0xba, 0x37, 0xcf, 0x37, 0xff, 0xfc, 0xfe, 0xc7, 0x86, 0xf7, 0x9b, 0xe4, 0x90, 0x8e, 0x8f,
0x72, 0x27, 0x93, 0x42, 0x8e, 0x37, 0x79, 0xbe, 0xb5, 0x0f, 0xc7, 0xbc, 0xcc, 0x69, 0x57, 0x35,
0xec, 0xaa, 0xd1, 0xbf, 0x5f, 0xe7, 0xf9, 0x7a, 0x27, 0xc7, 0xba, 0xf7, 0x74, 0x7a, 0x1e, 0x97,
0xe9, 0x5e, 0x16, 0x65, 0xb2, 0x3f, 0x9c, 0xe5, 0xc3, 0xdf, 0x26, 0x34, 0xa6, 0x79, 0xbe, 0xa5,
0x14, 0x1a, 0x59, 0xb2, 0x97, 0xcc, 0x18, 0x18, 0xa3, 0x36, 0xd7, 0x67, 0xc5, 0xb6, 0x69, 0xb6,
0x62, 0xb5, 0x33, 0x53, 0x67, 0xc5, 0x0e, 0x49, 0xb9, 0x61, 0xf5, 0x33, 0x53, 0x67, 0xda, 0x87,
0xd6, 0x3e, 0xc9, 0xd2, 0x67, 0x59, 0x94, 0xac, 0xa1, 0xf9, 0xb5, 0xa6, 0x1f, 0xc0, 0x92, 0x3f,
0x64, 0x56, 0x16, 0xcc, 0x1c, 0xd4, 0x47, 0xbd, 0x07, 0x66, 0xbf, 0x0c, 0x68, 0xab, 0xbb, 0x6d,
0x54, 0x02, 0x5e, 0xe9, 0xe8, 0x27, 0x68, 0xed, 0x92, 0xa2, 0x14, 0xc7, 0x53, 0xc6, 0xac, 0x81,
0x31, 0xea, 0x3c, 0xf4, 0xed, 0xf3, 0x1a, 0xf6, 0x65, 0x0d, 0x3b, 0xbe, 0xac, 0xc1, 0x9b, 0x4a,
0xcb, 0x4f, 0x19, 0x7d, 0x07, 0xd6, 0x4f, 0x99, 0xae, 0x37, 0x25, 0x6b, 0x0e, 0x8c, 0x91, 0xc9,
0xab, 0x8a, 0x4e, 0xe1, 0x6e, 0x25, 0x77, 0xb2, 0x94, 0xe2, 0x90, 0xef, 0xd2, 0xef, 0xa9, 0x2c,
0x58, 0x4b, 0x27, 0xb9, 0x7f, 0x25, 0x89, 0xa7, 0x95, 0x0b, 0x25, 0xfc, 0xc5, 0x7b, 0xab, 0x7f,
0x55, 0x2a, 0x8b, 0xe1, 0x1f, 0x03, 0x4c, 0x1d, 0x95, 0x76, 0xa0, 0xb9, 0x0c, 0xe6, 0x41, 0xf8,
0x25, 0x20, 0x37, 0xf4, 0x0e, 0x3a, 0x0b, 0x8e, 0x62, 0x16, 0x44, 0xb1, 0xe3, 0xfb, 0xc4, 0xa0,
0x04, 0xba, 0x8b, 0x30, 0x8a, 0xaf, 0xa4, 0x46, 0x7b, 0x00, 0x4a, 0xe2, 0xa1, 0x8f, 0x31, 0x92,
0xba, 0x1e, 0x51, 0x8a, 0x0a, 0x34, 0x2e, 0x1e, 0xcb, 0xc5, 0x67, 0xee, 0x78, 0x48, 0xcc, 0xab,
0xc7, 0x85, 0x58, 0x9a, 0x70, 0x14, 0x3c, 0xf4, 0xfd, 0x89, 0xe3, 0xce, 0x49, 0x93, 0xbe, 0x81,
0x5b, 0xad, 0xb9, 0xa2, 0x16, 0x65, 0xf0, 0x96, 0xa3, 0x8f, 0x4e, 0x84, 0x22, 0xc6, 0x28, 0x16,
0xd1, 0xd2, 0x75, 0x31, 0x8a, 0x48, 0xfb, 0xbf, 0xce, 0xa3, 0x33, 0xf3, 0x97, 0x1c, 0x09, 0xa8,
0xbb, 0x5d, 0xee, 0x5d, 0xd3, 0x76, 0x86, 0x27, 0xe8, 0xbe, 0x7c, 0x07, 0x7a, 0x0b, 0x6d, 0xed,
0x83, 0x1e, 0x7a, 0xe4, 0x86, 0x02, 0x58, 0x6a, 0x18, 0x3d, 0x62, 0x28, 0xd7, 0x09, 0x3e, 0x86,
0x1c, 0xc5, 0x34, 0x0c, 0xe7, 0xc2, 0xe5, 0xe8, 0xc4, 0xb3, 0x30, 0x20, 0x35, 0xe5, 0xea, 0xf8,
0xbe, 0xa8, 0x06, 0x49, 0x5d, 0xbd, 0x81, 0x13, 0x7c, 0x15, 0xd5, 0xa8, 0x5e, 0x79, 0x16, 0x08,
0x85, 0x5c, 0x27, 0x42, 0x62, 0x4e, 0xda, 0xdf, 0x9a, 0xd5, 0x5f, 0x3c, 0x59, 0xfa, 0xa3, 0x3f,
0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x3d, 0xc5, 0x43, 0xbb, 0xe6, 0x02, 0x00, 0x00,
}

@ -110,7 +110,7 @@ func (ListSort_SortOrder) EnumDescriptor() ([]byte, []int) { return fileDescript
//
// Releases can be retrieved in chunks by setting limit and offset.
//
// Releases can be sorted according to a few pre-determined sort stategies.
// Releases can be sorted according to a few pre-determined sort strategies.
type ListReleasesRequest struct {
// Limit is the maximum number of releases to be returned.
Limit int64 `protobuf:"varint,1,opt,name=limit" json:"limit,omitempty"`
@ -609,9 +609,9 @@ type InstallReleaseRequest struct {
Name string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"`
// DisableHooks causes the server to skip running any hooks for the install.
DisableHooks bool `protobuf:"varint,5,opt,name=disable_hooks,json=disableHooks" json:"disable_hooks,omitempty"`
// Namepace is the kubernetes namespace of the release.
// Namespace is the kubernetes namespace of the release.
Namespace string `protobuf:"bytes,6,opt,name=namespace" json:"namespace,omitempty"`
// ReuseName requests that Tiller re-uses a name, instead of erroring out.
// Reuse_name requests that Tiller re-uses a name, instead of erroring out.
ReuseName bool `protobuf:"varint,7,opt,name=reuse_name,json=reuseName" json:"reuse_name,omitempty"`
// timeout specifies the max amount of time any kubernetes client command can run.
Timeout int64 `protobuf:"varint,8,opt,name=timeout" json:"timeout,omitempty"`

@ -47,9 +47,12 @@ var events = map[string]release.Hook_Event{
// deletePolices represents a mapping between the key in the annotation for label deleting policy and its real meaning
var deletePolices = map[string]release.Hook_DeletePolicy{
hooks.HookSucceeded: release.Hook_SUCCEEDED,
hooks.HookFailed: release.Hook_FAILED,
hooks.BeforeHookCreation: release.Hook_BEFORE_HOOK_CREATION,
hooks.ThisHookSucceeded: release.Hook_SUCCEEDED,
hooks.ThisHookFailed: release.Hook_FAILED,
hooks.AllHooksSucceeded: release.Hook_ALL_SUCCEED,
hooks.AnyHookFailed: release.Hook_ANY_FAILED,
hooks.InAnyCase: release.Hook_IN_ANY_CASE,
}
// Manifest represents a manifest file, which has a name and some content.
@ -127,7 +130,7 @@ func sortManifests(files map[string]string, apis chartutil.VersionSet, sort Sort
// apiVersion: v1
// metadata:
// annotations:
// helm.sh/hook-delete-policy: hook-succeeded
// helm.sh/hook-delete-policy: this-hook-succeeded
func (file *manifestFile) sort(result *result) error {
for _, m := range file.entries {
var entry util.SimpleHead
@ -192,7 +195,21 @@ func (file *manifestFile) sort(result *result) error {
if exist {
h.DeletePolicies = append(h.DeletePolicies, policy)
} else {
log.Printf("info: skipping unknown hook delete policy: %q", value)
if value != hooks.HookFailed && value != hooks.HookSucceeded {
log.Printf("info: skipping unknown hook delete policy: %q", value)
} else {
if value == hooks.HookSucceeded {
log.Printf("warning: hook delete policy %q is deprecated, use %q instead.",
value, hooks.ThisHookSucceeded)
policy = deletePolices[hooks.ThisHookSucceeded]
} else if value == hooks.HookFailed {
log.Printf("warning: hook delete policy %q is deprecated, use %q instead.",
value, hooks.ThisHookFailed)
policy = deletePolices[hooks.ThisHookFailed]
}
log.Printf("warning: check https://docs.helm.sh/developing_charts#deprecated-hooks")
h.DeletePolicies = append(h.DeletePolicies, policy)
}
}
})
}

@ -244,3 +244,62 @@ func TestVersionSet(t *testing.T) {
t.Error("Found nonexistent extension")
}
}
func TestHookDeletePolicyAnnotationsShift(t *testing.T) {
data := []struct {
name []string
path string
kind []string
hooks map[string][]release.Hook_Event
manifest string
}{
{
name: []string{"first"},
path: "one",
kind: []string{"Job"},
hooks: map[string][]release.Hook_Event{"first": {release.Hook_PRE_INSTALL}},
manifest: `apiVersion: v1
kind: Job
metadata:
name: first
labels:
doesnot: matter
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-delete-policy": "hook-succeeded"
`,
}, {
name: []string{"second"},
path: "two",
kind: []string{"Job"},
hooks: map[string][]release.Hook_Event{"second": {release.Hook_PRE_INSTALL}},
manifest: `apiVersion: v1
kind: Job
metadata:
name: second
labels:
doesnot: matter
annotations:
"helm.sh/hook": pre-install
"helm.sh/hook-delete-policy": "hook-failed"
`,
},
}
manifests := make(map[string]string, len(data))
for _, o := range data {
manifests[o.path] = o.manifest
}
hs, _, err := sortManifests(manifests, chartutil.NewVersionSet("v1", "v1beta1"), InstallOrder)
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
if hs[0].DeletePolicies[0] != release.Hook_SUCCEEDED {
t.Errorf("Expected delete policy hook-succeed shifted to release.Hook_SUCCEEDED")
}
if hs[1].DeletePolicies[0] != release.Hook_FAILED {
t.Errorf("Expected delete policy hook-failed shifted to release.Hook_FAILED")
}
}

@ -365,7 +365,7 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
executingHooks = sortByHookWeight(executingHooks)
for index, h := range executingHooks {
if err := s.deleteHookByPolicy(h, hooks.BeforeHookCreation, name, namespace, hook, kubeCli); err != nil {
if err := s.deleteHookByPolicy(h, []string{hooks.BeforeHookCreation}, name, namespace, hook, kubeCli); err != nil {
return err
}
@ -384,13 +384,12 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
s.Log("warning: Release %s %s %s could not complete: %s", name, hook, h.Path, err)
// If a hook is failed, checkout the annotation of the hook to determine whether the hook should be deleted
// under failed condition. If so, then clear the corresponding resource object in the hook
// Delete previous succeeded hooks with hook-delete-policy hook-succeeded
for _, hp := range executingHooks[:index] {
if err := s.deleteHookByPolicy(hp, hooks.HookSucceeded, name, namespace, hook, kubeCli); err != nil {
if err := s.deleteHookByPolicy(hp, []string{hooks.ThisHookSucceeded, hooks.AnyHookFailed}, name, namespace, hook, kubeCli); err != nil {
return err
}
}
if err := s.deleteHookByPolicy(h, hooks.HookFailed, name, namespace, hook, kubeCli); err != nil {
if err := s.deleteHookByPolicy(h, []string{hooks.ThisHookFailed, hooks.AnyHookFailed}, name, namespace, hook, kubeCli); err != nil {
return err
}
return err
@ -402,7 +401,7 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin
// If all hooks are succeeded, checkout the annotation of each hook to determine whether the hook should be deleted
// under succeeded condition. If so, then clear the corresponding resource object in each hook
for _, h := range executingHooks {
if err := s.deleteHookByPolicy(h, hooks.HookSucceeded, name, namespace, hook, kubeCli); err != nil {
if err := s.deleteHookByPolicy(h, []string{hooks.ThisHookSucceeded, hooks.AllHooksSucceeded}, name, namespace, hook, kubeCli); err != nil {
return err
}
h.LastRun = timeconv.Now()
@ -429,13 +428,15 @@ func validateReleaseName(releaseName string) error {
return nil
}
func (s *ReleaseServer) deleteHookByPolicy(h *release.Hook, policy string, name, namespace, hook string, kubeCli environment.KubeClient) error {
func (s *ReleaseServer) deleteHookByPolicy(h *release.Hook, policies []string, name, namespace, hook string, kubeCli environment.KubeClient) error {
b := bytes.NewBufferString(h.Manifest)
if hookHasDeletePolicy(h, policy) {
s.Log("deleting %s hook %s for release %s due to %q policy", hook, h.Name, name, policy)
if errHookDelete := kubeCli.Delete(namespace, b); errHookDelete != nil {
s.Log("warning: Release %s %s %S could not be deleted: %s", name, hook, h.Path, errHookDelete)
return errHookDelete
for _, policy := range append(policies, hooks.InAnyCase) {
if hookHasDeletePolicy(h, policy) {
s.Log("deleting %s hook %s for release %s due to %q policy", hook, h.Name, name, policy)
if errHookDelete := kubeCli.Delete(namespace, b); errHookDelete != nil {
s.Log("warning: Release %s %s %S could not be deleted: %s", name, hook, h.Path, errHookDelete)
return errHookDelete
}
}
}
return nil

@ -23,6 +23,7 @@ import (
"io/ioutil"
"os"
"regexp"
"strings"
"testing"
"time"
@ -601,26 +602,34 @@ name: value`, hookName, extraAnnotationsStr),
}
}
func execHookShouldSucceed(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string) error {
err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600)
func getHooksNameList(hooks []*release.Hook) string {
var nameList []string
for _, hook := range hooks {
nameList = append(nameList, hook.Name)
}
return strings.Join(nameList, ",")
}
func execHooksShouldSucceed(rs *ReleaseServer, hooks []*release.Hook, releaseName string, namespace string, hookType string) error {
err := rs.execHook(hooks, releaseName, namespace, hookType, 600)
if err != nil {
return fmt.Errorf("expected hook %s to be successful: %s", hook.Name, err)
return fmt.Errorf("expected all these hooks %s to be successful: %s", getHooksNameList(hooks), err)
}
return nil
}
func execHookShouldFail(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string) error {
err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600)
func execHooksShouldFail(rs *ReleaseServer, hooks []*release.Hook, releaseName string, namespace string, hookType string) error {
err := rs.execHook(hooks, releaseName, namespace, hookType, 600)
if err == nil {
return fmt.Errorf("expected hook %s to be failed", hook.Name)
return fmt.Errorf("expected some of these hooks %s to be failed", getHooksNameList(hooks))
}
return nil
}
func execHookShouldFailWithError(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string, expectedError error) error {
err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600)
func execHooksShouldFailWithError(rs *ReleaseServer, hooks []*release.Hook, releaseName string, namespace string, hookType string, expectedError error) error {
err := rs.execHook(hooks, releaseName, namespace, hookType, 600)
if err != expectedError {
return fmt.Errorf("expected hook %s to fail with error %v, got %v", hook.Name, expectedError, err)
return fmt.Errorf("expected some of these hooks %s to fail with error %v, got %v", getHooksNameList(hooks), expectedError, err)
}
return nil
}
@ -647,11 +656,30 @@ func newDeletePolicyContext() *deletePolicyContext {
}
}
func newDeletePolicyContextsWithHookName(hookNames []string) []*deletePolicyContext {
kubeClient := &mockHooksKubeClient{
Resources: make(map[string]*mockHooksManifest),
}
releaseServer := deletePolicyStub(kubeClient)
var contexts []*deletePolicyContext
for _, hookName := range hookNames {
contexts = append(contexts, &deletePolicyContext{
KubeClient: kubeClient,
ReleaseServer: releaseServer,
ReleaseName: "flying-carp",
Namespace: "river",
HookName: hookName,
})
}
return contexts
}
func TestSuccessfulHookWithoutDeletePolicy(t *testing.T) {
ctx := newDeletePolicyContext()
hook := deletePolicyHookStub(ctx.HookName, nil, nil)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -667,7 +695,7 @@ func TestFailedHookWithoutDeletePolicy(t *testing.T) {
nil,
)
err := execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -679,11 +707,11 @@ func TestFailedHookWithoutDeletePolicy(t *testing.T) {
func TestSuccessfulHookWithSucceededDeletePolicy(t *testing.T) {
ctx := newDeletePolicyContext()
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{"helm.sh/hook-delete-policy": "hook-succeeded"},
map[string]string{"helm.sh/hook-delete-policy": "this-hook-succeeded"},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED},
)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -695,11 +723,11 @@ func TestSuccessfulHookWithSucceededDeletePolicy(t *testing.T) {
func TestSuccessfulHookWithFailedDeletePolicy(t *testing.T) {
ctx := newDeletePolicyContext()
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{"helm.sh/hook-delete-policy": "hook-failed"},
map[string]string{"helm.sh/hook-delete-policy": "this-hook-failed"},
[]release.Hook_DeletePolicy{release.Hook_FAILED},
)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -714,12 +742,12 @@ func TestFailedHookWithSucceededDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed",
"helm.sh/hook-delete-policy": "hook-succeeded",
"helm.sh/hook-delete-policy": "this-hook-succeeded",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED},
)
err := execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -734,12 +762,12 @@ func TestFailedHookWithFailedDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed",
"helm.sh/hook-delete-policy": "hook-failed",
"helm.sh/hook-delete-policy": "this-hook-failed",
},
[]release.Hook_DeletePolicy{release.Hook_FAILED},
)
err := execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -753,12 +781,12 @@ func TestSuccessfulHookWithSuccededOrFailedDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed",
"helm.sh/hook-delete-policy": "this-hook-succeeded,this-hook-failed",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED, release.Hook_FAILED},
)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -773,12 +801,12 @@ func TestFailedHookWithSuccededOrFailedDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed",
"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed",
"helm.sh/hook-delete-policy": "this-hook-succeeded,this-hook-failed",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED, release.Hook_FAILED},
)
err := execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -792,7 +820,7 @@ func TestHookAlreadyExists(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, nil, nil)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -801,7 +829,7 @@ func TestHookAlreadyExists(t *testing.T) {
t.Errorf("expected resource %s to be existing after hook succeeded", hook.Name)
}
err = execHookShouldFailWithError(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade, errResourceExists)
err = execHooksShouldFailWithError(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade, errResourceExists)
if err != nil {
t.Error(err)
}
@ -819,7 +847,7 @@ func TestHookDeletingWithBeforeHookCreationDeletePolicy(t *testing.T) {
[]release.Hook_DeletePolicy{release.Hook_BEFORE_HOOK_CREATION},
)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -828,7 +856,7 @@ func TestHookDeletingWithBeforeHookCreationDeletePolicy(t *testing.T) {
t.Errorf("expected resource %s to be existing after hook succeeded", hook.Name)
}
err = execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
err = execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
@ -843,12 +871,12 @@ func TestSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation",
"helm.sh/hook-delete-policy": "this-hook-succeeded,before-hook-creation",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED, release.Hook_BEFORE_HOOK_CREATION},
)
err := execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -857,7 +885,7 @@ func TestSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
t.Errorf("expected resource %s to be unexisting after hook succeeded", hook.Name)
}
err = execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
err = execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
@ -873,12 +901,12 @@ func TestFailedHookWithMixedDeletePolicies(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed",
"helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation",
"helm.sh/hook-delete-policy": "this-hook-succeeded,before-hook-creation",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED, release.Hook_BEFORE_HOOK_CREATION},
)
err := execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -887,7 +915,7 @@ func TestFailedHookWithMixedDeletePolicies(t *testing.T) {
t.Errorf("expected resource %s to be existing after hook failed", hook.Name)
}
err = execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
err = execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
@ -903,12 +931,12 @@ func TestFailedThenSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName,
map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed",
"helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation",
"helm.sh/hook-delete-policy": "this-hook-succeeded,before-hook-creation",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED, release.Hook_BEFORE_HOOK_CREATION},
)
err := execHookShouldFail(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
err := execHooksShouldFail(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreInstall)
if err != nil {
t.Error(err)
}
@ -919,12 +947,12 @@ func TestFailedThenSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
hook = deletePolicyHookStub(ctx.HookName,
map[string]string{
"helm.sh/hook-delete-policy": "hook-succeeded,before-hook-creation",
"helm.sh/hook-delete-policy": "this-hook-succeeded,before-hook-creation",
},
[]release.Hook_DeletePolicy{release.Hook_SUCCEEDED, release.Hook_BEFORE_HOOK_CREATION},
)
err = execHookShouldSucceed(ctx.ReleaseServer, hook, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
err = execHooksShouldSucceed(ctx.ReleaseServer, []*release.Hook{hook}, ctx.ReleaseName, ctx.Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
@ -933,3 +961,411 @@ func TestFailedThenSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
t.Errorf("expected resource %s to be unexisting after hook succeeded", hook.Name)
}
}
func TestAllHooksSucceedWithAndWithoutAllHooksSucceededPolicy(t *testing.T) {
hookCases := []struct {
hookName string
execResult string
shouldExist bool
policy []release.Hook_DeletePolicy
policyAnno string
}{
{
hookName: "hook1",
execResult: "",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_ALL_SUCCEED},
policyAnno: "all-hooks-succeeded",
}, {
hookName: "hook2",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{},
policyAnno: "",
},
}
var hookNames []string
var releaseHooks []*release.Hook
for _, hookCase := range hookCases {
hookNames = append(hookNames, hookCase.hookName)
}
ctxs := newDeletePolicyContextsWithHookName(hookNames)
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err := execHooksShouldSucceed(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after all hooks succeeded.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after all hooks succeeded.", hookCase.hookName)
}
}
}
}
func TestAnyHookFailedWithAndWithoutAllHooksSucceededPolicy(t *testing.T) {
hookCases := []struct {
hookName string
execResult string
shouldExist bool
policy []release.Hook_DeletePolicy
policyAnno string
}{
{
hookName: "hook1",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{release.Hook_ALL_SUCCEED},
policyAnno: "all-hooks-succeeded",
}, {
hookName: "hook2",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{},
policyAnno: "",
}, {
hookName: "hook3",
execResult: "hook-failed",
shouldExist: true,
policy: []release.Hook_DeletePolicy{},
policyAnno: "",
},
}
var hookNames []string
var releaseHooks []*release.Hook
for _, hookCase := range hookCases {
hookNames = append(hookNames, hookCase.hookName)
}
ctxs := newDeletePolicyContextsWithHookName(hookNames)
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err := execHooksShouldFail(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after any hook failed.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after any hook failed.", hookCase.hookName)
}
}
}
}
func TestAllHooksSucceedWithAndWithoutAnyHookFailedPolicy(t *testing.T) {
hookCases := []struct {
hookName string
execResult string
shouldExist bool
policy []release.Hook_DeletePolicy
policyAnno string
}{
{
hookName: "hook1",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{release.Hook_ANY_FAILED},
policyAnno: "any-hook-failed",
}, {
hookName: "hook2",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{},
policyAnno: "",
},
}
var hookNames []string
var releaseHooks []*release.Hook
for _, hookCase := range hookCases {
hookNames = append(hookNames, hookCase.hookName)
}
ctxs := newDeletePolicyContextsWithHookName(hookNames)
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err := execHooksShouldSucceed(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after all hooks succeeded.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after all hooks succeeded.", hookCase.hookName)
}
}
}
}
func TestAnyHookFailedWithAndWithoutAnyHookFailedPolicy(t *testing.T) {
hookCases := []struct {
hookName string
execResult string
shouldExist bool
policy []release.Hook_DeletePolicy
policyAnno string
}{
{
hookName: "hook1",
execResult: "",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_ANY_FAILED},
policyAnno: "any-hook-failed",
}, {
hookName: "hook2",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{},
policyAnno: "",
}, {
hookName: "hook3",
execResult: "hook-failed",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_ANY_FAILED},
policyAnno: "any-hook-failed",
},
}
var hookNames []string
var releaseHooks []*release.Hook
for _, hookCase := range hookCases {
hookNames = append(hookNames, hookCase.hookName)
}
ctxs := newDeletePolicyContextsWithHookName(hookNames)
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err := execHooksShouldFail(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after any hook failed.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after any hook failed.", hookCase.hookName)
}
}
}
}
func TestAllHooksSucceedWithMixedPolicy(t *testing.T) {
hookCases := []struct {
hookName string
execResult string
shouldExist bool
policy []release.Hook_DeletePolicy
policyAnno string
}{
{
hookName: "hook1",
execResult: "",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_SUCCEEDED},
policyAnno: "this-hook-succeeded, this-hook-failed",
}, {
hookName: "hook2",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{release.Hook_FAILED},
policyAnno: "this-hook-failed",
}, {
hookName: "hook3",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{release.Hook_ALL_SUCCEED},
policyAnno: "all-hooks-succeeded",
}, {
hookName: "hook4",
execResult: "",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_ANY_FAILED},
policyAnno: "any-hook-failed",
}, {
hookName: "hook5",
execResult: "hook-failed",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_IN_ANY_CASE},
policyAnno: "in-any-case",
},
}
var hookNames []string
var releaseHooks []*release.Hook
for _, hookCase := range hookCases {
hookNames = append(hookNames, hookCase.hookName)
}
ctxs := newDeletePolicyContextsWithHookName(hookNames)
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err := execHooksShouldFail(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after any hook failed.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after any hook failed.", hookCase.hookName)
}
}
}
}
func TestInAnyCasePolicy(t *testing.T) {
hookCases := []struct {
hookName string
execResult string
shouldExist bool
policy []release.Hook_DeletePolicy
policyAnno string
}{
{
hookName: "hook1",
execResult: "",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_IN_ANY_CASE},
policyAnno: "in-any-case",
}, {
hookName: "hook2",
execResult: "",
shouldExist: true,
policy: []release.Hook_DeletePolicy{},
policyAnno: "",
}, {
hookName: "hook3",
execResult: "hook-failed",
shouldExist: false,
policy: []release.Hook_DeletePolicy{release.Hook_IN_ANY_CASE},
policyAnno: "in-any-case",
},
}
var hookNames []string
var releaseHooks []*release.Hook
for _, hookCase := range hookCases {
hookNames = append(hookNames, hookCase.hookName)
}
ctxs := newDeletePolicyContextsWithHookName(hookNames)
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err := execHooksShouldFail(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after first release.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after first release.", hookCase.hookName)
}
}
}
hookCases[1].shouldExist = false
hookCases[1].policy = []release.Hook_DeletePolicy{release.Hook_IN_ANY_CASE}
hookCases[1].policyAnno = "in-any-case"
releaseHooks = releaseHooks[:0]
for _, hookCase := range hookCases {
releaseHooks = append(releaseHooks, deletePolicyHookStub(hookCase.hookName,
map[string]string{
"mockHooksKubeClient/Emulate": hookCase.execResult,
"helm.sh/hook-delete-policy": hookCase.policyAnno,
},
hookCase.policy,
))
}
err = execHooksShouldFail(ctxs[0].ReleaseServer, releaseHooks, ctxs[0].ReleaseName, ctxs[0].Namespace, hooks.PreUpgrade)
if err != nil {
t.Error(err)
}
for index, hookCase := range hookCases {
if _, hasResource := ctxs[index].KubeClient.Resources[releaseHooks[index].Name]; hasResource != hookCase.shouldExist {
if hasResource {
t.Errorf("expected resource %s to be unexisting after second release.", hookCase.hookName)
} else {
t.Errorf("expected resource %s to be existing after second release.", hookCase.hookName)
}
}
}
}

Loading…
Cancel
Save