Skip to content

Commit

Permalink
Added transforms for compose overrides
Browse files Browse the repository at this point in the history
Added transforms for when merging compose overrides to preserve the
functionality that was broken by bumping mergo to v0.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 <[email protected]>
  • Loading branch information
zappy-shu committed Jan 23, 2020
1 parent 6cf7970 commit 20ac8bf
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
24 changes: 24 additions & 0 deletions cli/compose/loader/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
}
Expand Down
94 changes: 94 additions & 0 deletions cli/compose/loader/merge_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package loader

import (
"reflect"
"testing"

"github.com/imdario/mergo"

"github.com/docker/cli/cli/compose/types"
"gotest.tools/assert"
)
Expand Down Expand Up @@ -1014,3 +1017,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",
},
},
)
}

0 comments on commit 20ac8bf

Please sign in to comment.