github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/network/connect.go (about)

     1  package network
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/docker/cli/cli"
     9  	"github.com/docker/cli/cli/command"
    10  	"github.com/docker/cli/cli/command/completion"
    11  	"github.com/docker/cli/opts"
    12  	"github.com/docker/docker/api/types/network"
    13  	"github.com/spf13/cobra"
    14  )
    15  
    16  type connectOptions struct {
    17  	network      string
    18  	container    string
    19  	ipaddress    string
    20  	ipv6address  string
    21  	links        opts.ListOpts
    22  	aliases      []string
    23  	linklocalips []string
    24  	driverOpts   []string
    25  }
    26  
    27  func newConnectCommand(dockerCli command.Cli) *cobra.Command {
    28  	options := connectOptions{
    29  		links: opts.NewListOpts(opts.ValidateLink),
    30  	}
    31  
    32  	cmd := &cobra.Command{
    33  		Use:   "connect [OPTIONS] NETWORK CONTAINER",
    34  		Short: "Connect a container to a network",
    35  		Args:  cli.ExactArgs(2),
    36  		RunE: func(cmd *cobra.Command, args []string) error {
    37  			options.network = args[0]
    38  			options.container = args[1]
    39  			return runConnect(cmd.Context(), dockerCli, options)
    40  		},
    41  		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
    42  			if len(args) == 0 {
    43  				return completion.NetworkNames(dockerCli)(cmd, args, toComplete)
    44  			}
    45  			network := args[0]
    46  			return completion.ContainerNames(dockerCli, true, not(isConnected(network)))(cmd, args, toComplete)
    47  		},
    48  	}
    49  
    50  	flags := cmd.Flags()
    51  	flags.StringVar(&options.ipaddress, "ip", "", `IPv4 address (e.g., "172.30.100.104")`)
    52  	flags.StringVar(&options.ipv6address, "ip6", "", `IPv6 address (e.g., "2001:db8::33")`)
    53  	flags.Var(&options.links, "link", "Add link to another container")
    54  	flags.StringSliceVar(&options.aliases, "alias", []string{}, "Add network-scoped alias for the container")
    55  	flags.StringSliceVar(&options.linklocalips, "link-local-ip", []string{}, "Add a link-local address for the container")
    56  	flags.StringSliceVar(&options.driverOpts, "driver-opt", []string{}, "driver options for the network")
    57  	return cmd
    58  }
    59  
    60  func runConnect(ctx context.Context, dockerCli command.Cli, options connectOptions) error {
    61  	client := dockerCli.Client()
    62  
    63  	driverOpts, err := convertDriverOpt(options.driverOpts)
    64  	if err != nil {
    65  		return err
    66  	}
    67  	epConfig := &network.EndpointSettings{
    68  		IPAMConfig: &network.EndpointIPAMConfig{
    69  			IPv4Address:  options.ipaddress,
    70  			IPv6Address:  options.ipv6address,
    71  			LinkLocalIPs: options.linklocalips,
    72  		},
    73  		Links:      options.links.GetAll(),
    74  		Aliases:    options.aliases,
    75  		DriverOpts: driverOpts,
    76  	}
    77  
    78  	return client.NetworkConnect(ctx, options.network, options.container, epConfig)
    79  }
    80  
    81  func convertDriverOpt(options []string) (map[string]string, error) {
    82  	driverOpt := make(map[string]string)
    83  	for _, opt := range options {
    84  		k, v, ok := strings.Cut(opt, "=")
    85  		// TODO(thaJeztah): we should probably not accept whitespace here (both for key and value).
    86  		k = strings.TrimSpace(k)
    87  		if !ok || k == "" {
    88  			return nil, fmt.Errorf("invalid key/value pair format in driver options")
    89  		}
    90  		driverOpt[k] = strings.TrimSpace(v)
    91  	}
    92  	return driverOpt, nil
    93  }