appmanager: helm package unpacker
diff --git a/appmanager/cmd/main.go b/appmanager/cmd/main.go
new file mode 100644
index 0000000..ec7dcd6
--- /dev/null
+++ b/appmanager/cmd/main.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ app "github.com/giolekva/pcloud/appmanager"
+
+ "github.com/golang/glog"
+)
+
+func main() {
+ unpacker := app.NewHelmUnpacker("/usr/local/bin/helm")
+ temps, err := unpacker.Unpack("/Users/lekva/dev/go/src/github.com/giolekva/pcloud/apps/rpuppy/chart",
+ "app-rpuppy",
+ "init-release",
+ map[string]string{
+ "replicas": "2",
+ "servicePort": "8080",
+ },
+ )
+ if err != nil {
+ panic(err)
+ }
+ glog.Info(temps)
+}
diff --git a/appmanager/go.mod b/appmanager/go.mod
new file mode 100644
index 0000000..966e59e
--- /dev/null
+++ b/appmanager/go.mod
@@ -0,0 +1,5 @@
+module github.com/giolekva/pcloud/appmanager
+
+go 1.14
+
+require github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
diff --git a/appmanager/go.sum b/appmanager/go.sum
new file mode 100644
index 0000000..e323037
--- /dev/null
+++ b/appmanager/go.sum
@@ -0,0 +1,2 @@
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
diff --git a/appmanager/unpacker.go b/appmanager/unpacker.go
new file mode 100644
index 0000000..e56d5f2
--- /dev/null
+++ b/appmanager/unpacker.go
@@ -0,0 +1,90 @@
+package appmanager
+
+import (
+ "errors"
+ "fmt"
+ "os/exec"
+ "strings"
+
+ "github.com/golang/glog"
+)
+
+type Unpacker interface {
+ Unpack(archive string,
+ namespace string,
+ releaseRame string,
+ values map[string]string) (map[string][]string, error)
+}
+
+type helmUnpacker struct {
+ helmBin string
+}
+
+func NewHelmUnpacker(helmBin string) Unpacker {
+ return &helmUnpacker{helmBin}
+}
+
+func (h *helmUnpacker) Unpack(
+ archive string,
+ namespace string,
+ releaseName string,
+ values map[string]string) (map[string][]string, error) {
+ cmd := h.generateHelmInstallCmd(archive, namespace, releaseName, 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 nil, errors.New(stderr.String())
+ }
+ return extractTemplates(stdout.String())
+}
+
+func (h *helmUnpacker) generateHelmInstallCmd(
+ archive string,
+ namespace string,
+ releaseName string,
+ values map[string]string) *exec.Cmd {
+ cmd := exec.Command(h.helmBin)
+ cmd.Args = append(cmd.Args, "template")
+ cmd.Args = append(cmd.Args, fmt.Sprintf("--namespace=%s", namespace))
+ cmd.Args = append(cmd.Args, fmt.Sprintf("%s", releaseName))
+ 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 extractTemplates(bundle string) (map[string][]string, error) {
+ items := strings.Split(bundle, "---")
+ temps := make(map[string][]string)
+ for _, item := range items {
+ if len(item) == 0 {
+ continue
+ }
+ tmp := strings.SplitN(item, "\n", 3)
+ if len(tmp) != 3 {
+ return nil, fmt.Errorf("Got invalid template: %s", item)
+ }
+ source := tmp[1]
+ glog.Info(source)
+ // if !strings.HasPrefix(source, "\n# Source: ") {
+ // return nil, fmt.Errorf("Got invalid source: %s", item)
+ // }
+ sourceItems := strings.Split(source, "/")
+ glog.Info(sourceItems)
+ if len(sourceItems) != 3 {
+ return nil, fmt.Errorf("Got invalid source: %s", item)
+ }
+ path := sourceItems[1] + "/" + sourceItems[2]
+ if _, ok := temps[path]; !ok {
+ temps[path] = make([]string, 1)
+ }
+ temps[path] = append(temps[path], tmp[2])
+ }
+ return temps, nil
+}