Skip to content

Commit 03fcc7c

Browse files
RipolinXun Jiang
authored and
Xun Jiang
committed
Add WaitForReady flag to check container readiness state before exec a hook
Signed-off-by: Ripolin <[email protected]>
1 parent d58761d commit 03fcc7c

File tree

7 files changed

+182
-77
lines changed

7 files changed

+182
-77
lines changed

changelogs/unreleased/6918-Ripolin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Optional check if targeted container is ready before executing a hook

internal/hook/item_hook_handler.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package hook
1919
import (
2020
"encoding/json"
2121
"fmt"
22+
"strconv"
2223
"strings"
2324
"time"
2425

@@ -37,6 +38,7 @@ import (
3738
"github.com/vmware-tanzu/velero/pkg/kuberesource"
3839
"github.com/vmware-tanzu/velero/pkg/podexec"
3940
"github.com/vmware-tanzu/velero/pkg/restorehelper"
41+
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
4042
"github.com/vmware-tanzu/velero/pkg/util/collections"
4143
"github.com/vmware-tanzu/velero/pkg/util/kube"
4244
)
@@ -61,6 +63,7 @@ const (
6163
podRestoreHookOnErrorAnnotationKey = "post.hook.restore.velero.io/on-error"
6264
podRestoreHookTimeoutAnnotationKey = "post.hook.restore.velero.io/exec-timeout"
6365
podRestoreHookWaitTimeoutAnnotationKey = "post.hook.restore.velero.io/wait-timeout"
66+
podRestoreHookWaitForReadyAnnotationKey = "post.hook.restore.velero.io/wait-for-ready"
6467
podRestoreHookInitContainerImageAnnotationKey = "init.hook.restore.velero.io/container-image"
6568
podRestoreHookInitContainerNameAnnotationKey = "init.hook.restore.velero.io/container-name"
6669
podRestoreHookInitContainerCommandAnnotationKey = "init.hook.restore.velero.io/command"
@@ -477,12 +480,23 @@ func getPodExecRestoreHookFromAnnotations(annotations map[string]string, log log
477480
}
478481
}
479482

483+
waitForReadyString := annotations[podRestoreHookWaitForReadyAnnotationKey]
484+
waitForReady := boolptr.False()
485+
if waitForReadyString != "" {
486+
var err error
487+
*waitForReady, err = strconv.ParseBool(waitForReadyString)
488+
if err != nil {
489+
log.Warn(errors.Wrapf(err, "Unable to parse wait for ready %s, ignoring", waitForReadyString))
490+
}
491+
}
492+
480493
return &velerov1api.ExecRestoreHook{
481-
Container: container,
482-
Command: parseStringToCommand(commandValue),
483-
OnError: onError,
484-
ExecTimeout: metav1.Duration{Duration: execTimeout},
485-
WaitTimeout: metav1.Duration{Duration: waitTimeout},
494+
Container: container,
495+
Command: parseStringToCommand(commandValue),
496+
OnError: onError,
497+
ExecTimeout: metav1.Duration{Duration: execTimeout},
498+
WaitTimeout: metav1.Duration{Duration: waitTimeout},
499+
WaitForReady: waitForReady,
486500
}
487501
}
488502

@@ -542,6 +556,10 @@ func GroupRestoreExecHooks(
542556
Hook: *rh.Exec,
543557
HookSource: "backupSpec",
544558
}
559+
// default to false if attr WaitForReady not set
560+
if named.Hook.WaitForReady == nil {
561+
named.Hook.WaitForReady = boolptr.False()
562+
}
545563
// default to first container in pod if unset, without mutating resource restore hook
546564
if named.Hook.Container == "" {
547565
named.Hook.Container = pod.Spec.Containers[0].Name

internal/hook/item_hook_handler_test.go

Lines changed: 87 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/vmware-tanzu/velero/pkg/builder"
3737
"github.com/vmware-tanzu/velero/pkg/kuberesource"
3838
velerotest "github.com/vmware-tanzu/velero/pkg/test"
39+
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
3940
"github.com/vmware-tanzu/velero/pkg/util/collections"
4041
)
4142

@@ -724,7 +725,8 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
724725
podRestoreHookCommandAnnotationKey: "/usr/bin/foo",
725726
},
726727
expected: &velerov1api.ExecRestoreHook{
727-
Command: []string{"/usr/bin/foo"},
728+
Command: []string{"/usr/bin/foo"},
729+
WaitForReady: boolptr.False(),
728730
},
729731
},
730732
{
@@ -733,7 +735,8 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
733735
podRestoreHookCommandAnnotationKey: `["a","b","c"]`,
734736
},
735737
expected: &velerov1api.ExecRestoreHook{
736-
Command: []string{"a", "b", "c"},
738+
Command: []string{"a", "b", "c"},
739+
WaitForReady: boolptr.False(),
737740
},
738741
},
739742
{
@@ -743,8 +746,9 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
743746
podRestoreHookOnErrorAnnotationKey: string(velerov1api.HookErrorModeContinue),
744747
},
745748
expected: &velerov1api.ExecRestoreHook{
746-
Command: []string{"/usr/bin/foo"},
747-
OnError: velerov1api.HookErrorModeContinue,
749+
Command: []string{"/usr/bin/foo"},
750+
OnError: velerov1api.HookErrorModeContinue,
751+
WaitForReady: boolptr.False(),
748752
},
749753
},
750754
{
@@ -754,8 +758,9 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
754758
podRestoreHookOnErrorAnnotationKey: string(velerov1api.HookErrorModeFail),
755759
},
756760
expected: &velerov1api.ExecRestoreHook{
757-
Command: []string{"/usr/bin/foo"},
758-
OnError: velerov1api.HookErrorModeFail,
761+
Command: []string{"/usr/bin/foo"},
762+
OnError: velerov1api.HookErrorModeFail,
763+
WaitForReady: boolptr.False(),
759764
},
760765
},
761766
{
@@ -766,9 +771,10 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
766771
podRestoreHookWaitTimeoutAnnotationKey: "1h",
767772
},
768773
expected: &velerov1api.ExecRestoreHook{
769-
Command: []string{"/usr/bin/foo"},
770-
ExecTimeout: metav1.Duration{Duration: 45 * time.Second},
771-
WaitTimeout: metav1.Duration{Duration: time.Hour},
774+
Command: []string{"/usr/bin/foo"},
775+
ExecTimeout: metav1.Duration{Duration: 45 * time.Second},
776+
WaitTimeout: metav1.Duration{Duration: time.Hour},
777+
WaitForReady: boolptr.False(),
772778
},
773779
},
774780
{
@@ -778,8 +784,9 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
778784
podRestoreHookContainerAnnotationKey: "my-app",
779785
},
780786
expected: &velerov1api.ExecRestoreHook{
781-
Command: []string{"/usr/bin/foo"},
782-
Container: "my-app",
787+
Command: []string{"/usr/bin/foo"},
788+
Container: "my-app",
789+
WaitForReady: boolptr.False(),
783790
},
784791
},
785792
{
@@ -790,9 +797,10 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
790797
podRestoreHookTimeoutAnnotationKey: "none",
791798
},
792799
expected: &velerov1api.ExecRestoreHook{
793-
Command: []string{"/usr/bin/foo"},
794-
Container: "my-app",
795-
ExecTimeout: metav1.Duration{Duration: 0},
800+
Command: []string{"/usr/bin/foo"},
801+
Container: "my-app",
802+
ExecTimeout: metav1.Duration{Duration: 0},
803+
WaitForReady: boolptr.False(),
796804
},
797805
},
798806
{
@@ -803,9 +811,10 @@ func TestGetPodExecRestoreHookFromAnnotations(t *testing.T) {
803811
podRestoreHookWaitTimeoutAnnotationKey: "none",
804812
},
805813
expected: &velerov1api.ExecRestoreHook{
806-
Command: []string{"/usr/bin/foo"},
807-
Container: "my-app",
808-
ExecTimeout: metav1.Duration{Duration: 0},
814+
Command: []string{"/usr/bin/foo"},
815+
Container: "my-app",
816+
ExecTimeout: metav1.Duration{Duration: 0},
817+
WaitForReady: boolptr.False(),
809818
},
810819
},
811820
}
@@ -842,6 +851,7 @@ func TestGroupRestoreExecHooks(t *testing.T) {
842851
podRestoreHookOnErrorAnnotationKey, string(velerov1api.HookErrorModeContinue),
843852
podRestoreHookTimeoutAnnotationKey, "1s",
844853
podRestoreHookWaitTimeoutAnnotationKey, "1m",
854+
podRestoreHookWaitForReadyAnnotationKey, "true",
845855
)).
846856
Containers(&corev1api.Container{
847857
Name: "container1",
@@ -853,11 +863,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
853863
HookName: "<from-annotation>",
854864
HookSource: "annotation",
855865
Hook: velerov1api.ExecRestoreHook{
856-
Container: "container1",
857-
Command: []string{"/usr/bin/foo"},
858-
OnError: velerov1api.HookErrorModeContinue,
859-
ExecTimeout: metav1.Duration{Duration: time.Second},
860-
WaitTimeout: metav1.Duration{Duration: time.Minute},
866+
Container: "container1",
867+
Command: []string{"/usr/bin/foo"},
868+
OnError: velerov1api.HookErrorModeContinue,
869+
ExecTimeout: metav1.Duration{Duration: time.Second},
870+
WaitTimeout: metav1.Duration{Duration: time.Minute},
871+
WaitForReady: boolptr.True(),
861872
},
862873
},
863874
},
@@ -883,11 +894,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
883894
HookName: "<from-annotation>",
884895
HookSource: "annotation",
885896
Hook: velerov1api.ExecRestoreHook{
886-
Container: "container1",
887-
Command: []string{"/usr/bin/foo"},
888-
OnError: velerov1api.HookErrorModeContinue,
889-
ExecTimeout: metav1.Duration{Duration: time.Second},
890-
WaitTimeout: metav1.Duration{Duration: time.Minute},
897+
Container: "container1",
898+
Command: []string{"/usr/bin/foo"},
899+
OnError: velerov1api.HookErrorModeContinue,
900+
ExecTimeout: metav1.Duration{Duration: time.Second},
901+
WaitTimeout: metav1.Duration{Duration: time.Minute},
902+
WaitForReady: boolptr.False(),
891903
},
892904
},
893905
},
@@ -923,11 +935,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
923935
HookName: "hook1",
924936
HookSource: "backupSpec",
925937
Hook: velerov1api.ExecRestoreHook{
926-
Container: "container1",
927-
Command: []string{"/usr/bin/foo"},
928-
OnError: velerov1api.HookErrorModeContinue,
929-
ExecTimeout: metav1.Duration{Duration: time.Second},
930-
WaitTimeout: metav1.Duration{Duration: time.Minute},
938+
Container: "container1",
939+
Command: []string{"/usr/bin/foo"},
940+
OnError: velerov1api.HookErrorModeContinue,
941+
ExecTimeout: metav1.Duration{Duration: time.Second},
942+
WaitTimeout: metav1.Duration{Duration: time.Minute},
943+
WaitForReady: boolptr.False(),
931944
},
932945
},
933946
},
@@ -962,11 +975,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
962975
HookName: "hook1",
963976
HookSource: "backupSpec",
964977
Hook: velerov1api.ExecRestoreHook{
965-
Container: "container1",
966-
Command: []string{"/usr/bin/foo"},
967-
OnError: velerov1api.HookErrorModeContinue,
968-
ExecTimeout: metav1.Duration{Duration: time.Second},
969-
WaitTimeout: metav1.Duration{Duration: time.Minute},
978+
Container: "container1",
979+
Command: []string{"/usr/bin/foo"},
980+
OnError: velerov1api.HookErrorModeContinue,
981+
ExecTimeout: metav1.Duration{Duration: time.Second},
982+
WaitTimeout: metav1.Duration{Duration: time.Minute},
983+
WaitForReady: boolptr.False(),
970984
},
971985
},
972986
},
@@ -1009,11 +1023,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
10091023
HookName: "<from-annotation>",
10101024
HookSource: "annotation",
10111025
Hook: velerov1api.ExecRestoreHook{
1012-
Container: "container1",
1013-
Command: []string{"/usr/bin/foo"},
1014-
OnError: velerov1api.HookErrorModeContinue,
1015-
ExecTimeout: metav1.Duration{Duration: time.Second},
1016-
WaitTimeout: metav1.Duration{Duration: time.Minute},
1026+
Container: "container1",
1027+
Command: []string{"/usr/bin/foo"},
1028+
OnError: velerov1api.HookErrorModeContinue,
1029+
ExecTimeout: metav1.Duration{Duration: time.Second},
1030+
WaitTimeout: metav1.Duration{Duration: time.Minute},
1031+
WaitForReady: boolptr.False(),
10171032
},
10181033
},
10191034
},
@@ -1105,11 +1120,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
11051120
RestoreHooks: []velerov1api.RestoreResourceHook{
11061121
{
11071122
Exec: &velerov1api.ExecRestoreHook{
1108-
Container: "container1",
1109-
Command: []string{"/usr/bin/aaa"},
1110-
OnError: velerov1api.HookErrorModeContinue,
1111-
ExecTimeout: metav1.Duration{Duration: time.Second * 4},
1112-
WaitTimeout: metav1.Duration{Duration: time.Minute * 4},
1123+
Container: "container1",
1124+
Command: []string{"/usr/bin/aaa"},
1125+
OnError: velerov1api.HookErrorModeContinue,
1126+
ExecTimeout: metav1.Duration{Duration: time.Second * 4},
1127+
WaitTimeout: metav1.Duration{Duration: time.Minute * 4},
1128+
WaitForReady: boolptr.True(),
11131129
},
11141130
},
11151131
},
@@ -1126,33 +1142,36 @@ func TestGroupRestoreExecHooks(t *testing.T) {
11261142
HookName: "hook1",
11271143
HookSource: "backupSpec",
11281144
Hook: velerov1api.ExecRestoreHook{
1129-
Container: "container1",
1130-
Command: []string{"/usr/bin/foo"},
1131-
OnError: velerov1api.HookErrorModeFail,
1132-
ExecTimeout: metav1.Duration{Duration: time.Second},
1133-
WaitTimeout: metav1.Duration{Duration: time.Minute},
1145+
Container: "container1",
1146+
Command: []string{"/usr/bin/foo"},
1147+
OnError: velerov1api.HookErrorModeFail,
1148+
ExecTimeout: metav1.Duration{Duration: time.Second},
1149+
WaitTimeout: metav1.Duration{Duration: time.Minute},
1150+
WaitForReady: boolptr.False(),
11341151
},
11351152
},
11361153
{
11371154
HookName: "hook1",
11381155
HookSource: "backupSpec",
11391156
Hook: velerov1api.ExecRestoreHook{
1140-
Container: "container1",
1141-
Command: []string{"/usr/bin/bar"},
1142-
OnError: velerov1api.HookErrorModeContinue,
1143-
ExecTimeout: metav1.Duration{Duration: time.Second * 2},
1144-
WaitTimeout: metav1.Duration{Duration: time.Minute * 2},
1157+
Container: "container1",
1158+
Command: []string{"/usr/bin/bar"},
1159+
OnError: velerov1api.HookErrorModeContinue,
1160+
ExecTimeout: metav1.Duration{Duration: time.Second * 2},
1161+
WaitTimeout: metav1.Duration{Duration: time.Minute * 2},
1162+
WaitForReady: boolptr.False(),
11451163
},
11461164
},
11471165
{
11481166
HookName: "hook2",
11491167
HookSource: "backupSpec",
11501168
Hook: velerov1api.ExecRestoreHook{
1151-
Container: "container1",
1152-
Command: []string{"/usr/bin/aaa"},
1153-
OnError: velerov1api.HookErrorModeContinue,
1154-
ExecTimeout: metav1.Duration{Duration: time.Second * 4},
1155-
WaitTimeout: metav1.Duration{Duration: time.Minute * 4},
1169+
Container: "container1",
1170+
Command: []string{"/usr/bin/aaa"},
1171+
OnError: velerov1api.HookErrorModeContinue,
1172+
ExecTimeout: metav1.Duration{Duration: time.Second * 4},
1173+
WaitTimeout: metav1.Duration{Duration: time.Minute * 4},
1174+
WaitForReady: boolptr.True(),
11561175
},
11571176
},
11581177
},
@@ -1161,11 +1180,12 @@ func TestGroupRestoreExecHooks(t *testing.T) {
11611180
HookName: "hook1",
11621181
HookSource: "backupSpec",
11631182
Hook: velerov1api.ExecRestoreHook{
1164-
Container: "container2",
1165-
Command: []string{"/usr/bin/baz"},
1166-
OnError: velerov1api.HookErrorModeContinue,
1167-
ExecTimeout: metav1.Duration{Duration: time.Second * 3},
1168-
WaitTimeout: metav1.Duration{Duration: time.Second * 3},
1183+
Container: "container2",
1184+
Command: []string{"/usr/bin/baz"},
1185+
OnError: velerov1api.HookErrorModeContinue,
1186+
ExecTimeout: metav1.Duration{Duration: time.Second * 3},
1187+
WaitTimeout: metav1.Duration{Duration: time.Second * 3},
1188+
WaitForReady: boolptr.False(),
11691189
},
11701190
},
11711191
},

0 commit comments

Comments
 (0)