/
util.go
131 lines (115 loc) · 3.2 KB
/
util.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package bridge
import (
"strconv"
"strings"
"github.com/cenkalti/backoff"
dockerapi "github.com/fsouza/go-dockerclient"
)
func retry(fn func() error) error {
return backoff.Retry(fn, backoff.NewExponentialBackOff())
}
func mapDefault(m map[string]string, key, default_ string) string {
v, ok := m[key]
if !ok || v == "" {
return default_
}
return v
}
// Golang regexp module does not support /(?!\\),/ syntax for spliting by not escaped comma
// Then this function is reproducing it
func recParseEscapedComma(str string) []string {
if len(str) == 0 {
return []string{}
} else if str[0] == ',' {
return recParseEscapedComma(str[1:])
}
offset := 0
for len(str[offset:]) > 0 {
index := strings.Index(str[offset:], ",")
if index == -1 {
break
} else if str[offset+index-1:offset+index] != "\\" {
return append(recParseEscapedComma(str[offset+index+1:]), str[:offset+index])
}
str = str[:offset+index-1] + str[offset+index:]
offset += index
}
return []string{str}
}
func combineTags(tagParts ...string) []string {
tags := make([]string, 0)
for _, element := range tagParts {
tags = append(tags, recParseEscapedComma(element)...)
}
return tags
}
func serviceMetaData(config *dockerapi.Config, port string) (map[string]string, map[string]bool) {
meta := config.Env
for k, v := range config.Labels {
meta = append(meta, k+"="+v)
}
metadata := make(map[string]string)
metadataFromPort := make(map[string]bool)
for _, kv := range meta {
kvp := strings.SplitN(kv, "=", 2)
if strings.HasPrefix(kvp[0], "SERVICE_") && len(kvp) > 1 {
key := strings.ToLower(strings.TrimPrefix(kvp[0], "SERVICE_"))
if metadataFromPort[key] {
continue
}
portkey := strings.SplitN(key, "_", 2)
_, err := strconv.Atoi(portkey[0])
if err == nil && len(portkey) > 1 {
if portkey[0] != port {
continue
}
metadata[portkey[1]] = kvp[1]
metadataFromPort[portkey[1]] = true
} else {
metadata[key] = kvp[1]
}
}
}
return metadata, metadataFromPort
}
func servicePort(container *dockerapi.Container, port dockerapi.Port, published []dockerapi.PortBinding) ServicePort {
var hp, hip, ep, ept, eip, nm string
if len(published) > 0 {
hp = published[0].HostPort
hip = published[0].HostIP
}
if hip == "" {
hip = "0.0.0.0"
}
//for overlay networks
//detect if container use overlay network, than set HostIP into NetworkSettings.Network[string].IPAddress
//better to use registrator with -internal flag
nm = container.HostConfig.NetworkMode
if nm != "bridge" && nm != "default" && nm != "host" {
hip = container.NetworkSettings.Networks[nm].IPAddress
}
exposedPort := strings.Split(string(port), "/")
ep = exposedPort[0]
if len(exposedPort) == 2 {
ept = exposedPort[1]
} else {
ept = "tcp" // default
}
// Nir: support docker NetworkSettings
eip = container.NetworkSettings.IPAddress
if eip == "" {
for _, network := range container.NetworkSettings.Networks {
eip = network.IPAddress
}
}
return ServicePort{
HostPort: hp,
HostIP: hip,
ExposedPort: ep,
ExposedIP: eip,
PortType: ept,
ContainerID: container.ID,
ContainerHostname: container.Config.Hostname,
container: container,
}
}