diff --git a/cmd/app.go b/cmd/app.go index 107f0ed7..c6e4ade4 100644 --- a/cmd/app.go +++ b/cmd/app.go @@ -33,7 +33,8 @@ func MakeApps() *cobra.Command { install.RunE = func(command *cobra.Command, args []string) error { if len(args) == 0 { - fmt.Printf("You can install: %s\n", strings.TrimRight(strings.Join(getApps(), ", "), ", ")) + fmt.Printf("You can install: %s\n%s\n\n", strings.TrimRight("\n - "+strings.Join(getApps(), "\n - "), "\n - "), + `Run k3sup app install NAME --help to see configuration options.`) return nil } diff --git a/cmd/apps/certmanager_app.go b/cmd/apps/certmanager_app.go index 8f3a6638..781f2415 100644 --- a/cmd/apps/certmanager_app.go +++ b/cmd/apps/certmanager_app.go @@ -9,7 +9,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" - + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -53,7 +53,7 @@ func MakeInstallCertManager() *cobra.Command { os.Setenv("HELM_HOME", path.Join(userPath, ".helm")) - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/chart_app.go b/cmd/apps/chart_app.go index 495a5e31..2f9f5c15 100644 --- a/cmd/apps/chart_app.go +++ b/cmd/apps/chart_app.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/alexellis/k3sup/pkg" - "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -77,7 +77,7 @@ before using the generic helm chart installer command.`, os.Setenv("HELM_HOME", path.Join(userPath, ".helm")) - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/cronconnector_app.go b/cmd/apps/cronconnector_app.go index 967b89e6..c11fbd97 100644 --- a/cmd/apps/cronconnector_app.go +++ b/cmd/apps/cronconnector_app.go @@ -7,9 +7,9 @@ import ( "path" "github.com/alexellis/k3sup/pkg" - "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -57,7 +57,7 @@ func MakeInstallCronConnector() *cobra.Command { os.Setenv("HELM_HOME", path.Join(userPath, ".helm")) - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/inletsoperator_app.go b/cmd/apps/inletsoperator_app.go index 1448d670..44e430a7 100644 --- a/cmd/apps/inletsoperator_app.go +++ b/cmd/apps/inletsoperator_app.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/alexellis/k3sup/pkg" - "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -75,7 +75,7 @@ func MakeInstallInletsOperator() *cobra.Command { if helm3 { os.Setenv("HELM_VERSION", helm3Version) } - _, err = tryDownloadHelm(userPath, clientArch, clientOS, helm3) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, helm3) if err != nil { return err } diff --git a/cmd/apps/istio_app.go b/cmd/apps/istio_app.go index 6815c28a..99e78699 100644 --- a/cmd/apps/istio_app.go +++ b/cmd/apps/istio_app.go @@ -10,7 +10,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" - + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -66,7 +66,7 @@ func MakeInstallIstio() *cobra.Command { os.Setenv("HELM_VERSION", helm3Version) } - _, err = tryDownloadHelm(userPath, clientArch, clientOS, helm3) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, helm3) if err != nil { return err } diff --git a/cmd/apps/kafkaconnector_app.go b/cmd/apps/kafkaconnector_app.go index b36de287..3d9311e9 100644 --- a/cmd/apps/kafkaconnector_app.go +++ b/cmd/apps/kafkaconnector_app.go @@ -9,6 +9,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -57,7 +58,7 @@ func MakeInstallKafkaConnector() *cobra.Command { os.Setenv("HELM_HOME", path.Join(userPath, ".helm")) - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/kubernetes_exec.go b/cmd/apps/kubernetes_exec.go index 2770e967..fc69b4be 100644 --- a/cmd/apps/kubernetes_exec.go +++ b/cmd/apps/kubernetes_exec.go @@ -2,19 +2,15 @@ package apps import ( "fmt" - "io/ioutil" "log" - "net/http" - "net/url" "os" "path" "strings" execute "github.com/alexellis/go-execute/pkg/v1" + "github.com/alexellis/k3sup/pkg/env" ) -const helmVersion = "v2.16.0" - func fetchChart(path, chart string, helm3 bool) error { subdir := "" @@ -29,7 +25,7 @@ func fetchChart(path, chart string, helm3 bool) error { } task := execute.ExecTask{ - Command: fmt.Sprintf("%s fetch %s --untar --untardir %s", localBinary("helm", subdir), chart, path), + Command: fmt.Sprintf("%s fetch %s --untar --untardir %s", env.LocalBinary("helm", subdir), chart, path), Env: os.Environ(), StreamStdio: true, } @@ -79,7 +75,7 @@ func helm3Upgrade(basePath, chart, namespace, values string, overrides map[strin } task := execute.ExecTask{ - Command: localBinary("helm", "helm3"), + Command: env.LocalBinary("helm", "helm3"), Args: args, Env: os.Environ(), Cwd: basePath, @@ -131,7 +127,7 @@ func templateChart(basePath, chart, namespace, outputPath, values string, overri task := execute.ExecTask{ Command: fmt.Sprintf("%s template %s --name %s --namespace %s --output-dir %s %s %s", - localBinary("helm", ""), chart, chart, namespace, outputPath, valuesStr, overridesStr), + env.LocalBinary("helm", ""), chart, chart, namespace, outputPath, valuesStr, overridesStr), Env: os.Environ(), Cwd: basePath, StreamStdio: true, @@ -154,16 +150,6 @@ func templateChart(basePath, chart, namespace, outputPath, values string, overri return nil } -func localBinary(name, subdir string) string { - home := os.Getenv("HOME") - val := path.Join(home, ".k3sup/bin/") - if len(subdir) > 0 { - val = path.Join(val, subdir) - } - - return path.Join(val, name) -} - func addHelmRepo(name, url string, helm3 bool) error { subdir := "" if helm3 { @@ -171,7 +157,7 @@ func addHelmRepo(name, url string, helm3 bool) error { } task := execute.ExecTask{ - Command: fmt.Sprintf("%s repo add %s %s", localBinary("helm", subdir), name, url), + Command: fmt.Sprintf("%s repo add %s %s", env.LocalBinary("helm", subdir), name, url), Env: os.Environ(), StreamStdio: true, } @@ -193,31 +179,8 @@ func updateHelmRepos(helm3 bool) error { subdir = "helm3" } task := execute.ExecTask{ - Command: fmt.Sprintf("%s repo update", localBinary("helm", subdir)), - Env: os.Environ(), - StreamStdio: true, - } - - res, err := task.Execute() - - if err != nil { - return err - } - - if res.ExitCode != 0 { - return fmt.Errorf("exit code %d", res.ExitCode) - } - return nil -} - -func helmInit() error { - fmt.Printf("Running helm init.\n") - subdir := "" - - task := execute.ExecTask{ - Command: fmt.Sprintf("%s", localBinary("helm", subdir)), + Command: fmt.Sprintf("%s repo update", env.LocalBinary("helm", subdir)), Env: os.Environ(), - Args: []string{"init", "--client-only"}, StreamStdio: true, } @@ -275,68 +238,3 @@ func getDefaultKubeconfig() string { return kubeConfigPath } - -func tryDownloadHelm(userPath, clientArch, clientOS string, helm3 bool) (string, error) { - helmVal := "helm" - if helm3 { - helmVal = "helm3" - } - - helmBinaryPath := path.Join(path.Join(userPath, "bin"), helmVal) - if _, statErr := os.Stat(helmBinaryPath); statErr != nil { - subdir := "" - if helm3 { - subdir = "helm3" - } - downloadHelm(userPath, clientArch, clientOS, subdir) - - if !helm3 { - err := helmInit() - if err != nil { - return "", err - } - } - } - return helmBinaryPath, nil -} - -func getHelmURL(arch, os, version string) string { - archSuffix := "amd64" - osSuffix := strings.ToLower(os) - - if strings.HasPrefix(arch, "armv7") { - archSuffix = "arm" - } else if strings.HasPrefix(arch, "aarch64") { - archSuffix = "arm64" - } - - return fmt.Sprintf("https://get.helm.sh/helm-%s-%s-%s.tar.gz", version, osSuffix, archSuffix) -} - -func downloadHelm(userPath, clientArch, clientOS, subdir string) error { - useHelmVersion := helmVersion - if val, ok := os.LookupEnv("HELM_VERSION"); ok && len(val) > 0 { - useHelmVersion = val - } - - helmURL := getHelmURL(clientArch, clientOS, useHelmVersion) - fmt.Println(helmURL) - parsedURL, _ := url.Parse(helmURL) - - res, err := http.DefaultClient.Get(parsedURL.String()) - if err != nil { - return err - } - - dest := path.Join(path.Join(userPath, "bin"), subdir) - os.MkdirAll(dest, 0700) - - defer res.Body.Close() - r := ioutil.NopCloser(res.Body) - untarErr := Untar(r, dest) - if untarErr != nil { - return untarErr - } - - return nil -} diff --git a/cmd/apps/linkerd_app.go b/cmd/apps/linkerd_app.go index d9c6bf4f..45474d6a 100644 --- a/cmd/apps/linkerd_app.go +++ b/cmd/apps/linkerd_app.go @@ -144,7 +144,7 @@ func downloadLinkerd(userPath, clientOS string) error { func linkerdCli(parts ...string) (execute.ExecResult, error) { task := execute.ExecTask{ - Command: fmt.Sprintf("%s", localBinary("linkerd", "")), + Command: fmt.Sprintf("%s", env.LocalBinary("linkerd", "")), Args: parts, Env: os.Environ(), StreamStdio: true, diff --git a/cmd/apps/metricsserver_app.go b/cmd/apps/metricsserver_app.go index 24e2e0b5..ace390cd 100644 --- a/cmd/apps/metricsserver_app.go +++ b/cmd/apps/metricsserver_app.go @@ -9,6 +9,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -49,7 +50,7 @@ func MakeInstallMetricsServer() *cobra.Command { os.Setenv("HELM_HOME", path.Join(userPath, ".helm")) - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/minio_app.go b/cmd/apps/minio_app.go index 46b16767..ee568a06 100644 --- a/cmd/apps/minio_app.go +++ b/cmd/apps/minio_app.go @@ -11,6 +11,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/sethvargo/go-password/password" "github.com/spf13/cobra" ) @@ -61,7 +62,7 @@ func MakeInstallMinio() *cobra.Command { return fmt.Errorf("please use the helm chart if you'd like to change the namespace to %s", ns) } - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/nginx_app.go b/cmd/apps/nginx_app.go index 87798036..d073e6d6 100644 --- a/cmd/apps/nginx_app.go +++ b/cmd/apps/nginx_app.go @@ -9,6 +9,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -53,7 +54,7 @@ func MakeInstallNginx() *cobra.Command { os.Setenv("HELM_HOME", path.Join(userPath, ".helm")) - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/openfaas_app.go b/cmd/apps/openfaas_app.go index 6182af3c..a41d7cc2 100644 --- a/cmd/apps/openfaas_app.go +++ b/cmd/apps/openfaas_app.go @@ -9,10 +9,11 @@ import ( "strings" "github.com/alexellis/k3sup/pkg" - "github.com/sethvargo/go-password/password" - "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" + "github.com/sethvargo/go-password/password" + "github.com/spf13/cobra" ) @@ -87,7 +88,7 @@ func MakeInstallOpenFaaS() *cobra.Command { os.Setenv("HELM_VERSION", helm3Version) } - _, err = tryDownloadHelm(userPath, clientArch, clientOS, helm3) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, helm3) if err != nil { return err } diff --git a/cmd/apps/postgres_app.go b/cmd/apps/postgres_app.go index 3bc67645..7b8e1756 100644 --- a/cmd/apps/postgres_app.go +++ b/cmd/apps/postgres_app.go @@ -11,6 +11,7 @@ import ( "github.com/alexellis/k3sup/pkg" "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -59,7 +60,7 @@ func MakeInstallPostgresql() *cobra.Command { return fmt.Errorf("please use the helm chart if you'd like to change the namespace to %s", ns) } - _, err = tryDownloadHelm(userPath, clientArch, clientOS, false) + _, err = helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/cmd/apps/tiller_app.go b/cmd/apps/tiller_app.go index ebf8f06a..e7b84cb8 100644 --- a/cmd/apps/tiller_app.go +++ b/cmd/apps/tiller_app.go @@ -8,10 +8,9 @@ import ( execute "github.com/alexellis/go-execute/pkg/v1" "github.com/alexellis/k3sup/pkg" - "github.com/alexellis/k3sup/pkg/config" "github.com/alexellis/k3sup/pkg/env" - + "github.com/alexellis/k3sup/pkg/helm" "github.com/spf13/cobra" ) @@ -83,7 +82,7 @@ func MakeInstallTiller() *cobra.Command { fmt.Println(res.Stdout, res.Stderr) - helmBinary, err := tryDownloadHelm(userPath, clientArch, clientOS, false) + helmBinary, err := helm.TryDownloadHelm(userPath, clientArch, clientOS, false) if err != nil { return err } diff --git a/pkg/env/env.go b/pkg/env/env.go index 9eaa80ce..c4d7d806 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -2,6 +2,8 @@ package env import ( "log" + "os" + "path" "strings" execute "github.com/alexellis/go-execute/pkg/v1" @@ -27,3 +29,13 @@ func GetClientArch() (string, string) { return arch, os } + +func LocalBinary(name, subdir string) string { + home := os.Getenv("HOME") + val := path.Join(home, ".k3sup/bin/") + if len(subdir) > 0 { + val = path.Join(val, subdir) + } + + return path.Join(val, name) +} diff --git a/pkg/helm/helm.go b/pkg/helm/helm.go new file mode 100644 index 00000000..3fc11b0e --- /dev/null +++ b/pkg/helm/helm.go @@ -0,0 +1,104 @@ +package helm + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os" + "path" + "strings" + + execute "github.com/alexellis/go-execute/pkg/v1" + "github.com/alexellis/k3sup/pkg/env" +) + +const helmVersion = "v2.16.0" + +func TryDownloadHelm(userPath, clientArch, clientOS string, helm3 bool) (string, error) { + helmVal := "helm" + if helm3 { + helmVal = "helm3" + } + + helmBinaryPath := path.Join(path.Join(userPath, "bin"), helmVal) + if _, statErr := os.Stat(helmBinaryPath); statErr != nil { + subdir := "" + if helm3 { + subdir = "helm3" + } + DownloadHelm(userPath, clientArch, clientOS, subdir) + + if !helm3 { + err := HelmInit() + if err != nil { + return "", err + } + } + } + return helmBinaryPath, nil +} + +func GetHelmURL(arch, os, version string) string { + archSuffix := "amd64" + osSuffix := strings.ToLower(os) + + if strings.HasPrefix(arch, "armv7") { + archSuffix = "arm" + } else if strings.HasPrefix(arch, "aarch64") { + archSuffix = "arm64" + } + + return fmt.Sprintf("https://get.helm.sh/helm-%s-%s-%s.tar.gz", version, osSuffix, archSuffix) +} + +func DownloadHelm(userPath, clientArch, clientOS, subdir string) error { + useHelmVersion := helmVersion + if val, ok := os.LookupEnv("HELM_VERSION"); ok && len(val) > 0 { + useHelmVersion = val + } + + helmURL := GetHelmURL(clientArch, clientOS, useHelmVersion) + fmt.Println(helmURL) + parsedURL, _ := url.Parse(helmURL) + + res, err := http.DefaultClient.Get(parsedURL.String()) + if err != nil { + return err + } + + dest := path.Join(path.Join(userPath, "bin"), subdir) + os.MkdirAll(dest, 0700) + + defer res.Body.Close() + r := ioutil.NopCloser(res.Body) + untarErr := Untar(r, dest) + if untarErr != nil { + return untarErr + } + + return nil +} + +func HelmInit() error { + fmt.Printf("Running helm init.\n") + subdir := "" + + task := execute.ExecTask{ + Command: fmt.Sprintf("%s", env.LocalBinary("helm", subdir)), + Env: os.Environ(), + Args: []string{"init", "--client-only"}, + StreamStdio: true, + } + + res, err := task.Execute() + + if err != nil { + return err + } + + if res.ExitCode != 0 { + return fmt.Errorf("exit code %d", res.ExitCode) + } + return nil +} diff --git a/cmd/apps/untar.go b/pkg/helm/untar.go similarity index 99% rename from cmd/apps/untar.go rename to pkg/helm/untar.go index 267865b2..c2807729 100644 --- a/cmd/apps/untar.go +++ b/pkg/helm/untar.go @@ -5,7 +5,7 @@ // Edited on 2019-10-11 to remove support for nested folders when un-taring // so that all files are placed in the same target directory -package apps +package helm import ( "archive/tar"