diff --git a/cmd/minikube/cmd/config/disable.go b/cmd/minikube/cmd/config/disable.go index b0838076d9..b70befbcb1 100644 --- a/cmd/minikube/cmd/config/disable.go +++ b/cmd/minikube/cmd/config/disable.go @@ -35,7 +35,10 @@ var addonsDisableCmd = &cobra.Command{ if len(args) != 1 { exit.Message(reason.Usage, "usage: minikube addons disable ADDON_NAME") } - + err := addons.VerifyNotPaused(ClusterFlagValue(), false) + if err != nil { + exit.Error(reason.InternalAddonDisablePaused, "disable failed", err) + } addon := args[0] if addon == "heapster" { exit.Message(reason.AddonUnsupported, "The heapster addon is depreciated. please try to disable metrics-server instead") @@ -46,7 +49,7 @@ var addonsDisableCmd = &cobra.Command{ exit.Message(reason.AddonUnsupported, `"'{{.minikube_addon}}' is not a valid minikube addon`, out.V{"minikube_addon": addon}) } if validAddon.IsEnabled(cc) { - err := addons.SetAndSave(ClusterFlagValue(), addon, "false") + err = addons.SetAndSave(ClusterFlagValue(), addon, "false") if err != nil { exit.Error(reason.InternalAddonDisable, "disable failed", err) } diff --git a/cmd/minikube/cmd/config/enable.go b/cmd/minikube/cmd/config/enable.go index cfd9c8cec1..9c15727151 100644 --- a/cmd/minikube/cmd/config/enable.go +++ b/cmd/minikube/cmd/config/enable.go @@ -48,6 +48,10 @@ var addonsEnableCmd = &cobra.Command{ exit.Message(reason.Usage, "You cannot enable addons on a cluster without Kubernetes, to enable Kubernetes on your cluster, run: minikube start --kubernetes-version=stable") } + err = addons.VerifyNotPaused(ClusterFlagValue(), true) + if err != nil { + exit.Error(reason.InternalAddonEnablePaused, "enabled failed", err) + } addon := args[0] isDeprecated, replacement, msg := addons.Deprecations(addon) if isDeprecated && replacement == "" { diff --git a/pkg/addons/addons.go b/pkg/addons/addons.go index c453562463..cba3b2f4b5 100644 --- a/pkg/addons/addons.go +++ b/pkg/addons/addons.go @@ -29,6 +29,7 @@ import ( "time" "github.com/blang/semver/v4" + "github.com/docker/machine/libmachine/state" "github.com/pkg/errors" "github.com/spf13/viper" @@ -36,9 +37,11 @@ import ( "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/kapi" "k8s.io/minikube/pkg/minikube/assets" + "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/command" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" @@ -585,3 +588,63 @@ func UpdateConfigToDisable(cc *config.ClusterConfig) { } } } + +// VerifyNotPaused verifies the cluster is not paused before enable/disable an addon. +func VerifyNotPaused(profile string, enable bool) error { + klog.Info("checking whether the cluster is paused") + + cc, err := config.Load(profile) + if err != nil { + return errors.Wrap(err, "loading profile") + } + + api, err := machine.NewAPIClient() + if err != nil { + return errors.Wrap(err, "machine client") + } + defer api.Close() + + cp, err := config.PrimaryControlPlane(cc) + if err != nil { + return errors.Wrap(err, "control plane") + } + + host, err := machine.LoadHost(api, config.MachineName(*cc, cp)) + if err != nil { + return errors.Wrap(err, "get host") + } + + s, err := host.Driver.GetState() + if err != nil { + return errors.Wrap(err, "get state") + } + if s != state.Running { + // can't check the status of pods on a non-running cluster + return nil + } + + runner, err := machine.CommandRunner(host) + if err != nil { + return errors.Wrap(err, "command runner") + } + + crName := cc.KubernetesConfig.ContainerRuntime + cr, err := cruntime.New(cruntime.Config{Type: crName, Runner: runner}) + if err != nil { + return errors.Wrap(err, "container runtime") + } + runtimePaused, err := cluster.CheckIfPaused(cr, []string{"kube-system"}) + if err != nil { + return errors.Wrap(err, "check paused") + } + if !runtimePaused { + return nil + } + action := "disable" + if enable { + action = "enable" + } + msg := fmt.Sprintf("Can't %s addon on a paused cluster, please unpause the cluster first.", action) + out.Styled(style.Shrug, msg) + return errors.New(msg) +} diff --git a/pkg/minikube/reason/reason.go b/pkg/minikube/reason/reason.go index e7f6b76fe3..aae3c5d34c 100644 --- a/pkg/minikube/reason/reason.go +++ b/pkg/minikube/reason/reason.go @@ -85,6 +85,11 @@ var ( InternalAddonDisable = Kind{ID: "MK_ADDON_DISABLE", ExitCode: ExProgramError} // minikube could not enable an addon, e.g. dashboard addon InternalAddonEnable = Kind{ID: "MK_ADDON_ENABLE", ExitCode: ExProgramError} + // minikube could not enable an addon on a paused cluster + InternalAddonEnablePaused = Kind{ID: "MK_ADDON_ENABLE_PAUSED", ExitCode: ExProgramConflict} + // minikube could not disable an addon on a paused cluster + InternalAddonDisablePaused = Kind{ID: "MK_ADDON_DISABLE_PAUSED", ExitCode: ExProgramConflict} + // minikube failed to update internal configuration, such as the cached images config map InternalAddConfig = Kind{ID: "MK_ADD_CONFIG", ExitCode: ExProgramError} // minikube failed to create a cluster bootstrapper