mirror of https://github.com/docker/cli.git
Merge pull request #2277 from zappy-shu/bump_mergo_v0.3.8
Bump mergo v0.3.8
This commit is contained in:
commit
7a0b138571
|
@ -57,6 +57,8 @@ func mergeServices(base, override []types.ServiceConfig) ([]types.ServiceConfig,
|
||||||
reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice),
|
reflect.TypeOf([]types.ServicePortConfig{}): mergeSlice(toServicePortConfigsMap, toServicePortConfigsSlice),
|
||||||
reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice),
|
reflect.TypeOf([]types.ServiceSecretConfig{}): mergeSlice(toServiceSecretConfigsMap, toServiceSecretConfigsSlice),
|
||||||
reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice),
|
reflect.TypeOf([]types.ServiceConfigObjConfig{}): mergeSlice(toServiceConfigObjConfigsMap, toSServiceConfigObjConfigsSlice),
|
||||||
|
reflect.TypeOf(&types.UlimitsConfig{}): mergeUlimitsConfig,
|
||||||
|
reflect.TypeOf(&types.ServiceNetworkConfig{}): mergeServiceNetworkConfig,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, overrideService := range overrideServices {
|
for name, overrideService := range overrideServices {
|
||||||
|
@ -201,6 +203,28 @@ func mergeLoggingConfig(dst, src reflect.Value) error {
|
||||||
return nil
|
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 {
|
func getLoggingDriver(v reflect.Value) string {
|
||||||
return v.FieldByName("Driver").String()
|
return v.FieldByName("Driver").String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package loader
|
package loader
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/compose/types"
|
"github.com/docker/cli/cli/compose/types"
|
||||||
|
"github.com/imdario/mergo"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1014,3 +1016,94 @@ func TestLoadMultipleNetworks(t *testing.T) {
|
||||||
Configs: map[string]types.ConfigObjConfig{},
|
Configs: map[string]types.ConfigObjConfig{},
|
||||||
}, config)
|
}, 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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ github.com/gorilla/mux 00bdffe0f3c77e27d2cf6f5c7023
|
||||||
github.com/grpc-ecosystem/grpc-gateway 1a03ca3bad1e1ebadaedd3abb76bc58d4ac8143b
|
github.com/grpc-ecosystem/grpc-gateway 1a03ca3bad1e1ebadaedd3abb76bc58d4ac8143b
|
||||||
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
github.com/grpc-ecosystem/grpc-opentracing 8e809c8a86450a29b90dcc9efbf062d0fe6d9746
|
||||||
github.com/hashicorp/golang-lru 7f827b33c0f158ec5dfbba01bb0b14a4541fd81d # v0.5.3
|
github.com/hashicorp/golang-lru 7f827b33c0f158ec5dfbba01bb0b14a4541fd81d # v0.5.3
|
||||||
github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7
|
github.com/imdario/mergo 1afb36080aec31e0d1528973ebe6721b191b0369 # v0.3.8
|
||||||
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0.0
|
github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 # v1.0.0
|
||||||
github.com/jaguilar/vt100 ad4c4a5743050fb7f88ce968dca9422f72a0e3f2 git://github.com/tonistiigi/vt100.git
|
github.com/jaguilar/vt100 ad4c4a5743050fb7f88ce968dca9422f72a0e3f2 git://github.com/tonistiigi/vt100.git
|
||||||
github.com/json-iterator/go 0ff49de124c6f76f8494e194af75bde0f1a49a29 # 1.1.6
|
github.com/json-iterator/go 0ff49de124c6f76f8494e194af75bde0f1a49a29 # 1.1.6
|
||||||
|
|
|
@ -26,10 +26,12 @@ func hasExportedField(dst reflect.Value) (exported bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Overwrite bool
|
Overwrite bool
|
||||||
AppendSlice bool
|
AppendSlice bool
|
||||||
Transformers Transformers
|
TypeCheck bool
|
||||||
overwriteWithEmptyValue bool
|
Transformers Transformers
|
||||||
|
overwriteWithEmptyValue bool
|
||||||
|
overwriteSliceWithEmptyValue bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Transformers interface {
|
type Transformers interface {
|
||||||
|
@ -41,7 +43,9 @@ type Transformers interface {
|
||||||
// short circuiting on recursive types.
|
// short circuiting on recursive types.
|
||||||
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
|
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
|
||||||
overwrite := config.Overwrite
|
overwrite := config.Overwrite
|
||||||
|
typeCheck := config.TypeCheck
|
||||||
overwriteWithEmptySrc := config.overwriteWithEmptyValue
|
overwriteWithEmptySrc := config.overwriteWithEmptyValue
|
||||||
|
overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
|
||||||
config.overwriteWithEmptyValue = false
|
config.overwriteWithEmptyValue = false
|
||||||
|
|
||||||
if !src.IsValid() {
|
if !src.IsValid() {
|
||||||
|
@ -128,11 +132,14 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
dstSlice = reflect.ValueOf(dstElement.Interface())
|
dstSlice = reflect.ValueOf(dstElement.Interface())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
||||||
|
if typeCheck && srcSlice.Type() != dstSlice.Type() {
|
||||||
|
return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
|
||||||
|
}
|
||||||
dstSlice = srcSlice
|
dstSlice = srcSlice
|
||||||
} else if config.AppendSlice {
|
} else if config.AppendSlice {
|
||||||
if srcSlice.Type() != dstSlice.Type() {
|
if srcSlice.Type() != dstSlice.Type() {
|
||||||
return fmt.Errorf("cannot append two slice with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
|
return fmt.Errorf("cannot append two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
|
||||||
}
|
}
|
||||||
dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
|
dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
|
||||||
}
|
}
|
||||||
|
@ -143,7 +150,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dstElement))) {
|
if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement)) {
|
||||||
if dst.IsNil() {
|
if dst.IsNil() {
|
||||||
dst.Set(reflect.MakeMap(dst.Type()))
|
dst.Set(reflect.MakeMap(dst.Type()))
|
||||||
}
|
}
|
||||||
|
@ -154,7 +161,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
if !dst.CanSet() {
|
if !dst.CanSet() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
if (!isEmptyValue(src) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
} else if config.AppendSlice {
|
} else if config.AppendSlice {
|
||||||
if src.Type() != dst.Type() {
|
if src.Type() != dst.Type() {
|
||||||
|
@ -168,11 +175,21 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
if src.IsNil() {
|
if src.IsNil() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if src.Kind() != reflect.Interface {
|
|
||||||
|
if dst.Kind() != reflect.Ptr && src.Type().AssignableTo(dst.Type()) {
|
||||||
if dst.IsNil() || overwrite {
|
if dst.IsNil() || overwrite {
|
||||||
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
|
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if src.Kind() != reflect.Interface {
|
||||||
|
if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) {
|
||||||
|
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
|
||||||
|
dst.Set(src)
|
||||||
|
}
|
||||||
} else if src.Kind() == reflect.Ptr {
|
} else if src.Kind() == reflect.Ptr {
|
||||||
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
|
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
|
||||||
return
|
return
|
||||||
|
@ -198,6 +215,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
|
||||||
dst.Set(src)
|
dst.Set(src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +227,7 @@ func Merge(dst, src interface{}, opts ...func(*Config)) error {
|
||||||
return merge(dst, src, opts...)
|
return merge(dst, src, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
|
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by
|
||||||
// non-empty src attribute values.
|
// non-empty src attribute values.
|
||||||
// Deprecated: use Merge(…) with WithOverride
|
// Deprecated: use Merge(…) with WithOverride
|
||||||
func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
|
func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
|
||||||
|
@ -228,11 +246,21 @@ func WithOverride(config *Config) {
|
||||||
config.Overwrite = true
|
config.Overwrite = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithAppendSlice will make merge append slices instead of overwriting it
|
// WithOverride will make merge override empty dst slice with empty src slice.
|
||||||
|
func WithOverrideEmptySlice(config *Config) {
|
||||||
|
config.overwriteSliceWithEmptyValue = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithAppendSlice will make merge append slices instead of overwriting it.
|
||||||
func WithAppendSlice(config *Config) {
|
func WithAppendSlice(config *Config) {
|
||||||
config.AppendSlice = true
|
config.AppendSlice = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
|
||||||
|
func WithTypeCheck(config *Config) {
|
||||||
|
config.TypeCheck = true
|
||||||
|
}
|
||||||
|
|
||||||
func merge(dst, src interface{}, opts ...func(*Config)) error {
|
func merge(dst, src interface{}, opts ...func(*Config)) error {
|
||||||
var (
|
var (
|
||||||
vDst, vSrc reflect.Value
|
vDst, vSrc reflect.Value
|
||||||
|
|
Loading…
Reference in New Issue