diff --git a/cmd/kuberlr/main.go b/cmd/kuberlr/main.go index aed61cc..fb1b110 100644 --- a/cmd/kuberlr/main.go +++ b/cmd/kuberlr/main.go @@ -1,18 +1,15 @@ package main import ( - "net/url" "os" "path/filepath" "strings" "syscall" - "github.com/blang/semver" "github.com/spf13/cobra" "github.com/flavio/kuberlr/cmd/kuberlr/flags" "github.com/flavio/kuberlr/internal/kubectl_versioner" - "github.com/flavio/kuberlr/internal/kubehelper" "k8s.io/klog" ) @@ -48,7 +45,7 @@ func newRootCmd() *cobra.Command { } func kubectlWrapperMode() { - version, err := kubectlVersionToUse() + version, err := kubectl_versioner.KubectlVersionToUse() if err != nil { klog.Fatal(err) } @@ -62,28 +59,3 @@ func kubectlWrapperMode() { err = syscall.Exec(kubectlBin, childArgs, os.Environ()) klog.Fatal(err) } - -func kubectlVersionToUse() (semver.Version, error) { - version, err := kubehelper.ApiVersion() - if err != nil && isTimeout(err) { - // the remote server is unreachable, let's get - // the latest version of kubectl that is available on the system - klog.Info("Remote kubernetes server unreachable") - version, err = kubectl_versioner.MostRecentKubectlDownloaded() - if err != nil && isNoVersionFound(err) { - klog.Info("No local kubectl binary found, fetching latest stable release version") - version, err = kubectl_versioner.UpstreamStableVersion() - } - } - return version, err -} - -func isTimeout(err error) bool { - urlError, ok := err.(*url.Error) - return ok && urlError.Timeout() -} - -func isNoVersionFound(err error) bool { - nvError, ok := err.(*kubectl_versioner.NoVersionFoundError) - return ok && nvError.NoVersionFound() -} diff --git a/internal/kubectl_versioner/filesystem.go b/internal/kubectl_versioner/filesystem.go new file mode 100644 index 0000000..c2b1429 --- /dev/null +++ b/internal/kubectl_versioner/filesystem.go @@ -0,0 +1,73 @@ +package kubectl_versioner + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "runtime" + + "github.com/flavio/kuberlr/internal/common" + + "github.com/blang/semver" +) + +const KUBECTL_LOCAL_NAMING_SCHEME = "kubectl-%d.%d.%d" + +func BuildKubectNameFromVersion(v semver.Version) string { + return fmt.Sprintf(KUBECTL_LOCAL_NAMING_SCHEME, v.Major, v.Minor, v.Patch) +} + +func LocalDownloadDir() string { + platform := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH) + + return filepath.Join( + common.HomeDir(), + ".kuberlr", + platform, + ) +} + +func IsKubectlAvailable(filename string) bool { + if _, err := os.Stat(filename); os.IsNotExist(err) { + return false + } + return true +} + +func SetupLocalDirs() error { + return os.MkdirAll(LocalDownloadDir(), os.ModePerm) +} + +func LocalKubectlVersions() (semver.Versions, error) { + var versions semver.Versions + + kubectlBins, err := ioutil.ReadDir(LocalDownloadDir()) + if err != nil { + if os.IsNotExist(err) { + err = &NoVersionFoundError{} + } + return versions, err + } + + for _, f := range kubectlBins { + var major, minor, patch uint64 + n, err := fmt.Sscanf( + f.Name(), + KUBECTL_LOCAL_NAMING_SCHEME, + &major, + &minor, + &patch) + + if n == 3 && err == nil { + sv := semver.Version{ + Major: major, + Minor: minor, + Patch: patch, + } + versions = append(versions, sv) + } + } + + return versions, nil +} diff --git a/internal/kubectl_versioner/versioner.go b/internal/kubectl_versioner/versioner.go index 8b0e7c4..18079b2 100644 --- a/internal/kubectl_versioner/versioner.go +++ b/internal/kubectl_versioner/versioner.go @@ -4,12 +4,11 @@ import ( "fmt" "io/ioutil" "net/http" - "os" + "net/url" "path/filepath" - "runtime" - "github.com/flavio/kuberlr/internal/common" "github.com/flavio/kuberlr/internal/downloader" + "github.com/flavio/kuberlr/internal/kubehelper" "github.com/blang/semver" "k8s.io/klog" @@ -17,29 +16,29 @@ import ( const KUBECTL_STABLE_URL = "https://storage.googleapis.com/kubernetes-release/release/stable.txt" -func BuildKubectNameFromVersion(v semver.Version) string { - return fmt.Sprintf("kubectl-%d.%d.%d", v.Major, v.Minor, v.Patch) -} - -func LocalDownloadDir() string { - platform := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH) - - return filepath.Join( - common.HomeDir(), - ".kuberlr", - platform, - ) +func KubectlVersionToUse() (semver.Version, error) { + version, err := kubehelper.ApiVersion() + if err != nil && isTimeout(err) { + // the remote server is unreachable, let's get + // the latest version of kubectl that is available on the system + klog.Info("Remote kubernetes server unreachable") + version, err = MostRecentKubectlDownloaded() + if err != nil && isNoVersionFound(err) { + klog.Info("No local kubectl binary found, fetching latest stable release version") + version, err = UpstreamStableVersion() + } + } + return version, err } -func IsKubectlAvailable(filename string) bool { - if _, err := os.Stat(filename); os.IsNotExist(err) { - return false - } - return true +func isTimeout(err error) bool { + urlError, ok := err.(*url.Error) + return ok && urlError.Timeout() } -func SetupLocalDirs() error { - return os.MkdirAll(LocalDownloadDir(), os.ModePerm) +func isNoVersionFound(err error) bool { + nvError, ok := err.(*NoVersionFoundError) + return ok && nvError.NoVersionFound() } func EnsureKubectlIsAvailable(v semver.Version) (string, error) { @@ -61,7 +60,7 @@ func EnsureKubectlIsAvailable(v semver.Version) (string, error) { return "", err } - klog.Info("Correct kubectl version missing, downloading...") + klog.Infof("Right kubectl missing, downloading version %s", v.String()) err = downloader.Download(downloadUrl, filename, 0755) if err != nil { return "", err @@ -70,29 +69,11 @@ func EnsureKubectlIsAvailable(v semver.Version) (string, error) { } func MostRecentKubectlDownloaded() (semver.Version, error) { - var versions []semver.Version - - kubectlBins, err := ioutil.ReadDir(LocalDownloadDir()) + versions, err := LocalKubectlVersions() if err != nil { - if os.IsNotExist(err) { - err = &NoVersionFoundError{} - } return semver.Version{}, err } - for _, f := range kubectlBins { - var major, minor, patch uint64 - n, err := fmt.Sscanf(f.Name(), "kubectl-%d.%d.%d", &major, &minor, &patch) - if n == 3 && err == nil { - sv := semver.Version{ - Major: major, - Minor: minor, - Patch: patch, - } - versions = append(versions, sv) - } - } - if len(versions) == 0 { return semver.Version{}, &NoVersionFoundError{} }