Skip to content

Commit

Permalink
Code refactoring
Browse files Browse the repository at this point in the history
Split versioning operations into smaller pieces
  • Loading branch information
flavio committed May 9, 2020
1 parent b4f9288 commit 56e5114
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 71 deletions.
30 changes: 1 addition & 29 deletions cmd/kuberlr/main.go
Original file line number Diff line number Diff line change
@@ -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"
)

Expand Down Expand Up @@ -48,7 +45,7 @@ func newRootCmd() *cobra.Command {
}

func kubectlWrapperMode() {
version, err := kubectlVersionToUse()
version, err := kubectl_versioner.KubectlVersionToUse()
if err != nil {
klog.Fatal(err)
}
Expand All @@ -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()
}
73 changes: 73 additions & 0 deletions internal/kubectl_versioner/filesystem.go
Original file line number Diff line number Diff line change
@@ -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
}
65 changes: 23 additions & 42 deletions internal/kubectl_versioner/versioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,41 @@ 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"
)

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) {
Expand All @@ -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
Expand All @@ -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{}
}
Expand Down

0 comments on commit 56e5114

Please sign in to comment.