Fix lot of things...
This commit is contained in:
8
generator/color_test.go
Normal file
8
generator/color_test.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestColor(t *testing.T) {
|
||||||
|
Red("Red text")
|
||||||
|
Grey("Grey text")
|
||||||
|
}
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"helm-compose/compose"
|
"helm-compose/compose"
|
||||||
"helm-compose/helm"
|
"helm-compose/helm"
|
||||||
"log"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -34,6 +34,7 @@ echo "Done"
|
|||||||
|
|
||||||
func CreateReplicaObject(name string, s compose.Service) (ret []interface{}) {
|
func CreateReplicaObject(name string, s compose.Service) (ret []interface{}) {
|
||||||
|
|
||||||
|
Magenta("Generating deployment for ", name)
|
||||||
o := helm.NewDeployment()
|
o := helm.NewDeployment()
|
||||||
ret = append(ret, o)
|
ret = append(ret, o)
|
||||||
o.Metadata.Name = "{{ .Release.Name }}-" + name
|
o.Metadata.Name = "{{ .Release.Name }}-" + name
|
||||||
@@ -45,14 +46,25 @@ func CreateReplicaObject(name string, s compose.Service) (ret []interface{}) {
|
|||||||
"image": s.Image,
|
"image": s.Image,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exists := make(map[int]string)
|
||||||
for _, port := range s.Ports {
|
for _, port := range s.Ports {
|
||||||
portNumber, _ := strconv.Atoi(port)
|
portNumber, _ := strconv.Atoi(port)
|
||||||
|
portName := name
|
||||||
|
for _, n := range exists {
|
||||||
|
if name == n {
|
||||||
|
portName = fmt.Sprintf("%s-%d", name, portNumber)
|
||||||
|
}
|
||||||
|
}
|
||||||
container.Ports = append(container.Ports, &helm.ContainerPort{
|
container.Ports = append(container.Ports, &helm.ContainerPort{
|
||||||
Name: name,
|
Name: portName,
|
||||||
ContainerPort: portNumber,
|
ContainerPort: portNumber,
|
||||||
})
|
})
|
||||||
|
exists[portNumber] = name
|
||||||
}
|
}
|
||||||
for _, port := range s.Expose {
|
for _, port := range s.Expose {
|
||||||
|
if _, exist := exists[port]; exist {
|
||||||
|
continue
|
||||||
|
}
|
||||||
container.Ports = append(container.Ports, &helm.ContainerPort{
|
container.Ports = append(container.Ports, &helm.ContainerPort{
|
||||||
Name: name,
|
Name: name,
|
||||||
ContainerPort: port,
|
ContainerPort: port,
|
||||||
@@ -70,9 +82,10 @@ func CreateReplicaObject(name string, s compose.Service) (ret []interface{}) {
|
|||||||
initContainers := make([]*helm.Container, 0)
|
initContainers := make([]*helm.Container, 0)
|
||||||
for _, dp := range s.DependsOn {
|
for _, dp := range s.DependsOn {
|
||||||
if len(s.Ports) == 0 && len(s.Expose) == 0 {
|
if len(s.Ports) == 0 && len(s.Expose) == 0 {
|
||||||
log.Fatalf("Sorry, you need to expose or declare at least one port for the %s service to check \"depends_on\"", name)
|
Redf("No port exposed for %s that is in dependency", name)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
c := helm.NewContainer("check-"+name, "busybox", nil, s.Labels)
|
c := helm.NewContainer("check-"+dp, "busybox", nil, s.Labels)
|
||||||
command := strings.ReplaceAll(strings.TrimSpace(DependScript), "__service__", dp)
|
command := strings.ReplaceAll(strings.TrimSpace(DependScript), "__service__", dp)
|
||||||
|
|
||||||
wait.Add(1)
|
wait.Add(1)
|
||||||
@@ -102,14 +115,19 @@ func CreateReplicaObject(name string, s compose.Service) (ret []interface{}) {
|
|||||||
ret = append(ret, ks)
|
ret = append(ret, ks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Green("Done deployment ", name)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createService(name string, s compose.Service) *helm.Service {
|
func createService(name string, s compose.Service) *helm.Service {
|
||||||
|
|
||||||
|
Magenta("Generating service for ", name)
|
||||||
ks := helm.NewService()
|
ks := helm.NewService()
|
||||||
ks.Metadata.Name = "{{ .Release.Name }}-" + name
|
ks.Metadata.Name = "{{ .Release.Name }}-" + name
|
||||||
defaultPort := 0
|
defaultPort := 0
|
||||||
|
names := make(map[int]int)
|
||||||
|
|
||||||
for i, p := range s.Ports {
|
for i, p := range s.Ports {
|
||||||
port := strings.Split(p, ":")
|
port := strings.Split(p, ":")
|
||||||
src, _ := strconv.Atoi(port[0])
|
src, _ := strconv.Atoi(port[0])
|
||||||
@@ -118,12 +136,16 @@ func createService(name string, s compose.Service) *helm.Service {
|
|||||||
target, _ = strconv.Atoi(port[1])
|
target, _ = strconv.Atoi(port[1])
|
||||||
}
|
}
|
||||||
ks.Spec.Ports = append(ks.Spec.Ports, helm.NewServicePort(src, target))
|
ks.Spec.Ports = append(ks.Spec.Ports, helm.NewServicePort(src, target))
|
||||||
|
names[target] = 1
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
defaultPort = target
|
defaultPort = target
|
||||||
detected(name, target)
|
detected(name, target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, p := range s.Expose {
|
for i, p := range s.Expose {
|
||||||
|
if _, ok := names[p]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ks.Spec.Ports = append(ks.Spec.Ports, helm.NewServicePort(p, p))
|
ks.Spec.Ports = append(ks.Spec.Ports, helm.NewServicePort(p, p))
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
defaultPort = p
|
defaultPort = p
|
||||||
@@ -134,16 +156,17 @@ func createService(name string, s compose.Service) *helm.Service {
|
|||||||
ks.Spec.Selector = buildSelector(name, s)
|
ks.Spec.Selector = buildSelector(name, s)
|
||||||
|
|
||||||
if v, ok := s.Labels[helm.K+"/expose-ingress"]; ok && v == "true" {
|
if v, ok := s.Labels[helm.K+"/expose-ingress"]; ok && v == "true" {
|
||||||
log.Println("Expose ingress for ", name)
|
|
||||||
createIngress(name, defaultPort, s)
|
createIngress(name, defaultPort, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Green("Done service ", name)
|
||||||
return ks
|
return ks
|
||||||
}
|
}
|
||||||
|
|
||||||
func createIngress(name string, port int, s compose.Service) {
|
func createIngress(name string, port int, s compose.Service) {
|
||||||
ingress := helm.NewIngress(name)
|
ingress := helm.NewIngress(name)
|
||||||
Values[name]["ingress"] = map[string]interface{}{
|
Values[name]["ingress"] = map[string]interface{}{
|
||||||
|
"class": "nginx",
|
||||||
"host": "chart.example.tld",
|
"host": "chart.example.tld",
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
}
|
}
|
||||||
@@ -166,6 +189,7 @@ func createIngress(name string, port int, s compose.Service) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
ingress.SetIngressClass(name)
|
||||||
|
|
||||||
locker.Lock()
|
locker.Lock()
|
||||||
Ingresses[name] = ingress
|
Ingresses[name] = ingress
|
||||||
|
76
generator/utils.go
Normal file
76
generator/utils.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Color int
|
||||||
|
|
||||||
|
const (
|
||||||
|
GREY Color = 30 + iota
|
||||||
|
RED
|
||||||
|
GREEN
|
||||||
|
YELLOW
|
||||||
|
BLUE
|
||||||
|
MAGENTA
|
||||||
|
CYAN
|
||||||
|
)
|
||||||
|
|
||||||
|
var waiter = sync.Mutex{}
|
||||||
|
|
||||||
|
func color(c Color, args ...interface{}) {
|
||||||
|
waiter.Lock()
|
||||||
|
fmt.Fprintf(os.Stdout, "\x1b[%dm", c)
|
||||||
|
fmt.Fprint(os.Stdout, args...)
|
||||||
|
fmt.Fprintf(os.Stdout, "\x1b[0m\n")
|
||||||
|
waiter.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func colorf(c Color, format string, args ...interface{}) {
|
||||||
|
waiter.Lock()
|
||||||
|
fmt.Fprintf(os.Stdout, "\x1b[%dm", c)
|
||||||
|
fmt.Fprintf(os.Stdout, format, args...)
|
||||||
|
fmt.Fprintf(os.Stdout, "\x1b[0m")
|
||||||
|
waiter.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Grey(args ...interface{}) {
|
||||||
|
color(GREY, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Red(args ...interface{}) {
|
||||||
|
color(RED, args...)
|
||||||
|
}
|
||||||
|
func Green(args ...interface{}) {
|
||||||
|
color(GREEN, args...)
|
||||||
|
}
|
||||||
|
func Yellow(args ...interface{}) {
|
||||||
|
color(YELLOW, args...)
|
||||||
|
}
|
||||||
|
func Blue(args ...interface{}) {
|
||||||
|
color(BLUE, args...)
|
||||||
|
}
|
||||||
|
func Magenta(args ...interface{}) {
|
||||||
|
color(MAGENTA, args...)
|
||||||
|
}
|
||||||
|
func Greyf(format string, args ...interface{}) {
|
||||||
|
colorf(GREY, format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Redf(format string, args ...interface{}) {
|
||||||
|
colorf(RED, format, args...)
|
||||||
|
}
|
||||||
|
func Greenf(format string, args ...interface{}) {
|
||||||
|
colorf(GREEN, format, args...)
|
||||||
|
}
|
||||||
|
func Yellowf(format string, args ...interface{}) {
|
||||||
|
colorf(YELLOW, format, args...)
|
||||||
|
}
|
||||||
|
func Bluef(format string, args ...interface{}) {
|
||||||
|
colorf(BLUE, format, args...)
|
||||||
|
}
|
||||||
|
func Magentaf(format string, args ...interface{}) {
|
||||||
|
colorf(MAGENTA, format, args...)
|
||||||
|
}
|
@@ -15,8 +15,15 @@ func NewIngress(name string) *Ingress {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Ingress) SetIngressClass(name string) {
|
||||||
|
class := "{{ .Values." + name + ".ingress.class }}"
|
||||||
|
i.Metadata.Annotations["kuberntes.io/ingress.class"] = class
|
||||||
|
i.Spec.IngressClassName = class
|
||||||
|
}
|
||||||
|
|
||||||
type IngressSpec struct {
|
type IngressSpec struct {
|
||||||
Rules []IngressRule
|
IngressClassName string `yaml:"ingressClassName,omitempty"`
|
||||||
|
Rules []IngressRule
|
||||||
}
|
}
|
||||||
|
|
||||||
type IngressRule struct {
|
type IngressRule struct {
|
||||||
@@ -30,7 +37,7 @@ type IngressHttp struct {
|
|||||||
|
|
||||||
type IngressPath struct {
|
type IngressPath struct {
|
||||||
Path string
|
Path string
|
||||||
PathType string
|
PathType string `yaml:"pathType"`
|
||||||
Backend IngressBackend
|
Backend IngressBackend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
helm/notes.go
Normal file
24
helm/notes.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package helm
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
var NOTES = `
|
||||||
|
Congratulations,
|
||||||
|
|
||||||
|
Your application is now deployed. This may take a while to be up and responding.
|
||||||
|
|
||||||
|
__list__
|
||||||
|
`
|
||||||
|
|
||||||
|
func GenNotes(ingressess map[string]*Ingress) string {
|
||||||
|
|
||||||
|
list := make([]string, 0)
|
||||||
|
|
||||||
|
for name, ing := range ingressess {
|
||||||
|
for _, r := range ing.Spec.Rules {
|
||||||
|
list = append(list, "{{ if .Values."+name+".ingress.enabled }}- "+name+" is accessible on : http://"+r.Host+"{{- end }}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.ReplaceAll(NOTES, "__list__", strings.Join(list, "\n"))
|
||||||
|
}
|
11
main.go
11
main.go
@@ -15,11 +15,13 @@ import (
|
|||||||
|
|
||||||
var ComposeFile = "docker-compose.yaml"
|
var ComposeFile = "docker-compose.yaml"
|
||||||
var AppName = "MyApp"
|
var AppName = "MyApp"
|
||||||
|
var AppVersion = "0.0.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
flag.StringVar(&ComposeFile, "compose", ComposeFile, "set the compose file to parse")
|
flag.StringVar(&ComposeFile, "compose", ComposeFile, "set the compose file to parse")
|
||||||
flag.StringVar(&AppName, "appname", AppName, "Give the helm chart app name")
|
flag.StringVar(&AppName, "appname", AppName, "Give the helm chart app name")
|
||||||
|
flag.StringVar(&AppVersion, "appversion", AppVersion, "Set the chart appVersion")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
p := compose.NewParser(ComposeFile)
|
p := compose.NewParser(ComposeFile)
|
||||||
@@ -39,6 +41,7 @@ func main() {
|
|||||||
wait.Wait()
|
wait.Wait()
|
||||||
|
|
||||||
dirname := filepath.Join("chart", AppName)
|
dirname := filepath.Join("chart", AppName)
|
||||||
|
os.RemoveAll(dirname)
|
||||||
templatesDir := filepath.Join(dirname, "templates")
|
templatesDir := filepath.Join(dirname, "templates")
|
||||||
os.MkdirAll(templatesDir, 0755)
|
os.MkdirAll(templatesDir, 0755)
|
||||||
|
|
||||||
@@ -56,7 +59,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for name, ing := range generator.Ingresses {
|
for name, ing := range generator.Ingresses {
|
||||||
|
|
||||||
fname := filepath.Join(templatesDir, name+".ingress.yaml")
|
fname := filepath.Join(templatesDir, name+".ingress.yaml")
|
||||||
fp, _ := os.Create(fname)
|
fp, _ := os.Create(fname)
|
||||||
enc := yaml.NewEncoder(fp)
|
enc := yaml.NewEncoder(fp)
|
||||||
@@ -82,7 +84,12 @@ func main() {
|
|||||||
"description": "A helm chart for " + AppName,
|
"description": "A helm chart for " + AppName,
|
||||||
"type": "application",
|
"type": "application",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"appVersion": "x",
|
"appVersion": AppVersion,
|
||||||
})
|
})
|
||||||
fp.Close()
|
fp.Close()
|
||||||
|
|
||||||
|
fp, _ = os.Create(filepath.Join(templatesDir, "NOTES.txt"))
|
||||||
|
fp.WriteString(helm.GenNotes(generator.Ingresses))
|
||||||
|
fp.Close()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user