mirror of
https://github.com/komodorio/helm-dashboard.git
synced 2026-03-24 11:48:04 +00:00
* Less logging when not in DEBUG * Check helm is fine * Display kube context switch * Cosmetics * Displays list of chartss * Linter stuff * Fix option name
126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
log "github.com/sirupsen/logrus"
|
|
"os/exec"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
type DataLayer struct {
|
|
}
|
|
|
|
func (l *DataLayer) runCommand(cmd ...string) (string, error) {
|
|
// TODO: --kube-context=context-name to juggle clusters
|
|
log.Debugf("Starting command: %s", cmd)
|
|
prog := exec.Command(cmd[0], cmd[1:]...)
|
|
|
|
var stdout bytes.Buffer
|
|
prog.Stdout = &stdout
|
|
|
|
var stderr bytes.Buffer
|
|
prog.Stderr = &stderr
|
|
|
|
//prog.Stdout, prog.Stderr = os.Stdout, os.Stderr
|
|
if err := prog.Run(); err != nil {
|
|
if eerr, ok := err.(*exec.ExitError); ok {
|
|
return "", fmt.Errorf("failed to run command %s: %s", cmd, eerr)
|
|
}
|
|
return "", err
|
|
}
|
|
|
|
sout := stdout.Bytes()
|
|
serr := stderr.Bytes()
|
|
log.Debugf("Command STDOUT:\n%s", sout)
|
|
log.Debugf("Command STDERR:\n%s", serr)
|
|
return string(sout), nil
|
|
}
|
|
|
|
func (l *DataLayer) CheckConnectivity() error {
|
|
contexts, err := l.ListContexts()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(contexts) < 1 {
|
|
return errors.New("did not find any kubectl contexts configured")
|
|
}
|
|
|
|
_, err = l.runCommand("helm", "env")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type KubeContext struct {
|
|
IsCurrent bool
|
|
Name string
|
|
Cluster string
|
|
AuthInfo string
|
|
Namespace string
|
|
}
|
|
|
|
func (l *DataLayer) ListContexts() (res []KubeContext, err error) {
|
|
out, err := l.runCommand("kubectl", "config", "get-contexts")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// kubectl has no JSON output for it, we'll have to do custom text parsing
|
|
lines := strings.Split(out, "\n")
|
|
|
|
// find field positions
|
|
fields := regexp.MustCompile(`(\w+\s+)`).FindAllString(lines[0], -1)
|
|
cur := len(fields[0])
|
|
name := cur + len(fields[1])
|
|
cluster := name + len(fields[2])
|
|
auth := cluster + len(fields[3])
|
|
|
|
// read items
|
|
for _, line := range lines[1:] {
|
|
if strings.TrimSpace(line) == "" {
|
|
continue
|
|
}
|
|
|
|
res = append(res, KubeContext{
|
|
IsCurrent: strings.TrimSpace(line[0:cur]) == "*",
|
|
Name: strings.TrimSpace(line[cur:name]),
|
|
Cluster: strings.TrimSpace(line[name:cluster]),
|
|
AuthInfo: strings.TrimSpace(line[cluster:auth]),
|
|
Namespace: strings.TrimSpace(line[auth:]),
|
|
})
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
// unpleasant copy from Helm sources, where they have it non-public
|
|
type releaseElement struct {
|
|
Name string `json:"name"`
|
|
Namespace string `json:"namespace"`
|
|
Revision string `json:"revision"`
|
|
Updated string `json:"updated"`
|
|
Status string `json:"status"`
|
|
Chart string `json:"chart"`
|
|
AppVersion string `json:"app_version"`
|
|
}
|
|
|
|
func (l *DataLayer) ListInstalled() (res []releaseElement, err error) {
|
|
out, err := l.runCommand("helm", "ls", "--all", "--all-namespaces", "--output", "json")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = json.Unmarshal([]byte(out), &res)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return res, nil
|
|
}
|