Files
katenary/main.go

214 lines
6.1 KiB
Go
Raw Normal View History

2021-11-30 12:04:28 +01:00
package main
import (
2021-11-30 17:29:42 +01:00
"bytes"
2021-11-30 12:04:28 +01:00
"flag"
2021-12-01 08:31:51 +01:00
"fmt"
"katenary/compose"
"katenary/generator"
"katenary/helm"
2021-11-30 12:04:28 +01:00
"os"
"path/filepath"
2021-12-02 16:07:15 +01:00
"regexp"
2021-11-30 12:09:07 +01:00
"strings"
2021-11-30 12:04:28 +01:00
"gopkg.in/yaml.v3"
)
var ComposeFile = "docker-compose.yaml"
var AppName = "MyApp"
2021-12-01 09:27:12 +01:00
var AppVersion = "0.0.1"
var Version = "master"
2021-12-01 10:36:43 +01:00
var ChartsDir = "chart"
2021-11-30 12:04:28 +01:00
2021-12-02 16:07:15 +01:00
var PrefixRE = regexp.MustCompile(`\{\{.*\}\}-?`)
2021-11-30 12:04:28 +01:00
func main() {
2021-12-01 10:36:43 +01:00
flag.StringVar(&ChartsDir, "chart-dir", ChartsDir, "set the chart directory")
2021-11-30 12:04:28 +01:00
flag.StringVar(&ComposeFile, "compose", ComposeFile, "set the compose file to parse")
flag.StringVar(&AppName, "appname", helm.GetProjectName(), "set the helm chart app name")
2021-12-01 10:36:43 +01:00
flag.StringVar(&AppVersion, "appversion", AppVersion, "set the chart appVersion")
version := flag.Bool("version", false, "Show version and exit")
force := flag.Bool("force", false, "force the removal of the chart-dir")
2021-11-30 12:04:28 +01:00
flag.Parse()
2021-12-01 08:31:51 +01:00
if *version {
2021-12-01 09:27:12 +01:00
fmt.Println(Version)
2021-12-01 08:31:51 +01:00
os.Exit(0)
}
2021-12-01 15:17:34 +01:00
// make the appname global (yes...)
helm.Appname = AppName
2021-12-01 10:36:43 +01:00
dirname := filepath.Join(ChartsDir, AppName)
if _, err := os.Stat(dirname); err == nil && !*force {
response := ""
for response != "y" && response != "n" {
response = "n"
2021-12-01 10:47:20 +01:00
fmt.Printf("The %s directory already exists, it will be \x1b[31;1mremoved\x1b[0m!\nDo you really want to continue ? [y/N]: ", dirname)
2021-12-01 10:36:43 +01:00
fmt.Scanf("%s", &response)
response = strings.ToLower(response)
}
if response == "n" {
2021-12-01 10:47:20 +01:00
fmt.Println("Cancelled")
2021-12-01 10:36:43 +01:00
os.Exit(0)
}
}
os.RemoveAll(dirname)
templatesDir := filepath.Join(dirname, "templates")
os.MkdirAll(templatesDir, 0755)
2021-12-01 09:27:12 +01:00
helm.Version = Version
2021-11-30 12:04:28 +01:00
p := compose.NewParser(ComposeFile)
p.Parse(AppName)
files := make(map[string]chan interface{})
2021-11-30 12:04:28 +01:00
//wait := sync.WaitGroup{}
2021-11-30 12:04:28 +01:00
for name, s := range p.Data.Services {
//wait.Add(1)
2021-12-01 08:31:51 +01:00
// it's mandatory to build in goroutines because some dependencies can
// wait for a port number discovery.
// So the entire services are built in parallel.
//go func(name string, s compose.Service) {
// defer wait.Done()
o := generator.CreateReplicaObject(name, s)
files[name] = o
//}(name, s)
2021-11-30 12:04:28 +01:00
}
//wait.Wait()
2021-11-30 12:04:28 +01:00
2021-12-01 08:31:51 +01:00
// to generate notes, we need to keep an Ingresses list
ingresses := make(map[string]*helm.Ingress)
2021-11-30 12:04:28 +01:00
for n, f := range files {
for c := range f {
if c == nil {
break
}
2021-11-30 12:04:28 +01:00
kind := c.(helm.Kinded).Get()
2021-11-30 12:09:07 +01:00
kind = strings.ToLower(kind)
2021-12-01 15:17:34 +01:00
c.(helm.Signable).BuildSHA(ComposeFile)
2021-11-30 17:29:42 +01:00
switch c := c.(type) {
case *helm.Storage:
fname := filepath.Join(templatesDir, n+"."+kind+".yaml")
fp, _ := os.Create(fname)
2021-11-30 17:29:42 +01:00
volname := c.K8sBase.Metadata.Labels[helm.K+"/pvc-name"]
fp.WriteString("{{ if .Values." + n + ".persistence." + volname + ".enabled }}\n")
enc := yaml.NewEncoder(fp)
enc.SetIndent(2)
enc.Encode(c)
fp.WriteString("{{- end -}}")
case *helm.Deployment:
fname := filepath.Join(templatesDir, n+"."+kind+".yaml")
fp, _ := os.Create(fname)
2021-11-30 17:32:14 +01:00
buffer := bytes.NewBuffer(nil)
2021-11-30 17:29:42 +01:00
enc := yaml.NewEncoder(buffer)
enc.SetIndent(2)
enc.Encode(c)
_content := string(buffer.Bytes())
content := strings.Split(string(_content), "\n")
dataname := ""
component := c.Spec.Selector["matchLabels"].(map[string]string)[helm.K+"/component"]
for _, line := range content {
if strings.Contains(line, "name:") {
dataname = strings.Split(line, ":")[1]
dataname = strings.TrimSpace(dataname)
} else if strings.Contains(line, "persistentVolumeClaim") {
line = " {{- if .Values." + component + ".persistence." + dataname + ".enabled }}\n" + line
} else if strings.Contains(line, "claimName") {
line += "\n {{ else }}"
line += "\n emptyDir: {}"
line += "\n {{- end }}"
}
fp.WriteString(line + "\n")
}
fp.Close()
case *helm.Service:
suffix := ""
if c.Spec.Type == "NodePort" {
suffix = "-external"
}
fname := filepath.Join(templatesDir, n+suffix+"."+kind+".yaml")
fp, _ := os.Create(fname)
enc := yaml.NewEncoder(fp)
enc.SetIndent(2)
enc.Encode(c)
fp.Close()
2021-12-01 08:31:51 +01:00
case *helm.Ingress:
buffer := bytes.NewBuffer(nil)
fname := filepath.Join(templatesDir, n+"."+kind+".yaml")
2021-12-01 08:31:51 +01:00
ingresses[n] = c // keep it to generate notes
enc := yaml.NewEncoder(buffer)
2021-12-01 08:31:51 +01:00
enc.SetIndent(2)
buffer.WriteString("{{- if .Values." + n + ".ingress.enabled -}}\n")
2021-12-01 08:31:51 +01:00
enc.Encode(c)
buffer.WriteString("{{- end -}}")
fp, _ := os.Create(fname)
content := string(buffer.Bytes())
lines := strings.Split(content, "\n")
for _, l := range lines {
if strings.Contains(l, "ingressClassName") {
p := strings.Split(l, ":")
condition := p[1]
condition = strings.ReplaceAll(condition, "'", "")
condition = strings.ReplaceAll(condition, "{{", "")
condition = strings.ReplaceAll(condition, "}}", "")
condition = strings.TrimSpace(condition)
condition = "{{- if " + condition + " }}"
l = " " + condition + "\n" + l + "\n {{- end }}"
}
fp.WriteString(l + "\n")
}
fp.Close()
2021-12-01 08:31:51 +01:00
2021-12-02 16:07:15 +01:00
case *helm.ConfigMap, *helm.Secret:
// there could be several files, so let's force the filename
name := c.(helm.Named).Name()
name = PrefixRE.ReplaceAllString(name, "")
fname := filepath.Join(templatesDir, n+"."+name+"."+kind+".yaml")
fp, _ := os.Create(fname)
enc := yaml.NewEncoder(fp)
enc.SetIndent(2)
enc.Encode(c)
fp.Close()
2021-11-30 17:29:42 +01:00
default:
fname := filepath.Join(templatesDir, n+"."+kind+".yaml")
fp, _ := os.Create(fname)
2021-11-30 17:29:42 +01:00
enc := yaml.NewEncoder(fp)
enc.SetIndent(2)
enc.Encode(c)
fp.Close()
2021-11-30 17:29:42 +01:00
}
2021-11-30 12:04:28 +01:00
}
}
2021-11-30 12:17:38 +01:00
fp, _ := os.Create(filepath.Join(dirname, "values.yaml"))
enc := yaml.NewEncoder(fp)
2021-11-30 12:04:28 +01:00
enc.SetIndent(2)
enc.Encode(generator.Values)
2021-11-30 12:17:38 +01:00
fp.Close()
2021-11-30 12:04:28 +01:00
2021-11-30 12:17:38 +01:00
fp, _ = os.Create(filepath.Join(dirname, "Chart.yaml"))
enc = yaml.NewEncoder(fp)
enc.SetIndent(2)
enc.Encode(map[string]interface{}{
"apiVersion": "v2",
"name": AppName,
"description": "A helm chart for " + AppName,
"type": "application",
"version": "0.1.0",
2021-11-30 15:35:32 +01:00
"appVersion": AppVersion,
2021-11-30 12:17:38 +01:00
})
fp.Close()
2021-11-30 15:35:32 +01:00
fp, _ = os.Create(filepath.Join(templatesDir, "NOTES.txt"))
2021-12-01 08:31:51 +01:00
fp.WriteString(helm.GenNotes(ingresses))
2021-11-30 15:35:32 +01:00
fp.Close()
2021-11-30 12:04:28 +01:00
}