diff --git a/cmd/minikube/cmd/config/enable.go b/cmd/minikube/cmd/config/enable.go index a2426ca3fb26..0df2abb53410 100644 --- a/cmd/minikube/cmd/config/enable.go +++ b/cmd/minikube/cmd/config/enable.go @@ -42,7 +42,7 @@ var addonsEnableCmd = &cobra.Command{ addon := args[0] // replace heapster as metrics-server because heapster is deprecated if addon == "heapster" { - out.Styled(style.Waiting, "enable metrics-server addon instead of heapster addon because heapster is deprecated") + out.Styled(style.Waiting, "using metrics-server addon, heapster is deprecated") addon = "metrics-server" } viper.Set(config.AddonImages, images) @@ -76,5 +76,6 @@ var ( func init() { addonsEnableCmd.Flags().StringVar(&images, "images", "", "Images used by this addon. Separated by commas.") addonsEnableCmd.Flags().StringVar(®istries, "registries", "", "Registries used by this addon. Separated by commas.") + addonsEnableCmd.Flags().BoolVar(&addons.Force, "force", false, "If true, will perform potentially dangerous operations. Use with discretion.") AddonsCmd.AddCommand(addonsEnableCmd) } diff --git a/cmd/minikube/cmd/root.go b/cmd/minikube/cmd/root.go index 590e523d60ad..d57f6a0e3926 100644 --- a/cmd/minikube/cmd/root.go +++ b/cmd/minikube/cmd/root.go @@ -35,7 +35,7 @@ import ( "k8s.io/minikube/pkg/minikube/audit" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/constants" - "k8s.io/minikube/pkg/minikube/driver" + "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out" @@ -80,7 +80,7 @@ func Execute() { defer audit.Log(time.Now()) // Check whether this is a windows binary (.exe) running inisde WSL. - if runtime.GOOS == "windows" && driver.IsMicrosoftWSL() { + if runtime.GOOS == "windows" && detect.IsMicrosoftWSL() { var found = false for _, a := range os.Args { if a == "--force" { diff --git a/pkg/addons/addons.go b/pkg/addons/addons.go index 4c44831f22af..34ae91c0faa1 100644 --- a/pkg/addons/addons.go +++ b/pkg/addons/addons.go @@ -38,20 +38,17 @@ import ( "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/exit" - "k8s.io/minikube/pkg/minikube/kubeconfig" "k8s.io/minikube/pkg/minikube/machine" - "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/out/register" "k8s.io/minikube/pkg/minikube/reason" - "k8s.io/minikube/pkg/minikube/storageclass" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/sysinit" "k8s.io/minikube/pkg/util/retry" ) -// defaultStorageClassProvisioner is the name of the default storage class provisioner -const defaultStorageClassProvisioner = "standard" +// Force is used to override checks for addons +var Force bool = false // 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 { @@ -174,7 +171,6 @@ https://github.com/kubernetes/minikube/issues/7332`, out.V{"driver_name": cc.Dri } } - // TODO(r2d4): config package should not reference API, pull this out api, err := machine.NewAPIClient() if err != nil { return errors.Wrap(err, "machine client") @@ -279,75 +275,10 @@ func enableOrDisableAddonInternal(cc *config.ClusterConfig, addon *assets.Addon, return retry.Expo(apply, 250*time.Millisecond, 2*time.Minute) } -// enableOrDisableStorageClasses enables or disables storage classes -func enableOrDisableStorageClasses(cc *config.ClusterConfig, name string, val string) error { - klog.Infof("enableOrDisableStorageClasses %s=%v on %q", name, val, cc.Name) - enable, err := strconv.ParseBool(val) - if err != nil { - return errors.Wrap(err, "Error parsing boolean") - } - - class := defaultStorageClassProvisioner - if name == "storage-provisioner-gluster" { - class = "glusterfile" - } - - api, err := machine.NewAPIClient() - if err != nil { - return errors.Wrap(err, "machine client") - } - defer api.Close() - - cp, err := config.PrimaryControlPlane(cc) - if err != nil { - return errors.Wrap(err, "getting control plane") - } - if !machine.IsRunning(api, config.MachineName(*cc, cp)) { - klog.Warningf("%q is not running, writing %s=%v to disk and skipping enablement", config.MachineName(*cc, cp), name, val) - return EnableOrDisableAddon(cc, name, val) - } - - storagev1, err := storageclass.GetStoragev1(cc.Name) - if err != nil { - return errors.Wrapf(err, "Error getting storagev1 interface %v ", err) - } - - if enable { - // Only StorageClass for 'name' should be marked as default - err = storageclass.SetDefaultStorageClass(storagev1, class) - if err != nil { - return errors.Wrapf(err, "Error making %s the default storage class", class) - } - } else { - // Unset the StorageClass as default - err := storageclass.DisableDefaultStorageClass(storagev1, class) - if err != nil { - return errors.Wrapf(err, "Error disabling %s as the default storage class", class) - } - } - - return EnableOrDisableAddon(cc, name, val) -} - func verifyAddonStatus(cc *config.ClusterConfig, name string, val string) error { return verifyAddonStatusInternal(cc, name, val, "kube-system") } -func verifyGCPAuthAddon(cc *config.ClusterConfig, name string, val string) error { - enable, err := strconv.ParseBool(val) - if err != nil { - return errors.Wrapf(err, "parsing bool: %s", name) - } - err = verifyAddonStatusInternal(cc, name, val, "gcp-auth") - - if enable && err == nil { - out.Styled(style.Notice, "Your GCP credentials will now be mounted into every pod created in the {{.name}} cluster.", out.V{"name": cc.Name}) - out.Styled(style.Notice, "If you don't want your credentials mounted into a specific pod, add a label with the `gcp-auth-skip-secret` key to your pod configuration.") - } - - return err -} - func verifyAddonStatusInternal(cc *config.ClusterConfig, name string, val string, ns string) error { klog.Infof("Verifying addon %s=%s in %q", name, val, cc.Name) enable, err := strconv.ParseBool(val) @@ -444,47 +375,3 @@ func Start(wg *sync.WaitGroup, cc *config.ClusterConfig, toEnable map[string]boo } } } - -// enableOrDisableAutoPause enables the service after the config was copied by generic enble -func enableOrDisableAutoPause(cc *config.ClusterConfig, name string, val string) error { - enable, err := strconv.ParseBool(val) - if err != nil { - return errors.Wrapf(err, "parsing bool: %s", name) - } - 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%2Fauto-pause") - - if !driver.IsKIC(cc.Driver) || runtime.GOARCH != "amd64" { - exit.Message(reason.Usage, `auto-pause currently is only supported on docker driver/docker runtime/amd64. Track progress of others here: https://github.com/kubernetes/minikube/issues/10601`) - } - co := mustload.Running(cc.Name) - if enable { - if err := sysinit.New(co.CP.Runner).EnableNow("auto-pause"); err != nil { - klog.ErrorS(err, "failed to enable", "service", "auto-pause") - } - } - - port := co.CP.Port // api server port - if enable { // if enable then need to calculate the forwarded port - port = constants.AutoPauseProxyPort - if driver.NeedsPortForward(cc.Driver) { - port, err = oci.ForwardedPort(cc.Driver, cc.Name, port) - if err != nil { - klog.ErrorS(err, "failed to get forwarded port for", "auto-pause port", port) - } - } - } - - updated, err := kubeconfig.UpdateEndpoint(cc.Name, co.CP.Hostname, port, kubeconfig.PathFromEnv(), kubeconfig.NewExtension()) - if err != nil { - klog.ErrorS(err, "failed to update kubeconfig", "auto-pause proxy endpoint") - return err - } - if updated { - klog.Infof("%s context has been updated to point to auto-pause proxy %s:%s", cc.Name, co.CP.Hostname, co.CP.Port) - } else { - klog.Info("no need to update kube-context for auto-pause proxy") - } - - return nil -} diff --git a/pkg/addons/addons_autopause.go b/pkg/addons/addons_autopause.go new file mode 100644 index 000000000000..936f51ff07e8 --- /dev/null +++ b/pkg/addons/addons_autopause.go @@ -0,0 +1,79 @@ +/* +Copyright 2021 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 addons + +import ( + "runtime" + "strconv" + + "github.com/pkg/errors" + "k8s.io/klog/v2" + "k8s.io/minikube/pkg/drivers/kic/oci" + "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/driver" + "k8s.io/minikube/pkg/minikube/exit" + "k8s.io/minikube/pkg/minikube/kubeconfig" + "k8s.io/minikube/pkg/minikube/mustload" + "k8s.io/minikube/pkg/minikube/out" + "k8s.io/minikube/pkg/minikube/reason" + "k8s.io/minikube/pkg/minikube/sysinit" +) + +// enableOrDisableAutoPause enables the service after the config was copied by generic enble +func enableOrDisableAutoPause(cc *config.ClusterConfig, name string, val string) error { + enable, err := strconv.ParseBool(val) + if err != nil { + return errors.Wrapf(err, "parsing bool: %s", name) + } + 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%2Fauto-pause") + + if !driver.IsKIC(cc.Driver) || runtime.GOARCH != "amd64" { + exit.Message(reason.Usage, `auto-pause currently is only supported on docker driver/docker runtime/amd64. Track progress of others here: https://github.com/kubernetes/minikube/issues/10601`) + } + co := mustload.Running(cc.Name) + if enable { + if err := sysinit.New(co.CP.Runner).EnableNow("auto-pause"); err != nil { + klog.ErrorS(err, "failed to enable", "service", "auto-pause") + } + } + + port := co.CP.Port // api server port + if enable { // if enable then need to calculate the forwarded port + port = constants.AutoPauseProxyPort + if driver.NeedsPortForward(cc.Driver) { + port, err = oci.ForwardedPort(cc.Driver, cc.Name, port) + if err != nil { + klog.ErrorS(err, "failed to get forwarded port for", "auto-pause port", port) + } + } + } + + updated, err := kubeconfig.UpdateEndpoint(cc.Name, co.CP.Hostname, port, kubeconfig.PathFromEnv(), kubeconfig.NewExtension()) + if err != nil { + klog.ErrorS(err, "failed to update kubeconfig", "auto-pause proxy endpoint") + return err + } + if updated { + klog.Infof("%s context has been updated to point to auto-pause proxy %s:%s", cc.Name, co.CP.Hostname, co.CP.Port) + } else { + klog.Info("no need to update kube-context for auto-pause proxy") + } + + return nil +} diff --git a/pkg/addons/gcpauth/enable.go b/pkg/addons/addons_gcpauth.go similarity index 65% rename from pkg/addons/gcpauth/enable.go rename to pkg/addons/addons_gcpauth.go index 11eecca77383..b5d54cb55821 100644 --- a/pkg/addons/gcpauth/enable.go +++ b/pkg/addons/addons_gcpauth.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Kubernetes Authors All rights reserved. +Copyright 2021 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. @@ -14,21 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ -package gcpauth +package addons import ( "bytes" "context" - "io/ioutil" "os" "os/exec" - "path" "strconv" "github.com/pkg/errors" "golang.org/x/oauth2/google" "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/mustload" "k8s.io/minikube/pkg/minikube/out" @@ -41,19 +40,23 @@ const ( projectPath = "/var/lib/minikube/google_cloud_project" ) -// EnableOrDisable enables or disables the metadata addon depending on the val parameter -func EnableOrDisable(cfg *config.ClusterConfig, name string, val string) error { +// enableOrDisableGCPAuth enables or disables the gcp-auth addon depending on the val parameter +func enableOrDisableGCPAuth(cfg *config.ClusterConfig, name string, val string) error { enable, err := strconv.ParseBool(val) if err != nil { return errors.Wrapf(err, "parsing bool: %s", name) } if enable { - return enableAddon(cfg) + return enableAddonGCPAuth(cfg) } - return disableAddon(cfg) + return disableAddonGCPAuth(cfg) } -func enableAddon(cfg *config.ClusterConfig) error { +func enableAddonGCPAuth(cfg *config.ClusterConfig) error { + if !Force && detect.IsOnGCE() { + exit.Message(reason.InternalCredsNotFound, "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.") + } + // Grab command runner from running cluster cc := mustload.Running(cfg.Name) r := cc.CP.Runner @@ -65,20 +68,9 @@ func enableAddon(cfg *config.ClusterConfig) error { exit.Message(reason.InternalCredsNotFound, "Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.") } + // Don't mount in empty credentials file if creds.JSON == nil { - // Cloud Shell sends credential files to an unusual location, let's check that location - // For example, CLOUDSDK_CONFIG=/tmp/tmp.cflmvysoQE - if e := os.Getenv("CLOUDSDK_CONFIG"); e != "" { - credFile := path.Join(e, "application_default_credentials.json") - b, err := ioutil.ReadFile(credFile) - if err != nil { - exit.Message(reason.InternalCredsNotFound, "Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.") - } - creds.JSON = b - } else { - // We don't currently support authentication through the metadata server - exit.Message(reason.InternalCredsNotFound, "Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.") - } + exit.Message(reason.InternalCredsNotFound, "Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.") } f := assets.NewMemoryAssetTarget(creds.JSON, credentialsPath, "0444") @@ -114,7 +106,7 @@ or set the GOOGLE_CLOUD_PROJECT environment variable.`) return r.Copy(emptyFile) } -func disableAddon(cfg *config.ClusterConfig) error { +func disableAddonGCPAuth(cfg *config.ClusterConfig) error { // Grab command runner from running cluster cc := mustload.Running(cfg.Name) r := cc.CP.Runner @@ -134,3 +126,18 @@ func disableAddon(cfg *config.ClusterConfig) error { return nil } + +func verifyGCPAuthAddon(cc *config.ClusterConfig, name string, val string) error { + enable, err := strconv.ParseBool(val) + if err != nil { + return errors.Wrapf(err, "parsing bool: %s", name) + } + err = verifyAddonStatusInternal(cc, name, val, "gcp-auth") + + if enable && err == nil { + out.Styled(style.Notice, "Your GCP credentials will now be mounted into every pod created in the {{.name}} cluster.", out.V{"name": cc.Name}) + out.Styled(style.Notice, "If you don't want your credentials mounted into a specific pod, add a label with the `gcp-auth-skip-secret` key to your pod configuration.") + } + + return err +} diff --git a/pkg/addons/addons_storage_classes.go b/pkg/addons/addons_storage_classes.go new file mode 100644 index 000000000000..cd8b67272900 --- /dev/null +++ b/pkg/addons/addons_storage_classes.go @@ -0,0 +1,79 @@ +/* +Copyright 2021 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 addons + +import ( + "strconv" + + "github.com/pkg/errors" + "k8s.io/klog/v2" + "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/machine" + "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 { + klog.Infof("enableOrDisableStorageClasses %s=%v on %q", name, val, cc.Name) + enable, err := strconv.ParseBool(val) + if err != nil { + return errors.Wrap(err, "Error parsing boolean") + } + + class := defaultStorageClassProvisioner + if name == "storage-provisioner-gluster" { + class = "glusterfile" + } + + api, err := machine.NewAPIClient() + if err != nil { + return errors.Wrap(err, "machine client") + } + defer api.Close() + + cp, err := config.PrimaryControlPlane(cc) + if err != nil { + return errors.Wrap(err, "getting control plane") + } + if !machine.IsRunning(api, config.MachineName(*cc, cp)) { + klog.Warningf("%q is not running, writing %s=%v to disk and skipping enablement", config.MachineName(*cc, cp), name, val) + return EnableOrDisableAddon(cc, name, val) + } + + storagev1, err := storageclass.GetStoragev1(cc.Name) + if err != nil { + return errors.Wrapf(err, "Error getting storagev1 interface %v ", err) + } + + if enable { + // Only StorageClass for 'name' should be marked as default + err = storageclass.SetDefaultStorageClass(storagev1, class) + if err != nil { + return errors.Wrapf(err, "Error making %s the default storage class", class) + } + } else { + // Unset the StorageClass as default + err := storageclass.DisableDefaultStorageClass(storagev1, class) + if err != nil { + return errors.Wrapf(err, "Error disabling %s as the default storage class", class) + } + } + + return EnableOrDisableAddon(cc, name, val) +} diff --git a/pkg/addons/config.go b/pkg/addons/config.go index f33a01f28363..22c242a7a533 100644 --- a/pkg/addons/config.go +++ b/pkg/addons/config.go @@ -17,7 +17,6 @@ limitations under the License. package addons import ( - "k8s.io/minikube/pkg/addons/gcpauth" "k8s.io/minikube/pkg/minikube/config" ) @@ -175,7 +174,7 @@ var Addons = []*Addon{ { name: "gcp-auth", set: SetBool, - callbacks: []setFn{gcpauth.EnableOrDisable, EnableOrDisableAddon, verifyGCPAuthAddon}, + callbacks: []setFn{enableOrDisableGCPAuth, EnableOrDisableAddon, verifyGCPAuthAddon}, }, { name: "volumesnapshots", diff --git a/pkg/minikube/detect/detect.go b/pkg/minikube/detect/detect.go new file mode 100644 index 000000000000..b3af332d4fe3 --- /dev/null +++ b/pkg/minikube/detect/detect.go @@ -0,0 +1,43 @@ +/* +Copyright 2021 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 detect + +import ( + "net/http" + "os" +) + +// IsMicrosoftWSL will return true if process is running in WSL in windows +// checking for WSL env var based on this https://github.com/microsoft/WSL/issues/423#issuecomment-608237689 +// also based on https://github.com/microsoft/vscode/blob/90a39ba0d49d75e9a4d7e62a6121ad946ecebc58/resources/win32/bin/code.sh#L24 +func IsMicrosoftWSL() bool { + return os.Getenv("WSL_DISTRO_NAME") != "" || os.Getenv("WSLPATH") != "" +} + +// IsOnGCE determines whether minikube is currently running on GCE. +func IsOnGCE() bool { + resp, err := http.Get("http://metadata.google.internal") + if err != nil { + return false + } + + if resp.Header.Get("Metadata-Flavor") == "Google" { + return true + } + + return false +} diff --git a/pkg/minikube/driver/driver.go b/pkg/minikube/driver/driver.go index 2edc1ef742d4..e574493c9c2e 100644 --- a/pkg/minikube/driver/driver.go +++ b/pkg/minikube/driver/driver.go @@ -26,6 +26,7 @@ import ( "k8s.io/klog/v2" "k8s.io/minikube/pkg/drivers/kic/oci" + "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/registry" ) @@ -167,14 +168,7 @@ func NeedsPortForward(name string) bool { return true } // Docker for Desktop - return runtime.GOOS == "darwin" || runtime.GOOS == "windows" || IsMicrosoftWSL() -} - -// IsMicrosoftWSL will return true if process is running in WSL in windows -// checking for WSL env var based on this https://github.com/microsoft/WSL/issues/423#issuecomment-608237689 -// also based on https://github.com/microsoft/vscode/blob/90a39ba0d49d75e9a4d7e62a6121ad946ecebc58/resources/win32/bin/code.sh#L24 -func IsMicrosoftWSL() bool { - return os.Getenv("WSL_DISTRO_NAME") != "" || os.Getenv("WSLPATH") != "" + return runtime.GOOS == "darwin" || runtime.GOOS == "windows" || detect.IsMicrosoftWSL() } // HasResourceLimits returns true if driver can set resource limits such as memory size or CPU count. diff --git a/pkg/minikube/node/start.go b/pkg/minikube/node/start.go index 017b99540840..87997f4b6b24 100644 --- a/pkg/minikube/node/start.go +++ b/pkg/minikube/node/start.go @@ -164,6 +164,9 @@ func Start(starter Starter, apiServer bool) (*kubeconfig.Settings, error) { // enable addons, both old and new! if starter.ExistingAddons != nil { + if viper.GetBool("force") { + addons.Force = true + } wg.Add(1) go addons.Start(&wg, starter.Cfg, starter.ExistingAddons, config.AddonList) } diff --git a/site/content/en/docs/commands/addons.md b/site/content/en/docs/commands/addons.md index 51023fa24dd9..7a783632a9b9 100644 --- a/site/content/en/docs/commands/addons.md +++ b/site/content/en/docs/commands/addons.md @@ -128,6 +128,7 @@ minikube addons enable dashboard ### Options ``` + --force If true, will perform potentially dangerous operations. Use with discretion. --images string Images used by this addon. Separated by commas. --registries string Registries used by this addon. Separated by commas. ``` diff --git a/test/integration/addons_test.go b/test/integration/addons_test.go index 7a875a218a76..7f9428e09eea 100644 --- a/test/integration/addons_test.go +++ b/test/integration/addons_test.go @@ -36,6 +36,7 @@ import ( "github.com/hashicorp/go-retryablehttp" "k8s.io/minikube/pkg/kapi" + "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/util/retry" ) @@ -58,18 +59,43 @@ func TestAddons(t *testing.T) { t.Fatalf("Failed setting GOOGLE_CLOUD_PROJECT env var: %v", err) } - args := append([]string{"start", "-p", profile, "--wait=true", "--memory=4000", "--alsologtostderr", "--addons=registry", "--addons=metrics-server", "--addons=olm", "--addons=volumesnapshots", "--addons=csi-hostpath-driver", "--addons=gcp-auth"}, StartArgs()...) + args := append([]string{"start", "-p", profile, "--wait=true", "--memory=4000", "--alsologtostderr", "--addons=registry", "--addons=metrics-server", "--addons=olm", "--addons=volumesnapshots", "--addons=csi-hostpath-driver"}, StartArgs()...) if !(runtime.GOOS == "darwin" && KicDriver()) { // macos docker driver does not support ingress args = append(args, "--addons=ingress") } if !arm64Platform() { args = append(args, "--addons=helm-tiller") } + if !detect.IsOnGCE() { + args = append(args, "--addons=gcp-auth") + } rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) if err != nil { t.Fatalf("%s failed: %v", rr.Command(), err) } + // If we're running the integration tests on GCE, which is frequently the case, first check to make sure we exit out properly, + // then use force to actually test using creds. + if detect.IsOnGCE() { + args = []string{"-p", profile, "addons", "enable", "gcp-auth"} + rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) + if err == nil { + t.Errorf("Expected error but didn't get one. command %v, output %v", rr.Command(), rr.Output()) + } else { + if !strings.Contains(rr.Output(), "It seems that you are running in GCE") { + t.Errorf("Unexpected error message: %v", rr.Output()) + } else { + // ok, use force here since we are in GCE + // do not use --force unless absolutely necessary + args = append(args, "--force") + rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) + if err != nil { + t.Errorf("%s failed: %v", rr.Command(), err) + } + } + } + } + // Parallelized tests t.Run("parallel", func(t *testing.T) { tests := []struct { diff --git a/test/integration/helpers_test.go b/test/integration/helpers_test.go index c41a20a20985..3e90b282bb73 100644 --- a/test/integration/helpers_test.go +++ b/test/integration/helpers_test.go @@ -86,7 +86,7 @@ func (rr RunResult) Output() string { return sb.String() } -// Run is a test helper to log a command being executed \_(ツ)_/¯ +// Run is a test helper to log a command being executed ¯\_(ツ)_/¯ func Run(t *testing.T, cmd *exec.Cmd) (*RunResult, error) { t.Helper() rr := &RunResult{Args: cmd.Args} diff --git a/test/integration/main_test.go b/test/integration/main_test.go index 1a72688bb748..3e1003df0b08 100644 --- a/test/integration/main_test.go +++ b/test/integration/main_test.go @@ -30,7 +30,7 @@ import ( "time" "k8s.io/minikube/pkg/minikube/constants" - "k8s.io/minikube/pkg/minikube/driver" + "k8s.io/minikube/pkg/minikube/detect" ) // General configuration: used to set the VM Driver @@ -169,7 +169,7 @@ func arm64Platform() bool { // NeedsPortForward returns access to endpoints with this driver needs port forwarding // (Docker on non-Linux platforms requires ports to be forwarded to 127.0.0.1) func NeedsPortForward() bool { - return KicDriver() && (runtime.GOOS == "windows" || runtime.GOOS == "darwin") || driver.IsMicrosoftWSL() + return KicDriver() && (runtime.GOOS == "windows" || runtime.GOOS == "darwin") || detect.IsMicrosoftWSL() } // CanCleanup returns if cleanup is allowed