diff --git a/api/server/router/network/network_routes.go b/api/server/router/network/network_routes.go index 876a420baf..e162ca92ac 100644 --- a/api/server/router/network/network_routes.go +++ b/api/server/router/network/network_routes.go @@ -299,6 +299,11 @@ func (n *networkRouter) buildNetworkResource(nw libnetwork.Network) *types.Netwo r.Containers = make(map[string]types.EndpointResource) buildIpamResources(r, info) r.Labels = info.Labels() + r.ConfigOnly = info.ConfigOnly() + + if cn := info.ConfigFrom(); cn != "" { + r.ConfigFrom = network.ConfigReference{Network: cn} + } peers := info.Peers() if len(peers) != 0 { diff --git a/api/types/network/network.go b/api/types/network/network.go index 8d15ed21b5..c021ce15a1 100644 --- a/api/types/network/network.go +++ b/api/types/network/network.go @@ -100,3 +100,8 @@ func (es *EndpointSettings) Copy() *EndpointSettings { type NetworkingConfig struct { EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network } + +// ConfigReference specifies the source which provides a network's configuration +type ConfigReference struct { + Network string +} diff --git a/api/types/types.go b/api/types/types.go index efba16bc97..fa205e1114 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -403,6 +403,8 @@ type NetworkResource struct { Internal bool // Internal represents if the network is used internal only Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. Ingress bool // Ingress indicates the network is providing the routing-mesh for the swarm cluster. + ConfigFrom network.ConfigReference // ConfigFrom specifies the source which will provide the configuration for this network. + ConfigOnly bool // ConfigOnly networks are place-holder networks for network configurations to be used by other networks. ConfigOnly networks cannot be used directly to run containers or services. Containers map[string]EndpointResource // Containers contains endpoints belonging to the network Options map[string]string // Options holds the network specific options to use for when creating the network Labels map[string]string // Labels holds metadata specific to the network being created @@ -435,6 +437,8 @@ type NetworkCreate struct { Internal bool Attachable bool Ingress bool + ConfigOnly bool + ConfigFrom *network.ConfigReference Options map[string]string Labels map[string]string } diff --git a/daemon/network.go b/daemon/network.go index 781953686a..6c026f160b 100644 --- a/daemon/network.go +++ b/daemon/network.go @@ -320,6 +320,10 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string libnetwork.NetworkOptionIngress(create.Ingress), } + if create.ConfigOnly { + nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigOnly()) + } + if create.IPAM != nil { ipam := create.IPAM v4Conf, v6Conf, err := getIpamConfig(ipam.Config) @@ -337,6 +341,10 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false)) } + if create.ConfigFrom != nil { + nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network)) + } + n, err := c.NewNetwork(driver, create.Name, id, nwOptions...) if err != nil { if _, ok := err.(libnetwork.ErrDataStoreNotInitialized); ok { @@ -501,10 +509,16 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error { if err := nw.Delete(); err != nil { return err } - daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release) - ipamType, _, _, _ := nw.Info().IpamConfig() - daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release) - daemon.LogNetworkEvent(nw, "destroy") + + // If this is not a configuration only network, we need to + // update the corresponding remote drivers' reference counts + if !nw.Info().ConfigOnly() { + daemon.pluginRefCount(nw.Type(), driverapi.NetworkPluginEndpointType, plugingetter.Release) + ipamType, _, _, _ := nw.Info().IpamConfig() + daemon.pluginRefCount(ipamType, ipamapi.PluginEndpointType, plugingetter.Release) + daemon.LogNetworkEvent(nw, "destroy") + } + return nil } diff --git a/daemon/prune.go b/daemon/prune.go index f757aba71e..c614de2fe1 100644 --- a/daemon/prune.go +++ b/daemon/prune.go @@ -315,6 +315,9 @@ func (daemon *Daemon) localNetworksPrune(ctx context.Context, pruneFilters filte return true default: } + if nw.Info().ConfigOnly() { + return false + } if !until.IsZero() && nw.Info().Created().After(until) { return false }