-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
merge.go
97 lines (78 loc) · 2.06 KB
/
merge.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.
package workloadmeta
import (
"reflect"
"strconv"
"time"
"github.com/imdario/mergo"
)
type (
merger struct{}
)
var (
timeType = reflect.TypeOf(time.Time{})
portSliceType = reflect.TypeOf([]ContainerPort{})
mergerInstance = merger{}
)
func (merger) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
switch typ {
case timeType:
return timeMerge
case portSliceType:
return portSliceMerge
}
return nil
}
func timeMerge(dst, src reflect.Value) error {
if !dst.CanSet() {
return nil
}
isZero := src.MethodByName("IsZero")
result := isZero.Call([]reflect.Value{})
if !result[0].Bool() {
dst.Set(src)
}
return nil
}
func portSliceMerge(dst, src reflect.Value) error {
if !dst.CanSet() {
return nil
}
srcSlice := src.Interface().([]ContainerPort)
dstSlice := dst.Interface().([]ContainerPort)
// Not allocation the map if nothing to do
if len(srcSlice) == 0 || len(dstSlice) == 0 {
return nil
}
mergeMap := make(map[string]ContainerPort, len(srcSlice)+len(dstSlice))
for _, port := range dstSlice {
mergeContainerPort(mergeMap, port)
}
for _, port := range srcSlice {
mergeContainerPort(mergeMap, port)
}
dstSlice = make([]ContainerPort, 0, len(mergeMap))
for _, port := range mergeMap {
dstSlice = append(dstSlice, port)
}
dst.Set(reflect.ValueOf(dstSlice))
return nil
}
func mergeContainerPort(mergeMap map[string]ContainerPort, port ContainerPort) {
portKey := strconv.Itoa(port.Port) + port.Protocol
existingPort, found := mergeMap[portKey]
if found {
if (existingPort.Name == "" && port.Name != "") ||
(existingPort.HostPort == 0 && port.HostPort != 0) {
mergeMap[portKey] = port
}
} else {
mergeMap[portKey] = port
}
}
func merge(dst, src interface{}) error {
return mergo.Merge(dst, src, mergo.WithAppendSlice, mergo.WithTransformers(mergerInstance))
}