github.com/docker/docker-ce@v17.12.1-ce-rc2+incompatible/components/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  	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  }
    22  
    23  // NetworkOpt represents a network config in swarm mode.
    24  type NetworkOpt struct {
    25  	options []NetworkAttachmentOpts
    26  }
    27  
    28  // Set networkopts value
    29  func (n *NetworkOpt) Set(value string) error {
    30  	longSyntax, err := regexp.MatchString(`\w+=\w+(,\w+=\w+)*`, value)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	var netOpt NetworkAttachmentOpts
    36  	if longSyntax {
    37  		csvReader := csv.NewReader(strings.NewReader(value))
    38  		fields, err := csvReader.Read()
    39  		if err != nil {
    40  			return err
    41  		}
    42  
    43  		netOpt.Aliases = []string{}
    44  		for _, field := range fields {
    45  			parts := strings.SplitN(field, "=", 2)
    46  
    47  			if len(parts) < 2 {
    48  				return fmt.Errorf("invalid field %s", field)
    49  			}
    50  
    51  			key := strings.TrimSpace(strings.ToLower(parts[0]))
    52  			value := strings.TrimSpace(strings.ToLower(parts[1]))
    53  
    54  			switch key {
    55  			case networkOptName:
    56  				netOpt.Target = value
    57  			case networkOptAlias:
    58  				netOpt.Aliases = append(netOpt.Aliases, value)
    59  			case driverOpt:
    60  				key, value, err = parseDriverOpt(value)
    61  				if err == nil {
    62  					if netOpt.DriverOpts == nil {
    63  						netOpt.DriverOpts = make(map[string]string)
    64  					}
    65  					netOpt.DriverOpts[key] = value
    66  				} else {
    67  					return err
    68  				}
    69  			default:
    70  				return fmt.Errorf("invalid field key %s", key)
    71  			}
    72  		}
    73  		if len(netOpt.Target) == 0 {
    74  			return fmt.Errorf("network name/id is not specified")
    75  		}
    76  	} else {
    77  		netOpt.Target = value
    78  	}
    79  	n.options = append(n.options, netOpt)
    80  	return nil
    81  }
    82  
    83  // Type returns the type of this option
    84  func (n *NetworkOpt) Type() string {
    85  	return "network"
    86  }
    87  
    88  // Value returns the networkopts
    89  func (n *NetworkOpt) Value() []NetworkAttachmentOpts {
    90  	return n.options
    91  }
    92  
    93  // String returns the network opts as a string
    94  func (n *NetworkOpt) String() string {
    95  	return ""
    96  }
    97  
    98  func parseDriverOpt(driverOpt string) (string, string, error) {
    99  	parts := strings.SplitN(driverOpt, "=", 2)
   100  	if len(parts) != 2 {
   101  		return "", "", fmt.Errorf("invalid key value pair format in driver options")
   102  	}
   103  	key := strings.TrimSpace(strings.ToLower(parts[0]))
   104  	value := strings.TrimSpace(strings.ToLower(parts[1]))
   105  	return key, value, nil
   106  }