Skip to content

Commit

Permalink
WIP network parsing refactoring, and preliminary support for multiple…
Browse files Browse the repository at this point in the history
… networks

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
  • Loading branch information
thaJeztah committed Mar 21, 2019
1 parent d53c3f3 commit 600ce6a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 29 deletions.
110 changes: 81 additions & 29 deletions cli/command/container/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
networktypes "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/strslice"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/signal"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
Expand Down Expand Up @@ -665,36 +666,11 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
}
}

if hostConfig.NetworkMode.IsUserDefined() && len(hostConfig.Links) > 0 {
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
if epConfig == nil {
epConfig = &networktypes.EndpointSettings{}
}
epConfig.Links = make([]string, len(hostConfig.Links))
copy(epConfig.Links, hostConfig.Links)
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
}
value := copts.netMode.Value()

if value != nil && hostConfig.NetworkMode.IsUserDefined() {
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
if epConfig == nil {
epConfig = &networktypes.EndpointSettings{}
}

if len(value[0].Aliases) > 0 {
if copts.aliases.Len() > 0 {
return nil, fmt.Errorf("ambiguity in alias options provided")
}
epConfig.Aliases = append(epConfig.Aliases, value[0].Aliases...)
}

if len(value[0].DriverOpts) > 0 {
epConfig.DriverOpts = make(map[string]string)
epConfig.DriverOpts = value[0].DriverOpts
}
networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig
endpoints, err := parseNetworkOpts(copts)
if err != nil {
return nil, err
}
networkingConfig.EndpointsConfig = endpoints

if copts.aliases.Len() > 0 {
epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)]
Expand All @@ -713,6 +689,82 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con
}, nil
}

// parseNetworkOpts converts --network advanced options to endpoint-specs, and combines
// them with the old --network-alias and --links. If returns an error if conflicting options
// are found.
//
// this function may return _multiple_ endpoints, which is not currently supported
// by the daemon, but may be in future; it's up to the daemon to produce an error
// in case that is not supported.
func parseNetworkOpts(copts *containerOptions) (map[string]*networktypes.EndpointSettings, error) {
var endpoints = make(map[string]*networktypes.EndpointSettings, len(copts.netMode.Value()))

var hasUserDefined, hasNonUserDefined bool

for i, n := range copts.netMode.Value() {
if container.NetworkMode(n.Target).IsUserDefined() {
hasUserDefined = true
} else {
hasNonUserDefined = true
}
if i == 0 {
// The first network corresponds with what was previously the "only"
// network, and what would be used when using the non-advanced syntax
// `--network-alias` and `--link` are set on this network, to preserve
// backward compatibility with the non-advanced notation
// TODO should we error if _any_ advanced option is used? (i.e. forbid to combine advanced notation with the "old" flags (`--network-alias`, `--links`, `--ip`, `--ip6`)?
if len(n.Aliases) > 0 && copts.aliases.Len() > 0 {
return nil, errdefs.InvalidParameter(errors.New("conflicting options: cannot specify both --network-alias and per-network alias"))
}
if len(n.Links) > 0 && copts.links.Len() > 0 {
return nil, errdefs.InvalidParameter(errors.New("conflicting options: cannot specify both --link and per-network links"))
}
// TODO map copts.ipv4Address (`--ip`) and copts.ipv6Address (--ip6) to the first network as well (or error-out; see above)
if copts.aliases.Len() > 0 {
n.Aliases = copts.aliases.GetAll()
}
if copts.links.Len() > 0 {
n.Links = make([]string, copts.aliases.Len())
copy(n.Links, copts.aliases.GetAll())
}
}
ep, err := parseNetworkAttachmentOpt(n)
if err != nil {
return nil, err
}
endpoints[n.Target] = ep
}
if hasUserDefined && hasNonUserDefined {
return nil, errdefs.InvalidParameter(errors.New("conflicting options: cannot attach both user-defined and non-user-defined network-modes"))
}
return endpoints, nil
}

func parseNetworkAttachmentOpt(ep opts.NetworkAttachmentOpts) (*networktypes.EndpointSettings, error) {
if strings.TrimSpace(ep.Target) == "" {
return nil, errors.New("no name set for network")
}
if !container.NetworkMode(ep.Target).IsUserDefined() {
if len(ep.Aliases) > 0 {
return nil, errors.New("network-scoped aliases are only supported for user-defined networks")
}
if len(ep.Links) > 0 {
return nil, errors.New("links are only supported for user-defined networks")
}
}

epConfig := &networktypes.EndpointSettings{}
epConfig.Aliases = append(epConfig.Aliases, ep.Aliases...)
if len(ep.DriverOpts) > 0 {
epConfig.DriverOpts = make(map[string]string)
epConfig.DriverOpts = ep.DriverOpts
}
if len(ep.Links) > 0 {
epConfig.Links = ep.Links
}
return epConfig, nil
}

func parsePortOpts(publishOpts []string) ([]string, error) {
optsList := []string{}
for _, publish := range publishOpts {
Expand Down
2 changes: 2 additions & 0 deletions opts/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ type NetworkAttachmentOpts struct {
Target string
Aliases []string
DriverOpts map[string]string
// TODO add support for links in the csv notation of `--network`
Links []string
}

// NetworkOpt represents a network config in swarm mode.
Expand Down

0 comments on commit 600ce6a

Please sign in to comment.