diff --git a/cmd/minikube/cmd/kubectl.go b/cmd/minikube/cmd/kubectl.go new file mode 100644 index 000000000000..fd411fbf8554 --- /dev/null +++ b/cmd/minikube/cmd/kubectl.go @@ -0,0 +1,104 @@ +/* +Copyright 2019 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 cmd + +import ( + "crypto" + "fmt" + "os" + "os/exec" + "path" + "runtime" + + "github.com/golang/glog" + download "github.com/jimmidyson/go-download" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/machine" +) + +// kubectlCmd represents the kubectl command +var kubectlCmd = &cobra.Command{ + Use: "kubectl", + Short: "Run kubectl", + Long: `Run the kubernetes client, download it if necessary.`, + Run: func(cmd *cobra.Command, args []string) { + api, err := machine.NewAPIClient() + if err != nil { + fmt.Fprintf(os.Stderr, "Error getting client: %v\n", err) + os.Exit(1) + } + defer api.Close() + + binary := "kubectl" + if runtime.GOOS == "windows" { + binary = "kubectl.exe" + } + version := constants.DefaultKubernetesVersion + path, err := maybeDownloadAndCache(binary, version) + + glog.Infof("Running %s %v", binary, args) + c := exec.Command(path, args...) + c.Stdout = os.Stdout + c.Stderr = os.Stderr + if err := c.Run(); err != nil { + fmt.Fprintf(os.Stderr, "Error running %s: %v\n", path, err) + os.Exit(1) + } + }, +} + +func maybeDownloadAndCache(binary, version string) (string, error) { + targetDir := constants.MakeMiniPath("cache", version) + targetFilepath := path.Join(targetDir, binary) + + _, err := os.Stat(targetFilepath) + // If it exists, do no verification and continue + if err == nil { + return targetFilepath, nil + } + if !os.IsNotExist(err) { + return "", errors.Wrapf(err, "stat %s version %s at %s", binary, version, targetDir) + } + + if err = os.MkdirAll(targetDir, 0777); err != nil { + return "", errors.Wrapf(err, "mkdir %s", targetDir) + } + + url := constants.GetKubernetesClientReleaseURL(binary, version) + options := download.FileOptions{ + Mkdirs: download.MkdirAll, + } + + options.Checksum = constants.GetKubernetesClientReleaseURLSha1(binary, version) + options.ChecksumHash = crypto.SHA1 + + glog.Infof("Downloading %s %s", binary, version) + if err := download.ToFile(url, targetFilepath, options); err != nil { + return "", errors.Wrapf(err, "Error downloading %s %s", binary, version) + } + glog.Infof("Finished Downloading %s %s", binary, version) + if err = os.Chmod(targetFilepath, 0755); err != nil { + return "", errors.Wrapf(err, "chmod +x %s", targetFilepath) + } + return targetFilepath, nil +} + +func init() { + RootCmd.AddCommand(kubectlCmd) +} diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index cb32d9b71cca..734a585c4eca 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -168,10 +168,18 @@ func GetKubernetesReleaseURL(binaryName, version string) string { return fmt.Sprintf("https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/%s/%s", version, runtime.GOARCH, binaryName) } +func GetKubernetesClientReleaseURL(binaryName, version string) string { + return fmt.Sprintf("https://storage.googleapis.com/kubernetes-release/release/%s/bin/%s/%s/%s", version, runtime.GOOS, runtime.GOARCH, binaryName) +} + func GetKubernetesReleaseURLSha1(binaryName, version string) string { return fmt.Sprintf("%s.sha1", GetKubernetesReleaseURL(binaryName, version)) } +func GetKubernetesClientReleaseURLSha1(binaryName, version string) string { + return fmt.Sprintf("%s.sha1", GetKubernetesClientReleaseURL(binaryName, version)) +} + const IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS" const DriverNone = "none" const FileScheme = "file"