github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/opts/opts.go (about) 1 package opts 2 3 import ( 4 "fmt" 5 "net" 6 "regexp" 7 "strings" 8 9 "github.com/docker/docker/api/types/filters" 10 ) 11 12 var ( 13 alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) 14 domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`) 15 ) 16 17 // ListOpts holds a list of values and a validation function. 18 type ListOpts struct { 19 values *[]string 20 validator ValidatorFctType 21 } 22 23 // NewListOpts creates a new ListOpts with the specified validator. 24 func NewListOpts(validator ValidatorFctType) ListOpts { 25 var values []string 26 return *NewListOptsRef(&values, validator) 27 } 28 29 // NewListOptsRef creates a new ListOpts with the specified values and validator. 30 func NewListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts { 31 return &ListOpts{ 32 values: values, 33 validator: validator, 34 } 35 } 36 37 func (opts *ListOpts) String() string { 38 return fmt.Sprintf("%v", []string((*opts.values))) 39 } 40 41 // Set validates if needed the input value and adds it to the 42 // internal slice. 43 func (opts *ListOpts) Set(value string) error { 44 if opts.validator != nil { 45 v, err := opts.validator(value) 46 if err != nil { 47 return err 48 } 49 value = v 50 } 51 (*opts.values) = append((*opts.values), value) 52 return nil 53 } 54 55 // Delete removes the specified element from the slice. 56 func (opts *ListOpts) Delete(key string) { 57 for i, k := range *opts.values { 58 if k == key { 59 (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...) 60 return 61 } 62 } 63 } 64 65 // GetMap returns the content of values in a map in order to avoid 66 // duplicates. 67 func (opts *ListOpts) GetMap() map[string]struct{} { 68 ret := make(map[string]struct{}) 69 for _, k := range *opts.values { 70 ret[k] = struct{}{} 71 } 72 return ret 73 } 74 75 // GetAll returns the values of slice. 76 func (opts *ListOpts) GetAll() []string { 77 return (*opts.values) 78 } 79 80 // GetAllOrEmpty returns the values of the slice 81 // or an empty slice when there are no values. 82 func (opts *ListOpts) GetAllOrEmpty() []string { 83 v := *opts.values 84 if v == nil { 85 return make([]string, 0) 86 } 87 return v 88 } 89 90 // Get checks the existence of the specified key. 91 func (opts *ListOpts) Get(key string) bool { 92 for _, k := range *opts.values { 93 if k == key { 94 return true 95 } 96 } 97 return false 98 } 99 100 // Len returns the amount of element in the slice. 101 func (opts *ListOpts) Len() int { 102 return len((*opts.values)) 103 } 104 105 // Type returns a string name for this Option type 106 func (opts *ListOpts) Type() string { 107 return "list" 108 } 109 110 // NamedOption is an interface that list and map options 111 // with names implement. 112 type NamedOption interface { 113 Name() string 114 } 115 116 // NamedListOpts is a ListOpts with a configuration name. 117 // This struct is useful to keep reference to the assigned 118 // field name in the internal configuration struct. 119 type NamedListOpts struct { 120 name string 121 ListOpts 122 } 123 124 var _ NamedOption = &NamedListOpts{} 125 126 // NewNamedListOptsRef creates a reference to a new NamedListOpts struct. 127 func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts { 128 return &NamedListOpts{ 129 name: name, 130 ListOpts: *NewListOptsRef(values, validator), 131 } 132 } 133 134 // Name returns the name of the NamedListOpts in the configuration. 135 func (o *NamedListOpts) Name() string { 136 return o.name 137 } 138 139 // MapOpts holds a map of values and a validation function. 140 type MapOpts struct { 141 values map[string]string 142 validator ValidatorFctType 143 } 144 145 // Set validates if needed the input value and add it to the 146 // internal map, by splitting on '='. 147 func (opts *MapOpts) Set(value string) error { 148 if opts.validator != nil { 149 v, err := opts.validator(value) 150 if err != nil { 151 return err 152 } 153 value = v 154 } 155 vals := strings.SplitN(value, "=", 2) 156 if len(vals) == 1 { 157 (opts.values)[vals[0]] = "" 158 } else { 159 (opts.values)[vals[0]] = vals[1] 160 } 161 return nil 162 } 163 164 // GetAll returns the values of MapOpts as a map. 165 func (opts *MapOpts) GetAll() map[string]string { 166 return opts.values 167 } 168 169 func (opts *MapOpts) String() string { 170 return fmt.Sprintf("%v", map[string]string((opts.values))) 171 } 172 173 // Type returns a string name for this Option type 174 func (opts *MapOpts) Type() string { 175 return "map" 176 } 177 178 // NewMapOpts creates a new MapOpts with the specified map of values and a validator. 179 func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts { 180 if values == nil { 181 values = make(map[string]string) 182 } 183 return &MapOpts{ 184 values: values, 185 validator: validator, 186 } 187 } 188 189 // NamedMapOpts is a MapOpts struct with a configuration name. 190 // This struct is useful to keep reference to the assigned 191 // field name in the internal configuration struct. 192 type NamedMapOpts struct { 193 name string 194 MapOpts 195 } 196 197 var _ NamedOption = &NamedMapOpts{} 198 199 // NewNamedMapOpts creates a reference to a new NamedMapOpts struct. 200 func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts { 201 return &NamedMapOpts{ 202 name: name, 203 MapOpts: *NewMapOpts(values, validator), 204 } 205 } 206 207 // Name returns the name of the NamedMapOpts in the configuration. 208 func (o *NamedMapOpts) Name() string { 209 return o.name 210 } 211 212 // ValidatorFctType defines a validator function that returns a validated string and/or an error. 213 type ValidatorFctType func(val string) (string, error) 214 215 // ValidatorFctListType defines a validator function that returns a validated list of string and/or an error 216 type ValidatorFctListType func(val string) ([]string, error) 217 218 // ValidateIPAddress validates an Ip address. 219 func ValidateIPAddress(val string) (string, error) { 220 var ip = net.ParseIP(strings.TrimSpace(val)) 221 if ip != nil { 222 return ip.String(), nil 223 } 224 return "", fmt.Errorf("%s is not an ip address", val) 225 } 226 227 // ValidateDNSSearch validates domain for resolvconf search configuration. 228 // A zero length domain is represented by a dot (.). 229 func ValidateDNSSearch(val string) (string, error) { 230 if val = strings.Trim(val, " "); val == "." { 231 return val, nil 232 } 233 return validateDomain(val) 234 } 235 236 func validateDomain(val string) (string, error) { 237 if alphaRegexp.FindString(val) == "" { 238 return "", fmt.Errorf("%s is not a valid domain", val) 239 } 240 ns := domainRegexp.FindSubmatch([]byte(val)) 241 if len(ns) > 0 && len(ns[1]) < 255 { 242 return string(ns[1]), nil 243 } 244 return "", fmt.Errorf("%s is not a valid domain", val) 245 } 246 247 // ValidateLabel validates that the specified string is a valid label, and returns it. 248 // Labels are in the form on key=value. 249 func ValidateLabel(val string) (string, error) { 250 if strings.Count(val, "=") < 1 { 251 return "", fmt.Errorf("bad attribute format: %s", val) 252 } 253 return val, nil 254 } 255 256 // ValidateSysctl validates a sysctl and returns it. 257 func ValidateSysctl(val string) (string, error) { 258 validSysctlMap := map[string]bool{ 259 "kernel.msgmax": true, 260 "kernel.msgmnb": true, 261 "kernel.msgmni": true, 262 "kernel.sem": true, 263 "kernel.shmall": true, 264 "kernel.shmmax": true, 265 "kernel.shmmni": true, 266 "kernel.shm_rmid_forced": true, 267 } 268 validSysctlPrefixes := []string{ 269 "net.", 270 "fs.mqueue.", 271 } 272 arr := strings.Split(val, "=") 273 if len(arr) < 2 { 274 return "", fmt.Errorf("sysctl '%s' is not whitelisted", val) 275 } 276 if validSysctlMap[arr[0]] { 277 return val, nil 278 } 279 280 for _, vp := range validSysctlPrefixes { 281 if strings.HasPrefix(arr[0], vp) { 282 return val, nil 283 } 284 } 285 return "", fmt.Errorf("sysctl '%s' is not whitelisted", val) 286 } 287 288 // FilterOpt is a flag type for validating filters 289 type FilterOpt struct { 290 filter filters.Args 291 } 292 293 // NewFilterOpt returns a new FilterOpt 294 func NewFilterOpt() FilterOpt { 295 return FilterOpt{filter: filters.NewArgs()} 296 } 297 298 func (o *FilterOpt) String() string { 299 repr, err := filters.ToParam(o.filter) 300 if err != nil { 301 return "invalid filters" 302 } 303 return repr 304 } 305 306 // Set sets the value of the opt by parsing the command line value 307 func (o *FilterOpt) Set(value string) error { 308 var err error 309 o.filter, err = filters.ParseFlag(value, o.filter) 310 return err 311 } 312 313 // Type returns the option type 314 func (o *FilterOpt) Type() string { 315 return "filter" 316 } 317 318 // Value returns the value of this option 319 func (o *FilterOpt) Value() filters.Args { 320 return o.filter 321 }