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; RELEASE_TEST_FAILURE = 10;
CRD_INSTALL = 11; CRD_INSTALL = 11;
} }
// SUCCEEDED represents 'this hook succeed', FAILED represents 'this hook failed'
enum DeletePolicy { enum DeletePolicy {
SUCCEEDED = 0; SUCCEEDED = 0;
FAILED = 1; FAILED = 1;
BEFORE_HOOK_CREATION = 2; BEFORE_HOOK_CREATION = 2;
ALL_SUCCEED = 3;
ANY_FAILED = 4;
IN_ANY_CASE = 5;
} }
string name = 1; string name = 1;
// Kind is the Kubernetes kind. // Kind is the Kubernetes kind.

@ -135,7 +135,7 @@ metadata:
# job is considered part of the release. # job is considered part of the release.
"helm.sh/hook": post-install "helm.sh/hook": post-install
"helm.sh/hook-weight": "-5" "helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": hook-succeeded "helm.sh/hook-delete-policy": all-hooks-succeeded
spec: spec:
template: template:
metadata: metadata:
@ -189,14 +189,24 @@ It is also possible to define policies that determine when to delete correspondi
``` ```
annotations: 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: You can choose one or more defined annotation values:
* `"hook-succeeded"` specifies Tiller should delete the hook after the hook is successfully executed. * `"before-hook-creation"` specifies Tiller should delete the previous hook before the new hook is launched. Deletion happened before any execution.
* `"hook-failed"` specifies Tiller should delete the hook if the hook failed during 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.
* `"before-hook-creation"` specifies Tiller should delete the previous hook before the new hook is launched. * `"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 ### 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. 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 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. * It may be necessary to keep succeeded hook resource in kubernetes for some reason.

@ -44,11 +44,20 @@ const (
CRDInstall = "crd-install" 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 // Type of policy for deleting the hook
const ( const (
HookSucceeded = "hook-succeeded"
HookFailed = "hook-failed"
BeforeHookCreation = "before-hook-creation" 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. // 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} } 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 type Hook_DeletePolicy int32
const ( const (
Hook_SUCCEEDED Hook_DeletePolicy = 0 Hook_SUCCEEDED Hook_DeletePolicy = 0
Hook_FAILED Hook_DeletePolicy = 1 Hook_FAILED Hook_DeletePolicy = 1
Hook_BEFORE_HOOK_CREATION Hook_DeletePolicy = 2 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{ var Hook_DeletePolicy_name = map[int32]string{
0: "SUCCEEDED", 0: "SUCCEEDED",
1: "FAILED", 1: "FAILED",
2: "BEFORE_HOOK_CREATION", 2: "BEFORE_HOOK_CREATION",
3: "ALL_SUCCEED",
4: "ANY_FAILED",
5: "IN_ANY_CASE",
} }
var Hook_DeletePolicy_value = map[string]int32{ var Hook_DeletePolicy_value = map[string]int32{
"SUCCEEDED": 0, "SUCCEEDED": 0,
"FAILED": 1, "FAILED": 1,
"BEFORE_HOOK_CREATION": 2, "BEFORE_HOOK_CREATION": 2,
"ALL_SUCCEED": 3,
"ANY_FAILED": 4,
"IN_ANY_CASE": 5,
} }
func (x Hook_DeletePolicy) String() string { func (x Hook_DeletePolicy) String() string {
@ -202,34 +212,35 @@ func init() {
func init() { proto.RegisterFile("hapi/release/hook.proto", fileDescriptor0) } func init() { proto.RegisterFile("hapi/release/hook.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 453 bytes of a gzipped FileDescriptorProto // 478 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0x51, 0x8f, 0x9a, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xc1, 0x8e, 0xda, 0x30,
0x10, 0x80, 0x8f, 0x53, 0x41, 0x47, 0xcf, 0xdb, 0x6e, 0x9a, 0x76, 0xe3, 0xcb, 0x19, 0x9f, 0x7c, 0x10, 0x86, 0x37, 0x40, 0x02, 0x0c, 0x2c, 0xeb, 0x5a, 0x55, 0x6b, 0x71, 0x59, 0xc4, 0x89, 0x53,
0xc2, 0xe6, 0x9a, 0xfe, 0x00, 0x84, 0xb9, 0x6a, 0x24, 0x60, 0x16, 0x4c, 0x93, 0xbe, 0x10, 0xae, 0xa8, 0xb6, 0xea, 0x03, 0x84, 0x64, 0xb6, 0x20, 0xa2, 0x04, 0x39, 0x41, 0x55, 0x7b, 0xb1, 0xb2,
0xee, 0x29, 0x11, 0x81, 0x08, 0xb6, 0xe9, 0x1f, 0xed, 0x3f, 0xe8, 0xff, 0x68, 0x76, 0x45, 0x7a, 0xc5, 0x0b, 0x11, 0x90, 0x20, 0x12, 0x5a, 0xf5, 0x0d, 0xfa, 0xa2, 0x7d, 0x8f, 0xca, 0x26, 0xd0,
0x49, 0xfb, 0x36, 0xf3, 0xcd, 0xb7, 0xb3, 0x33, 0xbb, 0xf0, 0x7e, 0x1f, 0x17, 0xc9, 0xec, 0x24, 0x95, 0xba, 0x37, 0xcf, 0x37, 0xff, 0xfc, 0xfe, 0xc7, 0x86, 0xf7, 0x9b, 0xe4, 0x90, 0x8e, 0x8f,
0x52, 0x11, 0x97, 0x62, 0xb6, 0xcf, 0xf3, 0x83, 0x59, 0x9c, 0xf2, 0x2a, 0xa7, 0x03, 0x59, 0x30, 0x72, 0x27, 0x93, 0x42, 0x8e, 0x37, 0x79, 0xbe, 0xb5, 0x0f, 0xc7, 0xbc, 0xcc, 0x69, 0x57, 0x35,
0xeb, 0xc2, 0xe8, 0x61, 0x97, 0xe7, 0xbb, 0x54, 0xcc, 0x54, 0xed, 0xf9, 0xfc, 0x32, 0xab, 0x92, 0xec, 0xaa, 0xd1, 0xbf, 0x5f, 0xe7, 0xf9, 0x7a, 0x27, 0xc7, 0xba, 0xf7, 0x74, 0x7a, 0x1e, 0x97,
0xa3, 0x28, 0xab, 0xf8, 0x58, 0x5c, 0xf4, 0xc9, 0xaf, 0x36, 0xb4, 0x17, 0x79, 0x7e, 0xa0, 0x14, 0xe9, 0x5e, 0x16, 0x65, 0xb2, 0x3f, 0x9c, 0xe5, 0xc3, 0xdf, 0x26, 0x34, 0xa6, 0x79, 0xbe, 0xa5,
0xda, 0x59, 0x7c, 0x14, 0x4c, 0x1b, 0x6b, 0xd3, 0x1e, 0x57, 0xb1, 0x64, 0x87, 0x24, 0xdb, 0xb2, 0x14, 0x1a, 0x59, 0xb2, 0x97, 0xcc, 0x18, 0x18, 0xa3, 0x36, 0xd7, 0x67, 0xc5, 0xb6, 0x69, 0xb6,
0xdb, 0x0b, 0x93, 0xb1, 0x64, 0x45, 0x5c, 0xed, 0x59, 0xeb, 0xc2, 0x64, 0x4c, 0x47, 0xd0, 0x3d, 0x62, 0xb5, 0x33, 0x53, 0x67, 0xc5, 0x0e, 0x49, 0xb9, 0x61, 0xf5, 0x33, 0x53, 0x67, 0xda, 0x87,
0xc6, 0x59, 0xf2, 0x22, 0xca, 0x8a, 0xb5, 0x15, 0x6f, 0x72, 0xfa, 0x01, 0x74, 0xf1, 0x5d, 0x64, 0xd6, 0x3e, 0xc9, 0xd2, 0x67, 0x59, 0x94, 0xac, 0xa1, 0xf9, 0xb5, 0xa6, 0x1f, 0xc0, 0x92, 0x3f,
0x55, 0xc9, 0x3a, 0xe3, 0xd6, 0x74, 0xf8, 0xc8, 0xcc, 0xd7, 0x03, 0x9a, 0xf2, 0x6e, 0x13, 0xa5, 0x64, 0x56, 0x16, 0xcc, 0x1c, 0xd4, 0x47, 0xbd, 0x07, 0x66, 0xbf, 0x0c, 0x68, 0xab, 0xbb, 0x6d,
0xc0, 0x6b, 0x8f, 0x7e, 0x82, 0x6e, 0x1a, 0x97, 0x55, 0x74, 0x3a, 0x67, 0x4c, 0x1f, 0x6b, 0xd3, 0x54, 0x02, 0x5e, 0xe9, 0xe8, 0x27, 0x68, 0xed, 0x92, 0xa2, 0x14, 0xc7, 0x53, 0xc6, 0xac, 0x81,
0xfe, 0xe3, 0xc8, 0xbc, 0xac, 0x61, 0x5e, 0xd7, 0x30, 0xc3, 0xeb, 0x1a, 0xdc, 0x90, 0x2e, 0x3f, 0x31, 0xea, 0x3c, 0xf4, 0xed, 0xf3, 0x1a, 0xf6, 0x65, 0x0d, 0x3b, 0xbe, 0xac, 0xc1, 0x9b, 0x4a,
0x67, 0xf4, 0x1d, 0xe8, 0x3f, 0x44, 0xb2, 0xdb, 0x57, 0xcc, 0x18, 0x6b, 0xd3, 0x0e, 0xaf, 0x33, 0xcb, 0x4f, 0x19, 0x7d, 0x07, 0xd6, 0x4f, 0x99, 0xae, 0x37, 0x25, 0x6b, 0x0e, 0x8c, 0x91, 0xc9,
0xba, 0x80, 0xfb, 0xad, 0x48, 0x45, 0x25, 0xa2, 0x22, 0x4f, 0x93, 0x6f, 0x89, 0x28, 0x59, 0x57, 0xab, 0x8a, 0x4e, 0xe1, 0x6e, 0x25, 0x77, 0xb2, 0x94, 0xe2, 0x90, 0xef, 0xd2, 0xef, 0xa9, 0x2c,
0x4d, 0xf2, 0xf0, 0x9f, 0x49, 0x1c, 0x65, 0xae, 0xa5, 0xf8, 0x93, 0x0f, 0xb7, 0x7f, 0xb3, 0x44, 0x58, 0x4b, 0x27, 0xb9, 0x7f, 0x25, 0x89, 0xa7, 0x95, 0x0b, 0x25, 0xfc, 0xc5, 0x7b, 0xab, 0x7f,
0x94, 0x93, 0xdf, 0x1a, 0x74, 0xd4, 0xa8, 0xb4, 0x0f, 0xc6, 0xc6, 0x5b, 0x79, 0xfe, 0x17, 0x8f, 0x55, 0x2a, 0x8b, 0xe1, 0x1f, 0x03, 0x4c, 0x1d, 0x95, 0x76, 0xa0, 0xb9, 0x0c, 0xe6, 0x41, 0xf8,
0xdc, 0xd0, 0x7b, 0xe8, 0xaf, 0x39, 0x46, 0x4b, 0x2f, 0x08, 0x2d, 0xd7, 0x25, 0x1a, 0x25, 0x30, 0x25, 0x20, 0x37, 0xf4, 0x0e, 0x3a, 0x0b, 0x8e, 0x62, 0x16, 0x44, 0xb1, 0xe3, 0xfb, 0xc4, 0xa0,
0x58, 0xfb, 0x41, 0xd8, 0x90, 0x5b, 0x3a, 0x04, 0x90, 0x8a, 0x83, 0x2e, 0x86, 0x48, 0x5a, 0xea, 0x04, 0xba, 0x8b, 0x30, 0x8a, 0xaf, 0xa4, 0x46, 0x7b, 0x00, 0x4a, 0xe2, 0xa1, 0x8f, 0x31, 0x92,
0x88, 0x34, 0x6a, 0xd0, 0xbe, 0xf6, 0xd8, 0xac, 0x3f, 0x73, 0xcb, 0x41, 0xd2, 0x69, 0x7a, 0x5c, 0xba, 0x1e, 0x51, 0x8a, 0x0a, 0x34, 0x2e, 0x1e, 0xcb, 0xc5, 0x67, 0xee, 0x78, 0x48, 0xcc, 0xab,
0x89, 0xae, 0x08, 0xc7, 0x88, 0xfb, 0xae, 0x3b, 0xb7, 0xec, 0x15, 0x31, 0xe8, 0x1b, 0xb8, 0x53, 0xc7, 0x85, 0x58, 0x9a, 0x70, 0x14, 0x3c, 0xf4, 0xfd, 0x89, 0xe3, 0xce, 0x49, 0x93, 0xbe, 0x81,
0x4e, 0x83, 0xba, 0x94, 0xc1, 0x5b, 0x8e, 0x2e, 0x5a, 0x01, 0x46, 0x21, 0x06, 0x61, 0x14, 0x6c, 0x5b, 0xad, 0xb9, 0xa2, 0x16, 0x65, 0xf0, 0x96, 0xa3, 0x8f, 0x4e, 0x84, 0x22, 0xc6, 0x28, 0x16,
0x6c, 0x1b, 0x83, 0x80, 0xf4, 0xfe, 0xa9, 0x3c, 0x59, 0x4b, 0x77, 0xc3, 0x91, 0x80, 0xbc, 0xdb, 0xd1, 0xd2, 0x75, 0x31, 0x8a, 0x48, 0xfb, 0xbf, 0xce, 0xa3, 0x33, 0xf3, 0x97, 0x1c, 0x09, 0xa8,
0xe6, 0x4e, 0x33, 0x6d, 0x7f, 0x62, 0xc3, 0xe0, 0xf5, 0x3b, 0xd0, 0x3b, 0xe8, 0xa9, 0x3e, 0xe8, 0xbb, 0x5d, 0xee, 0x5d, 0xd3, 0x76, 0x86, 0x27, 0xe8, 0xbe, 0x7c, 0x07, 0x7a, 0x0b, 0x6d, 0xed,
0xa0, 0x43, 0x6e, 0x28, 0x80, 0x2e, 0x0f, 0xa3, 0x43, 0x34, 0xd9, 0x75, 0x8e, 0x4f, 0x3e, 0xc7, 0x83, 0x1e, 0x7a, 0xe4, 0x86, 0x02, 0x58, 0x6a, 0x18, 0x3d, 0x62, 0x28, 0xd7, 0x09, 0x3e, 0x86,
0x68, 0xe1, 0xfb, 0xab, 0xc8, 0xe6, 0x68, 0x85, 0x4b, 0xdf, 0x23, 0xb7, 0xf3, 0xde, 0x57, 0xa3, 0x1c, 0xc5, 0x34, 0x0c, 0xe7, 0xc2, 0xe5, 0xe8, 0xc4, 0xb3, 0x30, 0x20, 0x35, 0xe5, 0xea, 0xf8,
0x7e, 0xd9, 0x67, 0x5d, 0x7d, 0xdb, 0xc7, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xcf, 0xed, 0xbe, 0xa8, 0x06, 0x49, 0x5d, 0xbd, 0x81, 0x13, 0x7c, 0x15, 0xd5, 0xa8, 0x5e, 0x79, 0x16, 0x08,
0xd9, 0xb4, 0x02, 0x00, 0x00, 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 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 { type ListReleasesRequest struct {
// Limit is the maximum number of releases to be returned. // Limit is the maximum number of releases to be returned.
Limit int64 `protobuf:"varint,1,opt,name=limit" json:"limit,omitempty"` 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"` Name string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"`
// DisableHooks causes the server to skip running any hooks for the install. // 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"` 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"` 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"` 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 specifies the max amount of time any kubernetes client command can run.
Timeout int64 `protobuf:"varint,8,opt,name=timeout" json:"timeout,omitempty"` 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 // 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{ 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.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. // 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 // apiVersion: v1
// metadata: // metadata:
// annotations: // annotations:
// helm.sh/hook-delete-policy: hook-succeeded // helm.sh/hook-delete-policy: this-hook-succeeded
func (file *manifestFile) sort(result *result) error { func (file *manifestFile) sort(result *result) error {
for _, m := range file.entries { for _, m := range file.entries {
var entry util.SimpleHead var entry util.SimpleHead
@ -192,7 +195,21 @@ func (file *manifestFile) sort(result *result) error {
if exist { if exist {
h.DeletePolicies = append(h.DeletePolicies, policy) h.DeletePolicies = append(h.DeletePolicies, policy)
} else { } else {
if value != hooks.HookFailed && value != hooks.HookSucceeded {
log.Printf("info: skipping unknown hook delete policy: %q", value) 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") 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) executingHooks = sortByHookWeight(executingHooks)
for index, h := range 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 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) 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 // 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 // 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] { 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 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
} }
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 // 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 // under succeeded condition. If so, then clear the corresponding resource object in each hook
for _, h := range executingHooks { 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 return err
} }
h.LastRun = timeconv.Now() h.LastRun = timeconv.Now()
@ -429,8 +428,9 @@ func validateReleaseName(releaseName string) error {
return nil 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) b := bytes.NewBufferString(h.Manifest)
for _, policy := range append(policies, hooks.InAnyCase) {
if hookHasDeletePolicy(h, policy) { if hookHasDeletePolicy(h, policy) {
s.Log("deleting %s hook %s for release %s due to %q policy", hook, h.Name, name, 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 { if errHookDelete := kubeCli.Delete(namespace, b); errHookDelete != nil {
@ -438,6 +438,7 @@ func (s *ReleaseServer) deleteHookByPolicy(h *release.Hook, policy string, name,
return errHookDelete return errHookDelete
} }
} }
}
return nil return nil
} }

@ -23,6 +23,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"regexp" "regexp"
"strings"
"testing" "testing"
"time" "time"
@ -601,26 +602,34 @@ name: value`, hookName, extraAnnotationsStr),
} }
} }
func execHookShouldSucceed(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string) error { func getHooksNameList(hooks []*release.Hook) string {
err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600) 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 { 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 return nil
} }
func execHookShouldFail(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string) error { func execHooksShouldFail(rs *ReleaseServer, hooks []*release.Hook, releaseName string, namespace string, hookType string) error {
err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600) err := rs.execHook(hooks, releaseName, namespace, hookType, 600)
if err == nil { 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 return nil
} }
func execHookShouldFailWithError(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string, expectedError error) error { func execHooksShouldFailWithError(rs *ReleaseServer, hooks []*release.Hook, releaseName string, namespace string, hookType string, expectedError error) error {
err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600) err := rs.execHook(hooks, releaseName, namespace, hookType, 600)
if err != expectedError { 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 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) { func TestSuccessfulHookWithoutDeletePolicy(t *testing.T) {
ctx := newDeletePolicyContext() ctx := newDeletePolicyContext()
hook := deletePolicyHookStub(ctx.HookName, nil, nil) 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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -667,7 +695,7 @@ func TestFailedHookWithoutDeletePolicy(t *testing.T) {
nil, 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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -679,11 +707,11 @@ func TestFailedHookWithoutDeletePolicy(t *testing.T) {
func TestSuccessfulHookWithSucceededDeletePolicy(t *testing.T) { func TestSuccessfulHookWithSucceededDeletePolicy(t *testing.T) {
ctx := newDeletePolicyContext() ctx := newDeletePolicyContext()
hook := deletePolicyHookStub(ctx.HookName, 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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -695,11 +723,11 @@ func TestSuccessfulHookWithSucceededDeletePolicy(t *testing.T) {
func TestSuccessfulHookWithFailedDeletePolicy(t *testing.T) { func TestSuccessfulHookWithFailedDeletePolicy(t *testing.T) {
ctx := newDeletePolicyContext() ctx := newDeletePolicyContext()
hook := deletePolicyHookStub(ctx.HookName, 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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -714,12 +742,12 @@ func TestFailedHookWithSucceededDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed", "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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -734,12 +762,12 @@ func TestFailedHookWithFailedDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed", "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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -753,12 +781,12 @@ func TestSuccessfulHookWithSuccededOrFailedDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ 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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -773,12 +801,12 @@ func TestFailedHookWithSuccededOrFailedDeletePolicy(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed", "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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -792,7 +820,7 @@ func TestHookAlreadyExists(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, nil, nil) 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 { if err != nil {
t.Error(err) 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) 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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -819,7 +847,7 @@ func TestHookDeletingWithBeforeHookCreationDeletePolicy(t *testing.T) {
[]release.Hook_DeletePolicy{release.Hook_BEFORE_HOOK_CREATION}, []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 { if err != nil {
t.Error(err) 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) 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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -843,12 +871,12 @@ func TestSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ 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}, []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 { if err != nil {
t.Error(err) 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) 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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -873,12 +901,12 @@ func TestFailedHookWithMixedDeletePolicies(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed", "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}, []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 { if err != nil {
t.Error(err) 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) 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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -903,12 +931,12 @@ func TestFailedThenSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
hook := deletePolicyHookStub(ctx.HookName, hook := deletePolicyHookStub(ctx.HookName,
map[string]string{ map[string]string{
"mockHooksKubeClient/Emulate": "hook-failed", "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}, []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 { if err != nil {
t.Error(err) t.Error(err)
} }
@ -919,12 +947,12 @@ func TestFailedThenSuccessfulHookWithMixedDeletePolicies(t *testing.T) {
hook = deletePolicyHookStub(ctx.HookName, hook = deletePolicyHookStub(ctx.HookName,
map[string]string{ 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}, []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 { if err != nil {
t.Error(err) 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) 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