appmanager: with web interface to upload chart archives
diff --git a/appmanager/helm.go b/appmanager/helm.go
new file mode 100644
index 0000000..5fd7e8e
--- /dev/null
+++ b/appmanager/helm.go
@@ -0,0 +1,113 @@
+package appmanager
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "github.com/golang/glog"
+ "gopkg.in/yaml.v2"
+)
+
+type Chart struct {
+ Name string `yaml:"name"`
+}
+
+type HelmChart struct {
+ Chart
+ chartDir string
+ Schema *Schema
+ Yamls []string
+}
+
+func HelmChartFromDir(chartDir string) (*HelmChart, error) {
+ var chart HelmChart
+ chart.chartDir = chartDir
+ c, err := ReadChart(path.Join(chartDir, "Chart.yaml"))
+ if err != nil {
+ return nil, err
+ }
+ chart.Chart = *c
+ schema, err := ReadSchema(path.Join(chartDir, "Schema.yaml"))
+ if err != nil && os.IsNotExist(err) {
+ return nil, err
+ }
+ chart.Schema = schema
+ return &chart, nil
+}
+
+func HelmChartFromTar(chartTar string) (*HelmChart, error) {
+ if !strings.HasSuffix(chartTar, ".tar.gz") {
+ return nil, errors.New("Expected .tar.gz file")
+ }
+ dir := filepath.Dir(chartTar)
+ archive := filepath.Base(chartTar)
+ extractDir := strings.TrimSuffix(archive, ".tar.gz")
+ cmd := exec.Command(fmt.Sprintf("cd %s && rm -rf %s && tar -ztvf %s -C %s", dir, extractDir, archive, extractDir))
+ if err := cmd.Run(); err != nil {
+ return nil, err
+ }
+ return HelmChartFromDir(dir + "/" + extractDir)
+}
+
+func (h *HelmChart) Install(
+ helmBin string,
+ values map[string]string) error {
+ namespace := fmt.Sprintf("app-%s", h.Chart.Name)
+ cmd := generateHelmInstallCmd(helmBin, h.chartDir, namespace, values)
+ glog.Info(cmd.String())
+ var stdout strings.Builder
+ var stderr strings.Builder
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ err := cmd.Run()
+ if err != nil {
+ return errors.New(stderr.String())
+ }
+ glog.Info(stdout.String())
+ return nil
+}
+
+func generateHelmInstallCmd(
+ helmBin string,
+ archive string,
+ namespace string,
+ values map[string]string) *exec.Cmd {
+ cmd := exec.Command(helmBin)
+ cmd.Args = append(cmd.Args, "install")
+ cmd.Args = append(cmd.Args, fmt.Sprintf("--namespace=%s", namespace))
+ cmd.Args = append(cmd.Args, "--generate-name")
+ cmd.Args = append(cmd.Args, fmt.Sprintf("%s", archive))
+ // TODO(giolekva): validate values
+ for key, value := range values {
+ cmd.Args = append(cmd.Args, fmt.Sprintf("--set=%s=%s", key, value))
+ }
+ return cmd
+}
+
+func ChartFromYaml(str string) (*Chart, error) {
+ var s Chart
+ err := yaml.Unmarshal([]byte(str), &s)
+ if err != nil {
+ return nil, err
+ }
+ return &s, nil
+}
+
+func ReadChart(chartFile string) (*Chart, error) {
+ f, err := os.Open(chartFile)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ b, err := ioutil.ReadAll(f)
+ if err != nil {
+ return nil, err
+ }
+ return ChartFromYaml(string(b))
+}