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