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 <nick.adcock@docker.com>
This commit is contained in:
Nick Adcock 2020-01-17 13:12:53 +00:00
parent 6cf7970cd3
commit 4006c42e13
2 changed files with 117 additions and 0 deletions

View File

@ -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()
}

View File

@ -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",
},
},
)
}