Add option --ipv4

Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
Rob Murray 2024-11-06 18:42:11 +00:00
parent d6c74e6031
commit afbbecd44f
5 changed files with 83 additions and 10 deletions

View File

@ -24,6 +24,7 @@ type createOptions struct {
driverOpts opts.MapOpts
labels opts.ListOpts
internal bool
ipv4 *bool
ipv6 *bool
attachable bool
ingress bool
@ -42,7 +43,7 @@ type ipamOptions struct {
}
func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
var ipv6 bool
var ipv4, ipv6 bool
options := createOptions{
driverOpts: *opts.NewMapOpts(nil, nil),
labels: opts.NewListOpts(opts.ValidateLabel),
@ -59,6 +60,9 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
options.name = args[0]
if cmd.Flag("ipv4").Changed {
options.ipv4 = &ipv4
}
if cmd.Flag("ipv6").Changed {
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.Var(&options.labels, "label", "Set metadata on a 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.SetAnnotation("attachable", "version", []string{"1.25"})
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(),
IPAM: ipamCfg,
Internal: options.internal,
EnableIPv4: options.ipv4,
EnableIPv6: options.ipv6,
Attachable: options.attachable,
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())))
}
// 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) {
strPtr := 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: strPtr(true),
},
{
doc: "IPv4 enabled (shorthand)",
name: "ipv4-enabled-shorthand",
flags: []string{"--ipv4"},
expected: strPtr(true),
},
{
doc: "IPv4 disabled",
name: "ipv4-disabled",
flags: []string{"--ipv4=false"},
expected: strPtr(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
// is an optional bool, and must default to "nil", not "true" or "false".
func TestNetworkCreateIPv6(t *testing.T) {

View File

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

View File

@ -42,6 +42,9 @@ func TestNetworkContext(t *testing.T) {
{networkContext{
n: network.Summary{Driver: "driver_name"},
}, "driver_name", ctx.Driver},
{networkContext{
n: network.Summary{EnableIPv4: true},
}, "true", ctx.IPv4},
{networkContext{
n: network.Summary{EnableIPv6: true},
}, "true", ctx.IPv6},
@ -180,8 +183,8 @@ func TestNetworkContextWriteJSON(t *testing.T) {
{ID: "networkID2", Name: "foobar_bar"},
}
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": "networkID2", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_bar", "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", "IPv4": "false", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_bar", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"},
}
out := bytes.NewBufferString("")

View File

@ -18,7 +18,8 @@ Create a network
| `--ip-range` | `stringSlice` | | Allocate container ip from a sub-range |
| `--ipam-driver` | `string` | `default` | IP Address Management Driver |
| `--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 |
| `-o`, `--opt` | `map` | `map[]` | Set driver specific options |
| `--scope` | `string` | | Control the network's scope |
@ -167,11 +168,14 @@ flags used for the docker0 bridge:
| Network create option | Daemon option for `docker0` | Description |
|-----------------------|-----------------------------|--------------------------------------------|
| `--gateway` | - | IPv4 or IPv6 Gateway for the master subnet |
| `--ip-range` | `--fixed-cidr` | Allocate IPs from a range |
| `--internal` | - | Restrict external access to the network |
| `--ipv6` | `--ipv6` | Enable or disable IPv6 networking |
| `--subnet` | `--bip` | Subnet for network |
| Network create option | Daemon option for `docker0` | Description |
|-----------------------|-----------------------------------|--------------------------------------------|
| `--gateway` | - | IPv4 or IPv6 Gateway for the master subnet |
| `--ip-range` | `--fixed-cidr`, `--fixed-cidr-v6` | Allocate IP addresses from a range |
| `--internal` | - | Restrict external access to the network |
| `--ipv4` | - | Enable or disable IPv4 address assignment |
| `--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
when publishing ports: