Skip to content

Commit

Permalink
Add kubeconfig_content configuration parameter to the provider
Browse files Browse the repository at this point in the history
  • Loading branch information
melan committed Aug 21, 2018
1 parent c8849b3 commit 1782090
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 9 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,28 @@ providers {
}
```

The provider takes optional configuration to specify a `kubeconfig` file:
The provider takes the following optional configuration parameters:

* If you have a kubeconfig available on the file system you can configure the provider as:

```hcl
provider "k8s" {
kubeconfig = "/path/to/kubeconfig"
}
```

* If you content of the kubeconfig is available in a variable, you can configure the provider as:

```hcl
provider "k8s" {
kubeconfig_content = "${var.kubeconfig}"
}
```

**WARNING:** Configuration from the variable will be recorded into a temporary file and the file will be removed as
soon as call is completed. This may impact performance if the code runs on a shared system because
and the global tempdir is used.

The k8s Terraform provider introduces a single Terraform resource, a `k8s_manifest`. The resource contains a `content` field, which contains a raw manifest.

```hcl
Expand Down
86 changes: 78 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"strings"

Expand All @@ -13,7 +16,8 @@ import (
)

type config struct {
kubeconfig string
kubeconfig string
kubeconfigContent string
}

func main() {
Expand All @@ -25,13 +29,18 @@ func main() {
Type: schema.TypeString,
Optional: true,
},
"kubeconfig_content": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
},
ResourcesMap: map[string]*schema.Resource{
"k8s_manifest": resourceManifest(),
},
ConfigureFunc: func(d *schema.ResourceData) (interface{}, error) {
return &config{
kubeconfig: d.Get("kubeconfig").(string),
kubeconfig: d.Get("kubeconfig").(string),
kubeconfigContent: d.Get("kubeconfig_content").(string),
}, nil
},
}
Expand Down Expand Up @@ -69,23 +78,65 @@ func run(cmd *exec.Cmd) error {
return nil
}

func kubectl(m interface{}, args ...string) *exec.Cmd {
func kubeconfigPath(m interface{}) (string, func(), error) {
kubeconfig := m.(*config).kubeconfig
kubeconfigContent := m.(*config).kubeconfigContent
var cleanupFunc = func() {}

if kubeconfig != "" && kubeconfigContent != "" {
return kubeconfig, cleanupFunc, fmt.Errorf("both kubeconfig and kubeconfig_content are defined, " +
"please use only one of the paramters")
} else if kubeconfigContent != "" {
tmpfile, err := ioutil.TempFile("", "kubeconfig_")
if err != nil {
defer cleanupFunc()
return "", cleanupFunc, fmt.Errorf("creating a kubeconfig file: %v", err)
}

cleanupFunc = func() { os.Remove(tmpfile.Name()) }

if _, err = io.WriteString(tmpfile, kubeconfigContent); err != nil {
defer cleanupFunc()
return "", cleanupFunc, fmt.Errorf("writing kubeconfig to file: %v", err)
}
if err = tmpfile.Close(); err != nil {
defer cleanupFunc()
return "", cleanupFunc, fmt.Errorf("completion of write to kubeconfig file: %v", err)
}

kubeconfig = tmpfile.Name()
}

if kubeconfig != "" {
return kubeconfig, cleanupFunc, nil
}

return "", cleanupFunc, nil
}

func kubectl(m interface{}, kubeconfig string, args ...string) *exec.Cmd {
if kubeconfig != "" {
args = append([]string{"--kubeconfig", kubeconfig}, args...)
}

return exec.Command("kubectl", args...)
}

func resourceManifestCreate(d *schema.ResourceData, m interface{}) error {
cmd := kubectl(m, "apply", "-f", "-")
kubeconfig, cleanup, err := kubeconfigPath(m)
if err != nil {
return fmt.Errorf("determining kubeconfig: %v", err)
}
defer cleanup()

cmd := kubectl(m, kubeconfig, "apply", "-f", "-")
cmd.Stdin = strings.NewReader(d.Get("content").(string))
if err := run(cmd); err != nil {
return err
}

stdout := &bytes.Buffer{}
cmd = kubectl(m, "get", "-f", "-", "-o", "json")
cmd = kubectl(m, kubeconfig, "get", "-f", "-", "-o", "json")
cmd.Stdin = strings.NewReader(d.Get("content").(string))
cmd.Stdout = stdout
if err := run(cmd); err != nil {
Expand Down Expand Up @@ -114,7 +165,13 @@ func resourceManifestCreate(d *schema.ResourceData, m interface{}) error {
}

func resourceManifestUpdate(d *schema.ResourceData, m interface{}) error {
cmd := kubectl(m, "apply", "-f", "-")
kubeconfig, cleanup, err := kubeconfigPath(m)
if err != nil {
return fmt.Errorf("determining kubeconfig: %v", err)
}
defer cleanup()

cmd := kubectl(m, kubeconfig, "apply", "-f", "-")
cmd.Stdin = strings.NewReader(d.Get("content").(string))
return run(cmd)
}
Expand Down Expand Up @@ -144,7 +201,14 @@ func resourceManifestDelete(d *schema.ResourceData, m interface{}) error {
if namespace != "" {
args = append(args, "-n", namespace)
}
return run(kubectl(m, args...))
kubeconfig, cleanup, err := kubeconfigPath(m)
if err != nil {
return fmt.Errorf("determining kubeconfig: %v", err)
}
defer cleanup()

cmd := kubectl(m, kubeconfig, args...)
return run(cmd)
}

func resourceManifestRead(d *schema.ResourceData, m interface{}) error {
Expand All @@ -159,7 +223,13 @@ func resourceManifestRead(d *schema.ResourceData, m interface{}) error {
}

stdout := &bytes.Buffer{}
cmd := kubectl(m, args...)
kubeconfig, cleanup, err := kubeconfigPath(m)
if err != nil {
return fmt.Errorf("determining kubeconfig: %v", err)
}
defer cleanup()

cmd := kubectl(m, kubeconfig, args...)
cmd.Stdout = stdout
if err := run(cmd); err != nil {
return err
Expand Down

0 comments on commit 1782090

Please sign in to comment.