...
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 networkOptMacAddress = "mac-address"
16 networkOptLinkLocalIP = "link-local-ip"
17 driverOpt = "driver-opt"
18 )
19
20
21 type NetworkAttachmentOpts struct {
22 Target string
23 Aliases []string
24 DriverOpts map[string]string
25 Links []string
26 IPv4Address string
27 IPv6Address string
28 LinkLocalIPs []string
29 MacAddress string
30 }
31
32
33 type NetworkOpt struct {
34 options []NetworkAttachmentOpts
35 }
36
37
38 func (n *NetworkOpt) Set(value string) error {
39 longSyntax, err := regexp.MatchString(`\w+=\w+(,\w+=\w+)*`, value)
40 if err != nil {
41 return err
42 }
43
44 var netOpt NetworkAttachmentOpts
45 if longSyntax {
46 csvReader := csv.NewReader(strings.NewReader(value))
47 fields, err := csvReader.Read()
48 if err != nil {
49 return err
50 }
51
52 netOpt.Aliases = []string{}
53 for _, field := range fields {
54
55 key, val, ok := strings.Cut(strings.ToLower(field), "=")
56 if !ok || key == "" {
57 return fmt.Errorf("invalid field %s", field)
58 }
59
60 key = strings.TrimSpace(key)
61 val = strings.TrimSpace(val)
62
63 switch key {
64 case networkOptName:
65 netOpt.Target = val
66 case networkOptAlias:
67 netOpt.Aliases = append(netOpt.Aliases, val)
68 case networkOptIPv4Address:
69 netOpt.IPv4Address = val
70 case networkOptIPv6Address:
71 netOpt.IPv6Address = val
72 case networkOptMacAddress:
73 netOpt.MacAddress = val
74 case networkOptLinkLocalIP:
75 netOpt.LinkLocalIPs = append(netOpt.LinkLocalIPs, val)
76 case driverOpt:
77 key, val, err = parseDriverOpt(val)
78 if err != nil {
79 return err
80 }
81 if netOpt.DriverOpts == nil {
82 netOpt.DriverOpts = make(map[string]string)
83 }
84 netOpt.DriverOpts[key] = val
85 default:
86 return fmt.Errorf("invalid field key %s", key)
87 }
88 }
89 if len(netOpt.Target) == 0 {
90 return fmt.Errorf("network name/id is not specified")
91 }
92 } else {
93 netOpt.Target = value
94 }
95 n.options = append(n.options, netOpt)
96 return nil
97 }
98
99
100 func (n *NetworkOpt) Type() string {
101 return "network"
102 }
103
104
105 func (n *NetworkOpt) Value() []NetworkAttachmentOpts {
106 return n.options
107 }
108
109
110 func (n *NetworkOpt) String() string {
111 return ""
112 }
113
114
115 func (n *NetworkOpt) NetworkMode() string {
116 networkIDOrName := "default"
117 netOptVal := n.Value()
118 if len(netOptVal) > 0 {
119 networkIDOrName = netOptVal[0].Target
120 }
121 return networkIDOrName
122 }
123
124 func parseDriverOpt(driverOpt string) (string, string, error) {
125
126
127 key, value, ok := strings.Cut(strings.ToLower(driverOpt), "=")
128 if !ok || key == "" {
129 return "", "", fmt.Errorf("invalid key value pair format in driver options")
130 }
131 key = strings.TrimSpace(key)
132 value = strings.TrimSpace(value)
133 return key, value, nil
134 }
135
View as plain text