diff --git a/README.md b/README.md index caf39e17..b922c650 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ We appreciate your contribution. Please refer to our [contributing guidelines](C ## Get build-tools -- [On my machine](https://buildtool.github.io/install/) +- [On my machine](https://buildtool.github.io/installation/) ## Documentation diff --git a/go.mod b/go.mod index 80147284..03aee6ea 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect + github.com/pkg/errors v0.8.1 github.com/sirupsen/logrus v1.2.0 // indirect github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.5 // indirect diff --git a/pkg/kubectl/kubectl.go b/pkg/kubectl/kubectl.go index 92d3d9f1..b9f267da 100644 --- a/pkg/kubectl/kubectl.go +++ b/pkg/kubectl/kubectl.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/buildtool/build-tools/pkg/config" "github.com/liamg/tml" + "github.com/pkg/errors" "io" "io/ioutil" _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" @@ -52,20 +53,13 @@ func argsFromEnvironment(e *config.Environment, tempDir string, out, eout io.Wri if len(e.Namespace) > 0 { args["namespace"] = e.Namespace } - if content, exist := os.LookupEnv(envKubeConfigContentBase64); exist { - // Not a file, create file from Base64 encoded content - _, _ = fmt.Fprintf(out, "Parsing config from env: %s\n", envKubeConfigContentBase64) - bytes, err := base64.StdEncoding.DecodeString(content) - if err != nil { - _, _ = fmt.Fprintln(eout, tml.Sprintf("Failed to decode content %+v", err)) - return nil - } - args[kubeConfigArg] = writeKubeConfigFile(tempDir, kubeConfigArg, bytes) - } else if content, exist := os.LookupEnv(envKubeConfigContent); exist { - // Not a file, create file from content - _, _ = fmt.Fprintf(out, "Parsing config from env: %s\n", envKubeConfigContent) - args[kubeConfigArg] = writeKubeConfigFile(tempDir, kubeConfigArg, []byte(content)) - } else if len(e.Kubeconfig) > 0 { + + if file, err := getKubeconfigFileFromEnvs(tempDir, out); err != nil { + _, _ = fmt.Fprintln(eout, err.Error()) + } else { + args[kubeConfigArg] = file + } + if len(e.Kubeconfig) > 0 { args[kubeConfigArg] = e.Kubeconfig } if _, exists := args[kubeConfigArg]; exists { @@ -75,10 +69,10 @@ func argsFromEnvironment(e *config.Environment, tempDir string, out, eout io.Wri return args } -func writeKubeConfigFile(tempDir string, kubeConfigArg string, content []byte) string { - kubeconfigFile := filepath.Join(tempDir, kubeConfigArg) - _ = ioutil.WriteFile(kubeconfigFile, content, 0777) - return kubeconfigFile +func writeKubeConfigFile(tempDir string, content []byte) (string, error) { + kubeconfigFile := filepath.Join(tempDir, "kubeconfig") + err := ioutil.WriteFile(kubeconfigFile, content, 0777) + return kubeconfigFile, err } func (k kubectl) defaultArgs() (args []string) { @@ -183,3 +177,30 @@ var _ Kubectl = &kubectl{} const envKubeConfigContent = "KUBECONFIG_CONTENT" const envKubeConfigContentBase64 = "KUBECONFIG_CONTENT_BASE64" + +func getKubeconfigFileFromEnvs(tempDir string, out io.Writer) (string, error) { + if content, exists := getEnv(envKubeConfigContentBase64, out); exists { + if decoded, err := base64.StdEncoding.DecodeString(content); err != nil { + return "", errors.Wrap(err, "Failed to decode content") + } else { + return writeKubeConfigFile(tempDir, decoded) + } + } + + if content, exists := getEnv(envKubeConfigContent, out); exists { + return writeKubeConfigFile(tempDir, []byte(content)) + } + return "", errors.New("failed to get kubeconfig from environment") +} + +func getEnv(env string, out io.Writer) (string, bool) { + if value, exists := os.LookupEnv(env); exists { + if len(value) > 0 { + _, _ = fmt.Fprintf(out, "Found content in env: %s\n", env) + return value, true + } else { + _, _ = fmt.Fprintf(out, "environment variable %s is set but has no value\n", env) + } + } + return "", false +} diff --git a/pkg/kubectl/kubectl_test.go b/pkg/kubectl/kubectl_test.go index bd8be47f..ae9ff899 100644 --- a/pkg/kubectl/kubectl_test.go +++ b/pkg/kubectl/kubectl_test.go @@ -26,7 +26,7 @@ func TestNew(t *testing.T) { assert.Equal(t, "missing", k.(*kubectl).args["context"]) assert.Equal(t, "dev", k.(*kubectl).args["namespace"]) assert.Equal(t, "", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestNew_NoNamespace(t *testing.T) { @@ -100,7 +100,7 @@ func TestKubectl_Environment(t *testing.T) { assert.Equal(t, "", k.(*kubectl).args["namespace"]) assert.Equal(t, "", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_DeploymentExistsTrue(t *testing.T) { @@ -117,7 +117,7 @@ func TestKubectl_DeploymentExistsTrue(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"get", "deployment", "image", "--context", "missing", "--namespace", "default"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default get deployment image\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_DeploymentExistsFalse(t *testing.T) { @@ -135,7 +135,7 @@ func TestKubectl_DeploymentExistsFalse(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"get", "deployment", "image", "--context", "missing", "--namespace", "default"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default get deployment image\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_RolloutStatusSuccess(t *testing.T) { @@ -152,7 +152,7 @@ func TestKubectl_RolloutStatusSuccess(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"rollout", "status", "deployment", "image", "--context", "missing", "--namespace", "default", "--timeout", "2m0s"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default rollout status deployment --timeout=2m image\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_RolloutStatusFailure(t *testing.T) { @@ -170,7 +170,7 @@ func TestKubectl_RolloutStatusFailure(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"rollout", "status", "deployment", "image", "--context", "missing", "--namespace", "default", "--timeout", "2m0s"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default rollout status deployment --timeout=2m image\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_RolloutStatusFatal(t *testing.T) { @@ -191,7 +191,7 @@ func TestKubectl_RolloutStatusFatal(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"rollout", "status", "deployment", "image", "--context", "missing", "--namespace", "default", "--timeout", "2m0s"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default rollout status deployment --timeout=2m image\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_KubeconfigSet(t *testing.T) { @@ -237,7 +237,7 @@ func TestKubectl_KubeconfigInvalidBase64Set(t *testing.T) { eout := &bytes.Buffer{} defer pkg.SetEnv(envKubeConfigContentBase64, "รครถ")() k := New(&config.Environment{}, out, eout) - assert.Equal(t, "\x1b[0mFailed to decode content illegal base64 data at input byte 0\x1b[0m\n", eout.String()) + assert.Equal(t, "Failed to decode content: illegal base64 data at input byte 0\n", eout.String()) k.Cleanup() } @@ -272,7 +272,7 @@ func TestKubectl_DeploymentEvents_Error(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"describe", "deployment", "image", "--context", "missing", "--namespace", "default", "--show-events", "true"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default describe deployment image --show-events=true\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_DeploymentEvents_NoEvents(t *testing.T) { @@ -295,7 +295,7 @@ Events: assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"describe", "deployment", "image", "--context", "missing", "--namespace", "default", "--show-events", "true"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default describe deployment image --show-events=true\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_DeploymentEvents_SomeEvents(t *testing.T) { @@ -324,7 +324,7 @@ Events: assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"describe", "deployment", "image", "--context", "missing", "--namespace", "default", "--show-events", "true"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default describe deployment image --show-events=true\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_PodEvents_Error(t *testing.T) { @@ -343,7 +343,7 @@ func TestKubectl_PodEvents_Error(t *testing.T) { assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"describe", "pods", "--context", "missing", "--namespace", "default", "--show-events", "true", "--selector", "app=image"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default describe pods -l app=image --show-events=true\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_PodEvents_NoEvents(t *testing.T) { @@ -366,7 +366,7 @@ Events: assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"describe", "pods", "--context", "missing", "--namespace", "default", "--show-events", "true", "--selector", "app=image"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default describe pods -l app=image --show-events=true\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } func TestKubectl_PodEvents_SomeEvents(t *testing.T) { @@ -394,7 +394,7 @@ Events: assert.Equal(t, 1, len(calls)) assert.Equal(t, []string{"describe", "pods", "--context", "missing", "--namespace", "default", "--show-events", "true", "--selector", "app=image"}, calls[0]) assert.Equal(t, "kubectl --context missing --namespace default describe pods -l app=image --show-events=true\n", out.String()) - assert.Equal(t, "", eout.String()) + assert.Equal(t, "failed to get kubeconfig from environment\n", eout.String()) } var calls [][]string