github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/cli/opts/network.go (about)

     1  package opts
     2  
     3  import (
     4  	"encoding/csv"
     5  	"fmt"
     6  	"regexp"
     7  	"strings"
     8  )
     9  
    10  const (
    11  	networkOptName        = "name"
    12  	networkOptAlias       = "alias"
    13  	networkOptIPv4Address = "ip"
    14  	networkOptIPv6Address = "ip6"
    15  	driverOpt             = "driver-opt"
    16  )
    17  
    18  // NetworkAttachmentOpts represents the network options for endpoint creation
    19  type NetworkAttachmentOpts struct {
    20  	Target       string
    21  	Aliases      []string
    22  	DriverOpts   map[string]string
    23  	Links        []string // TODO add support for links in the csv notation of `--network`
    24  	IPv4Address  string
    25  	IPv6Address  string
    26  	LinkLocalIPs []string // TODO add support for LinkLocalIPs in the csv notation of `--network` ?
    27  }
    28  
    29  // NetworkOpt represents a network config in swarm mode.
    30  type NetworkOpt struct {
    31  	options []NetworkAttachmentOpts
    32  }
    33  
    34  // Set networkopts value
    35  func (n *NetworkOpt) Set(value string) error {
    36  	longSyntax, err := regexp.MatchString(`\w+=\w+(,\w+=\w+)*`, value)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	var netOpt NetworkAttachmentOpts
    42  	if longSyntax {
    43  		csvReader := csv.NewReader(strings.NewReader(value))
    44  		fields, err := csvReader.Read()
    45  		if err != nil {
    46  			return err
    47  		}
    48  
    49  		netOpt.Aliases = []string{}
    50  		for _, field := range fields {
    51  			parts := strings.SplitN(field, "=", 2)
    52  
    53  			if len(parts) < 2 {
    54  				return fmt.Errorf("invalid field %s", field)
    55  			}
    56  
    57  			key := strings.TrimSpace(strings.ToLower(parts[0]))
    58  			value := strings.TrimSpace(strings.ToLower(parts[1]))
    59  
    60  			switch key {
    61  			case networkOptName:
    62  				netOpt.Target = value
    63  			case networkOptAlias:
    64  				netOpt.Aliases = append(netOpt.Aliases, value)
    65  			case networkOptIPv4Address:
    66  				netOpt.IPv4Address = value
    67  			case networkOptIPv6Address:
    68  				netOpt.IPv6Address = value
    69  			case driverOpt:
    70  				key, value, err = parseDriverOpt(value)
    71  				if err == nil {
    72  					if netOpt.DriverOpts == nil {
    73  						netOpt.DriverOpts = make(map[string]string)
    74  					}
    75  					netOpt.DriverOpts[key] = value
    76  				} else {
    77  					return err
    78  				}
    79  			default:
    80  				return fmt.Errorf("invalid field key %s", key)
    81  			}
    82  		}
    83  		if len(netOpt.Target) == 0 {
    84  			return fmt.Errorf("network name/id is not specified")
    85  		}
    86  	} else {
    87  		netOpt.Target = value
    88  	}
    89  	n.options = append(n.options, netOpt)
    90  	return nil
    91  }
    92  
    93  // Type returns the type of this option
    94  func (n *NetworkOpt) Type() string {
    95  	return "network"
    96  }
    97  
    98  // Value returns the networkopts
    99  func (n *NetworkOpt) Value() []NetworkAttachmentOpts {
   100  	return n.options
   101  }
   102  
   103  // String returns the network opts as a string
   104  func (n *NetworkOpt) String() string {
   105  	return ""
   106  }
   107  
   108  // NetworkMode return the network mode for the network option
   109  func (n *NetworkOpt) NetworkMode() string {
   110  	networkIDOrName := "default"
   111  	netOptVal := n.Value()
   112  	if len(netOptVal) > 0 {
   113  		networkIDOrName = netOptVal[0].Target
   114  	}
   115  	return networkIDOrName
   116  }
   117  
   118  func parseDriverOpt(driverOpt string) (string, string, error) {
   119  	parts := strings.SplitN(driverOpt, "=", 2)
   120  	if len(parts) != 2 {
   121  		return "", "", fmt.Errorf("invalid key value pair format in driver options")
   122  	}
   123  	key := strings.TrimSpace(strings.ToLower(parts[0]))
   124  	value := strings.TrimSpace(strings.ToLower(parts[1]))
   125  	return key, value, nil
   126  }