Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --cancel-scheduled flag to cancel all existing scheduled stops #9774

Merged
merged 3 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cmd/minikube/cmd/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var (
stopAll bool
keepActive bool
scheduledStopDuration time.Duration
cancelScheduledStop bool
)

// stopCmd represents the stop command
Expand All @@ -60,6 +61,8 @@ func init() {
stopCmd.Flags().BoolVar(&stopAll, "all", false, "Set flag to stop all profiles (clusters)")
stopCmd.Flags().BoolVar(&keepActive, "keep-context-active", false, "keep the kube-context active after cluster is stopped. Defaults to false.")
stopCmd.Flags().DurationVar(&scheduledStopDuration, "schedule", 0*time.Second, "Set flag to stop cluster after a set amount of time (e.g. --schedule=5m)")
stopCmd.Flags().BoolVar(&cancelScheduledStop, "cancel-scheduled", false, "cancel any existing scheduled stop requests")

if err := stopCmd.Flags().MarkHidden("schedule"); err != nil {
klog.Info("unable to mark --schedule flag as hidden")
}
Expand Down Expand Up @@ -97,6 +100,11 @@ func runStop(cmd *cobra.Command, args []string) {

// Kill any existing scheduled stops
schedule.KillExisting(profilesToStop)
if cancelScheduledStop {
register.Reg.SetStep(register.Done)
out.Step(style.Stopped, `All existing scheduled stops cancelled`)
return
}

if scheduledStopDuration != 0 {
if err := schedule.Daemonize(profilesToStop, scheduledStopDuration); err != nil {
Expand Down
1 change: 1 addition & 0 deletions site/content/en/docs/commands/stop.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ minikube stop [flags]

```
--all Set flag to stop all profiles (clusters)
--cancel-scheduled cancel any existing scheduled stop requests
--keep-context-active keep the kube-context active after cluster is stopped. Defaults to false.
-o, --output string Format to print stdout in. Options include: [text,json] (default "text")
```
Expand Down
37 changes: 24 additions & 13 deletions test/integration/scheduled_stop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestScheduledStopWindows(t *testing.T) {
startMinikube(ctx, t, profile)

// schedule a stop for 5m from now
scheduledStopMinikube(ctx, t, profile, "5m")
stopMinikube(ctx, t, profile, []string{"--schedule", "5m"})

// make sure the systemd service is running
rr, err := Run(t, exec.CommandContext(ctx, Target(), []string{"ssh", "-p", profile, "--", "sudo", "systemctl", "show", constants.ScheduledStopSystemdService, "--no-page"}...))
Expand All @@ -62,12 +62,12 @@ func TestScheduledStopWindows(t *testing.T) {
}

// reschedule stop for 5 seconds from now
scheduledStopMinikube(ctx, t, profile, "5s")
stopMinikube(ctx, t, profile, []string{"--schedule", "5s"})

// sleep for 5 seconds
time.Sleep(5 * time.Second)
// make sure minikube status is "Stopped"
ensureMinikubeStatusStopped(ctx, t, profile)
ensureMinikubeStatus(ctx, t, profile, state.Stopped.String())
}

func TestScheduledStopUnix(t *testing.T) {
Expand All @@ -83,20 +83,31 @@ func TestScheduledStopUnix(t *testing.T) {
startMinikube(ctx, t, profile)

// schedule a stop for 5 min from now and make sure PID is created
scheduledStopMinikube(ctx, t, profile, "5m")
stopMinikube(ctx, t, profile, []string{"--schedule", "5m"})
pid := checkPID(t, profile)
if !processRunning(t, pid) {
t.Fatalf("process %v is not running", pid)
}

// redo scheduled stop to be in 10s
scheduledStopMinikube(ctx, t, profile, "10s")
// schedule a second stop which should cancel the first scheduled stop
stopMinikube(ctx, t, profile, []string{"--schedule", "8s"})
if processRunning(t, pid) {
t.Fatalf("process %v running but should have been killed on reschedule of stop", pid)
}
checkPID(t, profile)
// make sure minikube status is "Stopped"
ensureMinikubeStatusStopped(ctx, t, profile)

// cancel the shutdown and make sure minikube is still running after 8 seconds
// sleep 12 just to be safe
stopMinikube(ctx, t, profile, []string{"--cancel-scheduled"})
time.Sleep(12 * time.Second)
ensureMinikubeStatus(ctx, t, profile, state.Running.String())

// schedule another stop, make sure minikube status is "Stopped"
stopMinikube(ctx, t, profile, []string{"--schedule", "5s"})
if processRunning(t, pid) {
t.Fatalf("process %v running but should have been killed on reschedule of stop", pid)
}
ensureMinikubeStatus(ctx, t, profile, state.Stopped.String())
}

func startMinikube(ctx context.Context, t *testing.T, profile string) {
Expand All @@ -107,8 +118,9 @@ func startMinikube(ctx context.Context, t *testing.T, profile string) {
}
}

func scheduledStopMinikube(ctx context.Context, t *testing.T, profile string, stop string) {
args := []string{"stop", "-p", profile, "--schedule", stop}
func stopMinikube(ctx context.Context, t *testing.T, profile string, additionalArgs []string) {
args := []string{"stop", "-p", profile}
args = append(args, additionalArgs...)
rr, err := Run(t, exec.CommandContext(ctx, Target(), args...))
if err != nil {
t.Fatalf("starting minikube: %v\n%s", err, rr.Output())
Expand Down Expand Up @@ -144,14 +156,13 @@ func processRunning(t *testing.T, pid string) bool {
t.Log("signal error was: ", err)
return err == nil
}

func ensureMinikubeStatusStopped(ctx context.Context, t *testing.T, profile string) {
func ensureMinikubeStatus(ctx context.Context, t *testing.T, profile, wantStatus string) {
// wait allotted time to make sure minikube status is "Stopped"
checkStatus := func() error {
ctx, cancel := context.WithDeadline(ctx, time.Now().Add(10*time.Second))
defer cancel()
got := Status(ctx, t, Target(), profile, "Host", profile)
if got != state.Stopped.String() {
if got != wantStatus {
return fmt.Errorf("expected post-stop host status to be -%q- but got *%q*", state.Stopped, got)
}
return nil
Expand Down