Skip to content

Commit 79c3809

Browse files
committed
feat: pre-restart hook before container restart
Signed-off-by: zwtop <wang.zhan@smartx.com>
1 parent 9068595 commit 79c3809

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

model/plugin.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,16 @@ type RuntimeDefinition struct {
9595
}
9696

9797
type UpdatePolicyDefinition struct {
98-
OnNoChange UpdatePolicyMode `yaml:"on_no_change,omitempty"`
98+
OnNoChange UpdatePolicyMode `yaml:"on_no_change,omitempty"`
99+
PreRestartHook *Hook `yaml:"pre_restart_hook,omitempty"` // exec when the previous container state is running
100+
}
101+
102+
type Hook struct {
103+
ExecCommand []string `yaml:"exec_command,omitempty"`
104+
ExecTimeout *int `yaml:"exec_timeout,omitempty"` // 0 means no timeout, default to 10(s)
105+
RetriesInterval *int `yaml:"retries_interval,omitempty"` // 0 means no waiting, default to 1(s)
106+
MaxRetries int `yaml:"max_retries,omitempty"` // 0 means no retries, default to 0
107+
IgnoreFailed bool `yaml:"ignore_failed,omitempty"` // ignore on hook failed
99108
}
100109

101110
type UpdatePolicyMode string

plugin/executor.go

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,11 @@ func (w *executor) runAndWaitContainers(ctx context.Context, containers ...model
437437
}
438438

439439
const (
440-
startProbeCheckInterval = 5 * time.Second
441-
defaultCheckTimeout = 3 * time.Second
442-
defaultProbeTimeout = 2 * time.Minute
440+
startProbeCheckInterval = 5 * time.Second
441+
defaultCheckTimeout = 3 * time.Second
442+
defaultProbeTimeout = 2 * time.Minute
443+
defaultHookExecTimeout = 10 * time.Second
444+
defaultHookRetriesInterval = time.Second
443445
)
444446

445447
func (w *executor) waitContainersReady(ctx context.Context, containers ...model.ContainerDefinition) error {
@@ -509,6 +511,9 @@ func (w *executor) runContainers(ctx context.Context, containers ...model.Contai
509511
}
510512
fallthrough
511513
case model.UpdatePolicyModeRestart:
514+
if err := w.doContainerPreRestart(ctx, c); err != nil {
515+
return fmt.Errorf("pre-restart container %s: %w", c.Name, err)
516+
}
512517
if _, err := w.runtime.GetContainer(ctx, c.Name); err == nil || !errdefs.IsNotFound(err) {
513518
w.Infof("remove container %s from containerd", c.Name)
514519
_ = w.runtime.RemoveContainer(ctx, c.Name)
@@ -626,6 +631,47 @@ func (w *executor) doUpdateOperationMetadata(ctx context.Context, pluginHash, ti
626631
return errdefs.FromGRPC(lo.T2(c.Update(ctx, &req)).B)
627632
}
628633

634+
func (w *executor) doContainerPreRestart(ctx context.Context, c model.ContainerDefinition) error {
635+
if c.UpdatePolicy == nil || c.UpdatePolicy.PreRestartHook == nil {
636+
return nil
637+
}
638+
return w.doContainerExecHook(ctx, c.Name, "pre-restart", c.UpdatePolicy.PreRestartHook)
639+
}
640+
641+
func (w *executor) doContainerExecHook(ctx context.Context, name, hookName string, hook *model.Hook) error {
642+
interval := defaultHookRetriesInterval
643+
if hook.RetriesInterval != nil {
644+
interval = time.Duration(*hook.RetriesInterval) * time.Second
645+
}
646+
timeout := defaultHookExecTimeout
647+
if hook.ExecTimeout != nil {
648+
timeout = time.Duration(*hook.ExecTimeout) * time.Second
649+
}
650+
651+
var herr error
652+
ctx, cancel := context.WithTimeout(ctx, timeout)
653+
defer cancel()
654+
655+
for retries := hook.MaxRetries; retries >= 0; retries-- {
656+
w.Infof("exec %s hook in container %s", hookName, name)
657+
result, err := w.runtime.ExecCommand(ctx, name, hook.ExecCommand)
658+
herr = client.HandleTaskResult(result, err)
659+
if herr == nil {
660+
break
661+
}
662+
w.Warningf("exec %s hook in container %s: %s", hookName, name, herr)
663+
if retries > 0 {
664+
time.Sleep(interval)
665+
}
666+
}
667+
668+
if herr != nil && hook.IgnoreFailed {
669+
w.Warningf("exec %s hook in container %s: failed after %d retries", hookName, name, hook.MaxRetries+1)
670+
return nil
671+
}
672+
return herr
673+
}
674+
629675
func (w *executor) setupLogging(ctx context.Context) error {
630676
if w.logging == nil {
631677
return nil

0 commit comments

Comments
 (0)