diff --git a/pkg/converter/linker.go b/pkg/converter/linker.go index 6fd33a0..7455376 100644 --- a/pkg/converter/linker.go +++ b/pkg/converter/linker.go @@ -76,9 +76,9 @@ func (l *Linker) Resolve(cf *ComposeFile, sf *SloppyFile) error { app.EnvVars[key] = targetVar // also consider special sloppy Env field - for i, s := range link.app.Env { - if s == strings.Join([]string{key, val}, "=") { - link.app.Env[i] = strings.Join([]string{key, targetVar}, "=") + for i, kv := range link.app.Env { + if _, ok := kv[key]; ok { + link.app.Env[i][key] = targetVar break } } diff --git a/pkg/converter/linker_test.go b/pkg/converter/linker_test.go index 1bb04e8..9e2ec4a 100644 --- a/pkg/converter/linker_test.go +++ b/pkg/converter/linker_test.go @@ -51,9 +51,9 @@ func TestLinker_Resolve(t *testing.T) { }, Image: ToStrPtr("hugo"), }, - Env: []string{ - "API_AUTH=some-external.service:80", - fmt.Sprintf("API_URL=b.apps.%s:8080", name), + Env: converter.SloppyEnvSlice{ + {"API_AUTH": "some-external.service:80"}, + {"API_URL": fmt.Sprintf("b.apps.%s:8080", name)}, }, }, "b": &converter.SloppyApp{ diff --git a/pkg/converter/sloppy_file.go b/pkg/converter/sloppy_file.go index 8b9bdc3..b2240e8 100644 --- a/pkg/converter/sloppy_file.go +++ b/pkg/converter/sloppy_file.go @@ -12,13 +12,15 @@ import ( type SloppyApps map[string]*SloppyApp +type SloppyEnvSlice []map[string]string + // Special intermediate type to fix the inconsistencies between // the yml and json format representation for the sloppy.App struct. type SloppyApp struct { *sloppy.App - Domain *string `json:"domain,omitempty"` - Env compose.MaporEqualSlice `json:"env,omitempty"` - Port *int `json:"port,omitempty"` + Domain *string `json:"domain,omitempty"` + Env SloppyEnvSlice `json:"env,omitempty"` + Port *int `json:"port,omitempty"` // hide conflicting fields from sloppy.App during serialization EnvVars map[string]string `json:"-"` @@ -31,6 +33,17 @@ type SloppyFile struct { Services map[string]SloppyApps `json:"services,omitempty"` } +func (p SloppyEnvSlice) Len() int { return len(p) } +func (p SloppyEnvSlice) Less(i, j int) bool { + for k := range p[i] { + for ok := range p[j] { + return k < ok + } + } + return false +} +func (p SloppyEnvSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + // Map docker-compose.yml to sloppy yml and return representation func NewSloppyFile(cf *ComposeFile) (*SloppyFile, error) { sf := &SloppyFile{ @@ -55,7 +68,7 @@ func NewSloppyFile(cf *ComposeFile) (*SloppyFile, error) { // Assign possible empty values in extra steps to hide empty object from output // Commands if len(config.Command) > 0 { - app.Command = sf.convertCommand(config.Command) + app.App.Command = sf.convertCommand(config.Command) } // Domain @@ -67,12 +80,14 @@ func NewSloppyFile(cf *ComposeFile) (*SloppyFile, error) { // Environment if len(config.Environment) > 0 { app.App.EnvVars = config.Environment.ToMap() - app.Env = config.Environment + for k, v := range app.App.EnvVars { + app.Env = append(app.Env, map[string]string{k: v}) + } } // Logging if config.Logging.Driver != "" && len(config.Logging.Options) > 0 { - app.Logging = &sloppy.Logging{ + app.App.Logging = &sloppy.Logging{ Driver: &config.Logging.Driver, Options: config.Logging.Options, } @@ -154,8 +169,8 @@ func (sf *SloppyFile) convertVolumes(volumes *compose.Volumes) (v []*sloppy.Volu func (sf *SloppyFile) sortFields() { for _, services := range sf.Services { for _, app := range services { - sort.Strings(app.Env) - sort.Strings(app.Dependencies) + sort.Sort(app.Env) + sort.Strings(app.App.Dependencies) } } } diff --git a/pkg/converter/testdata/golden0.yml b/pkg/converter/testdata/golden0.yml index 8ee8809..de2550a 100644 --- a/pkg/converter/testdata/golden0.yml +++ b/pkg/converter/testdata/golden0.yml @@ -7,16 +7,16 @@ services: dependencies: - ../apps/wordpress env: - - VAR_A=1 - - VAR_B=test + - VAR_A: "1" + - VAR_B: test image: busybox db: cmd: mysqld env: - - MYSQL_DATABASE=wordpress - - MYSQL_PASSWORD=wordpress - - MYSQL_ROOT_PASSWORD=somewordpress - - MYSQL_USER=wordpress + - MYSQL_DATABASE: wordpress + - MYSQL_PASSWORD: wordpress + - MYSQL_ROOT_PASSWORD: somewordpress + - MYSQL_USER: wordpress image: mysql:8.0.0 logging: driver: syslog @@ -29,9 +29,9 @@ services: - ../apps/db domain: mywords.sloppy.zone env: - - WORDPRESS_DB_HOST=db.apps.sloppy-test:3306 - - WORDPRESS_DB_PASSWORD=wordpress - - WORDPRESS_DB_USER=wordpress + - WORDPRESS_DB_HOST: db.apps.sloppy-test:3306 + - WORDPRESS_DB_PASSWORD: wordpress + - WORDPRESS_DB_USER: wordpress image: wordpress:4.7.4 port: 80 volumes: diff --git a/pkg/converter/yaml_writer_test.go b/pkg/converter/yaml_writer_test.go index abf41f3..a9450e2 100644 --- a/pkg/converter/yaml_writer_test.go +++ b/pkg/converter/yaml_writer_test.go @@ -1,6 +1,7 @@ package converter_test import ( + "flag" "io/ioutil" "strings" "testing" @@ -10,6 +11,14 @@ import ( "github.com/sloppyio/sloppose/pkg/converter" ) +var updateFlag = flag.Bool("update", false, "go test -update") + +func init() { + if !flag.Parsed() { + flag.Parse() + } +} + func TestYAMLWriter_WriteFile(t *testing.T) { helper := test.NewHelper(t) _, sf := loadSloppyFile("testdata/docker-compose-v2.yml") @@ -23,6 +32,12 @@ func TestYAMLWriter_WriteFile(t *testing.T) { helper.ChdirTest() + if *updateFlag { + err := writer.WriteFile(sf, "testdata/golden0.yml") + helper.Must(err) + t.Log("Successfully written updated golden file.") + } + goldenBuf, err := ioutil.ReadFile("testdata/golden0.yml") helper.Must(err)