3 Commits

Author SHA1 Message Date
165054ca53 For single env_file, it's a string...
see #8
2022-04-01 17:49:10 +02:00
a87391e726 Fix healthcheck
see #8
2022-04-01 17:39:41 +02:00
f8dcd2026b Fix test command to make it work as string / slice
see #8
2022-04-01 16:58:13 +02:00
4 changed files with 116 additions and 13 deletions

View File

@@ -60,6 +60,7 @@ func (p *Parser) Parse(appname string) {
parseEnv(s) parseEnv(s)
parseCommand(s) parseCommand(s)
parseEnvFiles(s) parseEnvFiles(s)
parseHealthCheck(s)
} }
c := p.Data c := p.Data
@@ -170,18 +171,18 @@ func parseCommand(s *Service) {
} }
// following the command type, it can be a "slice" or a simple sting, so we need to check it // following the command type, it can be a "slice" or a simple sting, so we need to check it
switch s.RawCommand.(type) { switch v := s.RawCommand.(type) {
case string: case string:
// use shlex to parse the command // use shlex to parse the command
command, err := shlex.Split(s.RawCommand.(string)) command, err := shlex.Split(v)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
s.Command = command s.Command = command
case []string: case []string:
s.Command = s.RawCommand.([]string) s.Command = v
case []interface{}: case []interface{}:
for _, v := range s.RawCommand.([]interface{}) { for _, v := range v {
s.Command = append(s.Command, v.(string)) s.Command = append(s.Command, v.(string))
} }
default: default:
@@ -196,16 +197,52 @@ func parseEnvFiles(s *Service) {
return return
} }
envfiles := make([]string, 0) envfiles := make([]string, 0)
switch s.RawEnvFiles.(type) { switch v := s.RawEnvFiles.(type) {
case []string: case []string:
envfiles = s.RawEnvFiles.([]string) envfiles = v
case []interface{}: case []interface{}:
for _, v := range s.RawEnvFiles.([]interface{}) { for _, v := range v {
envfiles = append(envfiles, v.(string)) envfiles = append(envfiles, v.(string))
} }
case string:
envfiles = append(envfiles, v)
default: default:
log.Printf("%+v %T", s.RawEnvFiles, s.RawEnvFiles) log.Printf("%+v %T", s.RawEnvFiles, s.RawEnvFiles)
log.Fatal("EnvFile type not supported") log.Fatal("EnvFile type not supported")
} }
s.EnvFiles = envfiles s.EnvFiles = envfiles
} }
func parseHealthCheck(s *Service) {
// HealthCheck command can be a string or slice of strings
if s.HealthCheck == nil {
return
}
if s.HealthCheck.RawTest == nil {
return
}
switch v := s.HealthCheck.RawTest.(type) {
case string:
c, err := shlex.Split(v)
if err != nil {
log.Fatal(err)
}
s.HealthCheck = &HealthCheck{
Test: c,
}
case []string:
s.HealthCheck = &HealthCheck{
Test: v,
}
case []interface{}:
for _, v := range v {
s.HealthCheck.Test = append(s.HealthCheck.Test, v.(string))
}
default:
log.Printf("%+v %T", s.HealthCheck.RawTest, s.HealthCheck.RawTest)
log.Fatal("HealthCheck type not supported")
}
}

View File

@@ -40,6 +40,22 @@ services:
image: foo image: foo
command: echo "hello world" command: echo "hello world"
hc1:
image: foo
healthcheck:
test: ["CMD-SHELL", "echo 'hello world1'"]
hc2:
image: foo
healthcheck:
test: echo "hello world2"
hc3:
image: foo
healthcheck:
test: ["CMD", "echo 'hello world3'"]
` `
func init() { func init() {
@@ -136,3 +152,48 @@ func TestParseCommand(t *testing.T) {
} }
} }
} }
func TestHealthChecks(t *testing.T) {
p := NewParser("", DOCKER_COMPOSE_YML1)
p.Parse("test")
for name, s := range p.Data.Services {
if name != "hc1" && name != "hc2" && name != "hc3" {
continue
}
if name == "hc1" {
if len(s.HealthCheck.Test) != 2 {
t.Errorf("Expected 2 healthcheck tests, got %d", len(s.HealthCheck.Test))
}
if s.HealthCheck.Test[0] != "CMD-SHELL" {
t.Errorf("Expected CMD-SHELL, got %s", s.HealthCheck.Test[0])
}
if s.HealthCheck.Test[1] != "echo 'hello world1'" {
t.Errorf("Expected echo 'hello world1', got %s", s.HealthCheck.Test[1])
}
}
if name == "hc2" {
if len(s.HealthCheck.Test) != 2 {
t.Errorf("Expected 2 healthcheck tests, got %d", len(s.HealthCheck.Test))
}
if s.HealthCheck.Test[0] != "echo" {
t.Errorf("Expected echo, got %s", s.HealthCheck.Test[1])
}
if s.HealthCheck.Test[1] != "hello world2" {
t.Errorf("Expected echo 'hello world2', got %s", s.HealthCheck.Test[1])
}
}
if name == "hc3" {
if len(s.HealthCheck.Test) != 2 {
t.Errorf("Expected 2 healthcheck tests, got %d", len(s.HealthCheck.Test))
}
if s.HealthCheck.Test[0] != "CMD" {
t.Errorf("Expected CMD, got %s", s.HealthCheck.Test[0])
}
if s.HealthCheck.Test[1] != "echo 'hello world3'" {
t.Errorf("Expected echo 'hello world3', got %s", s.HealthCheck.Test[1])
}
}
}
}

View File

@@ -17,7 +17,8 @@ func NewCompose() *Compose {
// HealthCheck manage generic type to handle TCP, HTTP and TCP health check. // HealthCheck manage generic type to handle TCP, HTTP and TCP health check.
type HealthCheck struct { type HealthCheck struct {
Test []string `yaml:"test"` Test []string `yaml:"-"`
RawTest interface{} `yaml:"test"`
Interval string `yaml:"interval"` Interval string `yaml:"interval"`
Timeout string `yaml:"timeout"` Timeout string `yaml:"timeout"`
Retries int `yaml:"retries"` Retries int `yaml:"retries"`

View File

@@ -607,10 +607,14 @@ func prepareProbes(name string, s *compose.Service, container *helm.Container) {
Command: c, Command: c,
} }
} }
} else if s.HealthCheck.Test[0] == "CMD" { } else if s.HealthCheck.Test[0] == "CMD" || s.HealthCheck.Test[0] == "CMD-SHELL" {
probe.Exec = &helm.Exec{ probe.Exec = &helm.Exec{
Command: s.HealthCheck.Test[1:], Command: s.HealthCheck.Test[1:],
} }
} else {
probe.Exec = &helm.Exec{
Command: s.HealthCheck.Test,
}
} }
container.LivenessProbe = probe container.LivenessProbe = probe
} }