From 4006c42e1395a7308dafae1795b6ebfea694fc91 Mon Sep 17 00:00:00 2001 From: Nick Adcock Date: Fri, 17 Jan 2020 13:12:53 +0000 Subject: [PATCH] Added transforms for compose overrides Added transforms for when merging compose overrides to preserve the functionality that was broken by bumping mergo to v1.3.8 This includes: - Special transform for ulimits so single overrides both soft/hard and the reverse - Special transform for service network configs so the override replaces all aliases Signed-off-by: Nick Adcock --- cli/compose/loader/merge.go | 24 +++++++++ cli/compose/loader/merge_test.go | 93 ++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/cli/compose/loader/merge.go b/cli/compose/loader/merge.go index 015b1f5a55..0de8d8a1b6 100644 --- a/cli/compose/loader/merge.go +++ b/cli/compose/loader/merge.go @@ -57,6 +57,8 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig, reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice), reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice), reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice), + reflect.TypeOf(&types.UlimitsConfig{}): mergeUlimitsConfig, + reflect.TypeOf(&types.ServiceNetworkConfig{}): mergeServiceNetworkConfig, }, } for name, overrideService := range overrideServices { @@ -201,6 +203,28 @@ func mergeLoggingConfig(dst, src reflect.Value) error { return nil } +//nolint: unparam +func mergeUlimitsConfig(dst, src reflect.Value) error { + if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() { + dst.Elem().Set(src.Elem()) + } + return nil +} + +//nolint: unparam +func mergeServiceNetworkConfig(dst, src reflect.Value) error { + if src.Interface() != reflect.Zero(reflect.TypeOf(src.Interface())).Interface() { + dst.Elem().FieldByName("Aliases").Set(src.Elem().FieldByName("Aliases")) + if ipv4 := src.Elem().FieldByName("Ipv4Address").Interface().(string); ipv4 != "" { + dst.Elem().FieldByName("Ipv4Address").SetString(ipv4) + } + if ipv6 := src.Elem().FieldByName("Ipv6Address").Interface().(string); ipv6 != "" { + dst.Elem().FieldByName("Ipv6Address").SetString(ipv6) + } + } + return nil +} + func getLoggingDriver(v reflect.Value) string { return v.FieldByName("Driver").String() } diff --git a/cli/compose/loader/merge_test.go b/cli/compose/loader/merge_test.go index 178d302da2..5055c68dba 100644 --- a/cli/compose/loader/merge_test.go +++ b/cli/compose/loader/merge_test.go @@ -1,9 +1,11 @@ package loader import ( + "reflect" "testing" "github.com/docker/cli/cli/compose/types" + "github.com/imdario/mergo" "gotest.tools/assert" ) @@ -1014,3 +1016,94 @@ func TestLoadMultipleNetworks(t *testing.T) { Configs: map[string]types.ConfigObjConfig{}, }, config) } + +func TestMergeUlimitsConfig(t *testing.T) { + specials := &specials{ + m: map[reflect.Type]func(dst, src reflect.Value) error{ + reflect.TypeOf(&types.UlimitsConfig{}): mergeUlimitsConfig, + }, + } + base := map[string]*types.UlimitsConfig{ + "override-single": &types.UlimitsConfig{Single: 100}, + "override-single-with-soft-hard": &types.UlimitsConfig{Single: 200}, + "override-soft-hard": &types.UlimitsConfig{Soft: 300, Hard: 301}, + "override-soft-hard-with-single": &types.UlimitsConfig{Soft: 400, Hard: 401}, + "dont-override": &types.UlimitsConfig{Single: 500}, + } + override := map[string]*types.UlimitsConfig{ + "override-single": &types.UlimitsConfig{Single: 110}, + "override-single-with-soft-hard": &types.UlimitsConfig{Soft: 210, Hard: 211}, + "override-soft-hard": &types.UlimitsConfig{Soft: 310, Hard: 311}, + "override-soft-hard-with-single": &types.UlimitsConfig{Single: 410}, + "add": &types.UlimitsConfig{Single: 610}, + } + err := mergo.Merge(&base, &override, mergo.WithOverride, mergo.WithTransformers(specials)) + assert.NilError(t, err) + assert.DeepEqual( + t, + base, + map[string]*types.UlimitsConfig{ + "override-single": &types.UlimitsConfig{Single: 110}, + "override-single-with-soft-hard": &types.UlimitsConfig{Soft: 210, Hard: 211}, + "override-soft-hard": &types.UlimitsConfig{Soft: 310, Hard: 311}, + "override-soft-hard-with-single": &types.UlimitsConfig{Single: 410}, + "dont-override": &types.UlimitsConfig{Single: 500}, + "add": &types.UlimitsConfig{Single: 610}, + }, + ) +} + +func TestMergeServiceNetworkConfig(t *testing.T) { + specials := &specials{ + m: map[reflect.Type]func(dst, src reflect.Value) error{ + reflect.TypeOf(&types.ServiceNetworkConfig{}): mergeServiceNetworkConfig, + }, + } + base := map[string]*types.ServiceNetworkConfig{ + "override-aliases": &types.ServiceNetworkConfig{ + Aliases: []string{"100", "101"}, + Ipv4Address: "127.0.0.1", + Ipv6Address: "0:0:0:0:0:0:0:1", + }, + "dont-override": &types.ServiceNetworkConfig{ + Aliases: []string{"200", "201"}, + Ipv4Address: "127.0.0.2", + Ipv6Address: "0:0:0:0:0:0:0:2", + }, + } + override := map[string]*types.ServiceNetworkConfig{ + "override-aliases": &types.ServiceNetworkConfig{ + Aliases: []string{"110", "111"}, + Ipv4Address: "127.0.1.1", + Ipv6Address: "0:0:0:0:0:0:1:1", + }, + "add": &types.ServiceNetworkConfig{ + Aliases: []string{"310", "311"}, + Ipv4Address: "127.0.3.1", + Ipv6Address: "0:0:0:0:0:0:3:1", + }, + } + err := mergo.Merge(&base, &override, mergo.WithOverride, mergo.WithTransformers(specials)) + assert.NilError(t, err) + assert.DeepEqual( + t, + base, + map[string]*types.ServiceNetworkConfig{ + "override-aliases": &types.ServiceNetworkConfig{ + Aliases: []string{"110", "111"}, + Ipv4Address: "127.0.1.1", + Ipv6Address: "0:0:0:0:0:0:1:1", + }, + "dont-override": &types.ServiceNetworkConfig{ + Aliases: []string{"200", "201"}, + Ipv4Address: "127.0.0.2", + Ipv6Address: "0:0:0:0:0:0:0:2", + }, + "add": &types.ServiceNetworkConfig{ + Aliases: []string{"310", "311"}, + Ipv4Address: "127.0.3.1", + Ipv6Address: "0:0:0:0:0:0:3:1", + }, + }, + ) +}