Currently, starting dockerd with
`--default-network-opt=bridge=com.docker.network.enable_ipv6=true` has
no effect as `NetworkCreateRequest.EnableIPv6` is a basic bool.
This change makes it a `*bool` to make it optional. If clients don't
specify it, the default-network-opt will be applied.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
| ... | ... |
@@ -451,7 +451,7 @@ type NetworkCreate struct {
|
| 451 | 451 |
CheckDuplicate bool `json:",omitempty"` |
| 452 | 452 |
Driver string // Driver is the driver-name used to create the network (e.g. `bridge`, `overlay`) |
| 453 | 453 |
Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level). |
| 454 |
- EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6. |
|
| 454 |
+ EnableIPv6 *bool `json:",omitempty"` // EnableIPv6 represents whether to enable IPv6. |
|
| 455 | 455 |
IPAM *network.IPAM // IPAM is the network's IP Address Management. |
| 456 | 456 |
Internal bool // Internal represents if the network is used internal only. |
| 457 | 457 |
Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. |
| ... | ... |
@@ -65,9 +65,10 @@ func TestNetworkCreate(t *testing.T) {
|
| 65 | 65 |
}), |
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 |
+ enableIPv6 := true |
|
| 68 | 69 |
networkResponse, err := client.NetworkCreate(context.Background(), "mynetwork", types.NetworkCreate{
|
| 69 | 70 |
Driver: "mydriver", |
| 70 |
- EnableIPv6: true, |
|
| 71 |
+ EnableIPv6: &enableIPv6, |
|
| 71 | 72 |
Internal: true, |
| 72 | 73 |
Options: map[string]string{
|
| 73 | 74 |
"opt-key": "opt-value", |
| ... | ... |
@@ -195,10 +195,12 @@ func BasicNetworkCreateToGRPC(create basictypes.NetworkCreateRequest) swarmapi.N |
| 195 | 195 |
Name: create.Driver, |
| 196 | 196 |
Options: create.Options, |
| 197 | 197 |
}, |
| 198 |
- Ipv6Enabled: create.EnableIPv6, |
|
| 199 |
- Internal: create.Internal, |
|
| 200 |
- Attachable: create.Attachable, |
|
| 201 |
- Ingress: create.Ingress, |
|
| 198 |
+ Internal: create.Internal, |
|
| 199 |
+ Attachable: create.Attachable, |
|
| 200 |
+ Ingress: create.Ingress, |
|
| 201 |
+ } |
|
| 202 |
+ if create.EnableIPv6 != nil {
|
|
| 203 |
+ ns.Ipv6Enabled = *create.EnableIPv6 |
|
| 202 | 204 |
} |
| 203 | 205 |
if create.IPAM != nil {
|
| 204 | 206 |
driver := create.IPAM.Driver |
| ... | ... |
@@ -621,13 +621,14 @@ func (c *containerConfig) networkCreateRequest(name string) (clustertypes.Networ |
| 621 | 621 |
return clustertypes.NetworkCreateRequest{}, errors.New("container: unknown network referenced")
|
| 622 | 622 |
} |
| 623 | 623 |
|
| 624 |
+ ipv6Enabled := na.Network.Spec.Ipv6Enabled |
|
| 624 | 625 |
options := types.NetworkCreate{
|
| 625 | 626 |
// ID: na.Network.ID, |
| 626 | 627 |
Labels: na.Network.Spec.Annotations.Labels, |
| 627 | 628 |
Internal: na.Network.Spec.Internal, |
| 628 | 629 |
Attachable: na.Network.Spec.Attachable, |
| 629 | 630 |
Ingress: convert.IsIngressNetwork(na.Network), |
| 630 |
- EnableIPv6: na.Network.Spec.Ipv6Enabled, |
|
| 631 |
+ EnableIPv6: &ipv6Enabled, |
|
| 631 | 632 |
Scope: scope.Swarm, |
| 632 | 633 |
} |
| 633 | 634 |
|
| ... | ... |
@@ -318,8 +318,19 @@ func (daemon *Daemon) createNetwork(cfg *config.Config, create types.NetworkCrea |
| 318 | 318 |
} |
| 319 | 319 |
} |
| 320 | 320 |
|
| 321 |
+ var enableIPv6 bool |
|
| 322 |
+ if create.EnableIPv6 != nil {
|
|
| 323 |
+ enableIPv6 = *create.EnableIPv6 |
|
| 324 |
+ } else {
|
|
| 325 |
+ var err error |
|
| 326 |
+ v, ok := networkOptions[netlabel.EnableIPv6] |
|
| 327 |
+ if enableIPv6, err = strconv.ParseBool(v); ok && err != nil {
|
|
| 328 |
+ return nil, errdefs.InvalidParameter(fmt.Errorf("driver-opt %q is not a valid bool", netlabel.EnableIPv6))
|
|
| 329 |
+ } |
|
| 330 |
+ } |
|
| 331 |
+ |
|
| 321 | 332 |
nwOptions := []libnetwork.NetworkOption{
|
| 322 |
- libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6), |
|
| 333 |
+ libnetwork.NetworkOptionEnableIPv6(enableIPv6), |
|
| 323 | 334 |
libnetwork.NetworkOptionDriverOpts(networkOptions), |
| 324 | 335 |
libnetwork.NetworkOptionLabels(create.Labels), |
| 325 | 336 |
libnetwork.NetworkOptionAttachable(create.Attachable), |
| ... | ... |
@@ -331,7 +342,7 @@ func (daemon *Daemon) createNetwork(cfg *config.Config, create types.NetworkCrea |
| 331 | 331 |
nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly()) |
| 332 | 332 |
} |
| 333 | 333 |
|
| 334 |
- if err := network.ValidateIPAM(create.IPAM, create.EnableIPv6); err != nil {
|
|
| 334 |
+ if err := network.ValidateIPAM(create.IPAM, enableIPv6); err != nil {
|
|
| 335 | 335 |
if agent {
|
| 336 | 336 |
// This function is called with agent=false for all networks. For swarm-scoped |
| 337 | 337 |
// networks, the configuration is validated but ManagerRedirectError is returned |
| ... | ... |
@@ -15,7 +15,8 @@ func WithDriver(driver string) func(*types.NetworkCreate) {
|
| 15 | 15 |
// WithIPv6 Enables IPv6 on the network |
| 16 | 16 |
func WithIPv6() func(*types.NetworkCreate) {
|
| 17 | 17 |
return func(n *types.NetworkCreate) {
|
| 18 |
- n.EnableIPv6 = true |
|
| 18 |
+ enableIPv6 := true |
|
| 19 |
+ n.EnableIPv6 = &enableIPv6 |
|
| 19 | 20 |
} |
| 20 | 21 |
} |
| 21 | 22 |
|
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/api/types/versions" |
| 12 | 12 |
ctr "github.com/docker/docker/integration/internal/container" |
| 13 | 13 |
"github.com/docker/docker/integration/internal/network" |
| 14 |
+ "github.com/docker/docker/testutil/daemon" |
|
| 14 | 15 |
"gotest.tools/v3/assert" |
| 15 | 16 |
"gotest.tools/v3/skip" |
| 16 | 17 |
) |
| ... | ... |
@@ -68,3 +69,31 @@ func TestCreateWithIPv6DefaultsToULAPrefix(t *testing.T) {
|
| 68 | 68 |
|
| 69 | 69 |
t.Fatalf("Network %s has no ULA prefix, expected one.", nwName)
|
| 70 | 70 |
} |
| 71 |
+ |
|
| 72 |
+func TestCreateWithIPv6WithoutEnableIPv6Flag(t *testing.T) {
|
|
| 73 |
+ skip.If(t, testEnv.DaemonInfo.OSType == "windows") // d.Start fails on Windows with `protocol not available` |
|
| 74 |
+ ctx := setupTest(t) |
|
| 75 |
+ |
|
| 76 |
+ d := daemon.New(t) |
|
| 77 |
+ d.StartWithBusybox(ctx, t, "-D", "--default-network-opt=bridge=com.docker.network.enable_ipv6=true") |
|
| 78 |
+ defer d.Stop(t) |
|
| 79 |
+ |
|
| 80 |
+ apiClient := d.NewClientT(t) |
|
| 81 |
+ defer apiClient.Close() |
|
| 82 |
+ |
|
| 83 |
+ const nwName = "testnetula" |
|
| 84 |
+ network.CreateNoError(ctx, t, apiClient, nwName) |
|
| 85 |
+ defer network.RemoveNoError(ctx, t, apiClient, nwName) |
|
| 86 |
+ |
|
| 87 |
+ nw, err := apiClient.NetworkInspect(ctx, "testnetula", networktypes.InspectOptions{})
|
|
| 88 |
+ assert.NilError(t, err) |
|
| 89 |
+ |
|
| 90 |
+ for _, ipam := range nw.IPAM.Config {
|
|
| 91 |
+ ipr := netip.MustParsePrefix(ipam.Subnet) |
|
| 92 |
+ if netip.MustParsePrefix("fd00::/8").Overlaps(ipr) {
|
|
| 93 |
+ return |
|
| 94 |
+ } |
|
| 95 |
+ } |
|
| 96 |
+ |
|
| 97 |
+ t.Fatalf("Network %s has no ULA prefix, expected one.", nwName)
|
|
| 98 |
+} |