mirror of https://github.com/docker/cli.git
docker stack: allow '=' separator in extra_hosts
extra_hosts in the compose file format allows '=' as a separator, and brackets
around IP addresses, the engine API doesn't.
So, transform the values when reading a compose file for 'docker stack'.
Signed-off-by: Rob Murray <rob.murray@docker.com>
(cherry picked from commit c986d09bca
)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
parent
a5937c6043
commit
1cddb2b03d
|
@ -328,7 +328,7 @@ func createTransformHook(additionalTransformers ...Transformer) mapstructure.Dec
|
|||
reflect.TypeOf(types.MappingWithEquals{}): transformMappingOrListFunc("=", true),
|
||||
reflect.TypeOf(types.Labels{}): transformMappingOrListFunc("=", false),
|
||||
reflect.TypeOf(types.MappingWithColon{}): transformMappingOrListFunc(":", false),
|
||||
reflect.TypeOf(types.HostsList{}): transformListOrMappingFunc(":", false),
|
||||
reflect.TypeOf(types.HostsList{}): transformHostsList,
|
||||
reflect.TypeOf(types.ServiceVolumeConfig{}): transformServiceVolumeConfig,
|
||||
reflect.TypeOf(types.BuildConfig{}): transformBuildConfig,
|
||||
reflect.TypeOf(types.Duration(0)): transformStringToDuration,
|
||||
|
@ -808,28 +808,58 @@ var transformStringList TransformerFunc = func(data any) (any, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func transformMappingOrListFunc(sep string, allowNil bool) TransformerFunc {
|
||||
return func(data any) (any, error) {
|
||||
return transformMappingOrList(data, sep, allowNil), nil
|
||||
var transformHostsList TransformerFunc = func(data any) (any, error) {
|
||||
hl := transformListOrMapping(data, ":", false, []string{"=", ":"})
|
||||
|
||||
// Remove brackets from IP addresses if present (for example "[::1]" -> "::1").
|
||||
result := make([]string, 0, len(hl))
|
||||
for _, hip := range hl {
|
||||
host, ip, _ := strings.Cut(hip, ":")
|
||||
if len(ip) > 2 && ip[0] == '[' && ip[len(ip)-1] == ']' {
|
||||
ip = ip[1 : len(ip)-1]
|
||||
}
|
||||
result = append(result, fmt.Sprintf("%s:%s", host, ip))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func transformListOrMappingFunc(sep string, allowNil bool) TransformerFunc {
|
||||
return func(data any) (any, error) {
|
||||
return transformListOrMapping(data, sep, allowNil), nil
|
||||
}
|
||||
}
|
||||
|
||||
func transformListOrMapping(listOrMapping any, sep string, allowNil bool) any {
|
||||
// transformListOrMapping transforms pairs of strings that may be represented as
|
||||
// a map, or a list of '=' or ':' separated strings, into a list of ':' separated
|
||||
// strings.
|
||||
func transformListOrMapping(listOrMapping any, sep string, allowNil bool, allowSeps []string) []string {
|
||||
switch value := listOrMapping.(type) {
|
||||
case map[string]any:
|
||||
return toStringList(value, sep, allowNil)
|
||||
case []any:
|
||||
return listOrMapping
|
||||
result := make([]string, 0, len(value))
|
||||
for _, entry := range value {
|
||||
for i, allowSep := range allowSeps {
|
||||
entry := fmt.Sprint(entry)
|
||||
k, v, ok := strings.Cut(entry, allowSep)
|
||||
if ok {
|
||||
// Entry uses this allowed separator. Add it to the result, using
|
||||
// sep as a separator.
|
||||
result = append(result, fmt.Sprintf("%s%s%s", k, sep, v))
|
||||
break
|
||||
} else if i == len(allowSeps)-1 {
|
||||
// No more separators to try, keep the entry if allowNil.
|
||||
if allowNil {
|
||||
result = append(result, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
panic(errors.Errorf("expected a map or a list, got %T: %#v", listOrMapping, listOrMapping))
|
||||
}
|
||||
|
||||
func transformMappingOrListFunc(sep string, allowNil bool) TransformerFunc {
|
||||
return func(data any) (any, error) {
|
||||
return transformMappingOrList(data, sep, allowNil), nil
|
||||
}
|
||||
}
|
||||
|
||||
func transformMappingOrList(mappingOrList any, sep string, allowNil bool) any {
|
||||
switch values := mappingOrList.(type) {
|
||||
case map[string]any:
|
||||
|
|
|
@ -1302,12 +1302,14 @@ services:
|
|||
extra_hosts:
|
||||
"zulu": "162.242.195.82"
|
||||
"alpha": "50.31.209.229"
|
||||
"beta": "[fd20:f8a7:6e5b::2]"
|
||||
"host.docker.internal": "host-gateway"
|
||||
`)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := types.HostsList{
|
||||
"alpha:50.31.209.229",
|
||||
"beta:fd20:f8a7:6e5b::2",
|
||||
"host.docker.internal:host-gateway",
|
||||
"zulu:162.242.195.82",
|
||||
}
|
||||
|
@ -1324,16 +1326,25 @@ services:
|
|||
image: busybox
|
||||
extra_hosts:
|
||||
- "zulu:162.242.195.82"
|
||||
- "whiskey=162.242.195.83"
|
||||
- "alpha:50.31.209.229"
|
||||
- "zulu:ff02::1"
|
||||
- "host.docker.internal:host-gateway"
|
||||
- "whiskey=ff02::2"
|
||||
- "foxtrot=[ff02::3]"
|
||||
- "bravo:[ff02::4]"
|
||||
- "host.docker.internal=host-gateway"
|
||||
- "noaddress"
|
||||
`)
|
||||
assert.NilError(t, err)
|
||||
|
||||
expected := types.HostsList{
|
||||
"zulu:162.242.195.82",
|
||||
"whiskey:162.242.195.83",
|
||||
"alpha:50.31.209.229",
|
||||
"zulu:ff02::1",
|
||||
"whiskey:ff02::2",
|
||||
"foxtrot:ff02::3",
|
||||
"bravo:ff02::4",
|
||||
"host.docker.internal:host-gateway",
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue