diff --git a/cmd/minikube/cmd/cache.go b/cmd/minikube/cmd/cache.go index 80c562d4e1fa..92908e99b0a5 100644 --- a/cmd/minikube/cmd/cache.go +++ b/cmd/minikube/cmd/cache.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/viper" "k8s.io/klog/v2" cmdConfig "k8s.io/minikube/cmd/minikube/cmd/config" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/image" @@ -49,8 +50,9 @@ var addCacheCmd = &cobra.Command{ Long: "Add an image to local cache.", Run: func(_ *cobra.Command, args []string) { out.WarningT("\"minikube cache\" will be deprecated in upcoming versions, please switch to \"minikube image load\"") + options := flags.Options() // Cache and load images into docker daemon - if err := machine.CacheAndLoadImages(args, cacheAddProfiles(), false); err != nil { + if err := machine.CacheAndLoadImages(args, cacheAddProfiles(), false, options); err != nil { exit.Error(reason.InternalCacheLoad, "Failed to cache and load images", err) } // Add images to config file @@ -103,7 +105,8 @@ var reloadCacheCmd = &cobra.Command{ Short: "reload cached images.", Long: "reloads images previously added using the 'cache add' subcommand", Run: func(_ *cobra.Command, _ []string) { - err := node.CacheAndLoadImagesInConfig(cacheAddProfiles()) + options := flags.Options() + err := node.CacheAndLoadImagesInConfig(cacheAddProfiles(), options) if err != nil { exit.Error(reason.GuestCacheLoad, "Failed to reload cached images", err) } diff --git a/cmd/minikube/cmd/config/addons_list.go b/cmd/minikube/cmd/config/addons_list.go index 91c082fe268d..af17e9903a61 100644 --- a/cmd/minikube/cmd/config/addons_list.go +++ b/cmd/minikube/cmd/config/addons_list.go @@ -28,6 +28,7 @@ import ( "github.com/olekukonko/tablewriter/tw" "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" @@ -55,9 +56,10 @@ var addonsListCmd = &cobra.Command{ exit.Message(reason.Usage, "usage: minikube addons list") } + options := flags.Options() var cc *config.ClusterConfig if config.ProfileExists(ClusterFlagValue()) { - _, cc = mustload.Partial(ClusterFlagValue()) + _, cc = mustload.Partial(ClusterFlagValue(), options) } switch strings.ToLower(addonListOutput) { case "list": diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 045aafca5587..79232acf64cc 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -27,6 +27,7 @@ import ( "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/addons" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/cluster" @@ -37,6 +38,7 @@ import ( "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/sysinit" ) @@ -59,6 +61,7 @@ var addonsConfigureCmd = &cobra.Command{ exit.Message(reason.Usage, "usage: minikube addons configure ADDON_NAME") } + options := flags.Options() profile := ClusterFlagValue() addon := args[0] addonConfig := loadAddonConfigFile(addon, addonConfigFile) @@ -69,16 +72,16 @@ var addonsConfigureCmd = &cobra.Command{ processRegistryCredsConfig(profile, addonConfig) case "metallb": - processMetalLBConfig(profile, addonConfig) + processMetalLBConfig(profile, addonConfig, options) case "ingress": - processIngressConfig(profile, addonConfig) + processIngressConfig(profile, addonConfig, options) case "registry-aliases": - processRegistryAliasesConfig(profile, addonConfig) + processRegistryAliasesConfig(profile, addonConfig, options) case "auto-pause": - processAutoPauseConfig(profile, addonConfig) + processAutoPauseConfig(profile, addonConfig, options) default: out.FailureT("{{.name}} has no available configuration options", out.V{"name": addon}) @@ -163,8 +166,8 @@ func loadAddonConfigFile(addon, configFilePath string) (ac *addonConfig) { } // Processes metallb addon config from configFile if it exists otherwise resorts to default behavior -func processMetalLBConfig(profile string, _ *addonConfig) { - _, cfg := mustload.Partial(profile) +func processMetalLBConfig(profile string, _ *addonConfig, options *run.Options) { + _, cfg := mustload.Partial(profile, options) validator := func(s string) bool { return net.ParseIP(s) != nil @@ -179,14 +182,14 @@ func processMetalLBConfig(profile string, _ *addonConfig) { } // Re-enable metallb addon in order to generate template manifest files with Load Balancer Start/End IP - if err := addons.EnableOrDisableAddon(cfg, "metallb", "true"); err != nil { + if err := addons.EnableOrDisableAddon(cfg, "metallb", "true", options); err != nil { out.ErrT(style.Fatal, "Failed to configure metallb IP {{.profile}}", out.V{"profile": profile}) } } // Processes ingress addon config from configFile if it exists otherwise resorts to default behavior -func processIngressConfig(profile string, _ *addonConfig) { - _, cfg := mustload.Partial(profile) +func processIngressConfig(profile string, _ *addonConfig, options *run.Options) { + _, cfg := mustload.Partial(profile, options) validator := func(s string) bool { format := regexp.MustCompile("^.+/.+$") @@ -209,8 +212,8 @@ func processIngressConfig(profile string, _ *addonConfig) { } // Processes auto-pause addon config from configFile if it exists otherwise resorts to default behavior -func processAutoPauseConfig(profile string, _ *addonConfig) { - lapi, cfg := mustload.Partial(profile) +func processAutoPauseConfig(profile string, _ *addonConfig, options *run.Options) { + lapi, cfg := mustload.Partial(profile, options) intervalInput := AskForStaticValue("-- Enter interval time of auto-pause-interval (ex. 1m0s): ") intervalTime, err := time.ParseDuration(intervalInput) if err != nil { @@ -235,11 +238,11 @@ func processAutoPauseConfig(profile string, _ *addonConfig) { out.ErrT(style.Fatal, "failed to load profile: {{.error}}", out.V{"error": err}) } if profileStatus(p, lapi).StatusCode/100 == 2 { // 2xx code - co := mustload.Running(profile) + co := mustload.Running(profile, options) // first unpause all nodes cluster immediately unpauseWholeCluster(co) // Re-enable auto-pause addon in order to update interval time - if err := addons.EnableOrDisableAddon(cfg, "auto-pause", "true"); err != nil { + if err := addons.EnableOrDisableAddon(cfg, "auto-pause", "true", options); err != nil { out.ErrT(style.Fatal, "Failed to configure auto-pause {{.profile}}", out.V{"profile": profile}) } // restart auto-pause service @@ -251,8 +254,8 @@ func processAutoPauseConfig(profile string, _ *addonConfig) { } // Processes registry-aliases addon config from configFile if it exists otherwise resorts to default behavior -func processRegistryAliasesConfig(profile string, _ *addonConfig) { - _, cfg := mustload.Partial(profile) +func processRegistryAliasesConfig(profile string, _ *addonConfig, options *run.Options) { + _, cfg := mustload.Partial(profile, options) validator := func(s string) bool { format := regexp.MustCompile(`^([a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)+(\ [a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)*$`) return format.MatchString(s) @@ -267,7 +270,7 @@ func processRegistryAliasesConfig(profile string, _ *addonConfig) { addon := assets.Addons["registry-aliases"] if addon.IsEnabled(cfg) { // Re-enable registry-aliases addon in order to generate template manifest files with custom hosts - if err := addons.EnableOrDisableAddon(cfg, "registry-aliases", "true"); err != nil { + if err := addons.EnableOrDisableAddon(cfg, "registry-aliases", "true", options); err != nil { out.ErrT(style.Fatal, "Failed to configure registry-aliases {{.profile}}", out.V{"profile": profile}) } } diff --git a/cmd/minikube/cmd/config/disable.go b/cmd/minikube/cmd/config/disable.go index 30459cd029a1..b49d325a3471 100644 --- a/cmd/minikube/cmd/config/disable.go +++ b/cmd/minikube/cmd/config/disable.go @@ -18,6 +18,7 @@ package config import ( "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/addons" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/exit" @@ -35,8 +36,10 @@ var addonsDisableCmd = &cobra.Command{ if len(args) != 1 { exit.Message(reason.Usage, "usage: minikube addons disable ADDON_NAME") } - _, cc := mustload.Partial(ClusterFlagValue()) - err := addons.VerifyNotPaused(ClusterFlagValue(), false) + + options := flags.Options() + _, cc := mustload.Partial(ClusterFlagValue(), options) + err := addons.VerifyNotPaused(ClusterFlagValue(), false, options) if err != nil { exit.Error(reason.InternalAddonDisablePaused, "disable failed", err) } @@ -49,7 +52,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", options) 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 74f382c8ea3b..853015bff5b7 100644 --- a/cmd/minikube/cmd/config/enable.go +++ b/cmd/minikube/cmd/config/enable.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/addons" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/config" @@ -41,12 +42,14 @@ var addonsEnableCmd = &cobra.Command{ if len(args) != 1 { exit.Message(reason.Usage, "usage: minikube addons enable ADDON_NAME") } - _, cc := mustload.Partial(ClusterFlagValue()) + + options := flags.Options() + _, cc := mustload.Partial(ClusterFlagValue(), options) if cc.KubernetesConfig.KubernetesVersion == constants.NoKubernetesVersion { 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) + err := addons.VerifyNotPaused(ClusterFlagValue(), true, options) if err != nil { exit.Error(reason.InternalAddonEnablePaused, "enabled failed", err) } @@ -83,7 +86,7 @@ You can view the list of minikube maintainers at: https://github.com/kubernetes/ if registries != "" { viper.Set(config.AddonRegistries, registries) } - err = addons.SetAndSave(ClusterFlagValue(), addon, "true") + err = addons.SetAndSave(ClusterFlagValue(), addon, "true", options) if err != nil && !errors.Is(err, addons.ErrSkipThisAddon) { exit.Error(reason.InternalAddonEnable, "enable failed", err) } diff --git a/cmd/minikube/cmd/config/open.go b/cmd/minikube/cmd/config/open.go index 9dae98558bc1..87c9b2327238 100644 --- a/cmd/minikube/cmd/config/open.go +++ b/cmd/minikube/cmd/config/open.go @@ -21,6 +21,7 @@ import ( "text/template" "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/browser" "k8s.io/minikube/pkg/minikube/exit" @@ -57,10 +58,12 @@ var addonsOpenCmd = &cobra.Command{ if len(args) != 1 { exit.Message(reason.Usage, "usage: minikube addons open ADDON_NAME") } + + options := flags.Options() addonName := args[0] cname := ClusterFlagValue() - co := mustload.Healthy(cname) + co := mustload.Healthy(cname, options) addon, ok := assets.Addons[addonName] // validate addon input if !ok { diff --git a/cmd/minikube/cmd/config/profile_list.go b/cmd/minikube/cmd/config/profile_list.go index 26efa837cea3..58279ef8df8d 100644 --- a/cmd/minikube/cmd/config/profile_list.go +++ b/cmd/minikube/cmd/config/profile_list.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" @@ -31,6 +32,7 @@ import ( "k8s.io/minikube/pkg/minikube/notify" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "github.com/docker/machine/libmachine" @@ -52,15 +54,16 @@ var profileListCmd = &cobra.Command{ Short: "Lists all minikube profiles.", Long: "Lists all valid minikube profiles and detects all possible invalid profiles.", Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() output := strings.ToLower(profileOutput) out.SetJSON(output == "json") - go notify.MaybePrintUpdateTextFromGithub() + go notify.MaybePrintUpdateTextFromGithub(options) switch output { case "json": - printProfilesJSON() + printProfilesJSON(options) case "table": - printProfilesTable() + printProfilesTable(options) default: exit.Message(reason.Usage, fmt.Sprintf("invalid output format: %s. Valid values: 'table', 'json'", profileOutput)) } @@ -77,7 +80,7 @@ func listProfiles() (validProfiles, invalidProfiles []*config.Profile, err error return validProfiles, invalidProfiles, err } -func printProfilesTable() { +func printProfilesTable(options *run.Options) { validProfiles, invalidProfiles, err := listProfiles() if err != nil { @@ -88,12 +91,12 @@ func printProfilesTable() { exit.Message(reason.UsageNoProfileRunning, "No minikube profile was found.") } - updateProfilesStatus(validProfiles) + updateProfilesStatus(validProfiles, options) renderProfilesTable(profilesToTableData(validProfiles)) warnInvalidProfiles(invalidProfiles) } -func updateProfilesStatus(profiles []*config.Profile) { +func updateProfilesStatus(profiles []*config.Profile, options *run.Options) { if isLight { for _, p := range profiles { p.Status = "Skipped" @@ -101,7 +104,7 @@ func updateProfilesStatus(profiles []*config.Profile) { return } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { klog.Errorf("failed to get machine api client %v", err) } @@ -205,9 +208,9 @@ func warnInvalidProfiles(invalidProfiles []*config.Profile) { } } -func printProfilesJSON() { +func printProfilesJSON(options *run.Options) { validProfiles, invalidProfiles, err := listProfiles() - updateProfilesStatus(validProfiles) + updateProfilesStatus(validProfiles, options) var body = map[string]interface{}{} if err == nil || config.IsNotExist(err) { diff --git a/cmd/minikube/cmd/config/set.go b/cmd/minikube/cmd/config/set.go index ee0cc1611472..41ae18c9e79a 100644 --- a/cmd/minikube/cmd/config/set.go +++ b/cmd/minikube/cmd/config/set.go @@ -56,7 +56,7 @@ func Set(name string, value string) error { return errors.Wrapf(err, "find settings for %q value of %q", name, value) } // Validate the new value - err = run(name, value, s.validations) + err = invoke(name, value, s.validations) if err != nil { return errors.Wrapf(err, "run validations for %q with value of %q", name, value) } @@ -72,7 +72,7 @@ func Set(name string, value string) error { } // Run any callbacks for this property - err = run(name, value, s.callbacks) + err = invoke(name, value, s.callbacks) if err != nil { return errors.Wrapf(err, "run callbacks for %q with value of %q", name, value) } diff --git a/cmd/minikube/cmd/config/util.go b/cmd/minikube/cmd/config/util.go index 0546590d5d94..14a4a67f4450 100644 --- a/cmd/minikube/cmd/config/util.go +++ b/cmd/minikube/cmd/config/util.go @@ -25,8 +25,8 @@ import ( "k8s.io/minikube/pkg/minikube/out" ) -// Runs all the validation or callback functions and collects errors -func run(name string, value string, fns []setFn) error { +// Invoke all the validation or callback functions and collects errors +func invoke(name string, value string, fns []setFn) error { var errors []error for _, fn := range fns { err := fn(name, value) diff --git a/cmd/minikube/cmd/cp.go b/cmd/minikube/cmd/cp.go index 6e3366806a97..87044f1ce3af 100644 --- a/cmd/minikube/cmd/cp.go +++ b/cmd/minikube/cmd/cp.go @@ -27,6 +27,7 @@ import ( pt "path" "strings" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/command" "k8s.io/minikube/pkg/minikube/exit" @@ -54,17 +55,18 @@ Example Command : "minikube cp a.txt /home/docker/b.txt" + "minikube cp minikube-m01:a.txt minikube-m02:/home/docker/b.txt"`, Run: func(_ *cobra.Command, args []string) { if len(args) != 2 { - exit.Message(reason.Usage, `Please specify the path to copy: + exit.Message(reason.Usage, `Please specify the path to copy: minikube cp (example: "minikube cp a/b.txt /copied.txt")`) } + options := flags.Options() srcPath := args[0] dstPath := setDstFileNameFromSrc(args[1], srcPath) src := newRemotePath(srcPath) dst := newRemotePath(dstPath) validateArgs(src, dst) - co := mustload.Running(ClusterFlagValue()) + co := mustload.Running(ClusterFlagValue(), options) var runner command.Runner if dst.node != "" { diff --git a/cmd/minikube/cmd/dashboard.go b/cmd/minikube/cmd/dashboard.go index 671cbfe02dbb..63f02cde0b28 100644 --- a/cmd/minikube/cmd/dashboard.go +++ b/cmd/minikube/cmd/dashboard.go @@ -30,6 +30,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/addons" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/style" @@ -58,8 +59,9 @@ var dashboardCmd = &cobra.Command{ Short: "Access the Kubernetes dashboard running within the minikube cluster", Long: `Access the Kubernetes dashboard running within the minikube cluster`, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() cname := ClusterFlagValue() - co := mustload.Healthy(cname) + co := mustload.Healthy(cname, options) for _, n := range co.Config.Nodes { if err := proxy.ExcludeIP(n.IP); err != nil { @@ -82,7 +84,7 @@ var dashboardCmd = &cobra.Command{ // Send status messages to stderr for folks reusing this output. out.ErrT(style.Enabling, "Enabling dashboard ...") // Enable the dashboard add-on - err = addons.SetAndSave(cname, "dashboard", "true") + err = addons.SetAndSave(cname, "dashboard", "true", options) if err != nil { exit.Error(reason.InternalAddonEnable, "Unable to enable dashboard", err) } diff --git a/cmd/minikube/cmd/delete.go b/cmd/minikube/cmd/delete.go index 67be68c5868f..0da905487fc7 100644 --- a/cmd/minikube/cmd/delete.go +++ b/cmd/minikube/cmd/delete.go @@ -35,6 +35,7 @@ import ( "github.com/spf13/viper" "k8s.io/klog/v2" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/kic" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/minikube/cluster" @@ -51,6 +52,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/out/register" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/sshagent" "k8s.io/minikube/pkg/minikube/style" ) @@ -211,6 +213,8 @@ func runDelete(_ *cobra.Command, args []string) { if len(args) > 0 { exit.Message(reason.Usage, "Usage: minikube delete") } + + options := flags.Options() out.SetJSON(outputFormat == "json") register.Reg.SetStep(register.Deleting) download.CleanUpOlderPreloads() @@ -236,7 +240,7 @@ func runDelete(_ *cobra.Command, args []string) { deleteContainersAndVolumes(delCtx, oci.Docker) deleteContainersAndVolumes(delCtx, oci.Podman) - errs := DeleteProfiles(profilesToDelete) + errs := DeleteProfiles(profilesToDelete, options) register.Reg.SetStep(register.Done) if len(errs) > 0 { @@ -258,7 +262,7 @@ func runDelete(_ *cobra.Command, args []string) { orphan = true } - errs := DeleteProfiles([]*config.Profile{profile}) + errs := DeleteProfiles([]*config.Profile{profile}, options) register.Reg.SetStep(register.Done) if len(errs) > 0 { @@ -297,22 +301,22 @@ func purgeMinikubeDirectory() { } // DeleteProfiles deletes one or more profiles -func DeleteProfiles(profiles []*config.Profile) []error { +func DeleteProfiles(profiles []*config.Profile, options *run.Options) []error { klog.Infof("DeleteProfiles") var errs []error for _, profile := range profiles { - errs = append(errs, deleteProfileTimeout(profile)...) + errs = append(errs, deleteProfileTimeout(profile, options)...) } return errs } -func deleteProfileTimeout(profile *config.Profile) []error { +func deleteProfileTimeout(profile *config.Profile, options *run.Options) []error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() - if err := deleteProfile(ctx, profile); err != nil { + if err := deleteProfile(ctx, profile, options); err != nil { - mm, loadErr := machine.LoadMachine(profile.Name) + mm, loadErr := machine.LoadMachine(profile.Name, options) if !profile.IsValid() || (loadErr != nil || !mm.IsValid()) { invalidProfileDeletionErrs := deleteInvalidProfile(profile) if len(invalidProfileDeletionErrs) > 0 { @@ -325,7 +329,7 @@ func deleteProfileTimeout(profile *config.Profile) []error { return nil } -func deleteProfile(ctx context.Context, profile *config.Profile) error { +func deleteProfile(ctx context.Context, profile *config.Profile, options *run.Options) error { klog.Infof("Deleting %s", profile.Name) register.Reg.SetStep(register.Deleting) @@ -335,7 +339,7 @@ func deleteProfile(ctx context.Context, profile *config.Profile) error { // if driver is oci driver, delete containers and volumes if driver.IsKIC(profile.Config.Driver) { - if err := unpauseIfNeeded(profile); err != nil { + if err := unpauseIfNeeded(profile, options); err != nil { klog.Warningf("failed to unpause %s : %v", profile.Name, err) } out.Styled(style.DeletingHost, `Deleting "{{.profile_name}}" in {{.driver_name}} ...`, out.V{"profile_name": profile.Name, "driver_name": profile.Config.Driver}) @@ -348,7 +352,7 @@ func deleteProfile(ctx context.Context, profile *config.Profile) error { klog.Infof("%s has no configuration, will try to make it work anyways", profile.Name) } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { delErr := profileDeletionErr(profile.Name, fmt.Sprintf("error getting client %v", err)) return DeletionError{Err: delErr, Errtype: Fatal} @@ -381,7 +385,7 @@ func deleteProfile(ctx context.Context, profile *config.Profile) error { return nil } -func unpauseIfNeeded(profile *config.Profile) error { +func unpauseIfNeeded(profile *config.Profile, options *run.Options) error { // there is a known issue with removing kicbase container with paused containerd/crio containers inside // unpause it before we delete it crName := profile.Config.KubernetesConfig.ContainerRuntime @@ -389,7 +393,7 @@ func unpauseIfNeeded(profile *config.Profile) error { return nil } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return err } diff --git a/cmd/minikube/cmd/delete_test.go b/cmd/minikube/cmd/delete_test.go index 945f844a7239..774adf60b1e0 100644 --- a/cmd/minikube/cmd/delete_test.go +++ b/cmd/minikube/cmd/delete_test.go @@ -33,6 +33,7 @@ import ( cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/localpath" + "k8s.io/minikube/pkg/minikube/run" ) // exclude returns a list of strings, minus the excluded ones @@ -87,6 +88,7 @@ func TestDeleteProfile(t *testing.T) { {"partial-mach", "p8_partial_machine_config", []string{"p8_partial_machine_config"}}, } + options := &run.Options{} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Setenv(localpath.MinikubeHome, td) @@ -106,7 +108,7 @@ func TestDeleteProfile(t *testing.T) { } hostAndDirsDeleter = hostAndDirsDeleterMock - errs := DeleteProfiles([]*config.Profile{profile}) + errs := DeleteProfiles([]*config.Profile{profile}, options) if len(errs) > 0 { HandleDeletionErrors(errs) t.Errorf("Errors while deleting profiles: %v", errs) @@ -197,7 +199,7 @@ func TestDeleteAllProfiles(t *testing.T) { profiles := validProfiles profiles = append(profiles, inValidProfiles...) hostAndDirsDeleter = hostAndDirsDeleterMock - errs := DeleteProfiles(profiles) + errs := DeleteProfiles(profiles, &run.Options{}) if errs != nil { t.Errorf("errors while deleting all profiles: %v", errs) diff --git a/cmd/minikube/cmd/docker-env.go b/cmd/minikube/cmd/docker-env.go index 6b65b21bcd42..f3675e7cb276 100644 --- a/cmd/minikube/cmd/docker-env.go +++ b/cmd/minikube/cmd/docker-env.go @@ -35,6 +35,7 @@ import ( "gopkg.in/yaml.v2" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/drivers/qemu" "k8s.io/minikube/pkg/minikube/bootstrapper/bsutil/kverify" @@ -271,6 +272,7 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc Run: func(_ *cobra.Command, _ []string) { var err error + options := flags.Options() shl := shell.ForceShell if shl == "" { shl, err = shell.Detect() @@ -296,7 +298,7 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc cname := ClusterFlagValue() - co := mustload.Running(cname) + co := mustload.Running(cname, options) driverName := co.CP.Host.DriverName @@ -316,7 +318,7 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc if cr == constants.Containerd { out.WarningT("Using the docker-env command with the containerd runtime is a highly experimental feature, please provide feedback or contribute to make it better") - startNerdctld() + startNerdctld(options) // docker-env on containerd depends on nerdctld (https://github.com/afbjorklund/nerdctld) as "docker" daeomn // and nerdctld daemon must be used with ssh connection (it is set in kicbase image's Dockerfile) @@ -330,7 +332,7 @@ docker-cli install instructions: https://minikube.sigs.k8s.io/docs/tutorials/doc } // cluster config must be reloaded // otherwise we won't be able to get SSH_AUTH_SOCK and SSH_AGENT_PID from cluster config. - co = mustload.Running(cname) + co = mustload.Running(cname, options) // set the ssh-agent envs for current process os.Setenv("SSH_AUTH_SOCK", co.Config.SSHAuthSock) diff --git a/cmd/minikube/cmd/flags/flags.go b/cmd/minikube/cmd/flags/flags.go new file mode 100644 index 000000000000..f8e35a0b4564 --- /dev/null +++ b/cmd/minikube/cmd/flags/flags.go @@ -0,0 +1,37 @@ +/* +Copyright 2025 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "github.com/spf13/viper" + "k8s.io/minikube/pkg/minikube/run" +) + +// Flag names passed to minikube via run.Options. +const ( + Interactive = "interactive" + DownloadOnly = "download-only" +) + +// Options returns minikube runtime options from command line flags. Flags that +// must be handled outside of the cmd package must be added to run.Options. +func Options() *run.Options { + return &run.Options{ + NonInteractive: !viper.GetBool(Interactive), + DownloadOnly: viper.GetBool(DownloadOnly), + } +} diff --git a/cmd/minikube/cmd/image.go b/cmd/minikube/cmd/image.go index bf70291eeb5c..3941b2767894 100644 --- a/cmd/minikube/cmd/image.go +++ b/cmd/minikube/cmd/image.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/image" @@ -84,6 +85,8 @@ var loadImageCmd = &cobra.Command{ if len(args) == 0 { exit.Message(reason.Usage, "Please provide an image in your local daemon to load into minikube via ") } + + options := flags.Options() // Cache and load images into container runtime profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { @@ -93,7 +96,7 @@ var loadImageCmd = &cobra.Command{ if pull { // Pull image from remote registry, without doing any caching except in container runtime. // This is similar to daemon.Image but it is done by the container runtime in the cluster. - if err := machine.PullImages(args, profile); err != nil { + if err := machine.PullImages(args, profile, options); err != nil { exit.Error(reason.GuestImageLoad, "Failed to pull image", err) } return @@ -136,13 +139,13 @@ var loadImageCmd = &cobra.Command{ if imgDaemon || imgRemote { image.UseDaemon(imgDaemon) image.UseRemote(imgRemote) - if err := machine.CacheAndLoadImages(args, []*config.Profile{profile}, overwrite); err != nil { + if err := machine.CacheAndLoadImages(args, []*config.Profile{profile}, overwrite, options); err != nil { exit.Error(reason.GuestImageLoad, "Failed to load image", err) } } else if local { // Load images from local files, without doing any caching or checks in container runtime // This is similar to tarball.Image but it is done by the container runtime in the cluster. - if err := machine.DoLoadImages(args, []*config.Profile{profile}, "", overwrite); err != nil { + if err := machine.DoLoadImages(args, []*config.Profile{profile}, "", overwrite, options); err != nil { exit.Error(reason.GuestImageLoad, "Failed to load image", err) } } @@ -175,6 +178,8 @@ var saveImageCmd = &cobra.Command{ if len(args) == 0 { exit.Message(reason.Usage, "Please provide an image in the container runtime to save from minikube via ") } + + options := flags.Options() // Save images from container runtime profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { @@ -193,7 +198,7 @@ var saveImageCmd = &cobra.Command{ output = tmp.Name() } - if err := machine.DoSaveImages([]string{args[0]}, output, []*config.Profile{profile}, ""); err != nil { + if err := machine.DoSaveImages([]string{args[0]}, output, []*config.Profile{profile}, "", options); err != nil { exit.Error(reason.GuestImageSave, "Failed to save image", err) } @@ -205,7 +210,7 @@ var saveImageCmd = &cobra.Command{ os.Remove(output) } } else { - if err := machine.SaveAndCacheImages([]string{args[0]}, []*config.Profile{profile}); err != nil { + if err := machine.SaveAndCacheImages([]string{args[0]}, []*config.Profile{profile}, options); err != nil { exit.Error(reason.GuestImageSave, "Failed to save image", err) } if imgDaemon || imgRemote { @@ -231,11 +236,12 @@ $ minikube image unload image busybox Args: cobra.MinimumNArgs(1), Aliases: []string{"remove", "unload"}, Run: func(_ *cobra.Command, args []string) { + options := flags.Options() profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { exit.Error(reason.Usage, "loading profile", err) } - if err := machine.RemoveImages(args, profile); err != nil { + if err := machine.RemoveImages(args, profile, options); err != nil { exit.Error(reason.GuestImageRemove, "Failed to remove image", err) } }, @@ -248,12 +254,13 @@ var pullImageCmd = &cobra.Command{ $ minikube image pull busybox `, Run: func(_ *cobra.Command, args []string) { + options := flags.Options() profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { exit.Error(reason.Usage, "loading profile", err) } - if err := machine.PullImages(args, profile); err != nil { + if err := machine.PullImages(args, profile, options); err != nil { exit.Error(reason.GuestImagePull, "Failed to pull images", err) } }, @@ -277,6 +284,8 @@ var buildImageCmd = &cobra.Command{ if len(args) < 1 { exit.Message(reason.Usage, "Please provide a path or url to build") } + + options := flags.Options() // Build images into container runtime profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { @@ -317,7 +326,7 @@ var buildImageCmd = &cobra.Command{ out.Stringf("minikube detects that you are using DOS-style path %s. minikube will convert it to UNIX-style by replacing all \\ to /\n", dockerFile) dockerFile = strings.ReplaceAll(dockerFile, "\\", "/") } - if err := machine.BuildImage(img, dockerFile, tag, push, buildEnv, buildOpt, []*config.Profile{profile}, allNodes, nodeName); err != nil { + if err := machine.BuildImage(img, dockerFile, tag, push, buildEnv, buildOpt, []*config.Profile{profile}, allNodes, nodeName, options); err != nil { exit.Error(reason.GuestImageBuild, "Failed to build image", err) } if tmp != "" { @@ -334,12 +343,13 @@ $ minikube image ls `, Aliases: []string{"list"}, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { exit.Error(reason.Usage, "loading profile", err) } - if err := machine.ListImages(profile, format); err != nil { + if err := machine.ListImages(profile, format, options); err != nil { exit.Error(reason.GuestImageList, "Failed to list images", err) } }, @@ -356,12 +366,14 @@ $ minikube image tag source target if len(args) != 2 { exit.Message(reason.Usage, "Please provide source and target image") } + + options := flags.Options() profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { exit.Error(reason.Usage, "loading profile", err) } - if err := machine.TagImage(profile, args[0], args[1]); err != nil { + if err := machine.TagImage(profile, args[0], args[1], options); err != nil { exit.Error(reason.GuestImageTag, "Failed to tag images", err) } }, @@ -374,12 +386,13 @@ var pushImageCmd = &cobra.Command{ $ minikube image push busybox `, Run: func(_ *cobra.Command, args []string) { + options := flags.Options() profile, err := config.LoadProfile(viper.GetString(config.ProfileName)) if err != nil { exit.Error(reason.Usage, "loading profile", err) } - if err := machine.PushImages(args, profile); err != nil { + if err := machine.PushImages(args, profile, options); err != nil { exit.Error(reason.GuestImagePush, "Failed to push images", err) } }, diff --git a/cmd/minikube/cmd/ip.go b/cmd/minikube/cmd/ip.go index 1ac6dde42beb..f5edef7535e7 100644 --- a/cmd/minikube/cmd/ip.go +++ b/cmd/minikube/cmd/ip.go @@ -18,6 +18,7 @@ package cmd import ( "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/node" @@ -31,7 +32,8 @@ var ipCmd = &cobra.Command{ Short: "Retrieves the IP address of the specified node", Long: `Retrieves the IP address of the specified node, and writes it to STDOUT.`, Run: func(_ *cobra.Command, _ []string) { - co := mustload.Running(ClusterFlagValue()) + options := flags.Options() + co := mustload.Running(ClusterFlagValue(), options) n, _, err := node.Retrieve(*co.Config, nodeName) if err != nil { exit.Error(reason.GuestNodeRetrieve, "retrieving node", err) diff --git a/cmd/minikube/cmd/kubectl.go b/cmd/minikube/cmd/kubectl.go index 01b10404bc48..5f1e1491ab21 100644 --- a/cmd/minikube/cmd/kubectl.go +++ b/cmd/minikube/cmd/kubectl.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/detect" @@ -54,6 +55,7 @@ This can be useful if you cannot run kubectl locally for some reason, like unsup host. Please be aware that when using --ssh all paths will apply to the remote machine.`, Example: "minikube kubectl -- --help\nminikube kubectl -- get pods --namespace kube-system", Run: func(_ *cobra.Command, args []string) { + options := flags.Options() cc, err := config.Load(ClusterFlagValue()) version := constants.DefaultKubernetesVersion @@ -66,7 +68,7 @@ host. Please be aware that when using --ssh all paths will apply to the remote m cname := ClusterFlagValue() if useSSH { - co := mustload.Running(cname) + co := mustload.Running(cname, options) n := co.CP.Node kc := []string{"sudo"} diff --git a/cmd/minikube/cmd/logs.go b/cmd/minikube/cmd/logs.go index 86a70e3c6346..524bb17709a3 100644 --- a/cmd/minikube/cmd/logs.go +++ b/cmd/minikube/cmd/logs.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/viper" "k8s.io/klog/v2" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/cruntime" @@ -33,6 +34,7 @@ import ( "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" ) @@ -63,6 +65,7 @@ var logsCmd = &cobra.Command{ Short: "Returns logs to debug a local Kubernetes cluster", Long: `Gets the logs of the running instance, used for debugging minikube, not user code.`, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() logOutput := os.Stdout var err error @@ -94,11 +97,11 @@ var logsCmd = &cobra.Command{ } logs.OutputOffline(numberOfLines, logOutput) - if shouldSilentFail() { + if shouldSilentFail(options) { return } - co := mustload.Running(ClusterFlagValue()) + co := mustload.Running(ClusterFlagValue(), options) bs, err := cluster.Bootstrapper(co.API, viper.GetString(cmdcfg.Bootstrapper), *co.Config, co.CP.Runner) if err != nil { @@ -131,12 +134,12 @@ var logsCmd = &cobra.Command{ // shouldSilentFail returns true if the user specifies the --file flag and the host isn't running // This is to prevent outputting the message 'The control plane node must be running for this command' which confuses // many users while gathering logs to report their issue as the message makes them think the log file wasn't generated -func shouldSilentFail() bool { +func shouldSilentFail(options *run.Options) bool { if fileOutput == "" { return false } - api, cc := mustload.Partial(ClusterFlagValue()) + api, cc := mustload.Partial(ClusterFlagValue(), options) cp, err := config.ControlPlane(*cc) if err != nil { diff --git a/cmd/minikube/cmd/mount.go b/cmd/minikube/cmd/mount.go index f8b1ab80ade1..1350ffe595a0 100644 --- a/cmd/minikube/cmd/mount.go +++ b/cmd/minikube/cmd/mount.go @@ -31,6 +31,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/detect" @@ -72,15 +73,15 @@ func defaultMountOptions() []string { // placeholders for flag values var ( - mountIP string - mountPort uint16 - mountVersion string - mountType string - isKill bool - uid string - gid string - mSize int - options []string + mountIP string + mountPort uint16 + mountVersion string + mountType string + isKill bool + uid string + gid string + mSize int + mountOptionsValue []string ) // supportedFilesystems is a map of filesystem types to not warn against. @@ -100,9 +101,11 @@ var mountCmd = &cobra.Command{ } if len(args) != 1 { - exit.Message(reason.Usage, `Please specify the directory to be mounted: + exit.Message(reason.Usage, `Please specify the directory to be mounted: minikube mount : (example: "/host-home:/vm-home")`) } + + options := flags.Options() mountString := args[0] idx := strings.LastIndex(mountString, ":") if idx == -1 { // no ":" was present @@ -125,7 +128,7 @@ var mountCmd = &cobra.Command{ debugVal = 1 // ufs.StartServer takes int debug param } - co := mustload.Running(ClusterFlagValue()) + co := mustload.Running(ClusterFlagValue(), options) if co.CP.Host.Driver.DriverName() == driver.None { exit.Message(reason.Usage, `'none' driver does not support 'minikube mount' command`) } @@ -177,7 +180,7 @@ var mountCmd = &cobra.Command{ Options: map[string]string{}, } - for _, o := range options { + for _, o := range mountOptionsValue { if !strings.Contains(o, "=") { cfg.Options[o] = "" continue @@ -265,7 +268,7 @@ func init() { mountCmd.Flags().BoolVar(&isKill, "kill", false, "Kill the mount process spawned by minikube start") mountCmd.Flags().StringVar(&uid, constants.MountUIDFlag, defaultMountUID, mountUIDDescription) mountCmd.Flags().StringVar(&gid, constants.MountGIDFlag, defaultMountGID, mountGIDDescription) - mountCmd.Flags().StringSliceVar(&options, constants.MountOptionsFlag, defaultMountOptions(), mountOptionsDescription) + mountCmd.Flags().StringSliceVar(&mountOptionsValue, constants.MountOptionsFlag, defaultMountOptions(), mountOptionsDescription) mountCmd.Flags().IntVar(&mSize, constants.MountMSizeFlag, defaultMountMSize, mountMSizeDescription) } diff --git a/cmd/minikube/cmd/node_add.go b/cmd/minikube/cmd/node_add.go index d6952ccbc3f2..d19335041cdc 100644 --- a/cmd/minikube/cmd/node_add.go +++ b/cmd/minikube/cmd/node_add.go @@ -20,6 +20,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cni" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/driver" @@ -43,7 +44,9 @@ var nodeAddCmd = &cobra.Command{ Short: "Adds a node to the given cluster.", Long: "Adds a node to the given cluster config, and starts it.", Run: func(cmd *cobra.Command, _ []string) { - co := mustload.Healthy(ClusterFlagValue()) + options := flags.Options() + + co := mustload.Healthy(ClusterFlagValue(), options) cc := co.Config if driver.BareMetal(cc.Driver) { @@ -90,8 +93,8 @@ var nodeAddCmd = &cobra.Command{ } register.Reg.SetStep(register.InitialSetup) - if err := node.Add(cc, n, deleteNodeOnFailure); err != nil { - _, err := maybeDeleteAndRetry(cmd, *cc, n, nil, err) + if err := node.Add(cc, n, deleteNodeOnFailure, options); err != nil { + _, err := maybeDeleteAndRetry(cmd, *cc, n, nil, err, options) if err != nil { exit.Error(reason.GuestNodeAdd, "failed to add node", err) } diff --git a/cmd/minikube/cmd/node_delete.go b/cmd/minikube/cmd/node_delete.go index 4a789da82c47..c411b244ad58 100644 --- a/cmd/minikube/cmd/node_delete.go +++ b/cmd/minikube/cmd/node_delete.go @@ -21,6 +21,7 @@ import ( "time" "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/delete" "k8s.io/minikube/pkg/minikube/driver" @@ -40,12 +41,14 @@ var nodeDeleteCmd = &cobra.Command{ if len(args) == 0 { exit.Message(reason.Usage, "Usage: minikube node delete [name]") } + + options := flags.Options() name := args[0] - co := mustload.Healthy(ClusterFlagValue()) + co := mustload.Healthy(ClusterFlagValue(), options) out.Step(style.DeletingHost, "Deleting node {{.name}} from cluster {{.cluster}}", out.V{"name": name, "cluster": co.Config.Name}) - n, err := node.Delete(*co.Config, name) + n, err := node.Delete(*co.Config, name, options) if err != nil { exit.Error(reason.GuestNodeDelete, "deleting node", err) } diff --git a/cmd/minikube/cmd/node_list.go b/cmd/minikube/cmd/node_list.go index 40f4687164e4..dd57412b60c7 100644 --- a/cmd/minikube/cmd/node_list.go +++ b/cmd/minikube/cmd/node_list.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/mustload" @@ -37,8 +38,9 @@ var nodeListCmd = &cobra.Command{ exit.Message(reason.Usage, "Usage: minikube node list") } + options := flags.Options() cname := ClusterFlagValue() - _, cc := mustload.Partial(cname) + _, cc := mustload.Partial(cname, options) if len(cc.Nodes) < 1 { klog.Warningf("Did not found any minikube node.") diff --git a/cmd/minikube/cmd/node_start.go b/cmd/minikube/cmd/node_start.go index 4e411edd5599..8a47f8ab571c 100644 --- a/cmd/minikube/cmd/node_start.go +++ b/cmd/minikube/cmd/node_start.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" @@ -41,7 +42,9 @@ var nodeStartCmd = &cobra.Command{ exit.Message(reason.Usage, "Usage: minikube node start [name]") } - api, cc := mustload.Partial(ClusterFlagValue()) + options := flags.Options() + + api, cc := mustload.Partial(ClusterFlagValue(), options) name := args[0] n, _, err := node.Retrieve(*cc, name) @@ -56,7 +59,7 @@ var nodeStartCmd = &cobra.Command{ } register.Reg.SetStep(register.InitialSetup) - r, p, m, h, err := node.Provision(cc, n, viper.GetBool(deleteOnFailure)) + r, p, m, h, err := node.Provision(cc, n, viper.GetBool(deleteOnFailure), options) if err != nil { exit.Error(reason.GuestNodeProvision, "provisioning host for node", err) } @@ -71,8 +74,8 @@ var nodeStartCmd = &cobra.Command{ ExistingAddons: cc.Addons, } - if _, err = node.Start(s); err != nil { - if _, err := maybeDeleteAndRetry(cmd, *cc, *n, nil, err); err != nil { + if _, err = node.Start(s, options); err != nil { + if _, err := maybeDeleteAndRetry(cmd, *cc, *n, nil, err, options); err != nil { node.ExitIfFatal(err, false) exit.Error(reason.GuestNodeStart, "failed to start node", err) } diff --git a/cmd/minikube/cmd/node_stop.go b/cmd/minikube/cmd/node_stop.go index a45fd35032e1..3932993054b7 100644 --- a/cmd/minikube/cmd/node_stop.go +++ b/cmd/minikube/cmd/node_stop.go @@ -20,6 +20,7 @@ import ( "os" "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/machine" @@ -39,8 +40,9 @@ var nodeStopCmd = &cobra.Command{ exit.Message(reason.Usage, "Usage: minikube node stop [name]") } + options := flags.Options() name := args[0] - api, cc := mustload.Partial(ClusterFlagValue()) + api, cc := mustload.Partial(ClusterFlagValue(), options) n, _, err := node.Retrieve(*cc, name) if err != nil { diff --git a/cmd/minikube/cmd/pause.go b/cmd/minikube/cmd/pause.go index ef5a7c941699..6bb63e56aa65 100644 --- a/cmd/minikube/cmd/pause.go +++ b/cmd/minikube/cmd/pause.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/viper" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" @@ -50,8 +51,9 @@ var pauseCmd = &cobra.Command{ } func runPause(_ *cobra.Command, _ []string) { + options := flags.Options() out.SetJSON(outputFormat == "json") - co := mustload.Running(ClusterFlagValue()) + co := mustload.Running(ClusterFlagValue(), options) register.SetEventLogPath(localpath.EventLog(ClusterFlagValue())) register.Reg.SetStep(register.Pausing) diff --git a/cmd/minikube/cmd/podman-env.go b/cmd/minikube/cmd/podman-env.go index e282000542c7..002a736d9350 100644 --- a/cmd/minikube/cmd/podman-env.go +++ b/cmd/minikube/cmd/podman-env.go @@ -26,6 +26,7 @@ import ( "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/ssh" "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/minikube/command" "k8s.io/minikube/pkg/minikube/constants" @@ -139,6 +140,7 @@ var podmanEnvCmd = &cobra.Command{ Short: "Configure environment to use minikube's Podman service", Long: `Sets up podman env variables; similar to '$(podman-machine env)'.`, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() sh := shell.EnvConfig{ Shell: shell.ForceShell, } @@ -156,7 +158,7 @@ var podmanEnvCmd = &cobra.Command{ } cname := ClusterFlagValue() - co := mustload.Running(cname) + co := mustload.Running(cname, options) driverName := co.CP.Host.DriverName if driverName == driver.None { diff --git a/cmd/minikube/cmd/service.go b/cmd/minikube/cmd/service.go index 32fe90c0ef60..c654aaa113c8 100644 --- a/cmd/minikube/cmd/service.go +++ b/cmd/minikube/cmd/service.go @@ -32,6 +32,7 @@ import ( "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/kapi" "k8s.io/minikube/pkg/minikube/browser" @@ -79,13 +80,14 @@ var serviceCmd = &cobra.Command{ exit.Message(reason.Usage, "You must specify service name(s) or --all") } + options := flags.Options() svcArgs := make(map[string]bool) for _, v := range args { svcArgs[v] = true } cname := ClusterFlagValue() - co := mustload.Healthy(cname) + co := mustload.Healthy(cname, options) if driver.IsQEMU(co.Config.Driver) && pkgnetwork.IsBuiltinQEMU(co.Config.Network) { msg := "minikube service is not currently implemented with the builtin network on QEMU" diff --git a/cmd/minikube/cmd/service_list.go b/cmd/minikube/cmd/service_list.go index 34bf7d55f4d3..bb21d2300d19 100644 --- a/cmd/minikube/cmd/service_list.go +++ b/cmd/minikube/cmd/service_list.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" core "k8s.io/api/core/v1" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/mustload" @@ -42,7 +43,8 @@ var serviceListCmd = &cobra.Command{ Short: "Lists the URLs for the services in your local cluster", Long: `Lists the URLs for the services in your local cluster`, Run: func(_ *cobra.Command, _ []string) { - co := mustload.Healthy(ClusterFlagValue()) + options := flags.Options() + co := mustload.Healthy(ClusterFlagValue(), options) output := strings.ToLower(profileOutput) serviceURLs, err := service.GetServiceURLs(co.API, co.Config.Name, serviceListNamespace, serviceURLTemplate) diff --git a/cmd/minikube/cmd/ssh-host.go b/cmd/minikube/cmd/ssh-host.go index 523357654ea9..60b9140c6377 100644 --- a/cmd/minikube/cmd/ssh-host.go +++ b/cmd/minikube/cmd/ssh-host.go @@ -24,6 +24,7 @@ import ( "github.com/spf13/cobra" "k8s.io/client-go/util/homedir" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/exit" @@ -50,8 +51,9 @@ var sshHostCmd = &cobra.Command{ } func appendKnownHelper(nodeName string, appendKnown bool) { + options := flags.Options() cname := ClusterFlagValue() - co := mustload.Running(cname) + co := mustload.Running(cname, options) if co.CP.Host.DriverName == driver.None { exit.Message(reason.Usage, "'none' driver does not support 'minikube ssh-host' command") } diff --git a/cmd/minikube/cmd/ssh-key.go b/cmd/minikube/cmd/ssh-key.go index cd62510df4f4..a938d1a34f72 100644 --- a/cmd/minikube/cmd/ssh-key.go +++ b/cmd/minikube/cmd/ssh-key.go @@ -20,6 +20,7 @@ import ( "path/filepath" "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/localpath" @@ -35,7 +36,8 @@ var sshKeyCmd = &cobra.Command{ Short: "Retrieve the ssh identity key path of the specified node", Long: "Retrieve the ssh identity key path of the specified node, and writes it to STDOUT.", Run: func(_ *cobra.Command, _ []string) { - _, cc := mustload.Partial(ClusterFlagValue()) + options := flags.Options() + _, cc := mustload.Partial(ClusterFlagValue(), options) n, _, err := node.Retrieve(*cc, nodeName) if err != nil { exit.Error(reason.GuestNodeRetrieve, "retrieving node", err) diff --git a/cmd/minikube/cmd/ssh.go b/cmd/minikube/cmd/ssh.go index c1a5db35c857..418d518aa1e8 100644 --- a/cmd/minikube/cmd/ssh.go +++ b/cmd/minikube/cmd/ssh.go @@ -21,6 +21,7 @@ import ( "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/exit" @@ -39,8 +40,9 @@ var sshCmd = &cobra.Command{ Short: "Log into the minikube environment (for debugging)", Long: "Log into or run a command on a machine with SSH; similar to 'docker-machine ssh'.", Run: func(_ *cobra.Command, args []string) { + options := flags.Options() cname := ClusterFlagValue() - co := mustload.Running(cname) + co := mustload.Running(cname, options) if co.CP.Host.DriverName == driver.None { exit.Message(reason.Usage, "'none' driver does not support 'minikube ssh' command") } diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 65d955f8dbde..7343a00f8ee4 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -51,6 +51,7 @@ import ( "k8s.io/klog/v2" cmdcfg "k8s.io/minikube/cmd/minikube/cmd/config" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/minikube/bootstrapper/bsutil" "k8s.io/minikube/pkg/minikube/bootstrapper/bsutil/kverify" @@ -76,6 +77,7 @@ import ( "k8s.io/minikube/pkg/minikube/pause" "k8s.io/minikube/pkg/minikube/reason" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/translate" netutil "k8s.io/minikube/pkg/network" @@ -154,6 +156,8 @@ func platform() string { // runStart handles the executes the flow of "minikube start" func runStart(cmd *cobra.Command, _ []string) { + options := flags.Options() + register.SetEventLogPath(localpath.EventLog(ClusterFlagValue())) ctx := context.Background() out.SetJSON(outputFormat == "json") @@ -166,7 +170,7 @@ func runStart(cmd *cobra.Command, _ []string) { go download.CleanUpOlderPreloads() // Avoid blocking execution on optional HTTP fetches - go notify.MaybePrintUpdateTextFromGithub() + go notify.MaybePrintUpdateTextFromGithub(options) displayEnviron(os.Environ()) if viper.GetBool(force) { @@ -203,11 +207,11 @@ func runStart(cmd *cobra.Command, _ []string) { validateProfileName() } - validateSpecifiedDriver(existing) + validateSpecifiedDriver(existing, options) validateKubernetesVersion(existing) validateContainerRuntime(existing) - ds, alts, specified := selectDriver(existing) + ds, alts, specified := selectDriver(existing, options) if cmd.Flag(kicBaseImage).Changed { if !isBaseImageApplicable(ds.Name) { exit.Message(reason.Usage, @@ -226,7 +230,7 @@ func runStart(cmd *cobra.Command, _ []string) { useForce := viper.GetBool(force) - starter, err := provisionWithDriver(cmd, ds, existing) + starter, err := provisionWithDriver(cmd, ds, existing, options) if err != nil { node.ExitIfFatal(err, useForce) machine.MaybeDisplayAdvice(err, ds.Name) @@ -249,11 +253,11 @@ func runStart(cmd *cobra.Command, _ []string) { klog.Warningf("%s profile does not exist, trying anyways.", ClusterFlagValue()) } - err = deleteProfile(ctx, profile) + err = deleteProfile(ctx, profile, options) if err != nil { out.WarningT("Failed to delete cluster {{.name}}, proceeding with retry anyway.", out.V{"name": ClusterFlagValue()}) } - starter, err = provisionWithDriver(cmd, ds, existing) + starter, err = provisionWithDriver(cmd, ds, existing, options) if err != nil { continue } @@ -283,7 +287,7 @@ func runStart(cmd *cobra.Command, _ []string) { } } - configInfo, err := startWithDriver(cmd, starter, existing) + configInfo, err := startWithDriver(cmd, starter, existing, options) if err != nil { node.ExitIfFatal(err, useForce) exit.Error(reason.GuestStart, "failed to start node", err) @@ -300,7 +304,7 @@ func runStart(cmd *cobra.Command, _ []string) { } } -func provisionWithDriver(cmd *cobra.Command, ds registry.DriverState, existing *config.ClusterConfig) (node.Starter, error) { +func provisionWithDriver(cmd *cobra.Command, ds registry.DriverState, existing *config.ClusterConfig, options *run.Options) (node.Starter, error) { driverName := ds.Name klog.Infof("selected driver: %s", driverName) validateDriver(ds, existing) @@ -342,14 +346,14 @@ func provisionWithDriver(cmd *cobra.Command, ds registry.DriverState, existing * } rtime := getContainerRuntime(existing) - cc, n, err := generateClusterConfig(cmd, existing, k8sVersion, rtime, driverName) + cc, n, err := generateClusterConfig(cmd, existing, k8sVersion, rtime, driverName, options) if err != nil { return node.Starter{}, errors.Wrap(err, "Failed to generate cluster config") } klog.Infof("cluster config:\n%+v", cc) if firewall.IsBootpdBlocked(cc) { - if err := firewall.UnblockBootpd(); err != nil { + if err := firewall.UnblockBootpd(options); err != nil { klog.Warningf("failed unblocking bootpd from firewall: %v", err) } } @@ -386,7 +390,7 @@ func provisionWithDriver(cmd *cobra.Command, ds registry.DriverState, existing * ssh.SetDefaultClient(ssh.External) } - mRunner, preExists, mAPI, host, err := node.Provision(&cc, &n, viper.GetBool(deleteOnFailure)) + mRunner, preExists, mAPI, host, err := node.Provision(&cc, &n, viper.GetBool(deleteOnFailure), options) if err != nil { return node.Starter{}, err } @@ -471,11 +475,11 @@ func imageMatchesBinaryVersion(imageVersion, binaryVersion string) bool { return ok && binaryVersion == imageVersion } -func startWithDriver(cmd *cobra.Command, starter node.Starter, existing *config.ClusterConfig) (*kubeconfig.Settings, error) { +func startWithDriver(cmd *cobra.Command, starter node.Starter, existing *config.ClusterConfig, options *run.Options) (*kubeconfig.Settings, error) { // start primary control-plane node - configInfo, err := node.Start(starter) + configInfo, err := node.Start(starter, options) if err != nil { - configInfo, err = maybeDeleteAndRetry(cmd, *starter.Cfg, *starter.Node, starter.ExistingAddons, err) + configInfo, err = maybeDeleteAndRetry(cmd, *starter.Cfg, *starter.Node, starter.ExistingAddons, err, options) if err != nil { return nil, err } @@ -516,7 +520,7 @@ func startWithDriver(cmd *cobra.Command, starter node.Starter, existing *config. } out.Ln("") // extra newline for clarity on the command line - if err := node.Add(starter.Cfg, n, viper.GetBool(deleteOnFailure)); err != nil { + if err := node.Add(starter.Cfg, n, viper.GetBool(deleteOnFailure), options); err != nil { return nil, errors.Wrap(err, "adding node") } } @@ -534,7 +538,7 @@ func updateDriver(driverName string) { v, err := version.GetSemverVersion() if err != nil { out.WarningT("Error parsing minikube version: {{.error}}", out.V{"error": err}) - } else if err := auxdriver.InstallOrUpdate(driverName, localpath.MakeMiniPath("bin"), v, viper.GetBool(interactive), viper.GetBool(autoUpdate)); err != nil { + } else if err := auxdriver.InstallOrUpdate(driverName, localpath.MakeMiniPath("bin"), v, viper.GetBool(flags.Interactive), viper.GetBool(autoUpdate)); err != nil { if errors.Is(err, auxdriver.ErrAuxDriverVersionCommandFailed) { exit.Error(reason.DrvAuxNotHealthy, "Aux driver "+driverName, err) } @@ -632,7 +636,7 @@ func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion, rtime, machineName st return nil } -func maybeDeleteAndRetry(cmd *cobra.Command, existing config.ClusterConfig, n config.Node, existingAddons map[string]bool, originalErr error) (*kubeconfig.Settings, error) { +func maybeDeleteAndRetry(cmd *cobra.Command, existing config.ClusterConfig, n config.Node, existingAddons map[string]bool, originalErr error, options *run.Options) (*kubeconfig.Settings, error) { if viper.GetBool(deleteOnFailure) { out.WarningT("Node {{.name}} failed to start, deleting and trying again.", out.V{"name": n.Name}) // Start failed, delete the cluster and try again @@ -641,7 +645,7 @@ func maybeDeleteAndRetry(cmd *cobra.Command, existing config.ClusterConfig, n co out.ErrT(style.Meh, `"{{.name}}" profile does not exist, trying anyways.`, out.V{"name": existing.Name}) } - err = deleteProfile(context.Background(), profile) + err = deleteProfile(context.Background(), profile, options) if err != nil { out.WarningT("Failed to delete cluster {{.name}}, proceeding with retry anyway.", out.V{"name": existing.Name}) } @@ -649,8 +653,9 @@ func maybeDeleteAndRetry(cmd *cobra.Command, existing config.ClusterConfig, n co // Re-generate the cluster config, just in case the failure was related to an old config format cc := updateExistingConfigFromFlags(cmd, &existing) var configInfo *kubeconfig.Settings + for _, n := range cc.Nodes { - r, p, m, h, err := node.Provision(&cc, &n, false) + r, p, m, h, err := node.Provision(&cc, &n, false, options) s := node.Starter{ Runner: r, PreExists: p, @@ -665,7 +670,7 @@ func maybeDeleteAndRetry(cmd *cobra.Command, existing config.ClusterConfig, n co return nil, err } - k, err := node.Start(s) + k, err := node.Start(s, options) if n.ControlPlane { configInfo = k } @@ -706,14 +711,14 @@ func kubectlVersion(path string) (string, error) { } // returns (current_driver, suggested_drivers, "true, if the driver is set by command line arg or in the config file") -func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []registry.DriverState, bool) { +func selectDriver(existing *config.ClusterConfig, options *run.Options) (registry.DriverState, []registry.DriverState, bool) { // Technically unrelated, but important to perform before detection driver.SetLibvirtURI(viper.GetString(kvmQemuURI)) register.Reg.SetStep(register.SelectingDriver) // By default, the driver is whatever we used last time if existing != nil { - old := hostDriver(existing) - ds := driver.Status(old) + old := hostDriver(existing, options) + ds := driver.Status(old, options) out.Step(style.Sparkle, `Using the {{.driver}} driver based on existing profile`, out.V{"driver": ds.String()}) return ds, nil, true } @@ -730,7 +735,7 @@ func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []regis ` out.WarningT(warning, out.V{"driver": d, "vmd": vmd}) } - ds := driver.Status(d) + ds := driver.Status(d, options) if ds.Name == "" { exit.Message(reason.DrvUnsupportedOS, "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}", out.V{"driver": d, "os": runtime.GOOS, "arch": runtime.GOARCH}) } @@ -740,7 +745,7 @@ func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []regis // Fallback to old driver parameter if d := viper.GetString("vm-driver"); d != "" { - ds := driver.Status(viper.GetString("vm-driver")) + ds := driver.Status(viper.GetString("vm-driver"), options) if ds.Name == "" { exit.Message(reason.DrvUnsupportedOS, "The driver '{{.driver}}' is not supported on {{.os}}/{{.arch}}", out.V{"driver": d, "os": runtime.GOOS, "arch": runtime.GOARCH}) } @@ -748,7 +753,7 @@ func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []regis return ds, nil, true } - choices := driver.Choices(viper.GetBool("vm")) + choices := driver.Choices(viper.GetBool("vm"), options) pick, alts, rejects := driver.Suggest(choices) if pick.Name == "" { out.Step(style.ThumbsDown, "Unable to pick a default driver. Here is what was considered, in preference order:") @@ -813,12 +818,12 @@ func selectDriver(existing *config.ClusterConfig) (registry.DriverState, []regis } // hostDriver returns the actual driver used by a libmachine host, which can differ from our config -func hostDriver(existing *config.ClusterConfig) string { +func hostDriver(existing *config.ClusterConfig, options *run.Options) string { if existing == nil { return "" } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { klog.Warningf("selectDriver NewAPIClient: %v", err) return existing.Driver @@ -861,7 +866,7 @@ func validateProfileName() { // validateSpecifiedDriver makes sure that if a user has passed in a driver // it matches the existing cluster if there is one -func validateSpecifiedDriver(existing *config.ClusterConfig) { +func validateSpecifiedDriver(existing *config.ClusterConfig, options *run.Options) { if existing == nil { return } @@ -878,7 +883,7 @@ func validateSpecifiedDriver(existing *config.ClusterConfig) { return } - old := hostDriver(existing) + old := hostDriver(existing, options) if requested == old { return } @@ -897,7 +902,7 @@ func validateSpecifiedDriver(existing *config.ClusterConfig) { out.ErrT(style.Meh, `"{{.name}}" profile does not exist, trying anyways.`, out.V{"name": existing.Name}) } - err = deleteProfile(context.Background(), profile) + err = deleteProfile(context.Background(), profile, options) if err != nil { out.WarningT("Failed to delete cluster {{.name}}.", out.V{"name": existing.Name}) } @@ -928,7 +933,7 @@ func validateDriver(ds registry.DriverState, existing *config.ClusterConfig) { } // if we are only downloading artifacts for a driver, we can stop validation here - if viper.GetBool("download-only") { + if viper.GetBool(flags.DownloadOnly) { return } @@ -1052,7 +1057,7 @@ func validateUser(drvName string) { // None driver works with root and without root on Linux if runtime.GOOS == "linux" && drvName == driver.None { - if !viper.GetBool(interactive) { + if !viper.GetBool(flags.Interactive) { test := exec.Command("sudo", "-n", "echo", "-n") if err := test.Run(); err != nil { exit.Message(reason.DrvNeedsRoot, `sudo requires a password, and --interactive=false`) @@ -2070,12 +2075,12 @@ func isTwoDigitSemver(ver string) bool { return majorMinorOnly.MatchString(ver) } -func startNerdctld() { +func startNerdctld(options *run.Options) { // for containerd runtime using ssh, we have installed nerdctld and nerdctl into kicbase // These things will be included in the ISO/Base image in the future versions // copy these binaries to the path of the containerd node - co := mustload.Running(ClusterFlagValue()) + co := mustload.Running(ClusterFlagValue(), options) runner := co.CP.Runner // and set 777 to these files diff --git a/cmd/minikube/cmd/start_flags.go b/cmd/minikube/cmd/start_flags.go index 92546e3f9c90..4b45da631c8f 100644 --- a/cmd/minikube/cmd/start_flags.go +++ b/cmd/minikube/cmd/start_flags.go @@ -28,6 +28,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/common/vmnet" "k8s.io/minikube/pkg/drivers/kic" "k8s.io/minikube/pkg/drivers/kic/oci" @@ -44,6 +45,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/proxy" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" pkgutil "k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/version" @@ -100,13 +102,11 @@ const ( vsockPorts = "hyperkit-vsock-ports" embedCerts = "embed-certs" noVTXCheck = "no-vtx-check" - downloadOnly = "download-only" dnsProxy = "dns-proxy" hostDNSResolver = "host-dns-resolver" waitComponents = "wait" force = "force" dryRun = "dry-run" - interactive = "interactive" waitTimeout = "wait-timeout" nativeSSH = "native-ssh" minUsableMem = 1800 // Kubernetes (kubeadm) will not start with less @@ -160,13 +160,13 @@ func initMinikubeFlags() { viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) viper.AutomaticEnv() startCmd.Flags().Bool(force, false, "Force minikube to perform possibly dangerous operations") - startCmd.Flags().Bool(interactive, true, "Allow user prompts for more information") + startCmd.Flags().Bool(flags.Interactive, true, "Allow user prompts for more information") startCmd.Flags().Bool(dryRun, false, "dry-run mode. Validates configuration, but does not mutate system state") startCmd.Flags().String(cpus, "2", fmt.Sprintf("Number of CPUs allocated to Kubernetes. Use %q to use the maximum number of CPUs. Use %q to not specify a limit (Docker/Podman only)", constants.MaxResources, constants.NoLimit)) startCmd.Flags().StringP(memory, "m", "", fmt.Sprintf("Amount of RAM to allocate to Kubernetes (format: [], where unit = b, k, m or g). Use %q to use the maximum amount of memory. Use %q to not specify a limit (Docker/Podman only)", constants.MaxResources, constants.NoLimit)) startCmd.Flags().String(humanReadableDiskSize, defaultDiskSize, "Disk size allocated to the minikube VM (format: [], where unit = b, k, m or g).") - startCmd.Flags().Bool(downloadOnly, false, "If true, only download and cache files for later use - don't install or start anything.") + startCmd.Flags().Bool(flags.DownloadOnly, false, "If true, only download and cache files for later use - don't install or start anything.") startCmd.Flags().Bool(cacheImages, true, "If true, cache docker images for the current bootstrapper and load them into the machine. Always false with --driver=none.") startCmd.Flags().StringSlice(isoURL, download.DefaultISOURLs(), "Locations to fetch the minikube ISO from.") startCmd.Flags().String(kicBaseImage, kic.BaseImage, "The base image to use for docker/podman drivers. Intended for local development.") @@ -314,7 +314,7 @@ func ClusterFlagValue() string { } // generateClusterConfig generate a config.ClusterConfig based on flags or existing cluster config -func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k8sVersion string, rtime string, drvName string) (config.ClusterConfig, config.Node, error) { +func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k8sVersion string, rtime string, drvName string, options *run.Options) (config.ClusterConfig, config.Node, error) { var cc config.ClusterConfig if existing != nil { cc = updateExistingConfigFromFlags(cmd, existing) @@ -325,7 +325,7 @@ func generateClusterConfig(cmd *cobra.Command, existing *config.ClusterConfig, k } } else { klog.Info("no existing cluster config was found, will generate one from the flags ") - cc = generateNewConfigFromFlags(cmd, k8sVersion, rtime, drvName) + cc = generateNewConfigFromFlags(cmd, k8sVersion, rtime, drvName, options) cnm, err := cni.New(&cc) if err != nil { @@ -484,12 +484,12 @@ func getCNIConfig(cmd *cobra.Command) string { return chosenCNI } -func getNetwork(driverName string) string { +func getNetwork(driverName string, options *run.Options) string { n := viper.GetString(network) if driver.IsQEMU(driverName) { return validateQemuNetwork(n) } else if driver.IsVFKit(driverName) { - return validateVfkitNetwork(n) + return validateVfkitNetwork(n, options) } return n } @@ -526,7 +526,7 @@ func validateQemuNetwork(n string) string { return n } -func validateVfkitNetwork(n string) string { +func validateVfkitNetwork(n string, options *run.Options) string { if runtime.GOOS != "darwin" { exit.Message(reason.Usage, "The vfkit driver is only supported on macOS") } @@ -535,7 +535,7 @@ func validateVfkitNetwork(n string) string { // always available case "vmnet-shared": // "vment-shared" provides access between machines, with lower performance compared to "nat". - if err := vmnet.ValidateHelper(); err != nil { + if err := vmnet.ValidateHelper(options); err != nil { vmnetErr := err.(*vmnet.Error) exit.Message(vmnetErr.Kind, "failed to validate {{.network}} network: {{.reason}}", out.V{"network": n, "reason": err}) } @@ -549,7 +549,7 @@ func validateVfkitNetwork(n string) string { } // generateNewConfigFromFlags generate a config.ClusterConfig based on flags -func generateNewConfigFromFlags(cmd *cobra.Command, k8sVersion string, rtime string, drvName string) config.ClusterConfig { +func generateNewConfigFromFlags(cmd *cobra.Command, k8sVersion string, rtime string, drvName string, options *run.Options) config.ClusterConfig { var cc config.ClusterConfig // networkPlugin cni deprecation warning @@ -574,7 +574,7 @@ func generateNewConfigFromFlags(cmd *cobra.Command, k8sVersion string, rtime str EmbedCerts: viper.GetBool(embedCerts), MinikubeISO: viper.GetString(isoURL), KicBaseImage: viper.GetString(kicBaseImage), - Network: getNetwork(drvName), + Network: getNetwork(drvName, options), Subnet: viper.GetString(subnet), Memory: getMemorySize(cmd, drvName), CPUs: getCPUCount(drvName), diff --git a/cmd/minikube/cmd/start_test.go b/cmd/minikube/cmd/start_test.go index 3a391d41f1c2..611e92d540e1 100644 --- a/cmd/minikube/cmd/start_test.go +++ b/cmd/minikube/cmd/start_test.go @@ -32,6 +32,7 @@ import ( "k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/proxy" + "k8s.io/minikube/pkg/minikube/run" ) func TestGetKubernetesVersion(t *testing.T) { @@ -169,7 +170,7 @@ func TestMirrorCountry(t *testing.T) { viper.SetDefault(imageRepository, test.imageRepository) viper.SetDefault(imageMirrorCountry, test.mirrorCountry) viper.SetDefault(kvmNUMACount, 1) - config, _, err := generateClusterConfig(cmd, nil, k8sVersion, rtime, driver.Mock) + config, _, err := generateClusterConfig(cmd, nil, k8sVersion, rtime, driver.Mock, &run.Options{}) if err != nil { t.Fatalf("Got unexpected error %v during config generation", err) } @@ -230,7 +231,7 @@ func TestGenerateCfgFromFlagsHTTPProxyHandling(t *testing.T) { cfg.DockerEnv = []string{} // clear docker env to avoid pollution proxy.SetDockerEnv() - config, _, err := generateClusterConfig(cmd, nil, k8sVersion, rtime, "none") + config, _, err := generateClusterConfig(cmd, nil, k8sVersion, rtime, "none", &run.Options{}) if err != nil { t.Fatalf("Got unexpected error %v during config generation", err) } diff --git a/cmd/minikube/cmd/status.go b/cmd/minikube/cmd/status.go index c0784692240d..a53afa86a92a 100644 --- a/cmd/minikube/cmd/status.go +++ b/cmd/minikube/cmd/status.go @@ -30,6 +30,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" @@ -89,11 +90,12 @@ var statusCmd = &cobra.Command{ exit.Message(reason.Usage, "Cannot use both --output and --format options") } + options := flags.Options() out.SetJSON(output == "json") - go notify.MaybePrintUpdateTextFromGithub() + go notify.MaybePrintUpdateTextFromGithub(options) cname := ClusterFlagValue() - api, cc := mustload.Partial(cname) + api, cc := mustload.Partial(cname, options) duration := watch if !cmd.Flags().Changed("watch") || watch < 0 { diff --git a/cmd/minikube/cmd/stop.go b/cmd/minikube/cmd/stop.go index 3b3e1beed779..dc5b1fa06438 100644 --- a/cmd/minikube/cmd/stop.go +++ b/cmd/minikube/cmd/stop.go @@ -27,6 +27,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/kubeconfig" @@ -36,6 +37,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/out/register" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/schedule" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/util/retry" @@ -70,6 +72,7 @@ func init() { // runStop handles the executes the flow of "minikube stop" func runStop(_ *cobra.Command, _ []string) { + options := flags.Options() out.SetJSON(outputFormat == "json") register.Reg.SetStep(register.Stopping) @@ -94,7 +97,7 @@ func runStop(_ *cobra.Command, _ []string) { } // Kill any existing scheduled stops - schedule.KillExisting(profilesToStop) + schedule.KillExisting(profilesToStop, options) if cancelScheduledStop { register.Reg.SetStep(register.Done) out.Step(style.Stopped, `All existing scheduled stops cancelled`) @@ -102,7 +105,7 @@ func runStop(_ *cobra.Command, _ []string) { } if scheduledStopDuration != 0 { - if err := schedule.Daemonize(profilesToStop, scheduledStopDuration); err != nil { + if err := schedule.Daemonize(profilesToStop, scheduledStopDuration, options); err != nil { exit.Message(reason.DaemonizeError, "unable to daemonize: {{.err}}", out.V{"err": err.Error()}) } // if OS is windows, scheduled stop is now being handled within minikube, so return @@ -115,19 +118,19 @@ func runStop(_ *cobra.Command, _ []string) { stoppedNodes := 0 for _, profile := range profilesToStop { - stoppedNodes = stopProfile(profile) + stoppedNodes = stopProfile(profile, options) } register.Reg.SetStep(register.Done) out.Step(style.Stopped, `{{.count}} node{{if gt .count 1}}s{{end}} stopped.`, out.V{"count": stoppedNodes}) } -func stopProfile(profile string) int { +func stopProfile(profile string, options *run.Options) int { stoppedNodes := 0 register.Reg.SetStep(register.Stopping) // end new code - api, cc := mustload.Partial(profile) + api, cc := mustload.Partial(profile, options) defer api.Close() if err := killMountProcess(); err != nil { diff --git a/cmd/minikube/cmd/tunnel.go b/cmd/minikube/cmd/tunnel.go index 279ab007eb60..4d179ed3121e 100644 --- a/cmd/minikube/cmd/tunnel.go +++ b/cmd/minikube/cmd/tunnel.go @@ -29,6 +29,7 @@ import ( "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/kapi" "k8s.io/minikube/pkg/minikube/config" @@ -57,9 +58,10 @@ var tunnelCmd = &cobra.Command{ RootCmd.PersistentPreRun(cmd, args) }, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() manager := tunnel.NewManager() cname := ClusterFlagValue() - co := mustload.Healthy(cname) + co := mustload.Healthy(cname, options) if driver.IsQEMU(co.Config.Driver) && pkgnetwork.IsBuiltinQEMU(co.Config.Network) { msg := "minikube tunnel is not currently implemented with the builtin network on QEMU" diff --git a/cmd/minikube/cmd/unpause.go b/cmd/minikube/cmd/unpause.go index fd305bca6c9b..82ac54092040 100644 --- a/cmd/minikube/cmd/unpause.go +++ b/cmd/minikube/cmd/unpause.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/viper" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" @@ -43,10 +44,11 @@ var unpauseCmd = &cobra.Command{ Aliases: []string{"resume"}, Short: "unpause Kubernetes", Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() cname := ClusterFlagValue() register.SetEventLogPath(localpath.EventLog(cname)) - co := mustload.Running(cname) + co := mustload.Running(cname, options) out.SetJSON(outputFormat == "json") register.Reg.SetStep(register.Unpausing) diff --git a/cmd/minikube/cmd/update-context.go b/cmd/minikube/cmd/update-context.go index 2be567dd709d..0565ac011075 100644 --- a/cmd/minikube/cmd/update-context.go +++ b/cmd/minikube/cmd/update-context.go @@ -18,6 +18,7 @@ package cmd import ( "github.com/spf13/cobra" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/kubeconfig" "k8s.io/minikube/pkg/minikube/mustload" @@ -33,8 +34,9 @@ var updateContextCmd = &cobra.Command{ Long: `Retrieves the IP address of the running cluster, checks it with IP in kubeconfig, and corrects kubeconfig if incorrect.`, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() cname := ClusterFlagValue() - co := mustload.Running(cname) + co := mustload.Running(cname, options) // cluster extension metada for kubeconfig updated, err := kubeconfig.UpdateEndpoint(cname, co.CP.Hostname, co.CP.Port, kubeconfig.PathFromEnv(), kubeconfig.NewExtension()) diff --git a/cmd/minikube/cmd/version.go b/cmd/minikube/cmd/version.go index 4e0e4bc71e6f..b7a2dd3268b8 100644 --- a/cmd/minikube/cmd/version.go +++ b/cmd/minikube/cmd/version.go @@ -26,6 +26,7 @@ import ( "github.com/spf13/cobra" "gopkg.in/yaml.v2" "k8s.io/klog/v2" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" @@ -44,6 +45,7 @@ var versionCmd = &cobra.Command{ Short: "Print the version of minikube", Long: `Print the version of minikube.`, Run: func(_ *cobra.Command, _ []string) { + options := flags.Options() minikubeVersion := version.GetVersion() gitCommitID := version.GetGitCommitID() data := map[string]interface{}{ @@ -52,7 +54,7 @@ var versionCmd = &cobra.Command{ } if listComponentsVersions && !shortVersion { - co := mustload.Running(ClusterFlagValue()) + co := mustload.Running(ClusterFlagValue(), options) runner := co.CP.Runner versionCMDS := map[string]*exec.Cmd{ "docker": exec.Command("docker", "--version"), diff --git a/cmd/minikube/main.go b/cmd/minikube/main.go index eb3fa841e2e7..c57b0f13a996 100644 --- a/cmd/minikube/main.go +++ b/cmd/minikube/main.go @@ -48,6 +48,7 @@ import ( "github.com/pkg/profile" "k8s.io/minikube/cmd/minikube/cmd" + "k8s.io/minikube/cmd/minikube/cmd/flags" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/out" @@ -70,6 +71,7 @@ var ( ) func main() { + options := flags.Options() bridgeLogMessages() defer klog.Flush() @@ -88,7 +90,7 @@ func main() { defer profile.Start(profile.TraceProfile).Stop() } if os.Getenv(constants.IsMinikubeChildProcess) == "" { - machine.StartDriver() + machine.StartDriver(options) } out.SetOutFile(os.Stdout) out.SetErrFile(os.Stderr) diff --git a/pkg/addons/addons.go b/pkg/addons/addons.go index 99d6110dd297..37c7dc16ad70 100644 --- a/pkg/addons/addons.go +++ b/pkg/addons/addons.go @@ -48,6 +48,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/out/register" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/sysinit" "k8s.io/minikube/pkg/util" @@ -65,7 +66,7 @@ var Refresh = false var ErrSkipThisAddon = errors.New("skipping this addon") // RunCallbacks runs all actions associated to an addon, but does not set it (thread-safe) -func RunCallbacks(cc *config.ClusterConfig, name string, value string) error { +func RunCallbacks(cc *config.ClusterConfig, name string, value string, options *run.Options) error { klog.Infof("Setting %s=%s in profile %q", name, value, cc.Name) a, valid := isAddonValid(name) if !valid { @@ -73,7 +74,7 @@ func RunCallbacks(cc *config.ClusterConfig, name string, value string) error { } // Run any additional validations for this property - if err := run(cc, name, value, a.validations); err != nil { + if err := invoke(cc, name, value, a.validations, options); err != nil { if errors.Is(err, ErrSkipThisAddon) { return err } @@ -83,7 +84,7 @@ func RunCallbacks(cc *config.ClusterConfig, name string, value string) error { preStartMessages(name, value) // Run any callbacks for this property - if err := run(cc, name, value, a.callbacks); err != nil { + if err := invoke(cc, name, value, a.callbacks, options); err != nil { if errors.Is(err, ErrSkipThisAddon) { return err } @@ -172,29 +173,29 @@ func Deprecations(name string) (bool, string, string) { } // Set sets a value in the config (not threadsafe) -func Set(cc *config.ClusterConfig, name string, value string) error { +func Set(cc *config.ClusterConfig, name string, value string, options *run.Options) error { a, valid := isAddonValid(name) if !valid { return errors.Errorf("%s is not a valid addon", name) } - return a.set(cc, name, value) + return a.set(cc, name, value, options) } // SetAndSave sets a value and saves the config -func SetAndSave(profile string, name string, value string) error { +func SetAndSave(profile string, name string, value string, options *run.Options) error { cc, err := config.Load(profile) if err != nil { return errors.Wrap(err, "loading profile") } - if err := RunCallbacks(cc, name, value); err != nil { + if err := RunCallbacks(cc, name, value, options); err != nil { if errors.Is(err, ErrSkipThisAddon) { return err } return errors.Wrap(err, "run callbacks") } - if err := Set(cc, name, value); err != nil { + if err := Set(cc, name, value, options); err != nil { return errors.Wrap(err, "set") } @@ -203,10 +204,10 @@ func SetAndSave(profile string, name string, value string) error { } // Runs all the validation or callback functions and collects errors -func run(cc *config.ClusterConfig, name string, value string, fns []setFn) error { +func invoke(cc *config.ClusterConfig, name string, value string, fns []setFn, options *run.Options) error { var errs []error for _, fn := range fns { - err := fn(cc, name, value) + err := fn(cc, name, value, options) if err != nil { if errors.Is(err, ErrSkipThisAddon) { return ErrSkipThisAddon @@ -221,7 +222,7 @@ func run(cc *config.ClusterConfig, name string, value string, fns []setFn) error } // SetBool sets a bool value in the config (not threadsafe) -func SetBool(cc *config.ClusterConfig, name string, val string) error { +func SetBool(cc *config.ClusterConfig, name string, val string, _ *run.Options) error { b, err := strconv.ParseBool(val) if err != nil { return err @@ -234,7 +235,7 @@ func SetBool(cc *config.ClusterConfig, name string, val string) error { } // EnableOrDisableAddon updates addon status executing any commands necessary -func EnableOrDisableAddon(cc *config.ClusterConfig, name string, val string) error { +func EnableOrDisableAddon(cc *config.ClusterConfig, name string, val string, options *run.Options) error { klog.Infof("Setting addon %s=%s in %q", name, val, cc.Name) enable, err := strconv.ParseBool(val) if err != nil { @@ -250,7 +251,7 @@ func EnableOrDisableAddon(cc *config.ClusterConfig, name string, val string) err } } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return errors.Wrap(err, "machine client") } @@ -467,15 +468,15 @@ func enableOrDisableAddonInternal(cc *config.ClusterConfig, addon *assets.Addon, return retry.Expo(apply, 250*time.Millisecond, 2*time.Minute) } -func verifyAddonStatus(cc *config.ClusterConfig, name string, val string) error { +func verifyAddonStatus(cc *config.ClusterConfig, name string, val string, options *run.Options) error { ns := "kube-system" if name == "ingress" { ns = "ingress-nginx" } - return verifyAddonStatusInternal(cc, name, val, ns) + return verifyAddonStatusInternal(cc, name, val, ns, options) } -func verifyAddonStatusInternal(cc *config.ClusterConfig, name string, val string, ns string) error { +func verifyAddonStatusInternal(cc *config.ClusterConfig, name string, val string, ns string, _ *run.Options) error { klog.Infof("Verifying addon %s=%s in %q", name, val, cc.Name) enable, err := strconv.ParseBool(val) if err != nil { @@ -504,7 +505,7 @@ func verifyAddonStatusInternal(cc *config.ClusterConfig, name string, val string // Since Enable is called asynchronously (so is not thread-safe for concurrent addons map updating/reading), to avoid race conditions, // ToEnable should be called synchronously before Enable to get complete list of addons to enable, and // UpdateConfig should be called synchronously after Enable to update the config with successfully enabled addons. -func Enable(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]bool, enabled chan<- []string) { +func Enable(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]bool, enabled chan<- []string, options *run.Options) { defer wg.Done() start := time.Now() @@ -531,7 +532,7 @@ func Enable(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]bo for _, a := range toEnableList { awg.Add(1) go func(name string) { - err := RunCallbacks(cc, name, "true") + err := RunCallbacks(cc, name, "true", options) if err != nil && !errors.Is(err, ErrSkipThisAddon) { out.WarningT("Enabling '{{.name}}' returned an error: {{.error}}", out.V{"name": name, "error": err}) } else { @@ -585,24 +586,24 @@ func ToEnable(cc *config.ClusterConfig, existing map[string]bool, additional []s // UpdateConfigToEnable tries to update config with all enabled addons (not thread-safe). // Any error will be logged and it will continue. -func UpdateConfigToEnable(cc *config.ClusterConfig, enabled []string) { +func UpdateConfigToEnable(cc *config.ClusterConfig, enabled []string, options *run.Options) { for _, a := range enabled { - if err := Set(cc, a, "true"); err != nil { + if err := Set(cc, a, "true", options); err != nil { klog.Errorf("store failed: %v", err) } } } -func UpdateConfigToDisable(cc *config.ClusterConfig) { +func UpdateConfigToDisable(cc *config.ClusterConfig, options *run.Options) { for name := range assets.Addons { - if err := Set(cc, name, "false"); err != nil { + if err := Set(cc, name, "false", options); err != nil { klog.Errorf("store failed: %v", err) } } } // VerifyNotPaused verifies the cluster is not paused before enable/disable an addon. -func VerifyNotPaused(profile string, enable bool) error { +func VerifyNotPaused(profile string, enable bool, options *run.Options) error { klog.Info("checking whether the cluster is paused") cc, err := config.Load(profile) @@ -610,7 +611,7 @@ func VerifyNotPaused(profile string, enable bool) error { return errors.Wrap(err, "loading profile") } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return errors.Wrap(err, "machine client") } diff --git a/pkg/addons/addons_autopause.go b/pkg/addons/addons_autopause.go index 3b33b7f9bded..21f0f212d3d9 100644 --- a/pkg/addons/addons_autopause.go +++ b/pkg/addons/addons_autopause.go @@ -28,11 +28,12 @@ import ( "k8s.io/minikube/pkg/minikube/kubeconfig" "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/sysinit" ) // enableOrDisableAutoPause enables the service after the config was copied by generic enable. -func enableOrDisableAutoPause(cc *config.ClusterConfig, name, val string) error { +func enableOrDisableAutoPause(cc *config.ClusterConfig, name, val string, options *run.Options) error { enable, err := strconv.ParseBool(val) if err != nil { return errors.Wrapf(err, "parsing bool: %s", name) @@ -40,7 +41,7 @@ func enableOrDisableAutoPause(cc *config.ClusterConfig, name, val string) error out.Infof("auto-pause addon is an alpha feature and still in early development. Please file issues to help us make it better.") out.Infof("https://github.com/kubernetes/minikube/labels/co/auto-pause") - co := mustload.Running(cc.Name) + co := mustload.Running(cc.Name, options) if enable { if err := sysinit.New(co.CP.Runner).EnableNow("auto-pause"); err != nil { klog.ErrorS(err, "failed to enable", "service", "auto-pause") diff --git a/pkg/addons/addons_gcpauth.go b/pkg/addons/addons_gcpauth.go index 7f5b27fe5e94..335ded5cd796 100644 --- a/pkg/addons/addons_gcpauth.go +++ b/pkg/addons/addons_gcpauth.go @@ -39,6 +39,7 @@ import ( "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/service" "k8s.io/minikube/pkg/minikube/style" ) @@ -54,20 +55,20 @@ const ( ) // enableOrDisableGCPAuth enables or disables the gcp-auth addon depending on the val parameter -func enableOrDisableGCPAuth(cfg *config.ClusterConfig, name, val string) error { +func enableOrDisableGCPAuth(cfg *config.ClusterConfig, name, val string, options *run.Options) error { enable, err := strconv.ParseBool(val) if err != nil { return errors.Wrapf(err, "parsing bool: %s", name) } if enable { - return enableAddonGCPAuth(cfg) + return enableAddonGCPAuth(cfg, options) } - return disableAddonGCPAuth(cfg) + return disableAddonGCPAuth(cfg, options) } -func enableAddonGCPAuth(cfg *config.ClusterConfig) error { +func enableAddonGCPAuth(cfg *config.ClusterConfig, options *run.Options) error { // Grab command runner from running cluster - cc := mustload.Running(cfg.Name) + cc := mustload.Running(cfg.Name, options) r := cc.CP.Runner // Grab credentials from where GCP would normally look @@ -244,9 +245,9 @@ func refreshExistingPods(cc *config.ClusterConfig) error { return nil } -func disableAddonGCPAuth(cfg *config.ClusterConfig) error { +func disableAddonGCPAuth(cfg *config.ClusterConfig, options *run.Options) error { // Grab command runner from running cluster - cc := mustload.Running(cfg.Name) + cc := mustload.Running(cfg.Name, options) r := cc.CP.Runner // Clean up the files generated when enabling the addon @@ -303,7 +304,7 @@ func disableAddonGCPAuth(cfg *config.ClusterConfig) error { return nil } -func verifyGCPAuthAddon(cc *config.ClusterConfig, name, val string) error { +func verifyGCPAuthAddon(cc *config.ClusterConfig, name, val string, options *run.Options) error { enable, err := strconv.ParseBool(val) if err != nil { return errors.Wrapf(err, "parsing bool: %s", name) @@ -321,7 +322,7 @@ func verifyGCPAuthAddon(cc *config.ClusterConfig, name, val string) error { } } - if err := verifyAddonStatusInternal(cc, name, val, "gcp-auth"); err != nil { + if err := verifyAddonStatusInternal(cc, name, val, "gcp-auth", options); err != nil { return err } diff --git a/pkg/addons/addons_storage_classes.go b/pkg/addons/addons_storage_classes.go index 4f68527f3618..4e47f35a37f1 100644 --- a/pkg/addons/addons_storage_classes.go +++ b/pkg/addons/addons_storage_classes.go @@ -23,13 +23,14 @@ import ( "k8s.io/klog/v2" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/machine" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/storageclass" ) const defaultStorageClassProvisioner = "standard" // enableOrDisableStorageClasses enables or disables storage classes -func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val string) error { +func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val string, options *run.Options) error { klog.Infof("enableOrDisableStorageClasses %s=%v on %q", name, val, cc.Name) enable, err := strconv.ParseBool(val) if err != nil { @@ -41,7 +42,7 @@ func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val st class = "local-path" } - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return errors.Wrap(err, "machine client") } @@ -54,7 +55,7 @@ func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val st machineName := config.MachineName(*cc, pcp) if !machine.IsRunning(api, machineName) { klog.Warningf("%q is not running, writing %s=%v to disk and skipping enablement", machineName, name, val) - return EnableOrDisableAddon(cc, name, val) + return EnableOrDisableAddon(cc, name, val, options) } storagev1, err := storageclass.GetStoragev1(cc.Name) @@ -64,7 +65,7 @@ func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val st if enable { // Enable addon before marking it as default - if err = EnableOrDisableAddon(cc, name, val); err != nil { + if err = EnableOrDisableAddon(cc, name, val, options); err != nil { return err } // Only StorageClass for 'name' should be marked as default @@ -78,7 +79,7 @@ func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val st if err != nil { return errors.Wrapf(err, "Error disabling %s as the default storage class", class) } - if err = EnableOrDisableAddon(cc, name, val); err != nil { + if err = EnableOrDisableAddon(cc, name, val, options); err != nil { return err } } diff --git a/pkg/addons/addons_test.go b/pkg/addons/addons_test.go index 2b73c8d77ce0..23f791906463 100644 --- a/pkg/addons/addons_test.go +++ b/pkg/addons/addons_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/localpath" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/tests" ) @@ -60,7 +61,7 @@ func TestIsAddonAlreadySet(t *testing.T) { Nodes: []config.Node{{ControlPlane: true}}, } - if err := Set(cc, "registry", "true"); err != nil { + if err := Set(cc, "registry", "true", &run.Options{}); err != nil { t.Errorf("unable to set registry true: %v", err) } if !assets.Addons["registry"].IsEnabled(cc) { @@ -79,7 +80,7 @@ func TestDisableUnknownAddon(t *testing.T) { Nodes: []config.Node{{ControlPlane: true}}, } - if err := Set(cc, "InvalidAddon", "false"); err == nil { + if err := Set(cc, "InvalidAddon", "false", &run.Options{}); err == nil { t.Fatalf("Disable did not return error for unknown addon") } } @@ -90,7 +91,7 @@ func TestEnableUnknownAddon(t *testing.T) { Nodes: []config.Node{{ControlPlane: true}}, } - if err := Set(cc, "InvalidAddon", "true"); err == nil { + if err := Set(cc, "InvalidAddon", "true", &run.Options{}); err == nil { t.Fatalf("Enable did not return error for unknown addon") } } @@ -99,7 +100,7 @@ func TestSetAndSave(t *testing.T) { profile := createTestProfile(t) // enable - if err := SetAndSave(profile, "dashboard", "true"); err != nil { + if err := SetAndSave(profile, "dashboard", "true", &run.Options{}); err != nil { t.Errorf("Disable returned unexpected error: %v", err) } @@ -112,7 +113,7 @@ func TestSetAndSave(t *testing.T) { } // disable - if err := SetAndSave(profile, "dashboard", "false"); err != nil { + if err := SetAndSave(profile, "dashboard", "false", &run.Options{}); err != nil { t.Errorf("Disable returned unexpected error: %v", err) } @@ -136,15 +137,15 @@ func TestStartWithAddonsEnabled(t *testing.T) { KubernetesConfig: config.KubernetesConfig{}, Nodes: []config.Node{{ControlPlane: true}}, } - + options := &run.Options{} toEnable := ToEnable(cc, map[string]bool{}, []string{"dashboard"}) enabled := make(chan []string, 1) var wg sync.WaitGroup wg.Add(1) - go Enable(&wg, cc, toEnable, enabled) + go Enable(&wg, cc, toEnable, enabled, options) wg.Wait() if ea, ok := <-enabled; ok { - UpdateConfigToEnable(cc, ea) + UpdateConfigToEnable(cc, ea, options) } if !assets.Addons["dashboard"].IsEnabled(cc) { @@ -164,7 +165,7 @@ func TestStartWithAllAddonsDisabled(t *testing.T) { Nodes: []config.Node{{ControlPlane: true}}, } - UpdateConfigToDisable(cc) + UpdateConfigToDisable(cc, &run.Options{}) for name := range assets.Addons { if assets.Addons[name].IsEnabled(cc) { diff --git a/pkg/addons/config.go b/pkg/addons/config.go index 104afeef7d10..b8c91bc6b847 100644 --- a/pkg/addons/config.go +++ b/pkg/addons/config.go @@ -18,14 +18,15 @@ package addons import ( "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/run" ) -type setFn func(*config.ClusterConfig, string, string) error +type setFn func(*config.ClusterConfig, string, string, *run.Options) error // Addon represents an addon type Addon struct { name string - set func(*config.ClusterConfig, string, string) error + set func(*config.ClusterConfig, string, string, *run.Options) error validations []setFn callbacks []setFn } diff --git a/pkg/addons/validations.go b/pkg/addons/validations.go index d24424b0d20f..01040fdc7e2c 100644 --- a/pkg/addons/validations.go +++ b/pkg/addons/validations.go @@ -28,6 +28,7 @@ import ( "k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" ) const volumesnapshotsAddon = "volumesnapshots" @@ -48,7 +49,7 @@ const volumesnapshotsDisabledMsg = `[WARNING] For full functionality, the 'csi-h You can enable 'volumesnapshots' addon by running: 'minikube addons enable volumesnapshots' ` -func isRuntimeContainerd(cc *config.ClusterConfig, _, _ string) error { +func isRuntimeContainerd(cc *config.ClusterConfig, _, _ string, _ *run.Options) error { r, err := cruntime.New(cruntime.Config{Type: cc.KubernetesConfig.ContainerRuntime}) if err != nil { return err @@ -62,7 +63,7 @@ func isRuntimeContainerd(cc *config.ClusterConfig, _, _ string) error { // isVolumesnapshotsEnabled is a validator that prints out a warning if the volumesnapshots addon // is disabled (does not return any errors!) -func isVolumesnapshotsEnabled(cc *config.ClusterConfig, _, value string) error { +func isVolumesnapshotsEnabled(cc *config.ClusterConfig, _, value string, _ *run.Options) error { isCsiDriverEnabled, _ := strconv.ParseBool(value) // assets.Addons[].IsEnabled() returns the current status of the addon or default value. // config.AddonList contains list of addons to be enabled. @@ -76,7 +77,7 @@ func isVolumesnapshotsEnabled(cc *config.ClusterConfig, _, value string) error { return nil } -func isKVMDriverForNVIDIA(cc *config.ClusterConfig, name, _ string) error { +func isKVMDriverForNVIDIA(cc *config.ClusterConfig, name, _ string, _ *run.Options) error { if driver.IsKVM(cc.Driver) { return nil } diff --git a/pkg/addons/validations_test.go b/pkg/addons/validations_test.go index 3a8bb216dc71..ee0849e42d63 100644 --- a/pkg/addons/validations_test.go +++ b/pkg/addons/validations_test.go @@ -20,6 +20,7 @@ import ( "testing" "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/run" ) func TestIsAddonValid(t *testing.T) { @@ -63,7 +64,7 @@ func TestIsKVMDriverForNVIDIA(t *testing.T) { } for _, tc := range tests { - err := isKVMDriverForNVIDIA(tc.cc, "", "") + err := isKVMDriverForNVIDIA(tc.cc, "", "", &run.Options{}) if gotError := (err != nil); gotError != tc.wantError { t.Errorf("isKVMDriverForNVIDIA(%v) got error %t (%v), want error %t", tc.cc, gotError, err, tc.wantError) } diff --git a/pkg/drivers/common/common.go b/pkg/drivers/common/common.go index 847eb6679e32..4d3d030d1bc8 100644 --- a/pkg/drivers/common/common.go +++ b/pkg/drivers/common/common.go @@ -35,6 +35,7 @@ import ( "github.com/pkg/errors" "k8s.io/klog/v2" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/util" ) @@ -85,7 +86,12 @@ func CreateRawDisk(diskPath string, sizeMB int) error { } // CommonDriver is the common driver base class -type CommonDriver struct{} +type CommonDriver struct { + // Options keeps the minikube command line options shared with the minikube + // packages. This is initialized when loading the driver and should not be + // persisted. + Options run.Options `json:"-"` +} // GetCreateFlags is not implemented yet func (d *CommonDriver) GetCreateFlags() []mcnflag.Flag { diff --git a/pkg/drivers/common/vmnet/vmnet.go b/pkg/drivers/common/vmnet/vmnet.go index 66190decafcf..4566f3cf1d45 100644 --- a/pkg/drivers/common/vmnet/vmnet.go +++ b/pkg/drivers/common/vmnet/vmnet.go @@ -32,10 +32,10 @@ import ( "github.com/docker/machine/libmachine/log" "github.com/docker/machine/libmachine/state" - "github.com/spf13/viper" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/process" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" ) @@ -71,11 +71,11 @@ type interfaceInfo struct { // ValidateHelper checks if vmnet-helper is installed and we can run it as root. // The returned error.Kind can be used to provide a suggestion for resolving the // issue. -func ValidateHelper() error { +func ValidateHelper(options *run.Options) error { // Ideally minikube will not try to validate in download-only mode, but this // is called from different places in different drivers, so the easier way // to skip validation is to skip it here. - if viper.GetBool("download-only") { + if options.DownloadOnly { log.Debug("Skipping vmnet-helper validation in download-only mode") return nil } @@ -93,7 +93,7 @@ func ValidateHelper() error { stdout, err := cmd.Output() if err != nil { // Can we interact with the user? - if !viper.GetBool("interactive") { + if options.NonInteractive { if exitErr, ok := err.(*exec.ExitError); ok { stderr := strings.TrimSpace(string(exitErr.Stderr)) err = fmt.Errorf("%w: %s", err, stderr) diff --git a/pkg/drivers/common/vmnet/vmnet_stub.go b/pkg/drivers/common/vmnet/vmnet_stub.go index ab94a4d380d6..460b711002ba 100644 --- a/pkg/drivers/common/vmnet/vmnet_stub.go +++ b/pkg/drivers/common/vmnet/vmnet_stub.go @@ -23,8 +23,9 @@ import ( "runtime" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" ) -func ValidateHelper() error { +func ValidateHelper(_ *run.Options) error { return &Error{Kind: reason.Usage, Err: fmt.Errorf("vmnet-helper is not available on %q", runtime.GOOS)} } diff --git a/pkg/drivers/krunkit/krunkit.go b/pkg/drivers/krunkit/krunkit.go index cbbeadb573cb..a48720db71e9 100644 --- a/pkg/drivers/krunkit/krunkit.go +++ b/pkg/drivers/krunkit/krunkit.go @@ -49,6 +49,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/process" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" ) @@ -81,14 +82,16 @@ type Driver struct { var _ drivers.Driver = &Driver{} // NewDriver returns a new krunkit.Driver. -func NewDriver(hostName, storePath string) drivers.Driver { +func NewDriver(hostName, storePath string, options *run.Options) drivers.Driver { return &Driver{ BaseDriver: &drivers.BaseDriver{ SSHUser: defaultSSHUser, MachineName: hostName, StorePath: storePath, }, - CommonDriver: &common.CommonDriver{}, + CommonDriver: &common.CommonDriver{ + Options: *options, + }, } } @@ -302,7 +305,7 @@ func (d *Driver) setupIP(mac string) error { if !isBootpdError(err) { return errors.Wrap(err, "IP address never found in dhcp leases file") } - if unblockErr := firewall.UnblockBootpd(); unblockErr != nil { + if unblockErr := firewall.UnblockBootpd(&d.Options); unblockErr != nil { klog.Errorf("failed unblocking bootpd from firewall: %v", unblockErr) exit.Error(reason.IfBootpdFirewall, "ip not found", err) } diff --git a/pkg/drivers/qemu/qemu.go b/pkg/drivers/qemu/qemu.go index 763a23158442..f70f4ce34849 100644 --- a/pkg/drivers/qemu/qemu.go +++ b/pkg/drivers/qemu/qemu.go @@ -47,6 +47,7 @@ import ( "k8s.io/minikube/pkg/minikube/firewall" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/network" "k8s.io/minikube/pkg/util/retry" @@ -144,7 +145,7 @@ func (d *Driver) GetURL() (string, error) { return fmt.Sprintf("tcp://%s:%d", ip, port), nil } -func NewDriver(hostName, storePath string) drivers.Driver { +func NewDriver(hostName, storePath string, options *run.Options) drivers.Driver { return &Driver{ BIOS: runtime.GOARCH != "arm64", PrivateNetwork: privateNetworkName, @@ -153,6 +154,9 @@ func NewDriver(hostName, storePath string) drivers.Driver { MachineName: hostName, StorePath: storePath, }, + CommonDriver: &common.CommonDriver{ + Options: *options, + }, } } @@ -537,7 +541,7 @@ func (d *Driver) Start() error { if !isBootpdError(err) { return errors.Wrap(err, "IP address never found in dhcp leases file") } - if unblockErr := firewall.UnblockBootpd(); unblockErr != nil { + if unblockErr := firewall.UnblockBootpd(&d.Options); unblockErr != nil { klog.Errorf("failed unblocking bootpd from firewall: %v", unblockErr) exit.Error(reason.IfBootpdFirewall, "ip not found", err) } diff --git a/pkg/drivers/vfkit/vfkit.go b/pkg/drivers/vfkit/vfkit.go index 88fbd96ad006..896c6c69500c 100644 --- a/pkg/drivers/vfkit/vfkit.go +++ b/pkg/drivers/vfkit/vfkit.go @@ -52,6 +52,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/process" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" ) @@ -79,14 +80,16 @@ type Driver struct { VmnetHelper *vmnet.Helper // For network=vmnet-shared } -func NewDriver(hostName, storePath string) drivers.Driver { +func NewDriver(hostName, storePath string, options *run.Options) drivers.Driver { return &Driver{ BaseDriver: &drivers.BaseDriver{ SSHUser: defaultSSHUser, MachineName: hostName, StorePath: storePath, }, - CommonDriver: &common.CommonDriver{}, + CommonDriver: &common.CommonDriver{ + Options: *options, + }, } } @@ -377,7 +380,7 @@ func (d *Driver) setupIP(mac string) error { if !isBootpdError(err) { return errors.Wrap(err, "IP address never found in dhcp leases file") } - if unblockErr := firewall.UnblockBootpd(); unblockErr != nil { + if unblockErr := firewall.UnblockBootpd(&d.Options); unblockErr != nil { klog.Errorf("failed unblocking bootpd from firewall: %v", unblockErr) exit.Error(reason.IfBootpdFirewall, "ip not found", err) } diff --git a/pkg/minikube/bootstrapper/bootstrapper.go b/pkg/minikube/bootstrapper/bootstrapper.go index a51ccc13e631..31eb22d5c626 100644 --- a/pkg/minikube/bootstrapper/bootstrapper.go +++ b/pkg/minikube/bootstrapper/bootstrapper.go @@ -23,6 +23,7 @@ import ( "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/cruntime" + "k8s.io/minikube/pkg/minikube/run" ) // LogOptions are options to be passed to LogCommands @@ -37,7 +38,7 @@ type LogOptions struct { type Bootstrapper interface { // LabelAndUntaintNode applies minikube labels to node and removes NoSchedule taints from control-plane nodes. LabelAndUntaintNode(config.ClusterConfig, config.Node) error - StartCluster(config.ClusterConfig) error + StartCluster(config.ClusterConfig, *run.Options) error UpdateCluster(config.ClusterConfig) error DeleteCluster(config.KubernetesConfig) error WaitForNode(config.ClusterConfig, config.Node, time.Duration) error diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index ce89ee133f2f..35b37835871a 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -61,6 +61,7 @@ import ( "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/out/register" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/sysinit" "k8s.io/minikube/pkg/minikube/vmpath" @@ -171,7 +172,7 @@ func (k *Bootstrapper) clearStaleConfigs(cfg config.ClusterConfig) { } // init initialises primary control-plane using kubeadm. -func (k *Bootstrapper) init(cfg config.ClusterConfig) error { +func (k *Bootstrapper) init(cfg config.ClusterConfig, options *run.Options) error { ver, err := util.ParseKubernetesVersion(cfg.KubernetesConfig.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing Kubernetes version") @@ -291,7 +292,7 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error { wg.Wait() // tunnel apiserver to guest - if err := k.tunnelToAPIServer(cfg); err != nil { + if err := k.tunnelToAPIServer(cfg, options); err != nil { klog.Warningf("apiserver tunnel failed: %v", err) } @@ -395,7 +396,7 @@ func (k *Bootstrapper) unpause(cfg config.ClusterConfig) error { } // StartCluster starts the cluster -func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig) error { +func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig, options *run.Options) error { start := time.Now() klog.Infof("StartCluster: %+v", cfg) defer func() { @@ -409,7 +410,7 @@ func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig) error { if err := bsutil.ExistingConfig(k.c); err == nil { // if the guest already exists and was stopped, re-establish the apiserver tunnel so checks pass - if err := k.tunnelToAPIServer(cfg); err != nil { + if err := k.tunnelToAPIServer(cfg, options); err != nil { klog.Warningf("apiserver tunnel failed: %v", err) } @@ -431,7 +432,7 @@ func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig) error { return errors.Wrap(err, "cp") } - err := k.init(cfg) + err := k.init(cfg, options) if err == nil { return nil } @@ -442,13 +443,13 @@ func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig) error { if err := k.DeleteCluster(cfg.KubernetesConfig); err != nil { klog.Warningf("delete failed: %v", err) } - return k.init(cfg) + return k.init(cfg, options) } return err } // tunnelToAPIServer creates ssh tunnel between apiserver:port inside control-plane node and host on port 8443. -func (k *Bootstrapper) tunnelToAPIServer(cfg config.ClusterConfig) error { +func (k *Bootstrapper) tunnelToAPIServer(cfg config.ClusterConfig, options *run.Options) error { if cfg.APIServerPort == 0 { return fmt.Errorf("apiserver port not set") } @@ -458,7 +459,7 @@ func (k *Bootstrapper) tunnelToAPIServer(cfg config.ClusterConfig) error { return nil } - m, err := machine.NewAPIClient() + m, err := machine.NewAPIClient(options) if err != nil { return errors.Wrapf(err, "create libmachine api client") } diff --git a/pkg/minikube/driver/driver.go b/pkg/minikube/driver/driver.go index 476b85c0c597..3e3c3aa75548 100644 --- a/pkg/minikube/driver/driver.go +++ b/pkg/minikube/driver/driver.go @@ -32,6 +32,7 @@ import ( "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -316,20 +317,20 @@ func FlagDefaults(name string) FlagHints { } // Choices returns a list of drivers which are possible on this system -func Choices(vm bool) []registry.DriverState { - options := registry.Available(vm) +func Choices(vm bool, options *run.Options) []registry.DriverState { + available := registry.Available(vm, options) // Descending priority for predictability and appearance - sort.Slice(options, func(i, j int) bool { - return options[i].Priority > options[j].Priority + sort.Slice(available, func(i, j int) bool { + return available[i].Priority > available[j].Priority }) - return options + return available } // Suggest returns a suggested driver, alternate drivers, and rejected drivers -func Suggest(options []registry.DriverState) (registry.DriverState, []registry.DriverState, []registry.DriverState) { +func Suggest(driversState []registry.DriverState) (registry.DriverState, []registry.DriverState, []registry.DriverState) { pick := registry.DriverState{} - for _, ds := range options { + for _, ds := range driversState { if !ds.State.Installed { continue } @@ -356,7 +357,7 @@ func Suggest(options []registry.DriverState) (registry.DriverState, []registry.D alternates := []registry.DriverState{} rejects := []registry.DriverState{} - for _, ds := range options { + for _, ds := range driversState { if ds != pick { if !ds.State.Installed { ds.Rejection = fmt.Sprintf("Not installed: %v", ds.State.Error) @@ -382,12 +383,12 @@ func Suggest(options []registry.DriverState) (registry.DriverState, []registry.D } // Status returns the status of a driver -func Status(name string) registry.DriverState { +func Status(name string, options *run.Options) registry.DriverState { d := registry.Driver(name) stateChannel := make(chan registry.State) timeoutChannel := time.After(20 * time.Second) go func() { - stateChannel <- registry.Status(name) + stateChannel <- registry.Status(name, options) }() select { case s := <-stateChannel: diff --git a/pkg/minikube/driver/driver_test.go b/pkg/minikube/driver/driver_test.go index 42d7691ed7c0..5fa834be1069 100644 --- a/pkg/minikube/driver/driver_test.go +++ b/pkg/minikube/driver/driver_test.go @@ -24,6 +24,7 @@ import ( "github.com/google/go-cmp/cmp" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) func TestSupportedDrivers(t *testing.T) { @@ -123,7 +124,7 @@ func TestSuggest(t *testing.T) { Name: "unhealthy", Default: true, Priority: registry.Default, - Status: func() registry.State { return registry.State{Installed: true, Healthy: false} }, + Status: func(_ *run.Options) registry.State { return registry.State{Installed: true, Healthy: false} }, }, choices: []string{"unhealthy"}, pick: "", @@ -135,7 +136,7 @@ func TestSuggest(t *testing.T) { Name: "discouraged", Default: false, Priority: registry.Discouraged, - Status: func() registry.State { return registry.State{Installed: true, Healthy: true} }, + Status: func(_ *run.Options) registry.State { return registry.State{Installed: true, Healthy: true} }, }, choices: []string{"discouraged", "unhealthy"}, pick: "", @@ -147,7 +148,7 @@ func TestSuggest(t *testing.T) { Name: "default", Default: true, Priority: registry.Default, - Status: func() registry.State { return registry.State{Installed: true, Healthy: true} }, + Status: func(_ *run.Options) registry.State { return registry.State{Installed: true, Healthy: true} }, }, choices: []string{"default", "discouraged", "unhealthy"}, pick: "default", @@ -159,7 +160,7 @@ func TestSuggest(t *testing.T) { Name: "preferred", Default: true, Priority: registry.Preferred, - Status: func() registry.State { return registry.State{Installed: true, Healthy: true} }, + Status: func(_ *run.Options) registry.State { return registry.State{Installed: true, Healthy: true} }, }, choices: []string{"preferred", "default", "discouraged", "unhealthy"}, pick: "preferred", @@ -175,7 +176,7 @@ func TestSuggest(t *testing.T) { } } - got := Choices(false) + got := Choices(false, &run.Options{}) gotNames := []string{} for _, c := range got { gotNames = append(gotNames, c.Name) diff --git a/pkg/minikube/firewall/firewall.go b/pkg/minikube/firewall/firewall.go index 63ccdfb41449..f80f74dd3f1b 100644 --- a/pkg/minikube/firewall/firewall.go +++ b/pkg/minikube/firewall/firewall.go @@ -24,11 +24,11 @@ import ( "slices" "strings" - "github.com/spf13/viper" "k8s.io/klog/v2" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" ) @@ -63,7 +63,7 @@ func IsBootpdBlocked(cc config.ClusterConfig) bool { } // UnblockBootpd adds bootpd to the built-in macOS firewall and then unblocks it -func UnblockBootpd() error { +func UnblockBootpd(options *run.Options) error { cmds := []*exec.Cmd{ exec.Command("sudo", "/usr/libexec/ApplicationFirewall/socketfilterfw", "--add", "/usr/libexec/bootpd"), exec.Command("sudo", "/usr/libexec/ApplicationFirewall/socketfilterfw", "--unblock", "/usr/libexec/bootpd"), @@ -82,7 +82,7 @@ func UnblockBootpd() error { klog.Infof("testing: %s", test.Args) if err := test.Run(); err != nil { klog.Infof("%v may require a password: %v", c.Args, err) - if !viper.GetBool("interactive") { + if !options.NonInteractive { klog.Warningf("%s requires a password, and --interactive=false", c.Args) c.Args = slices.Insert(c.Args, 1, "-n") } diff --git a/pkg/minikube/machine/build_images.go b/pkg/minikube/machine/build_images.go index 5366c2e710bc..d83f4feacb68 100644 --- a/pkg/minikube/machine/build_images.go +++ b/pkg/minikube/machine/build_images.go @@ -35,6 +35,7 @@ import ( "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/localpath" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/vmpath" ) @@ -42,8 +43,8 @@ import ( var buildRoot = path.Join(vmpath.GuestPersistentDir, "build") // BuildImage builds image to all profiles -func BuildImage(srcPath string, file string, tag string, push bool, env []string, opt []string, profiles []*config.Profile, allNodes bool, nodeName string) error { - api, err := NewAPIClient() +func BuildImage(srcPath string, file string, tag string, push bool, env []string, opt []string, profiles []*config.Profile, allNodes bool, nodeName string, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "api") } diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index f09d1a2c151e..35e57bbec1d0 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -47,6 +47,7 @@ import ( "k8s.io/minikube/pkg/minikube/image" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/vmpath" ) @@ -187,7 +188,7 @@ func LoadLocalImages(cc *config.ClusterConfig, runner command.Runner, images []s } // CacheAndLoadImages caches and loads images to all profiles -func CacheAndLoadImages(images []string, profiles []*config.Profile, overwrite bool) error { +func CacheAndLoadImages(images []string, profiles []*config.Profile, overwrite bool, options *run.Options) error { if len(images) == 0 { return nil } @@ -197,12 +198,12 @@ func CacheAndLoadImages(images []string, profiles []*config.Profile, overwrite b return errors.Wrap(err, "save to dir") } - return DoLoadImages(images, profiles, detect.ImageCacheDir(), overwrite) + return DoLoadImages(images, profiles, detect.ImageCacheDir(), overwrite, options) } // DoLoadImages loads images to all profiles -func DoLoadImages(images []string, profiles []*config.Profile, cacheDir string, overwrite bool) error { - api, err := NewAPIClient() +func DoLoadImages(images []string, profiles []*config.Profile, cacheDir string, overwrite bool, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "api") } @@ -384,17 +385,17 @@ func SaveLocalImages(cc *config.ClusterConfig, runner command.Runner, images []s } // SaveAndCacheImages saves images from all profiles into the cache -func SaveAndCacheImages(images []string, profiles []*config.Profile) error { +func SaveAndCacheImages(images []string, profiles []*config.Profile, options *run.Options) error { if len(images) == 0 { return nil } - return DoSaveImages(images, "", profiles, detect.ImageCacheDir()) + return DoSaveImages(images, "", profiles, detect.ImageCacheDir(), options) } // DoSaveImages saves images from all profiles -func DoSaveImages(images []string, output string, profiles []*config.Profile, cacheDir string) error { - api, err := NewAPIClient() +func DoSaveImages(images []string, output string, profiles []*config.Profile, cacheDir string, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "api") } @@ -552,8 +553,8 @@ func pullImages(crMgr cruntime.Manager, imgs []string) error { } // PullImages pulls images to all nodes in profile -func PullImages(images []string, profile *config.Profile) error { - api, err := NewAPIClient() +func PullImages(images []string, profile *config.Profile, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "error creating api client") } @@ -633,8 +634,8 @@ func removeImages(crMgr cruntime.Manager, imgs []string) error { } // RemoveImages removes images from all nodes in profile -func RemoveImages(images []string, profile *config.Profile) error { - api, err := NewAPIClient() +func RemoveImages(images []string, profile *config.Profile, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "error creating api client") } @@ -691,8 +692,8 @@ func RemoveImages(images []string, profile *config.Profile) error { } // ListImages lists images on all nodes in profile -func ListImages(profile *config.Profile, format string) error { - api, err := NewAPIClient() +func ListImages(profile *config.Profile, format string, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "error creating api client") } @@ -860,8 +861,8 @@ func renderImagesTable(images [][]string) { } // TagImage tags image in all nodes in profile -func TagImage(profile *config.Profile, source string, target string) error { - api, err := NewAPIClient() +func TagImage(profile *config.Profile, source string, target string, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "error creating api client") } @@ -941,8 +942,8 @@ func pushImages(crMgr cruntime.Manager, imgs []string) error { } // PushImages push images on all nodes in profile -func PushImages(images []string, profile *config.Profile) error { - api, err := NewAPIClient() +func PushImages(images []string, profile *config.Profile, options *run.Options) error { + api, err := NewAPIClient(options) if err != nil { return errors.Wrap(err, "error creating api client") } diff --git a/pkg/minikube/machine/client.go b/pkg/minikube/machine/client.go index 67f370f649e9..491d733c0c62 100644 --- a/pkg/minikube/machine/client.go +++ b/pkg/minikube/machine/client.go @@ -50,6 +50,7 @@ import ( "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) // NewRPCClient gets a new client. @@ -60,7 +61,7 @@ func NewRPCClient(storePath, certsDir string) libmachine.API { } // NewAPIClient gets a new client. -func NewAPIClient(miniHome ...string) (libmachine.API, error) { +func NewAPIClient(options *run.Options, miniHome ...string) (libmachine.API, error) { storePath := localpath.MiniPath() if len(miniHome) > 0 { storePath = miniHome[0] @@ -73,6 +74,7 @@ func NewAPIClient(miniHome ...string) (libmachine.API, error) { Filestore: persist.NewFilestore(storePath, certsDir, certsDir), legacyClient: NewRPCClient(storePath, certsDir), flock: fslock.New(localpath.MakeMiniPath("machine_client.lock")), + options: options, }, nil } @@ -84,6 +86,7 @@ type LocalClient struct { *persist.Filestore legacyClient libmachine.API flock *fslock.Lock + options *run.Options } // NewHost creates a new Host @@ -95,7 +98,7 @@ func (api *LocalClient) NewHost(drvName string, rawDriver []byte) (*host.Host, e if def.Init == nil { return api.legacyClient.NewHost(drvName, rawDriver) } - d := def.Init() + d := def.Init(api.options) err := json.Unmarshal(rawDriver, d) if err != nil { return nil, errors.Wrapf(err, "Error getting driver %s", string(rawDriver)) @@ -139,7 +142,7 @@ func (api *LocalClient) Load(name string) (*host.Host, error) { if def.Init == nil { return api.legacyClient.Load(name) } - h.Driver = def.Init() + h.Driver = def.Init(api.options) return h, json.Unmarshal(h.RawDriver, h.Driver) } @@ -248,11 +251,11 @@ func (api *LocalClient) Create(h *host.Host) error { } // StartDriver starts the driver -func StartDriver() { +func StartDriver(options *run.Options) { cert.SetCertGenerator(&CertGenerator{}) check.DefaultConnChecker = &ConnChecker{} if os.Getenv(localbinary.PluginEnvKey) == localbinary.PluginEnvVal { - registerDriver(os.Getenv(localbinary.PluginEnvDriverName)) + registerDriver(os.Getenv(localbinary.PluginEnvDriverName), options) } localbinary.CurrentBinaryIsDockerMachine = true @@ -296,10 +299,10 @@ func (cg *CertGenerator) ValidateCertificate(addr string, authOptions *auth.Opti return true, nil } -func registerDriver(drvName string) { +func registerDriver(drvName string, options *run.Options) { def := registry.Driver(drvName) if def.Empty() { exit.Message(reason.Usage, "unsupported or missing driver: {{.name}}", out.V{"name": drvName}) } - plugin.RegisterDriver(def.Init()) + plugin.RegisterDriver(def.Init(options)) } diff --git a/pkg/minikube/machine/client_test.go b/pkg/minikube/machine/client_test.go index 7ddd379babe2..253ae8559e6b 100644 --- a/pkg/minikube/machine/client_test.go +++ b/pkg/minikube/machine/client_test.go @@ -27,6 +27,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" _ "k8s.io/minikube/pkg/minikube/registry/drvs/virtualbox" + "k8s.io/minikube/pkg/minikube/run" testutil "k8s.io/minikube/pkg/minikube/tests" ) @@ -62,7 +63,7 @@ const vboxConfig = ` ` func TestLocalClientNewHost(t *testing.T) { - c, err := NewAPIClient() + c, err := NewAPIClient(&run.Options{}) if err != nil { t.Fatal(err) } @@ -112,7 +113,7 @@ func TestLocalClientNewHost(t *testing.T) { func TestRunNotDriver(t *testing.T) { testutil.MakeTempDir(t) - StartDriver() + StartDriver(&run.Options{}) if !localbinary.CurrentBinaryIsDockerMachine { t.Fatal("CurrentBinaryIsDockerMachine not set. This will break driver initialization.") } @@ -135,7 +136,7 @@ func TestRunDriver(t *testing.T) { }() // Run the command asynchronously. It should listen on a port for connections. - go StartDriver() + go StartDriver(&run.Options{}) // The command will write out what port it's listening on over stdout. reader := bufio.NewReader(r) diff --git a/pkg/minikube/machine/cluster_test.go b/pkg/minikube/machine/cluster_test.go index a4cb3347c906..34cc2904f438 100644 --- a/pkg/minikube/machine/cluster_test.go +++ b/pkg/minikube/machine/cluster_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/download" _ "k8s.io/minikube/pkg/minikube/registry/drvs/virtualbox" + "k8s.io/minikube/pkg/minikube/run" "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/host" @@ -57,7 +58,7 @@ func RegisterMockDriver(t *testing.T) { err := registry.Register(registry.DriverDef{ Name: driver.Mock, Config: createMockDriverHost, - Init: func() drivers.Driver { return &tests.MockDriver{T: t} }, + Init: func(_ *run.Options) drivers.Driver { return &tests.MockDriver{T: t} }, }) if err != nil { t.Fatalf("register failed: %v", err) diff --git a/pkg/minikube/machine/machine.go b/pkg/minikube/machine/machine.go index 62a24d4bae65..e6594523750c 100644 --- a/pkg/minikube/machine/machine.go +++ b/pkg/minikube/machine/machine.go @@ -29,6 +29,7 @@ import ( "k8s.io/klog/v2" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/driver" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/vmpath" "k8s.io/minikube/pkg/provision" "k8s.io/minikube/pkg/util/retry" @@ -68,8 +69,8 @@ func (h *Machine) IsValid() bool { } // LoadMachine returns a Machine abstracting a libmachine.Host -func LoadMachine(name string) (*Machine, error) { - api, err := NewAPIClient() +func LoadMachine(name string, options *run.Options) (*Machine, error) { + api, err := NewAPIClient(options) if err != nil { return nil, err } diff --git a/pkg/minikube/mustload/mustload.go b/pkg/minikube/mustload/mustload.go index 7d61b81e6da2..eed1e1b3123c 100644 --- a/pkg/minikube/mustload/mustload.go +++ b/pkg/minikube/mustload/mustload.go @@ -34,6 +34,7 @@ import ( "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" ) @@ -61,9 +62,9 @@ type ControlPlane struct { } // Partial is a cmd-friendly way to load a cluster which may or may not be running -func Partial(name string, miniHome ...string) (libmachine.API, *config.ClusterConfig) { +func Partial(name string, options *run.Options, miniHome ...string) (libmachine.API, *config.ClusterConfig) { klog.Infof("Loading cluster: %s", name) - api, err := machine.NewAPIClient(miniHome...) + api, err := machine.NewAPIClient(options, miniHome...) if err != nil { exit.Error(reason.NewAPIClient, "libmachine failed", err) } @@ -81,16 +82,16 @@ func Partial(name string, miniHome ...string) (libmachine.API, *config.ClusterCo } // Running is a cmd-friendly way to load a running cluster. -func Running(name string) ClusterController { - if r := running(name, true); r != nil { +func Running(name string, options *run.Options) ClusterController { + if r := running(name, true, options); r != nil { return r[0] } return ClusterController{} } // running returns first or all running ClusterControllers found or exits with specific error if none found. -func running(name string, first bool) []ClusterController { - api, cc := Partial(name) +func running(name string, first bool, options *run.Options) []ClusterController { + api, cc := Partial(name, options) cps := config.ControlPlanes(*cc) if len(cps) == 0 { @@ -179,8 +180,8 @@ func running(name string, first bool) []ClusterController { } // Healthy is a cmd-friendly way to load a healthy cluster. -func Healthy(name string) ClusterController { - ctrls := running(name, false) +func Healthy(name string, options *run.Options) ClusterController { + ctrls := running(name, false, options) for i, ctrl := range ctrls { // control flow depending on if we have any other cluster controllers to try in case of an error diff --git a/pkg/minikube/mustload/mustload_test.go b/pkg/minikube/mustload/mustload_test.go index 5e692239ba4d..2b2762bb31ea 100644 --- a/pkg/minikube/mustload/mustload_test.go +++ b/pkg/minikube/mustload/mustload_test.go @@ -19,12 +19,14 @@ package mustload import ( "path/filepath" "testing" + + "k8s.io/minikube/pkg/minikube/run" ) func TestPartial(t *testing.T) { path := filepath.Join("..", "config", "testdata", "profile", ".minikube") name := "p1" - api, cc := Partial(name, path) + api, cc := Partial(name, &run.Options{}, path) if cc.Name != name { t.Fatalf("cc.Name expected to be same as name(%s), but got %s", name, cc.Name) diff --git a/pkg/minikube/node/cache.go b/pkg/minikube/node/cache.go index 72f03fe18d0c..1567fc95218f 100644 --- a/pkg/minikube/node/cache.go +++ b/pkg/minikube/node/cache.go @@ -26,6 +26,7 @@ import ( "strings" "k8s.io/minikube/pkg/minikube/detect" + "k8s.io/minikube/pkg/minikube/run" "github.com/pkg/errors" "github.com/spf13/viper" @@ -74,9 +75,9 @@ func beginCacheKubernetesImages(g *errgroup.Group, imageRepository string, k8sVe } // handleDownloadOnly caches appropariate binaries and images -func handleDownloadOnly(cacheGroup, kicGroup *errgroup.Group, k8sVersion, containerRuntime, driverName string) { +func handleDownloadOnly(cacheGroup, kicGroup *errgroup.Group, k8sVersion, containerRuntime, driverName string, options *run.Options) { // If --download-only, complete the remaining downloads and exit. - if !viper.GetBool("download-only") { + if !options.DownloadOnly { return } @@ -217,7 +218,7 @@ func waitDownloadKicBaseImage(g *errgroup.Group) { klog.Warningf("Error downloading kic artifacts: %v", err) out.ErrT(style.Connectivity, "Unfortunately, could not download the base image {{.image_name}} ", out.V{"image_name": image.Tag(kic.BaseImage)}) out.WarningT("In order to use the fall back image, you need to log in to the github packages registry") - out.Styled(style.Documentation, `Please visit the following link for documentation around this: + out.Styled(style.Documentation, `Please visit the following link for documentation around this: https://help.github.com/en/packages/using-github-packages-with-your-projects-ecosystem/configuring-docker-for-use-with-github-packages#authenticating-to-github-packages `) } @@ -257,7 +258,7 @@ func saveImagesToTarFromConfig() error { // CacheAndLoadImagesInConfig loads the images currently in the config file // called by 'start' and 'cache reload' commands. -func CacheAndLoadImagesInConfig(profiles []*config.Profile) error { +func CacheAndLoadImagesInConfig(profiles []*config.Profile, options *run.Options) error { images, err := imagesInConfigFile() if err != nil { return errors.Wrap(err, "images") @@ -265,7 +266,7 @@ func CacheAndLoadImagesInConfig(profiles []*config.Profile) error { if len(images) == 0 { return nil } - return machine.CacheAndLoadImages(images, profiles, false) + return machine.CacheAndLoadImages(images, profiles, false, options) } func imagesInConfigFile() ([]string, error) { diff --git a/pkg/minikube/node/node.go b/pkg/minikube/node/node.go index 93e62747995e..725a30a69df0 100644 --- a/pkg/minikube/node/node.go +++ b/pkg/minikube/node/node.go @@ -36,13 +36,14 @@ import ( "k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/mustload" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/util/retry" kconst "k8s.io/minikube/third_party/kubeadm/app/constants" ) // Add adds a new node config to an existing cluster. -func Add(cc *config.ClusterConfig, n config.Node, delOnFail bool) error { +func Add(cc *config.ClusterConfig, n config.Node, delOnFail bool, options *run.Options) error { profiles, err := config.ListValidProfiles() if err != nil { return err @@ -69,7 +70,7 @@ func Add(cc *config.ClusterConfig, n config.Node, delOnFail bool) error { return errors.Wrap(err, "save node") } - r, p, m, h, err := Provision(cc, &n, delOnFail) + r, p, m, h, err := Provision(cc, &n, delOnFail, options) if err != nil { return err } @@ -83,13 +84,13 @@ func Add(cc *config.ClusterConfig, n config.Node, delOnFail bool) error { ExistingAddons: nil, } - _, err = Start(s) + _, err = Start(s, options) return err } // teardown drains, then resets and finally deletes node from cluster. // ref: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#tear-down -func teardown(cc config.ClusterConfig, name string) (*config.Node, error) { +func teardown(cc config.ClusterConfig, name string, options *run.Options) (*config.Node, error) { // get runner for named node - has to be done before node is drained n, _, err := Retrieve(cc, name) if err != nil { @@ -97,7 +98,7 @@ func teardown(cc config.ClusterConfig, name string) (*config.Node, error) { } m := config.MachineName(cc, *n) - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return n, errors.Wrap(err, "get api client") } @@ -113,7 +114,7 @@ func teardown(cc config.ClusterConfig, name string) (*config.Node, error) { } // get runner for healthy control-plane node - cpr := mustload.Healthy(cc.Name).CP.Runner + cpr := mustload.Healthy(cc.Name, options).CP.Runner kubectl := kapi.KubectlBinaryPath(cc.KubernetesConfig.KubernetesVersion) @@ -183,14 +184,14 @@ func teardown(cc config.ClusterConfig, name string) (*config.Node, error) { } // Delete calls teardownNode to remove node from cluster and deletes the host. -func Delete(cc config.ClusterConfig, name string) (*config.Node, error) { - n, err := teardown(cc, name) +func Delete(cc config.ClusterConfig, name string, options *run.Options) (*config.Node, error) { + n, err := teardown(cc, name, options) if err != nil { return n, err } m := config.MachineName(cc, *n) - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return n, err } diff --git a/pkg/minikube/node/start.go b/pkg/minikube/node/start.go index f533a6b0585b..5b01f60c2927 100755 --- a/pkg/minikube/node/start.go +++ b/pkg/minikube/node/start.go @@ -64,6 +64,7 @@ import ( "k8s.io/minikube/pkg/minikube/proxy" "k8s.io/minikube/pkg/minikube/reason" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/vmpath" "k8s.io/minikube/pkg/network" @@ -92,7 +93,7 @@ type Starter struct { } // Start spins up a guest and starts the Kubernetes node. -func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo +func Start(starter Starter, options *run.Options) (*kubeconfig.Settings, error) { // nolint:gocyclo var wg sync.WaitGroup stopk8s, err := handleNoKubernetes(starter) if err != nil { @@ -138,7 +139,7 @@ func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo var bs bootstrapper.Bootstrapper if config.IsPrimaryControlPlane(*starter.Cfg, *starter.Node) { // [re]start primary control-plane node - kcs, bs, err = startPrimaryControlPlane(starter, cr) + kcs, bs, err = startPrimaryControlPlane(starter, cr, options) if err != nil { return nil, err } @@ -169,7 +170,7 @@ func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo } // for ha (multi-control plane) cluster, use already running control-plane node to copy over certs to this secondary control-plane node - cpr := mustload.Running(starter.Cfg.Name).CP.Runner + cpr := mustload.Running(starter.Cfg.Name, options).CP.Runner if err = bs.SetupCerts(*starter.Cfg, *starter.Node, cpr); err != nil { return nil, errors.Wrap(err, "setting up certs") } @@ -186,7 +187,7 @@ func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo if err != nil { return nil, errors.Wrap(err, "get primary control-plane bootstrapper") } - if err := joinCluster(starter, pcpBs, bs); err != nil { + if err := joinCluster(starter, pcpBs, bs, options); err != nil { return nil, errors.Wrap(err, "join node to cluster") } } @@ -201,7 +202,7 @@ func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo if err != nil { out.FailureT("Unable to load profile: {{.error}}", out.V{"error": err}) } - if err := CacheAndLoadImagesInConfig([]*config.Profile{profile}); err != nil { + if err := CacheAndLoadImagesInConfig([]*config.Profile{profile}, options); err != nil { out.FailureT("Unable to push cached images: {{.error}}", out.V{"error": err}) } }() @@ -215,12 +216,12 @@ func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo } list := addons.ToEnable(starter.Cfg, starter.ExistingAddons, addonList) wg.Add(1) - go addons.Enable(&wg, starter.Cfg, list, enabledAddons) + go addons.Enable(&wg, starter.Cfg, list, enabledAddons, options) } // discourage use of the virtualbox driver if starter.Cfg.Driver == driver.VirtualBox && viper.GetBool(config.WantVirtualBoxDriverWarning) { - warnVirtualBox() + warnVirtualBox(options) } // special ops for "none" driver on control-plane node, like change minikube directory @@ -245,10 +246,10 @@ func Start(starter Starter) (*kubeconfig.Settings, error) { // nolint:gocyclo if starter.ExistingAddons != nil { klog.Infof("waiting for cluster config update ...") if ea, ok := <-enabledAddons; ok { - addons.UpdateConfigToEnable(starter.Cfg, ea) + addons.UpdateConfigToEnable(starter.Cfg, ea, options) } } else { - addons.UpdateConfigToDisable(starter.Cfg) + addons.UpdateConfigToDisable(starter.Cfg, options) } // Write enabled addons to the config before completion @@ -274,7 +275,7 @@ func handleNoKubernetes(starter Starter) (bool, error) { } // startPrimaryControlPlane starts control-plane node. -func startPrimaryControlPlane(starter Starter, cr cruntime.Manager) (*kubeconfig.Settings, bootstrapper.Bootstrapper, error) { +func startPrimaryControlPlane(starter Starter, cr cruntime.Manager, options *run.Options) (*kubeconfig.Settings, bootstrapper.Bootstrapper, error) { if !config.IsPrimaryControlPlane(*starter.Cfg, *starter.Node) { return nil, nil, fmt.Errorf("node not marked as primary control-plane") } @@ -297,7 +298,7 @@ func startPrimaryControlPlane(starter Starter, cr cruntime.Manager) (*kubeconfig return nil, nil, errors.Wrap(err, "Failed to setup kubeadm") } - if err := bs.StartCluster(*starter.Cfg); err != nil { + if err := bs.StartCluster(*starter.Cfg, options); err != nil { ExitIfFatal(err, false) out.LogEntries("Error starting cluster", err, logs.FindProblems(cr, bs, *starter.Cfg, starter.Runner)) return nil, bs, err @@ -312,7 +313,7 @@ func startPrimaryControlPlane(starter Starter, cr cruntime.Manager) (*kubeconfig } // joinCluster adds new or prepares and then adds existing node to the cluster. -func joinCluster(starter Starter, cpBs bootstrapper.Bootstrapper, bs bootstrapper.Bootstrapper) error { +func joinCluster(starter Starter, cpBs bootstrapper.Bootstrapper, bs bootstrapper.Bootstrapper, options *run.Options) error { start := time.Now() klog.Infof("joinCluster: %+v", starter.Cfg) defer func() { @@ -328,7 +329,7 @@ func joinCluster(starter Starter, cpBs bootstrapper.Bootstrapper, bs bootstrappe // You must delete the existing Node or change the name of this new joining Node" if starter.PreExists { klog.Infof("removing existing %s node %q before attempting to rejoin cluster: %+v", role, starter.Node.Name, starter.Node) - if _, err := teardown(*starter.Cfg, starter.Node.Name); err != nil { + if _, err := teardown(*starter.Cfg, starter.Node.Name, options); err != nil { klog.Errorf("error removing existing %s node %q before rejoining cluster, will continue anyway: %v", role, starter.Node.Name, err) } klog.Infof("successfully removed existing %s node %q from cluster: %+v", role, starter.Node.Name, starter.Node) @@ -367,7 +368,7 @@ func joinCluster(starter Starter, cpBs bootstrapper.Bootstrapper, bs bootstrappe } // Provision provisions the machine/container for the node -func Provision(cc *config.ClusterConfig, n *config.Node, delOnFail bool) (command.Runner, bool, libmachine.API, *host.Host, error) { +func Provision(cc *config.ClusterConfig, n *config.Node, delOnFail bool, options *run.Options) (command.Runner, bool, libmachine.API, *host.Host, error) { register.Reg.SetStep(register.StartingNode) name := config.MachineName(*cc, *n) @@ -386,7 +387,7 @@ func Provision(cc *config.ClusterConfig, n *config.Node, delOnFail bool) (comman } if driver.IsKIC(cc.Driver) { - beginDownloadKicBaseImage(&kicGroup, cc, viper.GetBool("download-only")) + beginDownloadKicBaseImage(&kicGroup, cc, options.DownloadOnly) } if !driver.BareMetal(cc.Driver) { @@ -399,12 +400,12 @@ func Provision(cc *config.ClusterConfig, n *config.Node, delOnFail bool) (comman return nil, false, nil, nil, errors.Wrap(err, "Failed to save config") } - handleDownloadOnly(&cacheGroup, &kicGroup, n.KubernetesVersion, cc.KubernetesConfig.ContainerRuntime, cc.Driver) + handleDownloadOnly(&cacheGroup, &kicGroup, n.KubernetesVersion, cc.KubernetesConfig.ContainerRuntime, cc.Driver, options) if driver.IsKIC(cc.Driver) { waitDownloadKicBaseImage(&kicGroup) } - return startMachine(cc, n, delOnFail) + return startMachine(cc, n, delOnFail, options) } // ConfigureRuntimes does what needs to happen to get a runtime going. @@ -654,8 +655,8 @@ func setupKubeconfig(h host.Host, cc config.ClusterConfig, n config.Node, cluste } // StartMachine starts a VM -func startMachine(cfg *config.ClusterConfig, node *config.Node, delOnFail bool) (runner command.Runner, preExists bool, machineAPI libmachine.API, hostInfo *host.Host, err error) { - m, err := machine.NewAPIClient() +func startMachine(cfg *config.ClusterConfig, node *config.Node, delOnFail bool, options *run.Options) (runner command.Runner, preExists bool, machineAPI libmachine.API, hostInfo *host.Host, err error) { + m, err := machine.NewAPIClient(options) if err != nil { return runner, preExists, m, hostInfo, errors.Wrap(err, "Failed to get machine client") } @@ -979,9 +980,9 @@ func addCoreDNSEntry(runner command.Runner, name, ip string, cc config.ClusterCo } // prints a warning to the console against the use of the 'virtualbox' driver, if alternatives are available and healthy -func warnVirtualBox() { +func warnVirtualBox(options *run.Options) { var altDriverList strings.Builder - for _, choice := range driver.Choices(true) { + for _, choice := range driver.Choices(true, options) { if !driver.IsVirtualBox(choice.Name) && choice.Priority != registry.Discouraged && choice.State.Installed && choice.State.Healthy { altDriverList.WriteString(fmt.Sprintf("\n\t- %s", choice.Name)) } diff --git a/pkg/minikube/notify/notify.go b/pkg/minikube/notify/notify.go index 489137bbe08e..8306fe7f6c86 100644 --- a/pkg/minikube/notify/notify.go +++ b/pkg/minikube/notify/notify.go @@ -33,6 +33,7 @@ import ( "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/util/lock" "k8s.io/minikube/pkg/version" @@ -44,22 +45,22 @@ var ( ) // MaybePrintUpdateTextFromGithub prints update text if needed, from github -func MaybePrintUpdateTextFromGithub() { - maybePrintUpdateText(GithubMinikubeReleasesURL, GithubMinikubeBetaReleasesURL, lastUpdateCheckFilePath) +func MaybePrintUpdateTextFromGithub(options *run.Options) { + maybePrintUpdateText(GithubMinikubeReleasesURL, GithubMinikubeBetaReleasesURL, lastUpdateCheckFilePath, options) } // MaybePrintUpdateTextFromAliyunMirror prints update text if needed, from Aliyun mirror -func MaybePrintUpdateTextFromAliyunMirror() { - maybePrintUpdateText(GithubMinikubeReleasesAliyunURL, GithubMinikubeBetaReleasesAliyunURL, lastUpdateCheckFilePath) +func MaybePrintUpdateTextFromAliyunMirror(options *run.Options) { + maybePrintUpdateText(GithubMinikubeReleasesAliyunURL, GithubMinikubeBetaReleasesAliyunURL, lastUpdateCheckFilePath, options) } -func maybePrintUpdateText(latestReleasesURL string, betaReleasesURL string, lastUpdatePath string) { +func maybePrintUpdateText(latestReleasesURL string, betaReleasesURL string, lastUpdatePath string, options *run.Options) { latestVersion, err := latestVersionFromURL(latestReleasesURL) if err != nil { klog.Warning(err) return } - if !shouldCheckURLVersion(lastUpdatePath) { + if !shouldCheckURLVersion(lastUpdatePath, options) { return } localVersion, err := version.GetSemverVersion() @@ -67,7 +68,7 @@ func maybePrintUpdateText(latestReleasesURL string, betaReleasesURL string, last klog.Warning(err) return } - if maybePrintBetaUpdateText(betaReleasesURL, localVersion, latestVersion, lastUpdatePath) { + if maybePrintBetaUpdateText(betaReleasesURL, localVersion, latestVersion, lastUpdatePath, options) { return } if localVersion.Compare(latestVersion) >= 0 { @@ -77,8 +78,8 @@ func maybePrintUpdateText(latestReleasesURL string, betaReleasesURL string, last } // maybePrintBetaUpdateText returns true if update text is printed -func maybePrintBetaUpdateText(betaReleasesURL string, localVersion semver.Version, latestFullVersion semver.Version, lastUpdatePath string) bool { - if !shouldCheckURLBetaVersion(lastUpdatePath) { +func maybePrintBetaUpdateText(betaReleasesURL string, localVersion semver.Version, latestFullVersion semver.Version, lastUpdatePath string, options *run.Options) bool { + if !shouldCheckURLBetaVersion(lastUpdatePath, options) { return false } latestBetaVersion, err := latestVersionFromURL(betaReleasesURL) @@ -115,11 +116,11 @@ func printBetaUpdateText(ver semver.Version) { out.Styled(style.Tip, "To disable update notices in general, run: 'minikube config set WantUpdateNotification false'\n") } -func shouldCheckURLVersion(filePath string) bool { +func shouldCheckURLVersion(filePath string, options *run.Options) bool { if !viper.GetBool(config.WantUpdateNotification) { return false } - if !viper.GetBool("interactive") { + if options.NonInteractive { return false } if out.JSON { @@ -129,12 +130,12 @@ func shouldCheckURLVersion(filePath string) bool { return time.Since(lastUpdateTime).Hours() >= viper.GetFloat64(config.ReminderWaitPeriodInHours) } -func shouldCheckURLBetaVersion(filePath string) bool { +func shouldCheckURLBetaVersion(filePath string, options *run.Options) bool { if !viper.GetBool(config.WantBetaUpdateNotification) { return false } - return shouldCheckURLVersion(filePath) + return shouldCheckURLVersion(filePath, options) } type operatingSystems struct { diff --git a/pkg/minikube/notify/notify_test.go b/pkg/minikube/notify/notify_test.go index 72ecca3f6116..3a287dd54d74 100644 --- a/pkg/minikube/notify/notify_test.go +++ b/pkg/minikube/notify/notify_test.go @@ -31,25 +31,25 @@ import ( "github.com/spf13/viper" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/tests" "k8s.io/minikube/pkg/version" ) func TestShouldCheckURLVersion(t *testing.T) { - viper.Set("interactive", true) tempDir := tests.MakeTempDir(t) lastUpdateCheckFilePath := filepath.Join(tempDir, "last_update_check") // test that if users disable update notification in config, the URL version does not get checked viper.Set(config.WantUpdateNotification, false) - if shouldCheckURLVersion(lastUpdateCheckFilePath) { + if shouldCheckURLVersion(lastUpdateCheckFilePath, &run.Options{}) { t.Fatalf("shouldCheckURLVersion returned true even though config had WantUpdateNotification: false") } // test that if users want update notification, the URL version does get checked viper.Set(config.WantUpdateNotification, true) - if !shouldCheckURLVersion(lastUpdateCheckFilePath) { + if !shouldCheckURLVersion(lastUpdateCheckFilePath, &run.Options{}) { t.Fatalf("shouldCheckURLVersion returned false even though there was no last_update_check file") } @@ -60,7 +60,7 @@ func TestShouldCheckURLVersion(t *testing.T) { if err := writeTimeToFile(lastUpdateCheckFilePath, time.Time{}); err != nil { t.Errorf("write failed: %v", err) } - if !shouldCheckURLVersion(lastUpdateCheckFilePath) { + if !shouldCheckURLVersion(lastUpdateCheckFilePath, &run.Options{}) { t.Fatalf("shouldCheckURLVersion returned false even though longer than 24 hours since last update") } @@ -68,7 +68,7 @@ func TestShouldCheckURLVersion(t *testing.T) { if err := writeTimeToFile(lastUpdateCheckFilePath, time.Now().UTC()); err != nil { t.Errorf("write failed: %v", err) } - if shouldCheckURLVersion(lastUpdateCheckFilePath) { + if shouldCheckURLVersion(lastUpdateCheckFilePath, &run.Options{}) { t.Fatalf("shouldCheckURLVersion returned true even though less than 24 hours since last update") } @@ -83,13 +83,13 @@ func TestShouldCheckURLBetaVersion(t *testing.T) { // test if the user disables beta update notification in config, the URL version does not get checked viper.Set(config.WantBetaUpdateNotification, false) - if shouldCheckURLBetaVersion(lastUpdateCheckFilePath) { + if shouldCheckURLBetaVersion(lastUpdateCheckFilePath, &run.Options{}) { t.Fatalf("shouldCheckURLBetaVersion returned true even though config had WantBetaUpdateNotification: false") } // test if the user enables beta update notification in config, the URL version does get checked viper.Set(config.WantBetaUpdateNotification, true) - if !shouldCheckURLBetaVersion(lastUpdateCheckFilePath) { + if !shouldCheckURLBetaVersion(lastUpdateCheckFilePath, &run.Options{}) { t.Fatalf("shouldCheckURLBetaVersion returned false even though config had WantBetaUpdateNotification: true") } } @@ -227,7 +227,7 @@ func TestMaybePrintUpdateText(t *testing.T) { } defer os.Remove(tmpfile.Name()) - maybePrintUpdateText(tt.latestFullVersionFromURL, tt.latestBetaVersionFromURL, tmpfile.Name()) + maybePrintUpdateText(tt.latestFullVersionFromURL, tt.latestBetaVersionFromURL, tmpfile.Name(), &run.Options{}) got := outputBuffer.String() if (tt.want == "" && len(got) != 0) || (tt.want != "" && !strings.Contains(got, tt.want)) { t.Fatalf("Expected MaybePrintUpdateText to contain the text %q as the current version is %s and full version %s and beta version %s, but output was [%s]", diff --git a/pkg/minikube/registry/drvs/docker/docker.go b/pkg/minikube/registry/drvs/docker/docker.go index 89f5da5617fa..4167541191dd 100644 --- a/pkg/minikube/registry/drvs/docker/docker.go +++ b/pkg/minikube/registry/drvs/docker/docker.go @@ -37,6 +37,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -49,7 +50,7 @@ func init() { if err := registry.Register(registry.DriverDef{ Name: driver.Docker, Config: configure, - Init: func() drivers.Driver { return kic.NewDriver(kic.Config{OCIBinary: oci.Docker}) }, + Init: func(_ *run.Options) drivers.Driver { return kic.NewDriver(kic.Config{OCIBinary: oci.Docker}) }, Status: status, Default: true, Priority: registry.HighlyPreferred, @@ -95,7 +96,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { }), nil } -func status() (retState registry.State) { +func status(_ *run.Options) (retState registry.State) { version, state := dockerVersionOrState() if state.Error != nil { return state diff --git a/pkg/minikube/registry/drvs/docker/docker_test.go b/pkg/minikube/registry/drvs/docker/docker_test.go index 2dcf69b2f4f8..54042be7fa10 100644 --- a/pkg/minikube/registry/drvs/docker/docker_test.go +++ b/pkg/minikube/registry/drvs/docker/docker_test.go @@ -25,6 +25,7 @@ import ( "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) type testCase struct { @@ -187,7 +188,7 @@ func TestStatus(t *testing.T) { for _, tt := range tests { dockerVersionOrState = func() (string, registry.State) { return tt.input, registry.State{} } oci.CachedDaemonInfo = func(string) (oci.SysInfo, error) { return oci.SysInfo{}, nil } - state := status() + state := status(&run.Options{}) err := state.Error if (err == nil && tt.shouldReturnError) || (err != nil && !tt.shouldReturnError) { t.Errorf("status(%q) = %+v; expected shouldReturnError = %t", tt.input, state, tt.shouldReturnError) diff --git a/pkg/minikube/registry/drvs/hyperkit/hyperkit.go b/pkg/minikube/registry/drvs/hyperkit/hyperkit.go index 1461bea7034a..a04afd6486d0 100644 --- a/pkg/minikube/registry/drvs/hyperkit/hyperkit.go +++ b/pkg/minikube/registry/drvs/hyperkit/hyperkit.go @@ -36,6 +36,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -85,7 +86,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) { }, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { path, err := exec.LookPath("hyperkit") if err != nil { return registry.State{Error: err, Fix: "Run 'brew install hyperkit'", Doc: docURL} diff --git a/pkg/minikube/registry/drvs/hyperv/hyperv.go b/pkg/minikube/registry/drvs/hyperv/hyperv.go index 7a3836c0f865..f12adcaf1a4c 100644 --- a/pkg/minikube/registry/drvs/hyperv/hyperv.go +++ b/pkg/minikube/registry/drvs/hyperv/hyperv.go @@ -34,6 +34,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -44,7 +45,7 @@ const ( func init() { if err := registry.Register(registry.DriverDef{ Name: driver.HyperV, - Init: func() drivers.Driver { return hyperv.NewDriver("", "") }, + Init: func(_ *run.Options) drivers.Driver { return hyperv.NewDriver("", "") }, Config: configure, Status: status, Default: true, @@ -81,7 +82,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) { return d, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { path, err := exec.LookPath("powershell") if err != nil { return registry.State{Error: err} diff --git a/pkg/minikube/registry/drvs/krunkit/krunkit.go b/pkg/minikube/registry/drvs/krunkit/krunkit.go index 2faf138dba5f..7411fd0a28e9 100644 --- a/pkg/minikube/registry/drvs/krunkit/krunkit.go +++ b/pkg/minikube/registry/drvs/krunkit/krunkit.go @@ -36,6 +36,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -44,8 +45,10 @@ const ( func init() { if err := registry.Register(registry.DriverDef{ - Name: driver.Krunkit, - Init: func() drivers.Driver { return krunkit.NewDriver("", "") }, + Name: driver.Krunkit, + Init: func(options *run.Options) drivers.Driver { + return krunkit.NewDriver("", "", options) + }, Config: configure, Status: status, Default: true, @@ -90,7 +93,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) { }, nil } -func status() registry.State { +func status(options *run.Options) registry.State { if runtime.GOOS != "darwin" && runtime.GOARCH != "arm64" { err := errors.New("the krunkit driver is only supported on macOS arm64 machines") return registry.State{Error: err, Fix: "Use another driver", Doc: docURL} @@ -98,7 +101,7 @@ func status() registry.State { if _, err := exec.LookPath("krunkit"); err != nil { return registry.State{Error: err, Fix: "Run 'brew tap slp/krunkit && brew install krunkit'", Doc: docURL} } - if err := vmnet.ValidateHelper(); err != nil { + if err := vmnet.ValidateHelper(options); err != nil { vmnetErr := err.(*vmnet.Error) return registry.State{Error: vmnetErr.Err, Fix: "Install and configure vment-helper", Doc: docURL} } diff --git a/pkg/minikube/registry/drvs/kvm2/kvm2.go b/pkg/minikube/registry/drvs/kvm2/kvm2.go index 492d5319c602..ac3f0ad9da40 100644 --- a/pkg/minikube/registry/drvs/kvm2/kvm2.go +++ b/pkg/minikube/registry/drvs/kvm2/kvm2.go @@ -36,6 +36,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -115,7 +116,7 @@ func defaultURI() string { return "qemu:///system" } -func status() registry.State { +func status(_ *run.Options) registry.State { // Allow no more than 6 seconds for querying state ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second) defer cancel() diff --git a/pkg/minikube/registry/drvs/none/none.go b/pkg/minikube/registry/drvs/none/none.go index 22a183281fb8..1f1ba055c300 100644 --- a/pkg/minikube/registry/drvs/none/none.go +++ b/pkg/minikube/registry/drvs/none/none.go @@ -29,6 +29,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) func init() { @@ -36,7 +37,7 @@ func init() { Name: driver.None, Alias: []string{driver.AliasNative}, Config: configure, - Init: func() drivers.Driver { return none.NewDriver(none.Config{}) }, + Init: func(_ *run.Options) drivers.Driver { return none.NewDriver(none.Config{}) }, Status: status, Default: false, // no isolation Priority: registry.Discouraged, @@ -53,7 +54,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { }), nil } -func status() registry.State { +func status(_ *run.Options) registry.State { _, err := exec.LookPath("iptables") if err != nil { return registry.State{Running: true, Error: err, Fix: "iptables must be installed", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"} diff --git a/pkg/minikube/registry/drvs/parallels/parallels.go b/pkg/minikube/registry/drvs/parallels/parallels.go index d03143d7c00f..cdf995578575 100644 --- a/pkg/minikube/registry/drvs/parallels/parallels.go +++ b/pkg/minikube/registry/drvs/parallels/parallels.go @@ -29,6 +29,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) func init() { @@ -38,7 +39,7 @@ func init() { Status: status, Default: true, Priority: registry.Default, - Init: func() drivers.Driver { return parallels.NewDriver("", "") }, + Init: func(_ *run.Options) drivers.Driver { return parallels.NewDriver("", "") }, }) if err != nil { panic(fmt.Sprintf("unable to register: %v", err)) @@ -55,7 +56,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) { return d, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { _, err := exec.LookPath("prlctl") if err != nil { return registry.State{Error: err, Fix: "Install Parallels Desktop for Mac", Doc: "https://minikube.sigs.k8s.io/docs/drivers/parallels/"} diff --git a/pkg/minikube/registry/drvs/podman/podman.go b/pkg/minikube/registry/drvs/podman/podman.go index 17fd054bbadd..daf5d5a174ca 100644 --- a/pkg/minikube/registry/drvs/podman/podman.go +++ b/pkg/minikube/registry/drvs/podman/podman.go @@ -36,6 +36,7 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) var docURL = "https://minikube.sigs.k8s.io/docs/drivers/podman/" @@ -57,7 +58,7 @@ func init() { if err := registry.Register(registry.DriverDef{ Name: driver.Podman, Config: configure, - Init: func() drivers.Driver { return kic.NewDriver(kic.Config{OCIBinary: oci.Podman}) }, + Init: func(_ *run.Options) drivers.Driver { return kic.NewDriver(kic.Config{OCIBinary: oci.Podman}) }, Status: status, Default: true, Priority: priority, @@ -100,7 +101,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { }), nil } -func status() registry.State { +func status(_ *run.Options) registry.State { podman, err := exec.LookPath(oci.Podman) if err != nil { return registry.State{Error: err, Installed: false, Healthy: false, Fix: "Install Podman", Doc: docURL} diff --git a/pkg/minikube/registry/drvs/qemu2/qemu2.go b/pkg/minikube/registry/drvs/qemu2/qemu2.go index 4b848694abcc..d67c62f8456a 100644 --- a/pkg/minikube/registry/drvs/qemu2/qemu2.go +++ b/pkg/minikube/registry/drvs/qemu2/qemu2.go @@ -36,6 +36,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const docURL = "https://minikube.sigs.k8s.io/docs/reference/drivers/qemu/" @@ -46,9 +47,11 @@ func init() { priority = registry.Experimental } if err := registry.Register(registry.DriverDef{ - Name: driver.QEMU2, - Alias: []string{driver.AliasQEMU}, - Init: func() drivers.Driver { return qemu.NewDriver("", "") }, + Name: driver.QEMU2, + Alias: []string{driver.AliasQEMU}, + Init: func(options *run.Options) drivers.Driver { + return qemu.NewDriver("", "", options) + }, Config: configure, Status: status, Default: true, @@ -192,7 +195,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { }, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { qemuSystem, err := qemuSystemProgram() if err != nil { return registry.State{Error: err, Doc: docURL} diff --git a/pkg/minikube/registry/drvs/ssh/ssh.go b/pkg/minikube/registry/drvs/ssh/ssh.go index 8308cf90053a..bd34754a7838 100644 --- a/pkg/minikube/registry/drvs/ssh/ssh.go +++ b/pkg/minikube/registry/drvs/ssh/ssh.go @@ -30,6 +30,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) func init() { @@ -40,7 +41,7 @@ func init() { Status: status, Default: false, // requires external VM Priority: registry.Discouraged, - Init: func() drivers.Driver { return ssh.NewDriver(ssh.Config{}) }, + Init: func(_ *run.Options) drivers.Driver { return ssh.NewDriver(ssh.Config{}) }, }) if err != nil { panic(fmt.Sprintf("unable to register: %v", err)) @@ -82,6 +83,6 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { return d, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { return registry.State{Installed: true, Healthy: true} } diff --git a/pkg/minikube/registry/drvs/vfkit/vfkit.go b/pkg/minikube/registry/drvs/vfkit/vfkit.go index 970a47246e86..fa8c1e807f78 100644 --- a/pkg/minikube/registry/drvs/vfkit/vfkit.go +++ b/pkg/minikube/registry/drvs/vfkit/vfkit.go @@ -36,6 +36,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -48,8 +49,10 @@ func init() { priority = registry.Preferred } if err := registry.Register(registry.DriverDef{ - Name: driver.VFKit, - Init: func() drivers.Driver { return vfkit.NewDriver("", "") }, + Name: driver.VFKit, + Init: func(options *run.Options) drivers.Driver { + return vfkit.NewDriver("", "", options) + }, Config: configure, Status: status, Default: true, @@ -112,7 +115,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) { }, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { _, err := exec.LookPath("vfkit") if err != nil { return registry.State{Error: err, Fix: "Run 'brew install vfkit'", Doc: docURL} diff --git a/pkg/minikube/registry/drvs/virtualbox/virtualbox.go b/pkg/minikube/registry/drvs/virtualbox/virtualbox.go index edff7849d71d..8842cdde830b 100644 --- a/pkg/minikube/registry/drvs/virtualbox/virtualbox.go +++ b/pkg/minikube/registry/drvs/virtualbox/virtualbox.go @@ -34,6 +34,7 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) const ( @@ -48,7 +49,7 @@ func init() { Status: status, Default: true, Priority: registry.Fallback, - Init: func() drivers.Driver { return virtualbox.NewDriver("", "") }, + Init: func(_ *run.Options) drivers.Driver { return virtualbox.NewDriver("", "") }, }) if err != nil { panic(fmt.Sprintf("unable to register: %v", err)) @@ -71,7 +72,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { return d, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { // Reuse this function as it's particularly helpful for Windows tryPath := driver.VBoxManagePath() path, err := exec.LookPath(tryPath) diff --git a/pkg/minikube/registry/drvs/vmware/vmware.go b/pkg/minikube/registry/drvs/vmware/vmware.go index efc17a78733b..dc5f12a0fde6 100644 --- a/pkg/minikube/registry/drvs/vmware/vmware.go +++ b/pkg/minikube/registry/drvs/vmware/vmware.go @@ -27,6 +27,7 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" + "k8s.io/minikube/pkg/minikube/run" ) func init() { @@ -35,7 +36,7 @@ func init() { Config: configure, Default: false, Priority: registry.Deprecated, - Init: func() drivers.Driver { return vmware.NewDriver("", "") }, + Init: func(_ *run.Options) drivers.Driver { return vmware.NewDriver("", "") }, Status: status, }) if err != nil { @@ -56,7 +57,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) { return d, nil } -func status() registry.State { +func status(_ *run.Options) registry.State { _, err := exec.LookPath("vmrun") if err != nil { return registry.State{Error: err, Fix: "Install vmrun", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/vmware/"} diff --git a/pkg/minikube/registry/global.go b/pkg/minikube/registry/global.go index 77b8f35f7928..739b1e68c0cf 100644 --- a/pkg/minikube/registry/global.go +++ b/pkg/minikube/registry/global.go @@ -23,6 +23,7 @@ import ( "time" "k8s.io/klog/v2" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/translate" ) @@ -107,7 +108,7 @@ func Driver(name string) DriverDef { } // Available returns a list of available drivers in the global registry -func Available(vm bool) []DriverState { +func Available(vm bool, options *run.Options) []DriverState { sts := []DriverState{} klog.Infof("Querying for installed drivers using PATH=%s", os.Getenv("PATH")) @@ -122,7 +123,7 @@ func Available(vm bool) []DriverState { stateChannel := make(chan State) timeoutChannel := time.After(20 * time.Second) go func() { - stateChannel <- d.Status() + stateChannel <- d.Status(options) }() s := State{} select { @@ -148,10 +149,10 @@ func Available(vm bool) []DriverState { } // Status returns the state of a driver within the global registry -func Status(name string) State { +func Status(name string, options *run.Options) State { d := globalRegistry.Driver(name) if d.Empty() { return State{} } - return d.Status() + return d.Status(options) } diff --git a/pkg/minikube/registry/global_test.go b/pkg/minikube/registry/global_test.go index 88d8268c32dd..d2ff726355fd 100644 --- a/pkg/minikube/registry/global_test.go +++ b/pkg/minikube/registry/global_test.go @@ -20,6 +20,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "k8s.io/minikube/pkg/minikube/run" ) func TestGlobalRegister(t *testing.T) { @@ -75,7 +76,7 @@ func TestGlobalAvailable(t *testing.T) { Name: "healthy-bar", Default: true, Priority: Default, - Status: func() State { return State{Healthy: true} }, + Status: func(_ *run.Options) State { return State{Healthy: true} }, } if err := Register(bar); err != nil { t.Errorf("register returned error: %v", err) @@ -85,7 +86,7 @@ func TestGlobalAvailable(t *testing.T) { Name: "unhealthy-foo", Default: true, Priority: Default, - Status: func() State { return State{Healthy: false} }, + Status: func(_ *run.Options) State { return State{Healthy: false} }, } if err := Register(foo); err != nil { t.Errorf("register returned error: %v", err) @@ -108,7 +109,7 @@ func TestGlobalAvailable(t *testing.T) { }, } - if diff := cmp.Diff(Available(false), expected); diff != "" { + if diff := cmp.Diff(Available(false, &run.Options{}), expected); diff != "" { t.Errorf("available mismatch (-want +got):\n%s", diff) } } @@ -125,13 +126,13 @@ func TestGlobalStatus(t *testing.T) { Name: "bar", Default: true, Priority: Default, - Status: func() State { return expected }, + Status: func(_ *run.Options) State { return expected }, } if err := Register(bar); err != nil { t.Errorf("register returned error: %v", err) } - if diff := cmp.Diff(Status("bar"), expected); diff != "" { + if diff := cmp.Diff(Status("bar", &run.Options{}), expected); diff != "" { t.Errorf("status mismatch (-want +got):\n%s", diff) } } diff --git a/pkg/minikube/registry/registry.go b/pkg/minikube/registry/registry.go index ef1d961315f4..d5fce1b1f016 100644 --- a/pkg/minikube/registry/registry.go +++ b/pkg/minikube/registry/registry.go @@ -25,6 +25,7 @@ import ( "github.com/docker/machine/libmachine/drivers" "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/run" ) // Priority is how we determine what driver to default to @@ -69,10 +70,10 @@ type Registry interface { type Configurator func(config.ClusterConfig, config.Node) (interface{}, error) // Loader is a function that loads a byte stream and creates a driver. -type Loader func() drivers.Driver +type Loader func(*run.Options) drivers.Driver // StatusChecker checks if a driver is available, offering a -type StatusChecker func() State +type StatusChecker func(*run.Options) State // State is the current state of the driver and its dependencies type State struct { diff --git a/pkg/minikube/run/options.go b/pkg/minikube/run/options.go new file mode 100644 index 000000000000..a25d14dc9467 --- /dev/null +++ b/pkg/minikube/run/options.go @@ -0,0 +1,29 @@ +/* +Copyright 2025 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package run + +// Options are minikube command line options. +type Options struct { + // NonInteractive is true if the minikube command run with the + // --interactive=false flag and we can not interact with the user. + NonInteractive bool + + // DownloadOnly is true if the minikube command run with the --download-only + // flag and we should If only download and cache files for later use and + // don't install or start anything. + DownloadOnly bool +} diff --git a/pkg/minikube/schedule/daemonize_unix.go b/pkg/minikube/schedule/daemonize_unix.go index 587fd89739a5..ab0d933bd218 100644 --- a/pkg/minikube/schedule/daemonize_unix.go +++ b/pkg/minikube/schedule/daemonize_unix.go @@ -30,16 +30,17 @@ import ( "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/mustload" + "k8s.io/minikube/pkg/minikube/run" ) // KillExisting kills existing scheduled stops by looking up the PID // of the scheduled stop from the PID file saved for the profile and killing the process -func KillExisting(profiles []string) { +func KillExisting(profiles []string, options *run.Options) { for _, profile := range profiles { if err := killPIDForProfile(profile); err != nil { klog.Warningf("error killng PID for profile %s: %v", profile, err) } - _, cc := mustload.Partial(profile) + _, cc := mustload.Partial(profile, options) cc.ScheduledStop = nil if err := config.SaveProfile(profile, cc); err != nil { klog.Errorf("error saving profile for profile %s: %v", profile, err) @@ -76,7 +77,7 @@ func killPIDForProfile(profile string) error { return nil } -func daemonize(profiles []string, _ time.Duration) error { +func daemonize(profiles []string, _ time.Duration, _ *run.Options) error { _, _, err := godaemon.MakeDaemon(&godaemon.DaemonAttr{}) if err != nil { return err diff --git a/pkg/minikube/schedule/daemonize_windows.go b/pkg/minikube/schedule/daemonize_windows.go index 9d24ac294eb5..7a5f0d43ea79 100644 --- a/pkg/minikube/schedule/daemonize_windows.go +++ b/pkg/minikube/schedule/daemonize_windows.go @@ -28,21 +28,22 @@ import ( "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/machine" + "k8s.io/minikube/pkg/minikube/run" "k8s.io/minikube/pkg/minikube/sysinit" ) // KillExisting will kill existing scheduled stops -func KillExisting(profiles []string) { +func KillExisting(profiles []string, options *run.Options) { for _, profile := range profiles { - if err := killExisting(profile); err != nil { + if err := killExisting(profile, options); err != nil { klog.Errorf("error terminating scheduled stop for profile %s: %v", profile, err) } } } -func killExisting(profile string) error { +func killExisting(profile string, options *run.Options) error { klog.Infof("trying to kill existing schedule stop for profile %s...", profile) - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return errors.Wrapf(err, "getting api client for profile %s", profile) } @@ -64,9 +65,9 @@ func killExisting(profile string) error { // to daemonize on windows, we schedule the stop within minikube itself // starting the minikube-scheduled-stop systemd service kicks off the scheduled stop -func daemonize(profiles []string, duration time.Duration) error { +func daemonize(profiles []string, duration time.Duration, options *run.Options) error { for _, profile := range profiles { - if err := startSystemdService(profile, duration); err != nil { + if err := startSystemdService(profile, duration, options); err != nil { return errors.Wrapf(err, "implementing scheduled stop for %s", profile) } } @@ -77,10 +78,10 @@ func daemonize(profiles []string, duration time.Duration) error { // before shutting down minikube from within // we do this by setting the SLEEP environment variable in the environment file to the users // requested duration -func startSystemdService(profile string, duration time.Duration) error { +func startSystemdService(profile string, duration time.Duration, options *run.Options) error { // get ssh runner klog.Infof("starting systemd service for profile %s...", profile) - api, err := machine.NewAPIClient() + api, err := machine.NewAPIClient(options) if err != nil { return errors.Wrapf(err, "getting api client for profile %s", profile) } diff --git a/pkg/minikube/schedule/schedule.go b/pkg/minikube/schedule/schedule.go index c8ca7b5f49c4..5239b33b7882 100644 --- a/pkg/minikube/schedule/schedule.go +++ b/pkg/minikube/schedule/schedule.go @@ -24,10 +24,11 @@ import ( "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/run" ) // Daemonize daemonizes minikube so that scheduled stop happens as expected -func Daemonize(profiles []string, duration time.Duration) error { +func Daemonize(profiles []string, duration time.Duration, options *run.Options) error { // save current time and expected duration in config scheduledStop := &config.ScheduledStopConfig{ InitiationTime: time.Now().Unix(), @@ -35,7 +36,7 @@ func Daemonize(profiles []string, duration time.Duration) error { } var daemonizeProfiles []string for _, p := range profiles { - _, cc := mustload.Partial(p) + _, cc := mustload.Partial(p, options) if driver.BareMetal(cc.Driver) { out.WarningT("scheduled stop is not supported on the none driver, skipping scheduling") continue @@ -43,13 +44,13 @@ func Daemonize(profiles []string, duration time.Duration) error { daemonizeProfiles = append(daemonizeProfiles, p) } - if err := daemonize(daemonizeProfiles, duration); err != nil { + if err := daemonize(daemonizeProfiles, duration, options); err != nil { return errors.Wrap(err, "daemonizing") } // save scheduled stop config if daemonize was successful for _, d := range daemonizeProfiles { - _, cc := mustload.Partial(d) + _, cc := mustload.Partial(d, options) cc.ScheduledStop = scheduledStop if err := config.SaveProfile(d, cc); err != nil { return errors.Wrap(err, "saving profile")