diff --git a/docs/docs/env-vars.md b/docs/docs/env-vars.md new file mode 100644 index 000000000..550c8f117 --- /dev/null +++ b/docs/docs/env-vars.md @@ -0,0 +1,11 @@ +--- +name: "Environment variables" +route: "/env-vars" +--- + +# Environment Variables + +### TANKA_KUBECTL_PATH + +**Description**: Path to the `kubectl` tool executable +**Default**: `$PATH/kubectl` diff --git a/docs/docs/tutorial/environments.mdx b/docs/docs/tutorial/environments.mdx index bbeeeeae8..8ad613bd2 100644 --- a/docs/docs/tutorial/environments.mdx +++ b/docs/docs/tutorial/environments.mdx @@ -10,7 +10,7 @@ At this point, our configuration is already flexible and concise, but not really reusable. Let's take a look at Tanka's third buzzword as well: **Environments**. These days, the same piece of software is usually deployed many times inside a -single organziation. This could be `dev`, `testing` and `prod` environments, but +single organization. This could be `dev`, `testing` and `prod` environments, but also regions (`europe`, `us`, `asia`) or individual customers (`foo-corp`, `bar-gmbh`, `baz-inc`). diff --git a/docs/docs/tutorial/jsonnet.mdx b/docs/docs/tutorial/jsonnet.mdx index 6dffa749b..8c2732e1b 100644 --- a/docs/docs/tutorial/jsonnet.mdx +++ b/docs/docs/tutorial/jsonnet.mdx @@ -373,7 +373,7 @@ interactive approval (type `yes`). After that, `kubectl` is used to apply to the cluster. By **piping to `kubectl`** Tanka makes sure it **behaves exactly** as you would expect it. No -edge-cases of differing Kubernetes client implemetations should ever occur. +edge-cases of differing Kubernetes client implementations should ever occur. ## Checking it worked diff --git a/docs/doczrc.js b/docs/doczrc.js index 37dce14ca..130c32b3a 100644 --- a/docs/doczrc.js +++ b/docs/doczrc.js @@ -40,14 +40,20 @@ export default { // "Using libraries", // "Creating and structure", "Installing and publishing", - "Overriding", + "Overriding", ], }, + + // additional features + "Output filtering", + "Exporting as YAML", "Command-line completion", - "Directory structure", "Diff strategies", - "Output filtering", - + + // reference + "Directory structure", + "Environment variables", + "Frequently asked questions", "Known issues", ], diff --git a/pkg/kubernetes/client/context.go b/pkg/kubernetes/client/context.go index f04bc1b90..27713ecf9 100644 --- a/pkg/kubernetes/client/context.go +++ b/pkg/kubernetes/client/context.go @@ -6,8 +6,6 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" - "path/filepath" "strings" "github.com/pkg/errors" @@ -50,17 +48,20 @@ func writeNamespacePatch(context objx.Map, namespace string) (string, error) { return "", err } - f := filepath.Join(os.TempDir(), "tk-kubectx-namespace.yaml") - if err := ioutil.WriteFile(f, []byte(out), 0644); err != nil { + f, err := ioutil.TempFile("", "tk-kubectx-namespace-*.yaml") + if err != nil { + return "", err + } + if err = ioutil.WriteFile(f.Name(), []byte(out), 0644); err != nil { return "", err } - return f, nil + return f.Name(), nil } // Kubeconfig returns the merged $KUBECONFIG of the host func Kubeconfig() (map[string]interface{}, error) { - cmd := exec.Command("kubectl", "config", "view", "-o", "json") + cmd := kubectlCmd("config", "view", "-o", "json") cfgJSON := bytes.Buffer{} cmd.Stdout = &cfgJSON cmd.Stderr = os.Stderr @@ -75,7 +76,7 @@ func Kubeconfig() (map[string]interface{}, error) { } func Contexts() ([]string, error) { - cmd := exec.Command("kubectl", "config", "get-contexts", "-o=name") + cmd := kubectlCmd("config", "get-contexts", "-o=name") buf := bytes.Buffer{} cmd.Stdout = &buf cmd.Stderr = os.Stderr diff --git a/pkg/kubernetes/client/delete.go b/pkg/kubernetes/client/delete.go index b9d8ebe97..4b3a5c0d6 100644 --- a/pkg/kubernetes/client/delete.go +++ b/pkg/kubernetes/client/delete.go @@ -3,7 +3,6 @@ package client import ( "fmt" "os" - "os/exec" ) // Delete removes the specified object from the cluster @@ -23,14 +22,11 @@ func (k Kubectl) DeleteByLabels(namespace string, labels map[string]interface{}, func (k Kubectl) delete(namespace string, sel []string, opts DeleteOpts) error { argv := append([]string{"-n", namespace}, sel...) - k.ctl("delete", argv...) - if opts.Force { argv = append(argv, "--force") } - cmd := exec.Command("kubectl", argv...) - + cmd := k.ctl("delete", argv...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin diff --git a/pkg/kubernetes/client/exec.go b/pkg/kubernetes/client/exec.go index 1f6ccc8ac..7af2880c3 100644 --- a/pkg/kubernetes/client/exec.go +++ b/pkg/kubernetes/client/exec.go @@ -9,6 +9,16 @@ import ( "strings" ) +// kubectlCmd returns command a object that will launch kubectl at an appropriate path. +func kubectlCmd(args ...string) *exec.Cmd { + binary := "kubectl" + if env := os.Getenv("TANKA_KUBECTL_PATH"); env != "" { + binary = env + } + + return exec.Command(binary, args...) +} + // ctl returns an `exec.Cmd` for `kubectl`. It also forces the correct context // and injects our patched $KUBECONFIG for the default namespace. func (k Kubectl) ctl(action string, args ...string) *exec.Cmd { @@ -19,7 +29,7 @@ func (k Kubectl) ctl(action string, args ...string) *exec.Cmd { argv = append(argv, args...) // prepare the cmd - cmd := exec.Command("kubectl", argv...) + cmd := kubectlCmd(argv...) cmd.Env = patchKubeconfig(k.nsPatch, os.Environ()) return cmd