Skip to content

Commit

Permalink
feat(kubernetes): kubectl context
Browse files Browse the repository at this point in the history
Adds support for automatically choosing the right kubectl context, based on data
from spec.json
  • Loading branch information
sh0rez committed Jul 30, 2019
1 parent 3155414 commit 2b3fd3c
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.4.0
github.com/stretchr/objx v0.2.0
github.com/thoas/go-funk v0.4.0
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f // indirect
golang.org/x/text v0.3.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/thoas/go-funk v0.4.0 h1:KBaa5NL7NMtsFlQaD8nQMbDt1wuM+OOaNQyYNYQFhVo=
github.com/thoas/go-funk v0.4.0/go.mod h1:mlR+dHGb+4YgXkf13rkQTuzrneeHANxOm6+ZnEV9HsA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
Expand Down
67 changes: 64 additions & 3 deletions pkg/provider/kubernetes/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,74 @@ import (
"bytes"
"encoding/json"
"fmt"
"net"
"net/url"
"os"
"os/exec"

"github.com/stretchr/objx"
funk "github.com/thoas/go-funk"
)

// Kubectl uses the `kubectl` command to operate on a Kubernetes cluster
type Kubectl struct{}
type Kubectl struct {
context string
}

func (k Kubectl) setupContext(apiServer, namespace string) error {
cmd := exec.Command("kubectl", "config", "view", "-o", "json")
cfgJSON := bytes.Buffer{}
cmd.Stdout = &cfgJSON
if err := cmd.Run(); err != nil {
return err
}
var cfg map[string]interface{}
if err := json.Unmarshal(cfgJSON.Bytes(), &cfg); err != nil {
return err
}

var err error
k.context, err = contextFromKubeconfig(cfg, apiServer, namespace)
if err != nil {
return err
}
return nil
}

func contextFromKubeconfig(kubeconfig map[string]interface{}, apiServer, namespace string) (string, error) {
cfg := objx.New(kubeconfig)

// find the correct cluster
cluster := objx.New(funk.Find(cfg.Get("clusters").MustMSISlice(), func(x map[string]interface{}) bool {
c := objx.New(x)
u, err := url.Parse(c.Get("cluster.server").MustStr())
if err != nil {
panic(err)
}
host, _, err := net.SplitHostPort(u.Host)
if err != nil {
panic(err)
}
return host == apiServer
}))

// find a context that uses the cluster
context := objx.New(funk.Find(cfg.Get("contexts").MustMSISlice(), func(x map[string]interface{}) bool {
c := objx.New(x)
return c.Get("context.cluster").MustStr() == cluster.Get("name").MustStr()
}))

return context.Get("name").MustStr(), nil
}

// Get retrieves an Kubernetes object from the API
func (k Kubectl) Get(namespace, kind, name string) (map[string]interface{}, error) {
argv := []string{"get", "-o", "json", "-n", namespace, kind, name}
argv := []string{"get",
"-o", "json",
"-n", namespace,
"--context", k.context,
kind, name,
}
cmd := exec.Command("kubectl", argv...)
raw := bytes.Buffer{}
cmd.Stdout = &raw
Expand All @@ -31,7 +89,10 @@ func (k Kubectl) Get(namespace, kind, name string) (map[string]interface{}, erro
// Diff takes a desired state as yaml and returns the differences
// to the system in common diff format
func (k Kubectl) Diff(yaml string) (string, error) {
argv := []string{"diff", "-f", "-"}
argv := []string{"diff",
"--context", k.context,
"-f", "-",
}
cmd := exec.Command("kubectl", argv...)
raw := bytes.Buffer{}
cmd.Stdout = &raw
Expand Down
1 change: 1 addition & 0 deletions pkg/provider/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var client = Kubectl{}

// Init makes the provider ready to be used
func (k *Kubernetes) Init() error {
return client.setupContext(k.APIServer, k.Namespace)
}

// Reconcile receives the raw evaluated jsonnet as a marshaled json dict and
Expand Down

0 comments on commit 2b3fd3c

Please sign in to comment.