| giolekva | d5a58c4 | 2020-05-07 22:18:35 +0400 | [diff] [blame^] | 1 | package appmanager |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "fmt" |
| 6 | "os/exec" |
| 7 | "strings" |
| 8 | |
| 9 | "github.com/golang/glog" |
| 10 | ) |
| 11 | |
| 12 | type Unpacker interface { |
| 13 | Unpack(archive string, |
| 14 | namespace string, |
| 15 | releaseRame string, |
| 16 | values map[string]string) (map[string][]string, error) |
| 17 | } |
| 18 | |
| 19 | type helmUnpacker struct { |
| 20 | helmBin string |
| 21 | } |
| 22 | |
| 23 | func NewHelmUnpacker(helmBin string) Unpacker { |
| 24 | return &helmUnpacker{helmBin} |
| 25 | } |
| 26 | |
| 27 | func (h *helmUnpacker) Unpack( |
| 28 | archive string, |
| 29 | namespace string, |
| 30 | releaseName string, |
| 31 | values map[string]string) (map[string][]string, error) { |
| 32 | cmd := h.generateHelmInstallCmd(archive, namespace, releaseName, values) |
| 33 | glog.Info(cmd.String()) |
| 34 | var stdout strings.Builder |
| 35 | var stderr strings.Builder |
| 36 | cmd.Stdout = &stdout |
| 37 | cmd.Stderr = &stderr |
| 38 | err := cmd.Run() |
| 39 | if err != nil { |
| 40 | return nil, errors.New(stderr.String()) |
| 41 | } |
| 42 | return extractTemplates(stdout.String()) |
| 43 | } |
| 44 | |
| 45 | func (h *helmUnpacker) generateHelmInstallCmd( |
| 46 | archive string, |
| 47 | namespace string, |
| 48 | releaseName string, |
| 49 | values map[string]string) *exec.Cmd { |
| 50 | cmd := exec.Command(h.helmBin) |
| 51 | cmd.Args = append(cmd.Args, "template") |
| 52 | cmd.Args = append(cmd.Args, fmt.Sprintf("--namespace=%s", namespace)) |
| 53 | cmd.Args = append(cmd.Args, fmt.Sprintf("%s", releaseName)) |
| 54 | cmd.Args = append(cmd.Args, fmt.Sprintf("%s", archive)) |
| 55 | // TODO(giolekva): validate values |
| 56 | for key, value := range values { |
| 57 | cmd.Args = append(cmd.Args, fmt.Sprintf("--set=%s=%s", key, value)) |
| 58 | } |
| 59 | return cmd |
| 60 | } |
| 61 | |
| 62 | func extractTemplates(bundle string) (map[string][]string, error) { |
| 63 | items := strings.Split(bundle, "---") |
| 64 | temps := make(map[string][]string) |
| 65 | for _, item := range items { |
| 66 | if len(item) == 0 { |
| 67 | continue |
| 68 | } |
| 69 | tmp := strings.SplitN(item, "\n", 3) |
| 70 | if len(tmp) != 3 { |
| 71 | return nil, fmt.Errorf("Got invalid template: %s", item) |
| 72 | } |
| 73 | source := tmp[1] |
| 74 | glog.Info(source) |
| 75 | // if !strings.HasPrefix(source, "\n# Source: ") { |
| 76 | // return nil, fmt.Errorf("Got invalid source: %s", item) |
| 77 | // } |
| 78 | sourceItems := strings.Split(source, "/") |
| 79 | glog.Info(sourceItems) |
| 80 | if len(sourceItems) != 3 { |
| 81 | return nil, fmt.Errorf("Got invalid source: %s", item) |
| 82 | } |
| 83 | path := sourceItems[1] + "/" + sourceItems[2] |
| 84 | if _, ok := temps[path]; !ok { |
| 85 | temps[path] = make([]string, 1) |
| 86 | } |
| 87 | temps[path] = append(temps[path], tmp[2]) |
| 88 | } |
| 89 | return temps, nil |
| 90 | } |