Add flag 'enableIPv4' to libnetwork.Network

Similar to EnableIPv6:
- Set it if EnableIPv4 is specified in a create request.
- Otherwise, set it if included in `default-network-opts`.
  - Apart from in a config-from network, so that it doesn't look
    like the API request set the field.
- Include the new field in  Network marshalling/unmarshalling test.

Signed-off-by: Rob Murray <rob.murray@docker.com>
This commit is contained in:
Rob Murray
2024-07-30 20:10:34 +01:00
parent d4d8611164
commit 903daa4dc4
5 changed files with 64 additions and 5 deletions

View File

@@ -316,18 +316,33 @@ func (daemon *Daemon) createNetwork(cfg *config.Config, create networktypes.Crea
}
}
enableIPv4 := create.ConfigFrom == nil
if create.EnableIPv4 != nil {
enableIPv4 = *create.EnableIPv4
} else if v, ok := networkOptions[netlabel.EnableIPv4]; ok {
var err error
if enableIPv4, err = strconv.ParseBool(v); err != nil {
return nil, errdefs.InvalidParameter(fmt.Errorf("driver-opt %q is not a valid bool", netlabel.EnableIPv4))
}
}
if !enableIPv4 && !daemon.config().Experimental && create.ConfigFrom == nil {
return nil, errdefs.InvalidParameter(
errors.New("IPv4 can only be disabled if experimental features are enabled"),
)
}
var enableIPv6 bool
if create.EnableIPv6 != nil {
enableIPv6 = *create.EnableIPv6
} else {
} else if v, ok := networkOptions[netlabel.EnableIPv6]; ok {
var err error
v, ok := networkOptions[netlabel.EnableIPv6]
if enableIPv6, err = strconv.ParseBool(v); ok && err != nil {
if enableIPv6, err = strconv.ParseBool(v); err != nil {
return nil, errdefs.InvalidParameter(fmt.Errorf("driver-opt %q is not a valid bool", netlabel.EnableIPv6))
}
}
nwOptions := []libnetwork.NetworkOption{
libnetwork.NetworkOptionEnableIPv4(enableIPv4),
libnetwork.NetworkOptionEnableIPv6(enableIPv6),
libnetwork.NetworkOptionDriverOpts(networkOptions),
libnetwork.NetworkOptionLabels(create.Labels),
@@ -620,6 +635,7 @@ func buildNetworkResource(nw *libnetwork.Network) networktypes.Inspect {
Created: nw.Created(),
Scope: nw.Scope(),
Driver: nw.Type(),
EnableIPv4: nw.IPv4Enabled(),
EnableIPv6: nw.IPv6Enabled(),
IPAM: buildIPAMResources(nw),
Internal: nw.Internal(),

View File

@@ -11,6 +11,14 @@ func WithDriver(driver string) func(*network.CreateOptions) {
}
}
// WithIPv4 enables/disables IPv4 on the network
func WithIPv4(enable bool) func(*network.CreateOptions) {
return func(n *network.CreateOptions) {
enableIPv4 := enable
n.EnableIPv4 = &enableIPv4
}
}
// WithIPv6 Enables IPv6 on the network
func WithIPv6() func(*network.CreateOptions) {
return func(n *network.CreateOptions) {

View File

@@ -29,6 +29,7 @@ func TestNetworkMarshalling(t *testing.T) {
ipamType: "default",
addrSpace: "viola",
networkType: "bridge",
enableIPv4: true,
enableIPv6: true,
persist: true,
configOnly: true,
@@ -138,7 +139,7 @@ func TestNetworkMarshalling(t *testing.T) {
}
if n.name != nn.name || n.id != nn.id || n.networkType != nn.networkType || n.ipamType != nn.ipamType ||
n.addrSpace != nn.addrSpace || n.enableIPv6 != nn.enableIPv6 ||
n.addrSpace != nn.addrSpace || n.enableIPv4 != nn.enableIPv4 || n.enableIPv6 != nn.enableIPv6 ||
n.persist != nn.persist || !compareIpamConfList(n.ipamV4Config, nn.ipamV4Config) ||
!compareIpamInfoList(n.ipamV4Info, nn.ipamV4Info) || !compareIpamConfList(n.ipamV6Config, nn.ipamV6Config) ||
!compareIpamInfoList(n.ipamV6Info, nn.ipamV6Info) ||

View File

@@ -30,6 +30,9 @@ const (
// where the interface name is represented by the string "IFNAME".
EndpointSysctls = Prefix + ".endpoint.sysctls"
// EnableIPv4 constant represents enabling IPV4 at network level
EnableIPv4 = Prefix + ".enable_ipv4"
// EnableIPv6 constant represents enabling IPV6 at network level
EnableIPv6 = Prefix + ".enable_ipv6"

View File

@@ -187,6 +187,7 @@ type Network struct {
ipamV6Config []*IpamConf
ipamV4Info []*IpamInfo
ipamV6Info []*IpamInfo
enableIPv4 bool
enableIPv6 bool
postIPv6 bool
epCnt *endpointCnt
@@ -368,7 +369,7 @@ func (n *Network) validateConfiguration() error {
}
if n.ipamType != "" &&
n.ipamType != defaultIpamForNetworkType(n.networkType) ||
n.enableIPv6 ||
n.enableIPv4 || n.enableIPv6 ||
len(n.labels) > 0 || len(n.ipamOptions) > 0 ||
len(n.ipamV4Config) > 0 || len(n.ipamV6Config) > 0 {
return types.ForbiddenErrorf("user specified configurations are not supported if the network depends on a configuration network")
@@ -401,6 +402,7 @@ func (n *Network) validateConfiguration() error {
// applyConfigurationTo applies network specific configurations.
func (n *Network) applyConfigurationTo(to *Network) error {
to.enableIPv4 = n.enableIPv4
to.enableIPv6 = n.enableIPv6
if len(n.labels) > 0 {
to.labels = make(map[string]string, len(n.labels))
@@ -450,6 +452,7 @@ func (n *Network) CopyTo(o datastore.KVObject) error {
dstN.scope = n.scope
dstN.dynamic = n.dynamic
dstN.ipamType = n.ipamType
dstN.enableIPv4 = n.enableIPv4
dstN.enableIPv6 = n.enableIPv6
dstN.persist = n.persist
dstN.postIPv6 = n.postIPv6
@@ -539,6 +542,7 @@ func (n *Network) MarshalJSON() ([]byte, error) {
netMap["ipamType"] = n.ipamType
netMap["ipamOptions"] = n.ipamOptions
netMap["addrSpace"] = n.addrSpace
netMap["enableIPv4"] = n.enableIPv4
netMap["enableIPv6"] = n.enableIPv6
if n.generic != nil {
netMap["generic"] = n.generic
@@ -601,6 +605,12 @@ func (n *Network) UnmarshalJSON(b []byte) (err error) {
}
}
n.networkType = netMap["networkType"].(string)
if v, ok := netMap["enableIPv4"]; ok {
n.enableIPv4 = v.(bool)
} else {
// Set enableIPv4 for IPv4 networks created before the option was added.
n.enableIPv4 = len(n.ipamV4Info) > 0
}
n.enableIPv6 = netMap["enableIPv6"].(bool)
// if we weren't unmarshaling to netMap we could simply set n.labels
@@ -713,6 +723,9 @@ func NetworkOptionGeneric(generic map[string]interface{}) NetworkOption {
if n.generic == nil {
n.generic = make(map[string]interface{})
}
if val, ok := generic[netlabel.EnableIPv4]; ok {
n.enableIPv4 = val.(bool)
}
if val, ok := generic[netlabel.EnableIPv6]; ok {
n.enableIPv6 = val.(bool)
}
@@ -740,6 +753,17 @@ func NetworkOptionPersist(persist bool) NetworkOption {
}
}
// NetworkOptionEnableIPv4 returns an option setter to explicitly configure IPv4
func NetworkOptionEnableIPv4(enableIPv4 bool) NetworkOption {
return func(n *Network) {
if n.generic == nil {
n.generic = make(map[string]interface{})
}
n.enableIPv4 = enableIPv4
n.generic[netlabel.EnableIPv4] = enableIPv4
}
}
// NetworkOptionEnableIPv6 returns an option setter to explicitly configure IPv6
func NetworkOptionEnableIPv6(enableIPv6 bool) NetworkOption {
return func(n *Network) {
@@ -1842,6 +1866,13 @@ func (n *Network) Dynamic() bool {
return n.dynamic
}
func (n *Network) IPv4Enabled() bool {
n.mu.Lock()
defer n.mu.Unlock()
return n.enableIPv4
}
func (n *Network) IPv6Enabled() bool {
n.mu.Lock()
defer n.mu.Unlock()