From ef0a383ec767ba64a50f64d53b384b8407e6ea6e Mon Sep 17 00:00:00 2001
From: Tomasz Maczukin <tomasz@maczukin.pl>
Date: Tue, 26 Mar 2019 20:54:34 +0100
Subject: [PATCH] Update github.com/imdario/mergo version

---
 Gopkg.lock                                    |   6 +-
 Gopkg.toml                                    |   8 +-
 .../github.com/imdario/mergo/issue17_test.go  |   4 +-
 .../github.com/imdario/mergo/issue23_test.go  |   2 +-
 .../github.com/imdario/mergo/issue33_test.go  |  33 +++
 .../github.com/imdario/mergo/issue38_test.go  |  59 +++++
 .../github.com/imdario/mergo/issue50_test.go  |  18 ++
 .../github.com/imdario/mergo/issue52_test.go  |  99 +++++++
 .../github.com/imdario/mergo/issue61_test.go  |  20 ++
 .../github.com/imdario/mergo/issue64_test.go  |  38 +++
 .../github.com/imdario/mergo/issue66_test.go  |  48 ++++
 .../github.com/imdario/mergo/issue84_test.go  |  82 ++++++
 vendor/github.com/imdario/mergo/map.go        |  53 ++--
 vendor/github.com/imdario/mergo/merge.go      | 164 ++++++++++--
 .../imdario/mergo/merge_appendslice_test.go   |  33 +++
 vendor/github.com/imdario/mergo/merge_test.go |  50 ++++
 vendor/github.com/imdario/mergo/mergo.go      |   9 +-
 vendor/github.com/imdario/mergo/mergo_test.go | 241 ++++++++++++++++--
 vendor/github.com/imdario/mergo/pr80_test.go  |  18 ++
 vendor/github.com/imdario/mergo/pr81_test.go  |  42 +++
 .../imdario/mergo/testdata/license.yml        |   1 +
 21 files changed, 969 insertions(+), 59 deletions(-)
 create mode 100644 vendor/github.com/imdario/mergo/issue33_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue38_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue50_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue52_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue61_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue64_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue66_test.go
 create mode 100644 vendor/github.com/imdario/mergo/issue84_test.go
 create mode 100644 vendor/github.com/imdario/mergo/merge_appendslice_test.go
 create mode 100644 vendor/github.com/imdario/mergo/merge_test.go
 create mode 100644 vendor/github.com/imdario/mergo/pr80_test.go
 create mode 100644 vendor/github.com/imdario/mergo/pr81_test.go

diff --git a/Gopkg.lock b/Gopkg.lock
index 2afd27df9f5..dec803bf0e2 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -411,11 +411,12 @@
   revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8"
 
 [[projects]]
-  digest = "1:ff6e83dd3b5a66d41c58a3d5e144bd06fcd4c376fd1a84379ad8c9a7dd308643"
+  digest = "1:158a976af1c463daebfa72efdfb66ccd78edfa475ed6d66937744bca05ee6c9c"
   name = "github.com/imdario/mergo"
   packages = ["."]
   pruneopts = "N"
-  revision = "50d4dbd4eb0e84778abe37cefef140271d96fade"
+  revision = "7c29201646fa3de8506f701213473dd407f19646"
+  version = "v0.3.7"
 
 [[projects]]
   digest = "1:485d36dae750af66fac78a968360bb1eb5a635d9d1e3a3b92116556cc2d45b6a"
@@ -1066,6 +1067,7 @@
     "github.com/gorilla/mux",
     "github.com/gorilla/websocket",
     "github.com/hashicorp/go-version",
+    "github.com/imdario/mergo",
     "github.com/jpillora/backoff",
     "github.com/kardianos/osext",
     "github.com/kr/pty",
diff --git a/Gopkg.toml b/Gopkg.toml
index d4939268916..0e8096b0fb0 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -166,6 +166,10 @@ ignored = ["test", "appengine"]
   name = "github.com/gofrs/flock"
   branch = "master"
 
+[[constraint]]
+  name = "github.com/imdario/mergo"
+  version = "v0.3.7"
+
 ##
 ## Refrain innovations ;)
 ##
@@ -230,10 +234,6 @@ ignored = ["test", "appengine"]
   name = "github.com/gorilla/mux"
   revision = "599cba5e7b6137d46ddf58fb1765f5d928e69604"
 
-[[override]]
-  name = "github.com/imdario/mergo"
-  revision = "50d4dbd4eb0e84778abe37cefef140271d96fade"
-
 [[override]]
   name = "github.com/jonboulle/clockwork"
   revision = "e3653ace2d63753697e0e5b07b9393971c0bba9d"
diff --git a/vendor/github.com/imdario/mergo/issue17_test.go b/vendor/github.com/imdario/mergo/issue17_test.go
index 0ee96f37714..f9de805ab77 100644
--- a/vendor/github.com/imdario/mergo/issue17_test.go
+++ b/vendor/github.com/imdario/mergo/issue17_test.go
@@ -17,9 +17,9 @@ var (
 func TestIssue17MergeWithOverwrite(t *testing.T) {
 	var something map[string]interface{}
 	if err := json.Unmarshal([]byte(request), &something); err != nil {
-		t.Errorf("Error while Unmarshalling maprequest %s", err)
+		t.Errorf("Error while Unmarshalling maprequest: %s", err)
 	}
 	if err := MergeWithOverwrite(&something, maprequest); err != nil {
-		t.Errorf("Error while merging %s", err)
+		t.Errorf("Error while merging: %s", err)
 	}
 }
diff --git a/vendor/github.com/imdario/mergo/issue23_test.go b/vendor/github.com/imdario/mergo/issue23_test.go
index 9c32584131e..283f8c6a3f5 100644
--- a/vendor/github.com/imdario/mergo/issue23_test.go
+++ b/vendor/github.com/imdario/mergo/issue23_test.go
@@ -21,7 +21,7 @@ func TestIssue23MergeWithOverwrite(t *testing.T) {
 	if err := MergeWithOverwrite(&dst, src); err != nil {
 		t.Errorf("Error while merging %s", err)
 	}
-	if dst.Created != src.Created {
+	if !dst.Created.Equal(*src.Created) { //--> https://golang.org/pkg/time/#pkg-overview
 		t.Fatalf("Created not merged in properly: dst.Created(%v) != src.Created(%v)", dst.Created, src.Created)
 	}
 }
diff --git a/vendor/github.com/imdario/mergo/issue33_test.go b/vendor/github.com/imdario/mergo/issue33_test.go
new file mode 100644
index 00000000000..ae55ae236f9
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue33_test.go
@@ -0,0 +1,33 @@
+package mergo
+
+import (
+	"testing"
+)
+
+type Foo struct {
+	Str    string
+	Bslice []byte
+}
+
+func TestIssue33Merge(t *testing.T) {
+	dest := Foo{Str: "a"}
+	toMerge := Foo{
+		Str:    "b",
+		Bslice: []byte{1, 2},
+	}
+	if err := Merge(&dest, toMerge); err != nil {
+		t.Errorf("Error while merging: %s", err)
+	}
+	// Merge doesn't overwrite an attribute if in destination it doesn't have a zero value.
+	// In this case, Str isn't a zero value string.
+	if dest.Str != "a" {
+		t.Errorf("dest.Str should have not been override as it has a non-zero value: dest.Str(%v) != 'a'", dest.Str)
+	}
+	// If we want to override, we must use MergeWithOverwrite or Merge using WithOverride.
+	if err := Merge(&dest, toMerge, WithOverride); err != nil {
+		t.Errorf("Error while merging: %s", err)
+	}
+	if dest.Str != toMerge.Str {
+		t.Errorf("dest.Str should have been override: dest.Str(%v) != toMerge.Str(%v)", dest.Str, toMerge.Str)
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue38_test.go b/vendor/github.com/imdario/mergo/issue38_test.go
new file mode 100644
index 00000000000..286b68cb1ce
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue38_test.go
@@ -0,0 +1,59 @@
+package mergo
+
+import (
+	"testing"
+	"time"
+)
+
+type structWithoutTimePointer struct {
+	Created time.Time
+}
+
+func TestIssue38Merge(t *testing.T) {
+	dst := structWithoutTimePointer{
+		time.Now(),
+	}
+
+	expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+	src := structWithoutTimePointer{
+		expected,
+	}
+	if err := Merge(&dst, src); err != nil {
+		t.Errorf("Error while merging %s", err)
+	}
+	if dst.Created == src.Created {
+		t.Fatalf("Created merged unexpectedly: dst.Created(%v) == src.Created(%v)", dst.Created, src.Created)
+	}
+}
+
+func TestIssue38MergeEmptyStruct(t *testing.T) {
+	dst := structWithoutTimePointer{}
+
+	expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+	src := structWithoutTimePointer{
+		expected,
+	}
+	if err := Merge(&dst, src); err != nil {
+		t.Errorf("Error while merging %s", err)
+	}
+	if dst.Created == src.Created {
+		t.Fatalf("Created merged unexpectedly: dst.Created(%v) == src.Created(%v)", dst.Created, src.Created)
+	}
+}
+
+func TestIssue38MergeWithOverwrite(t *testing.T) {
+	dst := structWithoutTimePointer{
+		time.Now(),
+	}
+
+	expected := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+	src := structWithoutTimePointer{
+		expected,
+	}
+	if err := MergeWithOverwrite(&dst, src); err != nil {
+		t.Errorf("Error while merging %s", err)
+	}
+	if dst.Created != src.Created {
+		t.Fatalf("Created not merged in properly: dst.Created(%v) != src.Created(%v)", dst.Created, src.Created)
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue50_test.go b/vendor/github.com/imdario/mergo/issue50_test.go
new file mode 100644
index 00000000000..89aa36345c8
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue50_test.go
@@ -0,0 +1,18 @@
+package mergo
+
+import (
+	"testing"
+	"time"
+)
+
+type testStruct struct {
+	time.Duration
+}
+
+func TestIssue50Merge(t *testing.T) {
+	to := testStruct{}
+	from := testStruct{}
+	if err := Merge(&to, from); err != nil {
+		t.Fail()
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue52_test.go b/vendor/github.com/imdario/mergo/issue52_test.go
new file mode 100644
index 00000000000..62cd9fa7c0c
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue52_test.go
@@ -0,0 +1,99 @@
+package mergo
+
+import (
+	"reflect"
+	"testing"
+	"time"
+)
+
+type structWithTime struct {
+	Birth time.Time
+}
+
+type timeTransfomer struct {
+	overwrite bool
+}
+
+func (t timeTransfomer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
+	if typ == reflect.TypeOf(time.Time{}) {
+		return func(dst, src reflect.Value) error {
+			if dst.CanSet() {
+				if t.overwrite {
+					isZero := src.MethodByName("IsZero")
+					result := isZero.Call([]reflect.Value{})
+					if !result[0].Bool() {
+						dst.Set(src)
+					}
+				} else {
+					isZero := dst.MethodByName("IsZero")
+					result := isZero.Call([]reflect.Value{})
+					if result[0].Bool() {
+						dst.Set(src)
+					}
+				}
+			}
+			return nil
+		}
+	}
+	return nil
+}
+
+func TestOverwriteZeroSrcTime(t *testing.T) {
+	now := time.Now()
+	dst := structWithTime{now}
+	src := structWithTime{}
+	if err := MergeWithOverwrite(&dst, src); err != nil {
+		t.FailNow()
+	}
+	if !dst.Birth.IsZero() {
+		t.Fatalf("dst should have been overwritten: dst.Birth(%v) != now(%v)", dst.Birth, now)
+	}
+}
+
+func TestOverwriteZeroSrcTimeWithTransformer(t *testing.T) {
+	now := time.Now()
+	dst := structWithTime{now}
+	src := structWithTime{}
+	if err := MergeWithOverwrite(&dst, src, WithTransformers(timeTransfomer{true})); err != nil {
+		t.FailNow()
+	}
+	if dst.Birth.IsZero() {
+		t.Fatalf("dst should not have been overwritten: dst.Birth(%v) != now(%v)", dst.Birth, now)
+	}
+}
+
+func TestOverwriteZeroDstTime(t *testing.T) {
+	now := time.Now()
+	dst := structWithTime{}
+	src := structWithTime{now}
+	if err := MergeWithOverwrite(&dst, src); err != nil {
+		t.FailNow()
+	}
+	if dst.Birth.IsZero() {
+		t.Fatalf("dst should have been overwritten: dst.Birth(%v) != zero(%v)", dst.Birth, time.Time{})
+	}
+}
+
+func TestZeroDstTime(t *testing.T) {
+	now := time.Now()
+	dst := structWithTime{}
+	src := structWithTime{now}
+	if err := Merge(&dst, src); err != nil {
+		t.FailNow()
+	}
+	if !dst.Birth.IsZero() {
+		t.Fatalf("dst should not have been overwritten: dst.Birth(%v) != zero(%v)", dst.Birth, time.Time{})
+	}
+}
+
+func TestZeroDstTimeWithTransformer(t *testing.T) {
+	now := time.Now()
+	dst := structWithTime{}
+	src := structWithTime{now}
+	if err := Merge(&dst, src, WithTransformers(timeTransfomer{})); err != nil {
+		t.FailNow()
+	}
+	if dst.Birth.IsZero() {
+		t.Fatalf("dst should have been overwritten: dst.Birth(%v) != now(%v)", dst.Birth, now)
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue61_test.go b/vendor/github.com/imdario/mergo/issue61_test.go
new file mode 100644
index 00000000000..8efa5e45704
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue61_test.go
@@ -0,0 +1,20 @@
+package mergo
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestIssue61MergeNilMap(t *testing.T) {
+	type T struct {
+		I map[string][]string
+	}
+	t1 := T{}
+	t2 := T{I: map[string][]string{"hi": {"there"}}}
+	if err := Merge(&t1, t2); err != nil {
+		t.Fail()
+	}
+	if !reflect.DeepEqual(t2, T{I: map[string][]string{"hi": {"there"}}}) {
+		t.FailNow()
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue64_test.go b/vendor/github.com/imdario/mergo/issue64_test.go
new file mode 100644
index 00000000000..32382bef16c
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue64_test.go
@@ -0,0 +1,38 @@
+package mergo
+
+import (
+	"testing"
+)
+
+type Student struct {
+	Name  string
+	Books []string
+}
+
+var testData = []struct {
+	S1            Student
+	S2            Student
+	ExpectedSlice []string
+}{
+	{Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{"1"}}, []string{"a", "B"}},
+	{Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{}}, []string{"a", "B"}},
+	{Student{"Jack", []string{}}, Student{"Tom", []string{"1"}}, []string{"1"}},
+	{Student{"Jack", []string{}}, Student{"Tom", []string{}}, []string{}},
+}
+
+func TestIssue64MergeSliceWithOverride(t *testing.T) {
+	for _, data := range testData {
+		err := Merge(&data.S2, data.S1, WithOverride)
+		if err != nil {
+			t.Errorf("Error while merging %s", err)
+		}
+		if len(data.S2.Books) != len(data.ExpectedSlice) {
+			t.Fatalf("Got %d elements in slice, but expected %d", len(data.S2.Books), len(data.ExpectedSlice))
+		}
+		for i, val := range data.S2.Books {
+			if val != data.ExpectedSlice[i] {
+				t.Fatalf("Expected %s, but got %s while merging slice with override", data.ExpectedSlice[i], val)
+			}
+		}
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue66_test.go b/vendor/github.com/imdario/mergo/issue66_test.go
new file mode 100644
index 00000000000..9e4bccedcb6
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue66_test.go
@@ -0,0 +1,48 @@
+package mergo
+
+import (
+	"testing"
+)
+
+type PrivateSliceTest66 struct {
+	PublicStrings  []string
+	privateStrings []string
+}
+
+func TestPrivateSlice(t *testing.T) {
+	p1 := PrivateSliceTest66{
+		PublicStrings:  []string{"one", "two", "three"},
+		privateStrings: []string{"four", "five"},
+	}
+	p2 := PrivateSliceTest66{
+		PublicStrings: []string{"six", "seven"},
+	}
+	if err := Merge(&p1, p2); err != nil {
+		t.Fatalf("Error during the merge: %v", err)
+	}
+	if len(p1.PublicStrings) != 3 {
+		t.Error("5 elements should be in 'PublicStrings' field")
+	}
+	if len(p1.privateStrings) != 2 {
+		t.Error("2 elements should be in 'privateStrings' field")
+	}
+}
+
+func TestPrivateSliceWithAppendSlice(t *testing.T) {
+	p1 := PrivateSliceTest66{
+		PublicStrings:  []string{"one", "two", "three"},
+		privateStrings: []string{"four", "five"},
+	}
+	p2 := PrivateSliceTest66{
+		PublicStrings: []string{"six", "seven"},
+	}
+	if err := Merge(&p1, p2, WithAppendSlice); err != nil {
+		t.Fatalf("Error during the merge: %v", err)
+	}
+	if len(p1.PublicStrings) != 5 {
+		t.Error("5 elements should be in 'PublicStrings' field")
+	}
+	if len(p1.privateStrings) != 2 {
+		t.Error("2 elements should be in 'privateStrings' field")
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/issue84_test.go b/vendor/github.com/imdario/mergo/issue84_test.go
new file mode 100644
index 00000000000..aa605269b43
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/issue84_test.go
@@ -0,0 +1,82 @@
+package mergo
+
+import (
+	"testing"
+)
+
+type DstStructIssue84 struct {
+	A int
+	B int
+	C int
+}
+
+type DstNestedStructIssue84 struct {
+	A struct {
+		A int
+		B int
+		C int
+	}
+	B int
+	C int
+}
+
+func TestIssue84MergeMapWithNilValueToStructWithOverride(t *testing.T) {
+	p1 := DstStructIssue84{
+		A: 0, B: 1, C: 2,
+	}
+	p2 := map[string]interface{}{
+		"A": 3, "B": 4, "C": 0,
+	}
+	if err := Map(&p1, p2, WithOverride); err != nil {
+		t.Fatalf("Error during the merge: %v", err)
+	}
+	if p1.C != 0 {
+		t.Error("C field should become '0'")
+	}
+}
+
+func TestIssue84MergeMapWithoutKeyExistsToStructWithOverride(t *testing.T) {
+	p1 := DstStructIssue84{
+		A: 0, B: 1, C: 2,
+	}
+	p2 := map[string]interface{}{
+		"A": 3, "B": 4,
+	}
+	if err := Map(&p1, p2, WithOverride); err != nil {
+		t.Fatalf("Error during the merge: %v", err)
+	}
+	if p1.C != 2 {
+		t.Error("C field should be '2'")
+	}
+}
+
+func TestIssue84MergeNestedMapWithNilValueToStructWithOverride(t *testing.T) {
+	p1 := DstNestedStructIssue84{
+		A: struct {
+			A int
+			B int
+			C int
+		}{A: 1, B: 2, C: 0},
+		B: 0,
+		C: 2,
+	}
+	p2 := map[string]interface{}{
+		"A": map[string]interface{}{
+			"A": 0, "B": 0, "C": 5,
+		}, "B": 4, "C": 0,
+	}
+	if err := Map(&p1, p2, WithOverride); err != nil {
+		t.Fatalf("Error during the merge: %v", err)
+	}
+	if p1.B != 4 {
+		t.Error("A.C field should become '4'")
+	}
+
+	if p1.A.C != 5 {
+		t.Error("A.C field should become '5'")
+	}
+
+	if p1.A.B != 0 || p1.A.A != 0 {
+		t.Error("A.A and A.B field should become '0'")
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/map.go b/vendor/github.com/imdario/mergo/map.go
index 8e8c4ba8ebe..3f5afa83a13 100644
--- a/vendor/github.com/imdario/mergo/map.go
+++ b/vendor/github.com/imdario/mergo/map.go
@@ -31,7 +31,8 @@ func isExported(field reflect.StructField) bool {
 // Traverses recursively both values, assigning src's fields values to dst.
 // The map argument tracks comparisons that have already been seen, which allows
 // short circuiting on recursive types.
-func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
+func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
+	overwrite := config.Overwrite
 	if dst.CanAddr() {
 		addr := dst.UnsafeAddr()
 		h := 17 * addr
@@ -61,9 +62,17 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
 				dstMap[fieldName] = src.Field(i).Interface()
 			}
 		}
+	case reflect.Ptr:
+		if dst.IsNil() {
+			v := reflect.New(dst.Type().Elem())
+			dst.Set(v)
+		}
+		dst = dst.Elem()
+		fallthrough
 	case reflect.Struct:
 		srcMap := src.Interface().(map[string]interface{})
 		for key := range srcMap {
+			config.overwriteWithEmptyValue = true
 			srcValue := srcMap[key]
 			fieldName := changeInitialCase(key, unicode.ToUpper)
 			dstElement := dst.FieldByName(fieldName)
@@ -85,21 +94,24 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
 					srcKind = reflect.Ptr
 				}
 			}
+
 			if !srcElement.IsValid() {
 				continue
 			}
 			if srcKind == dstKind {
-				if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
+				if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
 					return
 				}
-			} else {
-				if srcKind == reflect.Map {
-					if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
-						return
-					}
-				} else {
-					return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
+			} else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
+				if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
+					return
+				}
+			} else if srcKind == reflect.Map {
+				if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil {
+					return
 				}
+			} else {
+				return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
 			}
 		}
 	}
@@ -117,28 +129,35 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
 // doesn't apply if dst is a map.
 // This is separated method from Merge because it is cleaner and it keeps sane
 // semantics: merging equal types, mapping different (restricted) types.
-func Map(dst, src interface{}) error {
-	return _map(dst, src, false)
+func Map(dst, src interface{}, opts ...func(*Config)) error {
+	return _map(dst, src, opts...)
 }
 
-// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
+// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overridden by
 // non-empty src attribute values.
-func MapWithOverwrite(dst, src interface{}) error {
-	return _map(dst, src, true)
+// Deprecated: Use Map(…) with WithOverride
+func MapWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
+	return _map(dst, src, append(opts, WithOverride)...)
 }
 
-func _map(dst, src interface{}, overwrite bool) error {
+func _map(dst, src interface{}, opts ...func(*Config)) error {
 	var (
 		vDst, vSrc reflect.Value
 		err        error
 	)
+	config := &Config{}
+
+	for _, opt := range opts {
+		opt(config)
+	}
+
 	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
 		return err
 	}
 	// To be friction-less, we redirect equal-type arguments
 	// to deepMerge. Only because arguments can be anything.
 	if vSrc.Kind() == vDst.Kind() {
-		return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
+		return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
 	}
 	switch vSrc.Kind() {
 	case reflect.Struct:
@@ -152,5 +171,5 @@ func _map(dst, src interface{}, overwrite bool) error {
 	default:
 		return ErrNotSupported
 	}
-	return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
+	return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config)
 }
diff --git a/vendor/github.com/imdario/mergo/merge.go b/vendor/github.com/imdario/mergo/merge.go
index 513774f4c7d..f8de6c54305 100644
--- a/vendor/github.com/imdario/mergo/merge.go
+++ b/vendor/github.com/imdario/mergo/merge.go
@@ -9,13 +9,41 @@
 package mergo
 
 import (
+	"fmt"
 	"reflect"
 )
 
+func hasExportedField(dst reflect.Value) (exported bool) {
+	for i, n := 0, dst.NumField(); i < n; i++ {
+		field := dst.Type().Field(i)
+		if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
+			exported = exported || hasExportedField(dst.Field(i))
+		} else {
+			exported = exported || len(field.PkgPath) == 0
+		}
+	}
+	return
+}
+
+type Config struct {
+	Overwrite               bool
+	AppendSlice             bool
+	Transformers            Transformers
+	overwriteWithEmptyValue bool
+}
+
+type Transformers interface {
+	Transformer(reflect.Type) func(dst, src reflect.Value) error
+}
+
 // Traverses recursively both values, assigning src's fields values to dst.
 // The map argument tracks comparisons that have already been seen, which allows
 // short circuiting on recursive types.
-func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
+func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
+	overwrite := config.Overwrite
+	overwriteWithEmptySrc := config.overwriteWithEmptyValue
+	config.overwriteWithEmptyValue = false
+
 	if !src.IsValid() {
 		return
 	}
@@ -32,14 +60,31 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
 		// Remember, remember...
 		visited[h] = &visit{addr, typ, seen}
 	}
+
+	if config.Transformers != nil && !isEmptyValue(dst) {
+		if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
+			err = fn(dst, src)
+			return
+		}
+	}
+
 	switch dst.Kind() {
 	case reflect.Struct:
-		for i, n := 0, dst.NumField(); i < n; i++ {
-			if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
-				return
+		if hasExportedField(dst) {
+			for i, n := 0, dst.NumField(); i < n; i++ {
+				if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
+					return
+				}
+			}
+		} else {
+			if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
+				dst.Set(src)
 			}
 		}
 	case reflect.Map:
+		if dst.IsNil() && !src.IsNil() {
+			dst.Set(reflect.MakeMap(dst.Type()))
+		}
 		for _, key := range src.MapKeys() {
 			srcElement := src.MapIndex(key)
 			if !srcElement.IsValid() {
@@ -47,7 +92,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
 			}
 			dstElement := dst.MapIndex(key)
 			switch srcElement.Kind() {
-			case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
+			case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice:
 				if srcElement.IsNil() {
 					continue
 				}
@@ -62,32 +107,94 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
 				case reflect.Ptr:
 					fallthrough
 				case reflect.Map:
-					if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
+					srcMapElm := srcElement
+					dstMapElm := dstElement
+					if srcMapElm.CanInterface() {
+						srcMapElm = reflect.ValueOf(srcMapElm.Interface())
+						if dstMapElm.IsValid() {
+							dstMapElm = reflect.ValueOf(dstMapElm.Interface())
+						}
+					}
+					if err = deepMerge(dstMapElm, srcMapElm, visited, depth+1, config); err != nil {
 						return
 					}
+				case reflect.Slice:
+					srcSlice := reflect.ValueOf(srcElement.Interface())
+
+					var dstSlice reflect.Value
+					if !dstElement.IsValid() || dstElement.IsNil() {
+						dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
+					} else {
+						dstSlice = reflect.ValueOf(dstElement.Interface())
+					}
+
+					if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
+						dstSlice = srcSlice
+					} else if config.AppendSlice {
+						if srcSlice.Type() != dstSlice.Type() {
+							return fmt.Errorf("cannot append two slice with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
+						}
+						dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
+					}
+					dst.SetMapIndex(key, dstSlice)
 				}
 			}
-			if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
+			if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) {
+				continue
+			}
+
+			if srcElement.IsValid() && (overwrite || (!dstElement.IsValid() || isEmptyValue(dstElement))) {
 				if dst.IsNil() {
 					dst.Set(reflect.MakeMap(dst.Type()))
 				}
 				dst.SetMapIndex(key, srcElement)
 			}
 		}
+	case reflect.Slice:
+		if !dst.CanSet() {
+			break
+		}
+		if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice {
+			dst.Set(src)
+		} else if config.AppendSlice {
+			if src.Type() != dst.Type() {
+				return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
+			}
+			dst.Set(reflect.AppendSlice(dst, src))
+		}
 	case reflect.Ptr:
 		fallthrough
 	case reflect.Interface:
 		if src.IsNil() {
 			break
-		} else if dst.IsNil() || overwrite {
+		}
+		if src.Kind() != reflect.Interface {
+			if dst.IsNil() || overwrite {
+				if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
+					dst.Set(src)
+				}
+			} else if src.Kind() == reflect.Ptr {
+				if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
+					return
+				}
+			} else if dst.Elem().Type() == src.Type() {
+				if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
+					return
+				}
+			} else {
+				return ErrDifferentArgumentsTypes
+			}
+			break
+		}
+		if dst.IsNil() || overwrite {
 			if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
 				dst.Set(src)
 			}
-		} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
+		} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
 			return
 		}
 	default:
-		if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
+		if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) {
 			dst.Set(src)
 		}
 	}
@@ -98,26 +205,51 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
 // src attributes if they themselves are not empty. dst and src must be valid same-type structs
 // and dst must be a pointer to struct.
 // It won't merge unexported (private) fields and will do recursively any exported field.
-func Merge(dst, src interface{}) error {
-	return merge(dst, src, false)
+func Merge(dst, src interface{}, opts ...func(*Config)) error {
+	return merge(dst, src, opts...)
 }
 
 // MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
 // non-empty src attribute values.
-func MergeWithOverwrite(dst, src interface{}) error {
-	return merge(dst, src, true)
+// Deprecated: use Merge(…) with WithOverride
+func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
+	return merge(dst, src, append(opts, WithOverride)...)
+}
+
+// WithTransformers adds transformers to merge, allowing to customize the merging of some types.
+func WithTransformers(transformers Transformers) func(*Config) {
+	return func(config *Config) {
+		config.Transformers = transformers
+	}
+}
+
+// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
+func WithOverride(config *Config) {
+	config.Overwrite = true
 }
 
-func merge(dst, src interface{}, overwrite bool) error {
+// WithAppendSlice will make merge append slices instead of overwriting it
+func WithAppendSlice(config *Config) {
+	config.AppendSlice = true
+}
+
+func merge(dst, src interface{}, opts ...func(*Config)) error {
 	var (
 		vDst, vSrc reflect.Value
 		err        error
 	)
+
+	config := &Config{}
+
+	for _, opt := range opts {
+		opt(config)
+	}
+
 	if vDst, vSrc, err = resolveValues(dst, src); err != nil {
 		return err
 	}
 	if vDst.Type() != vSrc.Type() {
 		return ErrDifferentArgumentsTypes
 	}
-	return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
+	return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
 }
diff --git a/vendor/github.com/imdario/mergo/merge_appendslice_test.go b/vendor/github.com/imdario/mergo/merge_appendslice_test.go
new file mode 100644
index 00000000000..a780f34a3c2
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/merge_appendslice_test.go
@@ -0,0 +1,33 @@
+package mergo
+
+import (
+	"testing"
+)
+
+var testDataS = []struct {
+	S1            Student
+	S2            Student
+	ExpectedSlice []string
+}{
+	{Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{"1"}}, []string{"1", "a", "B"}},
+	{Student{"Jack", []string{"a", "B"}}, Student{"Tom", []string{}}, []string{"a", "B"}},
+	{Student{"Jack", []string{}}, Student{"Tom", []string{"1"}}, []string{"1"}},
+	{Student{"Jack", []string{}}, Student{"Tom", []string{}}, []string{}},
+}
+
+func TestMergeSliceWithOverrideWithAppendSlice(t *testing.T) {
+	for _, data := range testDataS {
+		err := Merge(&data.S2, data.S1, WithOverride, WithAppendSlice)
+		if err != nil {
+			t.Errorf("Error while merging %s", err)
+		}
+		if len(data.S2.Books) != len(data.ExpectedSlice) {
+			t.Fatalf("Got %d elements in slice, but expected %d", len(data.S2.Books), len(data.ExpectedSlice))
+		}
+		for i, val := range data.S2.Books {
+			if val != data.ExpectedSlice[i] {
+				t.Fatalf("Expected %s, but got %s while merging slice with override", data.ExpectedSlice[i], val)
+			}
+		}
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/merge_test.go b/vendor/github.com/imdario/mergo/merge_test.go
new file mode 100644
index 00000000000..5bf808a786a
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/merge_test.go
@@ -0,0 +1,50 @@
+package mergo
+
+import (
+	"reflect"
+	"testing"
+)
+
+type transformer struct {
+	m map[reflect.Type]func(dst, src reflect.Value) error
+}
+
+func (s *transformer) Transformer(t reflect.Type) func(dst, src reflect.Value) error {
+	if fn, ok := s.m[t]; ok {
+		return fn
+	}
+	return nil
+}
+
+type foo struct {
+	s   string
+	Bar *bar
+}
+
+type bar struct {
+	i int
+	s map[string]string
+}
+
+func TestMergeWithTransformerNilStruct(t *testing.T) {
+	a := foo{s: "foo"}
+	b := foo{Bar: &bar{i: 2, s: map[string]string{"foo": "bar"}}}
+	if err := Merge(&a, &b, WithOverride, WithTransformers(&transformer{
+		m: map[reflect.Type]func(dst, src reflect.Value) error{
+			reflect.TypeOf(&bar{}): func(dst, src reflect.Value) error {
+				// Do sthg with Elem
+				t.Log(dst.Elem().FieldByName("i"))
+				t.Log(src.Elem())
+				return nil
+			},
+		},
+	})); err != nil {
+		t.Fatal(err)
+	}
+	if a.s != "foo" {
+		t.Fatalf("b not merged in properly: a.s.Value(%s) != expected(%s)", a.s, "foo")
+	}
+	if a.Bar == nil {
+		t.Fatalf("b not merged in properly: a.Bar shouldn't be nil")
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/mergo.go b/vendor/github.com/imdario/mergo/mergo.go
index f8a0991ec63..a82fea2fdcc 100644
--- a/vendor/github.com/imdario/mergo/mergo.go
+++ b/vendor/github.com/imdario/mergo/mergo.go
@@ -32,7 +32,7 @@ type visit struct {
 	next *visit
 }
 
-// From src/pkg/encoding/json.
+// From src/pkg/encoding/json/encode.go.
 func isEmptyValue(v reflect.Value) bool {
 	switch v.Kind() {
 	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
@@ -46,7 +46,14 @@ func isEmptyValue(v reflect.Value) bool {
 	case reflect.Float32, reflect.Float64:
 		return v.Float() == 0
 	case reflect.Interface, reflect.Ptr:
+		if v.IsNil() {
+			return true
+		}
+		return isEmptyValue(v.Elem())
+	case reflect.Func:
 		return v.IsNil()
+	case reflect.Invalid:
+		return true
 	}
 	return false
 }
diff --git a/vendor/github.com/imdario/mergo/mergo_test.go b/vendor/github.com/imdario/mergo/mergo_test.go
index c43c61cdd60..1f2ab0bc0a3 100644
--- a/vendor/github.com/imdario/mergo/mergo_test.go
+++ b/vendor/github.com/imdario/mergo/mergo_test.go
@@ -10,7 +10,8 @@ import (
 	"reflect"
 	"testing"
 	"time"
-	"gopkg.in/yaml.v1"
+
+	"gopkg.in/yaml.v2"
 )
 
 type simpleTest struct {
@@ -23,6 +24,14 @@ type complexTest struct {
 	ID string
 }
 
+type mapTest struct {
+	M map[int]int
+}
+
+type ifcTest struct {
+	I interface{}
+}
+
 type moreComplextText struct {
 	Ct complexTest
 	St simpleTest
@@ -217,29 +226,120 @@ func TestPointerStructNil(t *testing.T) {
 	}
 }
 
-func TestSliceStruct(t *testing.T) {
-	a := sliceTest{}
-	b := sliceTest{[]int{1, 2, 3}}
-	if err := Merge(&a, b); err != nil {
+func testSlice(t *testing.T, a []int, b []int, e []int, opts ...func(*Config)) {
+	t.Helper()
+	bc := b
+
+	sa := sliceTest{a}
+	sb := sliceTest{b}
+	if err := Merge(&sa, sb, opts...); err != nil {
 		t.FailNow()
 	}
-	if len(b.S) != 3 {
+	if !reflect.DeepEqual(sb.S, bc) {
+		t.Fatalf("Source slice was modified %d != %d", sb.S, bc)
+	}
+	if !reflect.DeepEqual(sa.S, e) {
+		t.Fatalf("b not merged in a proper way %d != %d", sa.S, e)
+	}
+
+	ma := map[string][]int{"S": a}
+	mb := map[string][]int{"S": b}
+	if err := Merge(&ma, mb, opts...); err != nil {
 		t.FailNow()
 	}
-	if len(a.S) != len(b.S) {
-		t.Fatalf("b not merged in a proper way %d != %d", len(a.S), len(b.S))
+	if !reflect.DeepEqual(mb["S"], bc) {
+		t.Fatalf("map value: Source slice was modified %d != %d", mb["S"], bc)
+	}
+	if !reflect.DeepEqual(ma["S"], e) {
+		t.Fatalf("map value: b not merged in a proper way %d != %d", ma["S"], e)
 	}
 
-	a = sliceTest{[]int{1}}
-	b = sliceTest{[]int{1, 2, 3}}
+	if a == nil {
+		// test case with missing dst key
+		ma := map[string][]int{}
+		mb := map[string][]int{"S": b}
+		if err := Merge(&ma, mb); err != nil {
+			t.FailNow()
+		}
+		if !reflect.DeepEqual(mb["S"], bc) {
+			t.Fatalf("missing dst key: Source slice was modified %d != %d", mb["S"], bc)
+		}
+		if !reflect.DeepEqual(ma["S"], e) {
+			t.Fatalf("missing dst key: b not merged in a proper way %d != %d", ma["S"], e)
+		}
+	}
+
+	if b == nil {
+		// test case with missing src key
+		ma := map[string][]int{"S": a}
+		mb := map[string][]int{}
+		if err := Merge(&ma, mb); err != nil {
+			t.FailNow()
+		}
+		if !reflect.DeepEqual(mb["S"], bc) {
+			t.Fatalf("missing src key: Source slice was modified %d != %d", mb["S"], bc)
+		}
+		if !reflect.DeepEqual(ma["S"], e) {
+			t.Fatalf("missing src key: b not merged in a proper way %d != %d", ma["S"], e)
+		}
+	}
+}
+
+func TestSlice(t *testing.T) {
+	testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3})
+	testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3})
+	testSlice(t, []int{1}, []int{2, 3}, []int{1})
+	testSlice(t, []int{1}, []int{}, []int{1})
+	testSlice(t, []int{1}, nil, []int{1})
+	testSlice(t, nil, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice)
+	testSlice(t, []int{}, []int{1, 2, 3}, []int{1, 2, 3}, WithAppendSlice)
+	testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice)
+	testSlice(t, []int{1}, []int{2, 3}, []int{1, 2, 3}, WithAppendSlice, WithOverride)
+	testSlice(t, []int{1}, []int{}, []int{1}, WithAppendSlice)
+	testSlice(t, []int{1}, nil, []int{1}, WithAppendSlice)
+}
+
+func TestEmptyMaps(t *testing.T) {
+	a := mapTest{}
+	b := mapTest{
+		map[int]int{},
+	}
 	if err := Merge(&a, b); err != nil {
+		t.Fail()
+	}
+	if !reflect.DeepEqual(a, b) {
 		t.FailNow()
 	}
-	if len(a.S) != 1 {
+}
+
+func TestEmptyToEmptyMaps(t *testing.T) {
+	a := mapTest{}
+	b := mapTest{}
+	if err := Merge(&a, b); err != nil {
+		t.Fail()
+	}
+	if !reflect.DeepEqual(a, b) {
 		t.FailNow()
 	}
-	if len(a.S) == len(b.S) {
-		t.Fatalf("b merged unexpectedly %d != %d", len(a.S), len(b.S))
+}
+
+func TestEmptyToNotEmptyMaps(t *testing.T) {
+	a := mapTest{map[int]int{
+		1: 2,
+		3: 4,
+	}}
+	aa := mapTest{map[int]int{
+		1: 2,
+		3: 4,
+	}}
+	b := mapTest{
+		map[int]int{},
+	}
+	if err := Merge(&a, b); err != nil {
+		t.Fail()
+	}
+	if !reflect.DeepEqual(a, aa) {
+		t.FailNow()
 	}
 }
 
@@ -312,12 +412,37 @@ func TestMaps(t *testing.T) {
 	}
 }
 
+func TestMapsWithNilPointer(t *testing.T) {
+	m := map[string]*simpleTest{
+		"a": nil,
+		"b": nil,
+	}
+	n := map[string]*simpleTest{
+		"b": nil,
+		"c": nil,
+	}
+	expect := map[string]*simpleTest{
+		"a": nil,
+		"b": nil,
+		"c": nil,
+	}
+
+	if err := Merge(&m, n, WithOverride); err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	if !reflect.DeepEqual(m, expect) {
+		t.Fatalf("Test failed:\ngot   :\n%#v\n\nwant :\n%#v\n\n", m, expect)
+	}
+}
+
 func TestYAMLMaps(t *testing.T) {
 	thing := loadYAML("testdata/thing.yml")
 	license := loadYAML("testdata/license.yml")
 	ft := thing["fields"].(map[interface{}]interface{})
 	fl := license["fields"].(map[interface{}]interface{})
-	expectedLength := len(ft) + len(fl)
+	// license has one extra field (site) and another already existing in thing (author) that Mergo won't override.
+	expectedLength := len(ft) + len(fl) - 1
 	if err := Merge(&license, thing); err != nil {
 		t.Fatal(err.Error())
 	}
@@ -392,6 +517,45 @@ func TestSimpleMap(t *testing.T) {
 	}
 }
 
+func TestIfcMap(t *testing.T) {
+	a := ifcTest{}
+	b := ifcTest{42}
+	if err := Map(&a, b); err != nil {
+		t.FailNow()
+	}
+	if a.I != 42 {
+		t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I)
+	}
+	if !reflect.DeepEqual(a, b) {
+		t.FailNow()
+	}
+}
+
+func TestIfcMapNoOverwrite(t *testing.T) {
+	a := ifcTest{13}
+	b := ifcTest{42}
+	if err := Map(&a, b); err != nil {
+		t.FailNow()
+	}
+	if a.I != 13 {
+		t.Fatalf("a not left alone: a.I(%d) == b.I(%d)", a.I, b.I)
+	}
+}
+
+func TestIfcMapWithOverwrite(t *testing.T) {
+	a := ifcTest{13}
+	b := ifcTest{42}
+	if err := MapWithOverwrite(&a, b); err != nil {
+		t.FailNow()
+	}
+	if a.I != 42 {
+		t.Fatalf("b not merged in properly: a.I(%d) != b.I(%d)", a.I, b.I)
+	}
+	if !reflect.DeepEqual(a, b) {
+		t.FailNow()
+	}
+}
+
 type pointerMapTest struct {
 	A      int
 	hidden int
@@ -433,6 +597,29 @@ func TestBackAndForth(t *testing.T) {
 	}
 }
 
+func TestEmbeddedPointerUnpacking(t *testing.T) {
+	tests := []struct{ input pointerMapTest }{
+		{pointerMapTest{42, 1, nil}},
+		{pointerMapTest{42, 1, &simpleTest{66}}},
+	}
+	newValue := 77
+	m := map[string]interface{}{
+		"b": map[string]interface{}{
+			"value": newValue,
+		},
+	}
+	for _, test := range tests {
+		pt := test.input
+		if err := MapWithOverwrite(&pt, m); err != nil {
+			t.FailNow()
+		}
+		if pt.B.Value != newValue {
+			t.Fatalf("pt not mapped properly: pt.A.Value(%d) != m[`b`][`value`](%d)", pt.B.Value, newValue)
+		}
+
+	}
+}
+
 type structWithTimePointer struct {
 	Birth *time.Time
 }
@@ -510,10 +697,10 @@ type structWithUnexportedProperty struct {
 
 func TestUnexportedProperty(t *testing.T) {
 	a := structWithMap{map[string]structWithUnexportedProperty{
-		"key": structWithUnexportedProperty{"hello"},
+		"key": {"hello"},
 	}}
 	b := structWithMap{map[string]structWithUnexportedProperty{
-		"key": structWithUnexportedProperty{"hi"},
+		"key": {"hi"},
 	}}
 	defer func() {
 		if r := recover(); r != nil {
@@ -545,3 +732,25 @@ func TestBooleanPointer(t *testing.T) {
 		t.Fatalf("dst.C should be true")
 	}
 }
+
+func TestMergeMapWithInnerSliceOfDifferentType(t *testing.T) {
+	src := map[string]interface{}{
+		"foo": []string{"a", "b"},
+	}
+	dst := map[string]interface{}{
+		"foo": []int{1, 2},
+	}
+
+	if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil {
+		t.Fatal("expected an error, got nothing")
+	}
+}
+
+func TestMergeSliceDifferentType(t *testing.T) {
+	src := []string{"a", "b"}
+	dst := []int{1, 2}
+
+	if err := Merge(&src, &dst, WithOverride, WithAppendSlice); err == nil {
+		t.Fatal("expected an error, got nothing")
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/pr80_test.go b/vendor/github.com/imdario/mergo/pr80_test.go
new file mode 100644
index 00000000000..0b3220f3bcd
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/pr80_test.go
@@ -0,0 +1,18 @@
+package mergo
+
+import (
+	"testing"
+)
+
+type mapInterface map[string]interface{}
+
+func TestMergeMapsEmptyString(t *testing.T) {
+	a := mapInterface{"s": ""}
+	b := mapInterface{"s": "foo"}
+	if err := Merge(&a, b); err != nil {
+		t.Fatal(err)
+	}
+	if a["s"] != "foo" {
+		t.Fatalf("b not merged in properly: a.s.Value(%s) != expected(%s)", a["s"], "foo")
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/pr81_test.go b/vendor/github.com/imdario/mergo/pr81_test.go
new file mode 100644
index 00000000000..e90e923feb9
--- /dev/null
+++ b/vendor/github.com/imdario/mergo/pr81_test.go
@@ -0,0 +1,42 @@
+package mergo
+
+import (
+	"testing"
+)
+
+func TestMapInterfaceWithMultipleLayer(t *testing.T) {
+	m1 := map[string]interface{}{
+		"k1": map[string]interface{}{
+			"k1.1": "v1",
+		},
+	}
+
+	m2 := map[string]interface{}{
+		"k1": map[string]interface{}{
+			"k1.1": "v2",
+			"k1.2": "v3",
+		},
+	}
+
+	if err := Map(&m1, m2, WithOverride); err != nil {
+		t.Fatalf("Error merging: %v", err)
+	}
+
+	// Check overwrite of sub map works
+	expected := "v2"
+	actual := m1["k1"].(map[string]interface{})["k1.1"].(string)
+	if actual != expected {
+		t.Fatalf("Expected %v but got %v",
+			expected,
+			actual)
+	}
+
+	// Check new key is merged
+	expected = "v3"
+	actual = m1["k1"].(map[string]interface{})["k1.2"].(string)
+	if actual != expected {
+		t.Fatalf("Expected %v but got %v",
+			expected,
+			actual)
+	}
+}
diff --git a/vendor/github.com/imdario/mergo/testdata/license.yml b/vendor/github.com/imdario/mergo/testdata/license.yml
index 62fdb61ec32..2f1ad0082bb 100644
--- a/vendor/github.com/imdario/mergo/testdata/license.yml
+++ b/vendor/github.com/imdario/mergo/testdata/license.yml
@@ -1,3 +1,4 @@
 import: ../../../../fossene/db/schema/thing.yml
 fields:
     site: string
+    author: root
-- 
GitLab