From 7dc5d509f78d5f297497d5b1024b07b8bcb34ddf Mon Sep 17 00:00:00 2001 From: Patrice Ferlet Date: Fri, 1 Apr 2022 09:22:00 +0200 Subject: [PATCH] Fix the problem with "ugly" environment syntax We can now manage "- A=B" format as "A: B" Some others properties than environment may have this problem (e.g., command) so we will fix this later. fix #4 --- compose/parser.go | 36 ++++++++++++++++++++++++++++++++++++ compose/types.go | 23 ++++++++++++----------- generator/main.go | 10 ++++++++++ generator/main_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 11 deletions(-) diff --git a/compose/parser.go b/compose/parser.go index 9b4da6c..4df8aa5 100644 --- a/compose/parser.go +++ b/compose/parser.go @@ -54,6 +54,10 @@ func (p *Parser) Parse(appname string) { services := make(map[string][]string) // get the service list, to be sure that everything is ok + for _, s := range p.Data.Services { + parseEnv(s) + } + c := p.Data for name, s := range c.Services { if portlabel, ok := s.Labels[helm.LABEL_PORT]; ok { @@ -121,4 +125,36 @@ func (p *Parser) Parse(appname string) { " for the \"" + name + "\" service \x1b[0m") } + +} + +// manage environment variables, if the type is map[string]string so we can use it, else we need to split "=" sign +// and apply this in env variable +func parseEnv(s *Service) { + env := make(map[string]string) + if s.RawEnvironment == nil { + return + } + switch s.RawEnvironment.(type) { + case map[string]string: + env = s.RawEnvironment.(map[string]string) + case map[string]interface{}: + for k, v := range s.RawEnvironment.(map[string]interface{}) { + env[k] = v.(string) + } + case []interface{}: + for _, v := range s.RawEnvironment.([]interface{}) { + // Splot the value of the env variable with "=" + parts := strings.Split(v.(string), "=") + env[parts[0]] = parts[1] + } + case string: + parts := strings.Split(s.RawEnvironment.(string), "=") + 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 } diff --git a/compose/types.go b/compose/types.go index f033515..013147b 100644 --- a/compose/types.go +++ b/compose/types.go @@ -26,15 +26,16 @@ type HealthCheck struct { // Service represent a "service" in a docker-compose file. type Service struct { - Image string `yaml:"image"` - Ports []string `yaml:"ports"` - Environment map[string]string `yaml:"environment"` - Labels map[string]string `yaml:"labels"` - DependsOn []string `yaml:"depends_on"` - Volumes []string `yaml:"volumes"` - Expose []int `yaml:"expose"` - EnvFiles []string `yaml:"env_file"` - RawBuild interface{} `yaml:"build"` - HealthCheck *HealthCheck `yaml:"healthcheck"` - Command []string `yaml:"command"` + Image string `yaml:"image"` + Ports []string `yaml:"ports"` + Environment map[string]string `yaml:"-"` + RawEnvironment interface{} `yaml:"environment"` + Labels map[string]string `yaml:"labels"` + DependsOn []string `yaml:"depends_on"` + Volumes []string `yaml:"volumes"` + Expose []int `yaml:"expose"` + EnvFiles []string `yaml:"env_file"` + RawBuild interface{} `yaml:"build"` + HealthCheck *HealthCheck `yaml:"healthcheck"` + Command []string `yaml:"command"` } diff --git a/generator/main.go b/generator/main.go index 4793fa0..66027c1 100644 --- a/generator/main.go +++ b/generator/main.go @@ -128,6 +128,13 @@ func parseService(name string, s *compose.Service, linked map[string]*compose.Se if len(s.Ports) == 0 { // alert any current or **future** waiters that this service is not exposed go func() { + defer func() { + // recover from panic + if r := recover(); r != nil { + // log the stack trace + fmt.Println(r) + } + }() for { select { case <-time.Tick(1 * time.Millisecond): @@ -378,12 +385,15 @@ func prepareVolumes(deployment, name string, s *compose.Service, container *helm if v, ok := s.Labels[helm.LABEL_VOL_CM]; ok { configMapsVolumes = strings.Split(v, ",") } + for _, volume := range s.Volumes { + parts := strings.Split(volume, ":") if len(parts) == 1 { // this is a volume declaration for Docker only, avoid it continue } + volname := parts[0] volepath := parts[1] diff --git a/generator/main_test.go b/generator/main_test.go index 7797b4b..a2be637 100644 --- a/generator/main_test.go +++ b/generator/main_test.go @@ -79,6 +79,13 @@ services: labels: katenary.io/ports: 80 + # use = sign for environment variables + eqenv: + image: nginx + environment: + - SOME_ENV_VAR=some_value + - ANOTHER_ENV_VAR=another_value + volumes: data: driver: local @@ -291,3 +298,34 @@ func TestUnmappedVolumes(t *testing.T) { } } } + +// Check if service using equal sign for environment works +func TestEqualSignOnEnv(t *testing.T) { + tmp, p := setUp(t) + defer os.RemoveAll(tmp) + + // if the name is eqenv, the service should habe environment + for name, _ := range p.Data.Services { + if name == "eqenv" { + path := filepath.Join(tmp, "templates", name+".deployment.yaml") + fp, _ := os.Open(path) + defer fp.Close() + lines, _ := ioutil.ReadAll(fp) + match := 0 + for _, line := range strings.Split(string(lines), "\n") { + // we must find the line with the environment variable name + if strings.Contains(line, "SOME_ENV_VAR") { + // we must find the line with the environment variable value + match++ + } + if strings.Contains(line, "ANOTHER_ENV_VAR") { + // we must find the line with the environment variable value + match++ + } + } + if match != 2 { + t.Error("eqenv service should have 2 environment variables") + } + } + } +}