From c4844b1fddf6d86e1eece5cf2e92cd975aa5a422 Mon Sep 17 00:00:00 2001 From: Abhinandan Prativadi Date: Mon, 10 Jul 2017 13:44:45 -0700 Subject: [PATCH] Cli change to pass driver specific options to docker run The commit contains cli changes to support driver options for a network in docker run and docker network connect cli's. The driver-opt, aliases is now supported in the form of csv as per network option in service commands in swarm mode since docker/cli#62 . This commit extends this support to docker run command as well. For docker connect command `--driver-opt` is added to pass driver specific options for the network the container is connecting to. Signed-off-by: Abhinandan Prativadi Signed-off-by: Sebastiaan van Stijn --- cli/command/container/opts.go | 29 +++++++++++++++++++++++++---- cli/command/network/connect.go | 29 ++++++++++++++++++++++++++--- opts/network.go | 10 ++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/cli/command/container/opts.go b/cli/command/container/opts.go index 6b10185081..327c91e3ad 100644 --- a/cli/command/container/opts.go +++ b/cli/command/container/opts.go @@ -97,7 +97,7 @@ type containerOptions struct { ioMaxBandwidth opts.MemBytes ioMaxIOps uint64 swappiness int64 - netMode string + netMode opts.NetworkOpt macAddress string ipv4Address string ipv6Address string @@ -215,8 +215,8 @@ func addFlags(flags *pflag.FlagSet) *containerOptions { flags.VarP(&copts.publish, "publish", "p", "Publish a container's port(s) to the host") flags.BoolVarP(&copts.publishAll, "publish-all", "P", false, "Publish all exposed ports to random ports") // We allow for both "--net" and "--network", although the latter is the recommended way. - flags.StringVar(&copts.netMode, "net", "default", "Connect a container to a network") - flags.StringVar(&copts.netMode, "network", "default", "Connect a container to a network") + flags.Var(&copts.netMode, "net", "Connect a container to a network") + flags.Var(&copts.netMode, "network", "Connect a container to a network") flags.MarkHidden("net") // We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way. flags.Var(&copts.aliases, "net-alias", "Add network-scoped alias for the container") @@ -613,8 +613,8 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con DNSOptions: copts.dnsOptions.GetAllOrEmpty(), ExtraHosts: copts.extraHosts.GetAll(), VolumesFrom: copts.volumesFrom.GetAll(), - NetworkMode: container.NetworkMode(copts.netMode), IpcMode: container.IpcMode(copts.ipcMode), + NetworkMode: container.NetworkMode(copts.netMode.NetworkMode()), PidMode: pidMode, UTSMode: utsMode, UsernsMode: usernsMode, @@ -678,6 +678,27 @@ func parse(flags *pflag.FlagSet, copts *containerOptions, serverOS string) (*con 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 + } if copts.aliases.Len() > 0 { epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] diff --git a/cli/command/network/connect.go b/cli/command/network/connect.go index 7ff055aaba..a5a4e12408 100644 --- a/cli/command/network/connect.go +++ b/cli/command/network/connect.go @@ -3,6 +3,9 @@ package network import ( "context" + "fmt" + "strings" + "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/opts" @@ -18,6 +21,7 @@ type connectOptions struct { links opts.ListOpts aliases []string linklocalips []string + driverOpts []string } func newConnectCommand(dockerCli command.Cli) *cobra.Command { @@ -42,22 +46,41 @@ func newConnectCommand(dockerCli command.Cli) *cobra.Command { flags.Var(&options.links, "link", "Add link to another container") flags.StringSliceVar(&options.aliases, "alias", []string{}, "Add network-scoped alias for the container") flags.StringSliceVar(&options.linklocalips, "link-local-ip", []string{}, "Add a link-local address for the container") - + flags.StringSliceVar(&options.driverOpts, "driver-opt", []string{}, "driver options for the network") return cmd } func runConnect(dockerCli command.Cli, options connectOptions) error { client := dockerCli.Client() + driverOpts, err := convertDriverOpt(options.driverOpts) + if err != nil { + return err + } epConfig := &network.EndpointSettings{ IPAMConfig: &network.EndpointIPAMConfig{ IPv4Address: options.ipaddress, IPv6Address: options.ipv6address, LinkLocalIPs: options.linklocalips, }, - Links: options.links.GetAll(), - Aliases: options.aliases, + Links: options.links.GetAll(), + Aliases: options.aliases, + DriverOpts: driverOpts, } return client.NetworkConnect(context.Background(), options.network, options.container, epConfig) } + +func convertDriverOpt(opts []string) (map[string]string, error) { + driverOpt := make(map[string]string) + for _, opt := range opts { + parts := strings.SplitN(opt, "=", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("invalid key/value pair format in driver options") + } + key := strings.TrimSpace(parts[0]) + value := strings.TrimSpace(parts[1]) + driverOpt[key] = value + } + return driverOpt, nil +} diff --git a/opts/network.go b/opts/network.go index ec4967ff32..3026a7efee 100644 --- a/opts/network.go +++ b/opts/network.go @@ -95,6 +95,16 @@ func (n *NetworkOpt) String() string { return "" } +// NetworkMode return the network mode for the network option +func (n *NetworkOpt) NetworkMode() string { + networkIDOrName := "default" + netOptVal := n.Value() + if len(netOptVal) > 0 { + networkIDOrName = netOptVal[0].Target + } + return networkIDOrName +} + func parseDriverOpt(driverOpt string) (string, string, error) { parts := strings.SplitN(driverOpt, "=", 2) if len(parts) != 2 {