diff --git a/cli/command/container/opts_test.go b/cli/command/container/opts_test.go index 556e013066fa..bb5dd51cefbd 100644 --- a/cli/command/container/opts_test.go +++ b/cli/command/container/opts_test.go @@ -609,6 +609,17 @@ func TestParseNetworkConfig(t *testing.T) { expected: map[string]*networktypes.EndpointSettings{}, expectedHostCfg: container.HostConfig{NetworkMode: "net1"}, }, + { + name: "single-network-advanced-preserves-case", + flags: []string{"--network", "name=MyNetwork,alias=WebApp,driver-opt=CustomKey=CaseSensitiveValue"}, + expected: map[string]*networktypes.EndpointSettings{ + "MyNetwork": { + Aliases: []string{"WebApp"}, + DriverOpts: map[string]string{"CustomKey": "CaseSensitiveValue"}, + }, + }, + expectedHostCfg: container.HostConfig{NetworkMode: "MyNetwork"}, + }, { name: "single-network-legacy-with-options", flags: []string{ diff --git a/opts/network.go b/opts/network.go index 51f50f2070b1..94cd6b8eb6b8 100644 --- a/opts/network.go +++ b/opts/network.go @@ -60,12 +60,12 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo netOpt.Aliases = []string{} for _, field := range fields { // TODO(thaJeztah): these options should not be case-insensitive. - key, val, ok := strings.Cut(strings.ToLower(field), "=") + key, val, ok := strings.Cut(field, "=") if !ok || key == "" { return fmt.Errorf("invalid field %s", field) } - key = strings.TrimSpace(key) + key = strings.ToLower(strings.TrimSpace(key)) val = strings.TrimSpace(val) switch key { @@ -148,9 +148,7 @@ func (n *NetworkOpt) NetworkMode() string { } func parseDriverOpt(driverOpt string) (string, string, error) { - // TODO(thaJeztah): these options should not be case-insensitive. - // TODO(thaJeztah): should value be converted to lowercase as well, or only the key? - key, value, ok := strings.Cut(strings.ToLower(driverOpt), "=") + key, value, ok := strings.Cut(driverOpt, "=") if !ok || key == "" { return "", "", errors.New("invalid key value pair format in driver options") } diff --git a/opts/network_test.go b/opts/network_test.go index ad7f50ece7b5..19e0084f2838 100644 --- a/opts/network_test.go +++ b/opts/network_test.go @@ -35,6 +35,30 @@ func TestNetworkOptAdvancedSyntax(t *testing.T) { value string expected []NetworkAttachmentOpts }{ + { + value: "name=MyNetwork,alias=WebApp,driver-opt=CustomKey=CaseSensitiveValue", + expected: []NetworkAttachmentOpts{ + { + Target: "MyNetwork", + Aliases: []string{"WebApp"}, + DriverOpts: map[string]string{ + "CustomKey": "CaseSensitiveValue", + }, + }, + }, + }, + { + value: "NAME=MyNetwork,ALIAS=WebApp,DRIVER-OPT=CustomKey=CaseSensitiveValue", + expected: []NetworkAttachmentOpts{ + { + Target: "MyNetwork", + Aliases: []string{"WebApp"}, + DriverOpts: map[string]string{ + "CustomKey": "CaseSensitiveValue", + }, + }, + }, + }, { value: "name=docknet1,alias=web,driver-opt=field1=value1", expected: []NetworkAttachmentOpts{ @@ -107,9 +131,7 @@ func TestNetworkOptAdvancedSyntax(t *testing.T) { Target: "docknet1", Aliases: []string{}, DriverOpts: map[string]string{ - // The CLI converts IFNAME to ifname - it probably shouldn't, but the API - // allows ifname to cater for this. - "com.docker.network.endpoint.sysctls": "net.ipv6.conf.ifname.accept_ra=2,net.ipv6.conf.ifname.forwarding=1", + "com.docker.network.endpoint.sysctls": "net.ipv6.conf.IFNAME.accept_ra=2,net.ipv6.conf.IFNAME.forwarding=1", }, }, },