Merge pull request #5599 from robmry/option_ipv4

Add option --ipv4
This commit is contained in:
Rob Murray 2024-12-12 15:10:48 +00:00 committed by GitHub
commit 2080e09905
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 95 additions and 24 deletions

View File

@ -24,6 +24,7 @@ type createOptions struct {
driverOpts opts.MapOpts driverOpts opts.MapOpts
labels opts.ListOpts labels opts.ListOpts
internal bool internal bool
ipv4 *bool
ipv6 *bool ipv6 *bool
attachable bool attachable bool
ingress bool ingress bool
@ -42,7 +43,7 @@ type ipamOptions struct {
} }
func newCreateCommand(dockerCLI command.Cli) *cobra.Command { func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
var ipv6 bool var ipv4, ipv6 bool
options := createOptions{ options := createOptions{
driverOpts: *opts.NewMapOpts(nil, nil), driverOpts: *opts.NewMapOpts(nil, nil),
labels: opts.NewListOpts(opts.ValidateLabel), labels: opts.NewListOpts(opts.ValidateLabel),
@ -59,6 +60,9 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
options.name = args[0] options.name = args[0]
if cmd.Flag("ipv4").Changed {
options.ipv4 = &ipv4
}
if cmd.Flag("ipv6").Changed { if cmd.Flag("ipv6").Changed {
options.ipv6 = &ipv6 options.ipv6 = &ipv6
} }
@ -73,7 +77,8 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
flags.VarP(&options.driverOpts, "opt", "o", "Set driver specific options") flags.VarP(&options.driverOpts, "opt", "o", "Set driver specific options")
flags.Var(&options.labels, "label", "Set metadata on a network") flags.Var(&options.labels, "label", "Set metadata on a network")
flags.BoolVar(&options.internal, "internal", false, "Restrict external access to the network") flags.BoolVar(&options.internal, "internal", false, "Restrict external access to the network")
flags.BoolVar(&ipv6, "ipv6", false, "Enable or disable IPv6 networking") flags.BoolVar(&ipv4, "ipv4", true, "Enable or disable IPv4 address assignment")
flags.BoolVar(&ipv6, "ipv6", false, "Enable or disable IPv6 address assignment")
flags.BoolVar(&options.attachable, "attachable", false, "Enable manual container attachment") flags.BoolVar(&options.attachable, "attachable", false, "Enable manual container attachment")
flags.SetAnnotation("attachable", "version", []string{"1.25"}) flags.SetAnnotation("attachable", "version", []string{"1.25"})
flags.BoolVar(&options.ingress, "ingress", false, "Create swarm routing-mesh network") flags.BoolVar(&options.ingress, "ingress", false, "Create swarm routing-mesh network")
@ -113,6 +118,7 @@ func runCreate(ctx context.Context, apiClient client.NetworkAPIClient, output io
Options: options.driverOpts.GetAll(), Options: options.driverOpts.GetAll(),
IPAM: ipamCfg, IPAM: ipamCfg,
Internal: options.internal, Internal: options.internal,
EnableIPv4: options.ipv4,
EnableIPv6: options.ipv6, EnableIPv6: options.ipv6,
Attachable: options.attachable, Attachable: options.attachable,
Ingress: options.ingress, Ingress: options.ingress,

View File

@ -182,6 +182,60 @@ func TestNetworkCreateWithFlags(t *testing.T) {
assert.Check(t, is.Equal("banana", strings.TrimSpace(cli.OutBuffer().String()))) assert.Check(t, is.Equal("banana", strings.TrimSpace(cli.OutBuffer().String())))
} }
// TestNetworkCreateIPv4 verifies behavior of the "--ipv4" option. This option
// is an optional bool, and must default to "nil", not "true" or "false".
func TestNetworkCreateIPv4(t *testing.T) {
boolPtr := func(val bool) *bool { return &val }
tests := []struct {
doc, name string
flags []string
expected *bool
}{
{
doc: "IPv4 default",
name: "ipv4-default",
expected: nil,
},
{
doc: "IPv4 enabled",
name: "ipv4-enabled",
flags: []string{"--ipv4=true"},
expected: boolPtr(true),
},
{
doc: "IPv4 enabled (shorthand)",
name: "ipv4-enabled-shorthand",
flags: []string{"--ipv4"},
expected: boolPtr(true),
},
{
doc: "IPv4 disabled",
name: "ipv4-disabled",
flags: []string{"--ipv4=false"},
expected: boolPtr(false),
},
}
for _, tc := range tests {
t.Run(tc.doc, func(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
networkCreateFunc: func(ctx context.Context, name string, createBody network.CreateOptions) (network.CreateResponse, error) {
assert.Check(t, is.DeepEqual(createBody.EnableIPv4, tc.expected))
return network.CreateResponse{ID: name}, nil
},
})
cmd := newCreateCommand(cli)
cmd.SetArgs([]string{tc.name})
if tc.expected != nil {
assert.Check(t, cmd.ParseFlags(tc.flags))
}
assert.NilError(t, cmd.Execute())
assert.Check(t, is.Equal(tc.name, strings.TrimSpace(cli.OutBuffer().String())))
})
}
}
// TestNetworkCreateIPv6 verifies behavior of the "--ipv6" option. This option // TestNetworkCreateIPv6 verifies behavior of the "--ipv6" option. This option
// is an optional bool, and must default to "nil", not "true" or "false". // is an optional bool, and must default to "nil", not "true" or "false".
func TestNetworkCreateIPv6(t *testing.T) { func TestNetworkCreateIPv6(t *testing.T) {

View File

@ -13,6 +13,7 @@ const (
defaultNetworkTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.Scope}}" defaultNetworkTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.Scope}}"
networkIDHeader = "NETWORK ID" networkIDHeader = "NETWORK ID"
ipv4Header = "IPV4"
ipv6Header = "IPV6" ipv6Header = "IPV6"
internalHeader = "INTERNAL" internalHeader = "INTERNAL"
) )
@ -51,6 +52,7 @@ func FormatWrite(ctx formatter.Context, networks []network.Summary) error {
"Name": formatter.NameHeader, "Name": formatter.NameHeader,
"Driver": formatter.DriverHeader, "Driver": formatter.DriverHeader,
"Scope": formatter.ScopeHeader, "Scope": formatter.ScopeHeader,
"IPv4": ipv4Header,
"IPv6": ipv6Header, "IPv6": ipv6Header,
"Internal": internalHeader, "Internal": internalHeader,
"Labels": formatter.LabelsHeader, "Labels": formatter.LabelsHeader,
@ -88,6 +90,10 @@ func (c *networkContext) Scope() string {
return c.n.Scope return c.n.Scope
} }
func (c *networkContext) IPv4() string {
return strconv.FormatBool(c.n.EnableIPv4)
}
func (c *networkContext) IPv6() string { func (c *networkContext) IPv6() string {
return strconv.FormatBool(c.n.EnableIPv6) return strconv.FormatBool(c.n.EnableIPv6)
} }

View File

@ -42,6 +42,9 @@ func TestNetworkContext(t *testing.T) {
{networkContext{ {networkContext{
n: network.Summary{Driver: "driver_name"}, n: network.Summary{Driver: "driver_name"},
}, "driver_name", ctx.Driver}, }, "driver_name", ctx.Driver},
{networkContext{
n: network.Summary{EnableIPv4: true},
}, "true", ctx.IPv4},
{networkContext{ {networkContext{
n: network.Summary{EnableIPv6: true}, n: network.Summary{EnableIPv6: true},
}, "true", ctx.IPv6}, }, "true", ctx.IPv6},
@ -180,8 +183,8 @@ func TestNetworkContextWriteJSON(t *testing.T) {
{ID: "networkID2", Name: "foobar_bar"}, {ID: "networkID2", Name: "foobar_bar"},
} }
expectedJSONs := []map[string]any{ expectedJSONs := []map[string]any{
{"Driver": "", "ID": "networkID1", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_baz", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"}, {"Driver": "", "ID": "networkID1", "IPv4": "false", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_baz", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"},
{"Driver": "", "ID": "networkID2", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_bar", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"}, {"Driver": "", "ID": "networkID2", "IPv4": "false", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_bar", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"},
} }
out := bytes.NewBufferString("") out := bytes.NewBufferString("")

View File

@ -18,7 +18,8 @@ Create a network
| `--ip-range` | `stringSlice` | | Allocate container ip from a sub-range | | `--ip-range` | `stringSlice` | | Allocate container ip from a sub-range |
| `--ipam-driver` | `string` | `default` | IP Address Management Driver | | `--ipam-driver` | `string` | `default` | IP Address Management Driver |
| `--ipam-opt` | `map` | `map[]` | Set IPAM driver specific options | | `--ipam-opt` | `map` | `map[]` | Set IPAM driver specific options |
| `--ipv6` | `bool` | | Enable or disable IPv6 networking | | `--ipv4` | `bool` | `true` | Enable or disable IPv4 address assignment |
| `--ipv6` | `bool` | | Enable or disable IPv6 address assignment |
| `--label` | `list` | | Set metadata on a network | | `--label` | `list` | | Set metadata on a network |
| `-o`, `--opt` | `map` | `map[]` | Set driver specific options | | `-o`, `--opt` | `map` | `map[]` | Set driver specific options |
| `--scope` | `string` | | Control the network's scope | | `--scope` | `string` | | Control the network's scope |
@ -148,30 +149,31 @@ fails and Docker Engine returns an error.
### Bridge driver options ### Bridge driver options
When creating a custom network, the default network driver (i.e. `bridge`) has When creating a custom `bridge` network, the following additional options can
additional options that can be passed. The following are those options and the be passed. Some of these have equivalent flags that can be used on the dockerd
equivalent Docker daemon flags used for docker0 bridge: command line or in `daemon.json` to configure the default bridge, `docker0`:
| Option | Equivalent | Description | | Network create option | Daemon option for `docker0` | Description |
|--------------------------------------------------|-------------|-------------------------------------------------------| |--------------------------------------------------|-----------------------------|-------------------------------------------------------|
| `com.docker.network.bridge.name` | - | Bridge name to be used when creating the Linux bridge | | `com.docker.network.bridge.name` | - | Bridge name to be used when creating the Linux bridge |
| `com.docker.network.bridge.enable_ip_masquerade` | `--ip-masq` | Enable IP masquerading | | `com.docker.network.bridge.enable_ip_masquerade` | `--ip-masq` | Enable IP masquerading |
| `com.docker.network.bridge.enable_icc` | `--icc` | Enable or Disable Inter Container Connectivity | | `com.docker.network.bridge.enable_icc` | `--icc` | Enable or Disable Inter Container Connectivity |
| `com.docker.network.bridge.host_binding_ipv4` | `--ip` | Default IP when binding container ports | | `com.docker.network.bridge.host_binding_ipv4` | `--ip` | Default IP when binding container ports |
| `com.docker.network.driver.mtu` | `--mtu` | Set the containers network MTU | | `com.docker.network.driver.mtu` | `--mtu` | Set the containers network MTU |
| `com.docker.network.container_iface_prefix` | - | Set a custom prefix for container interfaces | | `com.docker.network.container_iface_prefix` | - | Set a custom prefix for container interfaces |
The following arguments can be passed to `docker network create` for any The following arguments can be passed to `docker network create` for any
network driver, again with their approximate equivalents to Docker daemon network driver, again with their approximate equivalents to Docker daemon
flags used for the docker0 bridge: flags used for the `docker0` bridge:
| Argument | Equivalent | Description | | Network create option | Daemon option for `docker0` | Description |
|--------------|----------------|--------------------------------------------| |-----------------------|-----------------------------------|--------------------------------------------|
| `--gateway` | - | IPv4 or IPv6 Gateway for the master subnet | | `--gateway` | - | IPv4 or IPv6 Gateway for the master subnet |
| `--ip-range` | `--fixed-cidr` | Allocate IPs from a range | | `--ip-range` | `--fixed-cidr`, `--fixed-cidr-v6` | Allocate IP addresses from a range |
| `--internal` | - | Restrict external access to the network | | `--internal` | - | Restrict external access to the network |
| `--ipv6` | `--ipv6` | Enable or disable IPv6 networking | | `--ipv4` | - | Enable or disable IPv4 address assignment |
| `--subnet` | `--bip` | Subnet for network | | `--ipv6` | `--ipv6` | Enable or disable IPv6 address assignment |
| `--subnet` | `--bip`, `--bip6` | Subnet for network |
For example, let's use `-o` or `--opt` options to specify an IP address binding For example, let's use `-o` or `--opt` options to specify an IP address binding
when publishing ports: when publishing ports: