diff --git a/compose/parser.go b/compose/parser.go index 4975655..ca9b8b0 100644 --- a/compose/parser.go +++ b/compose/parser.go @@ -59,6 +59,7 @@ func (p *Parser) Parse(appname string) { for _, s := range p.Data.Services { parseEnv(s) parseCommand(s) + parseEnvFiles(s) } c := p.Data @@ -143,7 +144,8 @@ func parseEnv(s *Service) { env = s.RawEnvironment.(map[string]string) case map[string]interface{}: for k, v := range s.RawEnvironment.(map[string]interface{}) { - env[k] = v.(string) + // force to string + env[k] = fmt.Sprintf("%v", v) } case []interface{}: for _, v := range s.RawEnvironment.([]interface{}) { @@ -156,7 +158,6 @@ func parseEnv(s *Service) { env[parts[0]] = parts[1] default: log.Printf("%+v, %T", s.RawEnvironment, s.RawEnvironment) - log.Printf("%+v", s) log.Fatal("Environment type not supported") } s.Environment = env @@ -188,3 +189,23 @@ func parseCommand(s *Service) { log.Fatal("Command type not supported") } } + +func parseEnvFiles(s *Service) { + // Same than parseEnv, but for env files + if s.RawEnvFiles == nil { + return + } + envfiles := make([]string, 0) + switch s.RawEnvFiles.(type) { + case []string: + envfiles = s.RawEnvFiles.([]string) + case []interface{}: + for _, v := range s.RawEnvFiles.([]interface{}) { + envfiles = append(envfiles, v.(string)) + } + default: + log.Printf("%+v %T", s.RawEnvFiles, s.RawEnvFiles) + log.Fatal("EnvFile type not supported") + } + s.EnvFiles = envfiles +} diff --git a/compose/parser_test.go b/compose/parser_test.go index 79876b1..b6f5b74 100644 --- a/compose/parser_test.go +++ b/compose/parser_test.go @@ -1,6 +1,9 @@ package compose -import "testing" +import ( + "katenary/logger" + "testing" +) const DOCKER_COMPOSE_YML1 = ` version: "3" @@ -29,8 +32,20 @@ services: labels: katenary.io/ports: "5432" + commander1: + image: foo + command: ["/bin/sh", "-c", "echo 'hello world'"] + + commander2: + image: foo + command: echo "hello world" + ` +func init() { + logger.NOLOG = true +} + func TestParser(t *testing.T) { p := NewParser("", DOCKER_COMPOSE_YML1) p.Parse("test") @@ -85,5 +100,39 @@ func TestParser(t *testing.T) { } } } - +} + +func TestParseCommand(t *testing.T) { + p := NewParser("", DOCKER_COMPOSE_YML1) + p.Parse("test") + + for name, s := range p.Data.Services { + if name == "commander1" { + t.Log(s.Command) + if len(s.Command) != 3 { + t.Errorf("Expected 3 command, got %d", len(s.Command)) + } + if s.Command[0] != "/bin/sh" { + t.Errorf("Expected /bin/sh, got %s", s.Command[0]) + } + if s.Command[1] != "-c" { + t.Errorf("Expected -c, got %s", s.Command[1]) + } + if s.Command[2] != "echo 'hello world'" { + t.Errorf("Expected echo 'hello world', got %s", s.Command[2]) + } + } + if name == "commander2" { + t.Log(s.Command) + if len(s.Command) != 2 { + t.Errorf("Expected 1 command, got %d", len(s.Command)) + } + if s.Command[0] != "echo" { + t.Errorf("Expected echo, got %s", s.Command[0]) + } + if s.Command[1] != "hello world" { + t.Errorf("Expected hello world, got %s", s.Command[1]) + } + } + } } diff --git a/compose/types.go b/compose/types.go index 013147b..ce77f72 100644 --- a/compose/types.go +++ b/compose/types.go @@ -34,8 +34,10 @@ type Service struct { DependsOn []string `yaml:"depends_on"` Volumes []string `yaml:"volumes"` Expose []int `yaml:"expose"` - EnvFiles []string `yaml:"env_file"` + EnvFiles []string `yaml:"-"` + RawEnvFiles interface{} `yaml:"env_file"` RawBuild interface{} `yaml:"build"` HealthCheck *HealthCheck `yaml:"healthcheck"` - Command []string `yaml:"command"` + Command []string `yaml:"-"` + RawCommand interface{} `yaml:"command"` } diff --git a/generator/main.go b/generator/main.go index 66027c1..8c1f9aa 100644 --- a/generator/main.go +++ b/generator/main.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "katenary/compose" "katenary/helm" + "katenary/logger" "log" "net/url" "os" @@ -63,12 +64,13 @@ func CreateReplicaObject(name string, s *compose.Service, linked map[string]*com // This function will try to yied deployment and services based on a service from the compose file structure. func parseService(name string, s *compose.Service, linked map[string]*compose.Service, ret chan interface{}) { - Magenta(ICON_PACKAGE+" Generating deployment for ", name) + logger.Magenta(ICON_PACKAGE+" Generating deployment for ", name) o := helm.NewDeployment(name) container := helm.NewContainer(name, s.Image, s.Environment, s.Labels) prepareContainer(container, s, name) + prepareEnvFromFiles(name, s, container, ret) // Set the container to the deployment o.Spec.Template.Spec.Containers = []*helm.Container{container} @@ -91,6 +93,7 @@ func parseService(name string, s *compose.Service, linked map[string]*compose.Se for lname, link := range linked { container := helm.NewContainer(lname, link.Image, link.Environment, link.Labels) prepareContainer(container, link, lname) + prepareEnvFromFiles(lname, link, container, ret) o.Spec.Template.Spec.Containers = append(o.Spec.Template.Spec.Containers, container) o.Spec.Template.Spec.Volumes = append(o.Spec.Template.Spec.Volumes, prepareVolumes(name, lname, link, container, madePVC, ret)...) o.Spec.Template.Spec.InitContainers = append(o.Spec.Template.Spec.InitContainers, prepareInitContainers(lname, link, container)...) @@ -182,7 +185,7 @@ func prepareContainer(container *helm.Container, service *compose.Service, servi func generateServicesAndIngresses(name string, s *compose.Service) []interface{} { ret := make([]interface{}, 0) // can handle helm.Service or helm.Ingress - Magenta(ICON_SERVICE+" Generating service for ", name) + logger.Magenta(ICON_SERVICE+" Generating service for ", name) ks := helm.NewService(name) for i, p := range s.Ports { @@ -205,13 +208,13 @@ func generateServicesAndIngresses(name string, s *compose.Service) []interface{} if err != nil { log.Fatalf("The given port \"%v\" as ingress port in \"%s\" service is not an integer\n", v, name) } - Cyanf(ICON_INGRESS+" Create an ingress for port %d on %s service\n", port, name) + logger.Cyanf(ICON_INGRESS+" Create an ingress for port %d on %s service\n", port, name) ing := createIngress(name, port, s) ret = append(ret, ing) } if len(s.Expose) > 0 { - Magenta(ICON_SERVICE+" Generating service for ", name+"-external") + logger.Magenta(ICON_SERVICE+" Generating service for ", name+"-external") ks := helm.NewService(name + "-external") ks.Spec.Type = "NodePort" for _, p := range s.Expose { @@ -322,10 +325,10 @@ func buildCMFromPath(path string) *helm.ConfigMap { if err != nil { fmt.Fprintf(os.Stderr, "An error occured reading volume path %s\n", err.Error()) } else { - ActivateColors = true - Yellowf("Warning, %s is a directory, at this time we only "+ + logger.ActivateColors = true + logger.Yellowf("Warning, %s is a directory, at this time we only "+ "can create configmap for first level file list\n", f) - ActivateColors = false + logger.ActivateColors = false } continue } @@ -408,9 +411,9 @@ func prepareVolumes(deployment, name string, s *compose.Service, container *helm if !isCM && (strings.HasPrefix(volname, ".") || strings.HasPrefix(volname, "/")) { // local volume cannt be mounted - ActivateColors = true - Redf("You cannot, at this time, have local volume in %s deployment\n", name) - ActivateColors = false + logger.ActivateColors = true + logger.Redf("You cannot, at this time, have local volume in %s deployment\n", name) + logger.ActivateColors = false continue } if isCM { @@ -485,7 +488,7 @@ func prepareVolumes(deployment, name string, s *compose.Service, container *helm "mountPath": volepath, }) - Yellow(ICON_STORE+" Generate volume values", volname, "for container named", name, "in deployment", deployment) + logger.Yellow(ICON_STORE+" Generate volume values", volname, "for container named", name, "in deployment", deployment) locker.Lock() if _, ok := VolumeValues[deployment]; !ok { VolumeValues[deployment] = make(map[string]map[string]interface{}) @@ -637,16 +640,16 @@ func prepareEnvFromFiles(name string, s *compose.Service, container *helm.Contai } var store helm.InlineConfig if !isSecret { - Bluef(ICON_CONF+" Generating configMap %s\n", cf) + logger.Bluef(ICON_CONF+" Generating configMap %s\n", cf) store = helm.NewConfigMap(cf) } else { - Bluef(ICON_SECRET+" Generating secret %s\n", cf) + logger.Bluef(ICON_SECRET+" Generating secret %s\n", cf) store = helm.NewSecret(cf) } if err := store.AddEnvFile(envfile); err != nil { - ActivateColors = true - Red(err.Error()) - ActivateColors = false + logger.ActivateColors = true + logger.Red(err.Error()) + logger.ActivateColors = false os.Exit(2) } diff --git a/generator/main_test.go b/generator/main_test.go index a2be637..583f0b0 100644 --- a/generator/main_test.go +++ b/generator/main_test.go @@ -4,6 +4,7 @@ import ( "io/ioutil" "katenary/compose" "katenary/helm" + "katenary/logger" "os" "path/filepath" "strings" @@ -91,6 +92,10 @@ volumes: driver: local ` +func init() { + logger.NOLOG = true +} + func setUp(t *testing.T) (string, *compose.Parser) { p := compose.NewParser("", DOCKER_COMPOSE_YML) p.Parse("testapp") diff --git a/generator/color_test.go b/logger/color_test.go similarity index 74% rename from generator/color_test.go rename to logger/color_test.go index 00c2479..6f0dea0 100644 --- a/generator/color_test.go +++ b/logger/color_test.go @@ -1,8 +1,9 @@ -package generator +package logger import "testing" func TestColor(t *testing.T) { + NOLOG = false Red("Red text") Grey("Grey text") } diff --git a/generator/utils.go b/logger/utils.go similarity index 95% rename from generator/utils.go rename to logger/utils.go index 4ed1e39..18438e2 100644 --- a/generator/utils.go +++ b/logger/utils.go @@ -1,4 +1,4 @@ -package generator +package logger import ( "fmt" @@ -9,6 +9,7 @@ import ( type Color int var ActivateColors = false +var NOLOG = false const ( GREY Color = 30 + iota @@ -23,6 +24,9 @@ const ( var waiter = sync.Mutex{} func color(c Color, args ...interface{}) { + if NOLOG { + return + } if !ActivateColors { fmt.Println(args...) return @@ -35,6 +39,9 @@ func color(c Color, args ...interface{}) { } func colorf(c Color, format string, args ...interface{}) { + if NOLOG { + return + } if !ActivateColors { fmt.Printf(format, args...) return