diff --git a/loader/override_test.go b/loader/override_test.go index 1433cc2c..25758b1f 100644 --- a/loader/override_test.go +++ b/loader/override_test.go @@ -47,7 +47,7 @@ services: - alias1 - alias2 ` - _, err := LoadWithContext(context.Background(), types.ConfigDetails{ + p, err := LoadWithContext(context.Background(), types.ConfigDetails{ ConfigFiles: []types.ConfigFile{ { Filename: "base", @@ -60,4 +60,71 @@ services: }, }) assert.NilError(t, err) + assert.DeepEqual(t, p.Services["test"].Networks["test_network"].Aliases, []string{"alias1", "alias2"}) +} + +func TestOverrideBuildContext(t *testing.T) { + yaml := ` +name: test-override-networks +services: + test: + build: . +` + + override := ` +services: + test: + build: + context: src +` + p, err := LoadWithContext(context.Background(), types.ConfigDetails{ + ConfigFiles: []types.ConfigFile{ + { + Filename: "base", + Content: []byte(yaml), + }, + { + Filename: "override", + Content: []byte(override), + }, + }, + }) + assert.NilError(t, err) + assert.Equal(t, p.Services["test"].Build.Context, "src") +} + +func TestOverrideDepends_on(t *testing.T) { + yaml := ` +name: test-override-networks +services: + test: + image: test + depends_on: + - foo + foo: + image: foo +` + + override := ` +services: + test: + depends_on: + foo: + condition: service_healthy + required: false +` + p, err := LoadWithContext(context.Background(), types.ConfigDetails{ + ConfigFiles: []types.ConfigFile{ + { + Filename: "base", + Content: []byte(yaml), + }, + { + Filename: "override", + Content: []byte(override), + }, + }, + }) + assert.NilError(t, err) + assert.Check(t, p.Services["test"].DependsOn["foo"].Required == false) } diff --git a/override/merge.go b/override/merge.go index c22ca78c..d8e91d30 100644 --- a/override/merge.go +++ b/override/merge.go @@ -39,6 +39,8 @@ type merger func(any, any, tree.Path) (any, error) var mergeSpecials = map[tree.Path]merger{} func init() { + mergeSpecials["services.*.build"] = mergeBuild + mergeSpecials["services.*.depends_on"] = mergeDependsOn mergeSpecials["services.*.logging"] = mergeLogging mergeSpecials["services.*.networks"] = mergeNetworks mergeSpecials["services.*.command"] = override @@ -107,9 +109,36 @@ func mergeLogging(c any, o any, p tree.Path) (any, error) { return other, nil } +func mergeBuild(c any, o any, path tree.Path) (any, error) { + toBuild := func(c any) map[string]any { + switch v := c.(type) { + case string: + return map[string]any{ + "context": v, + } + case map[string]any: + return v + } + return nil + } + return mergeMappings(toBuild(c), toBuild(o), path) +} + +func mergeDependsOn(c any, o any, path tree.Path) (any, error) { + right := convertIntoMapping(c, map[string]any{ + "condition": "service_started", + "required": true, + }) + left := convertIntoMapping(o, map[string]any{ + "condition": "service_started", + "required": true, + }) + return mergeMappings(right, left, path) +} + func mergeNetworks(c any, o any, path tree.Path) (any, error) { - right := convertIntoMapping(c) - left := convertIntoMapping(o) + right := convertIntoMapping(c, nil) + left := convertIntoMapping(o, nil) return mergeMappings(right, left, path) } @@ -151,14 +180,14 @@ func mergeUlimit(_ any, o any, p tree.Path) (any, error) { return o, nil } -func convertIntoMapping(a any) map[string]any { +func convertIntoMapping(a any, defaultValue any) map[string]any { switch v := a.(type) { case map[string]any: return v case []any: converted := map[string]any{} for _, s := range v { - converted[s.(string)] = nil + converted[s.(string)] = defaultValue } return converted }