github.com/akerouanton/docker@v1.11.0-rc3/opts/opts.go (about) 1 package opts 2 3 import ( 4 "fmt" 5 "net" 6 "regexp" 7 "strings" 8 ) 9 10 var ( 11 alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) 12 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*$`) 13 ) 14 15 // ListOpts holds a list of values and a validation function. 16 type ListOpts struct { 17 values *[]string 18 validator ValidatorFctType 19 } 20 21 // NewListOpts creates a new ListOpts with the specified validator. 22 func NewListOpts(validator ValidatorFctType) ListOpts { 23 var values []string 24 return *NewListOptsRef(&values, validator) 25 } 26 27 // NewListOptsRef creates a new ListOpts with the specified values and validator. 28 func NewListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts { 29 return &ListOpts{ 30 values: values, 31 validator: validator, 32 } 33 } 34 35 func (opts *ListOpts) String() string { 36 return fmt.Sprintf("%v", []string((*opts.values))) 37 } 38 39 // Set validates if needed the input value and add it to the 40 // internal slice. 41 func (opts *ListOpts) Set(value string) error { 42 if opts.validator != nil { 43 v, err := opts.validator(value) 44 if err != nil { 45 return err 46 } 47 value = v 48 } 49 (*opts.values) = append((*opts.values), value) 50 return nil 51 } 52 53 // Delete removes the specified element from the slice. 54 func (opts *ListOpts) Delete(key string) { 55 for i, k := range *opts.values { 56 if k == key { 57 (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...) 58 return 59 } 60 } 61 } 62 63 // GetMap returns the content of values in a map in order to avoid 64 // duplicates. 65 func (opts *ListOpts) GetMap() map[string]struct{} { 66 ret := make(map[string]struct{}) 67 for _, k := range *opts.values { 68 ret[k] = struct{}{} 69 } 70 return ret 71 } 72 73 // GetAll returns the values of slice. 74 func (opts *ListOpts) GetAll() []string { 75 return (*opts.values) 76 } 77 78 // GetAllOrEmpty returns the values of the slice 79 // or an empty slice when there are no values. 80 func (opts *ListOpts) GetAllOrEmpty() []string { 81 v := *opts.values 82 if v == nil { 83 return make([]string, 0) 84 } 85 return v 86 } 87 88 // Get checks the existence of the specified key. 89 func (opts *ListOpts) Get(key string) bool { 90 for _, k := range *opts.values { 91 if k == key { 92 return true 93 } 94 } 95 return false 96 } 97 98 // Len returns the amount of element in the slice. 99 func (opts *ListOpts) Len() int { 100 return len((*opts.values)) 101 } 102 103 // NamedOption is an interface that list and map options 104 // with names implement. 105 type NamedOption interface { 106 Name() string 107 } 108 109 // NamedListOpts is a ListOpts with a configuration name. 110 // This struct is useful to keep reference to the assigned 111 // field name in the internal configuration struct. 112 type NamedListOpts struct { 113 name string 114 ListOpts 115 } 116 117 var _ NamedOption = &NamedListOpts{} 118 119 // NewNamedListOptsRef creates a reference to a new NamedListOpts struct. 120 func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts { 121 return &NamedListOpts{ 122 name: name, 123 ListOpts: *NewListOptsRef(values, validator), 124 } 125 } 126 127 // Name returns the name of the NamedListOpts in the configuration. 128 func (o *NamedListOpts) Name() string { 129 return o.name 130 } 131 132 //MapOpts holds a map of values and a validation function. 133 type MapOpts struct { 134 values map[string]string 135 validator ValidatorFctType 136 } 137 138 // Set validates if needed the input value and add it to the 139 // internal map, by splitting on '='. 140 func (opts *MapOpts) Set(value string) error { 141 if opts.validator != nil { 142 v, err := opts.validator(value) 143 if err != nil { 144 return err 145 } 146 value = v 147 } 148 vals := strings.SplitN(value, "=", 2) 149 if len(vals) == 1 { 150 (opts.values)[vals[0]] = "" 151 } else { 152 (opts.values)[vals[0]] = vals[1] 153 } 154 return nil 155 } 156 157 // GetAll returns the values of MapOpts as a map. 158 func (opts *MapOpts) GetAll() map[string]string { 159 return opts.values 160 } 161 162 func (opts *MapOpts) String() string { 163 return fmt.Sprintf("%v", map[string]string((opts.values))) 164 } 165 166 // NewMapOpts creates a new MapOpts with the specified map of values and a validator. 167 func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts { 168 if values == nil { 169 values = make(map[string]string) 170 } 171 return &MapOpts{ 172 values: values, 173 validator: validator, 174 } 175 } 176 177 // NamedMapOpts is a MapOpts struct with a configuration name. 178 // This struct is useful to keep reference to the assigned 179 // field name in the internal configuration struct. 180 type NamedMapOpts struct { 181 name string 182 MapOpts 183 } 184 185 var _ NamedOption = &NamedMapOpts{} 186 187 // NewNamedMapOpts creates a reference to a new NamedMapOpts struct. 188 func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts { 189 return &NamedMapOpts{ 190 name: name, 191 MapOpts: *NewMapOpts(values, validator), 192 } 193 } 194 195 // Name returns the name of the NamedMapOpts in the configuration. 196 func (o *NamedMapOpts) Name() string { 197 return o.name 198 } 199 200 // ValidatorFctType defines a validator function that returns a validated string and/or an error. 201 type ValidatorFctType func(val string) (string, error) 202 203 // ValidatorFctListType defines a validator function that returns a validated list of string and/or an error 204 type ValidatorFctListType func(val string) ([]string, error) 205 206 // ValidateIPAddress validates an Ip address. 207 func ValidateIPAddress(val string) (string, error) { 208 var ip = net.ParseIP(strings.TrimSpace(val)) 209 if ip != nil { 210 return ip.String(), nil 211 } 212 return "", fmt.Errorf("%s is not an ip address", val) 213 } 214 215 // ValidateDNSSearch validates domain for resolvconf search configuration. 216 // A zero length domain is represented by a dot (.). 217 func ValidateDNSSearch(val string) (string, error) { 218 if val = strings.Trim(val, " "); val == "." { 219 return val, nil 220 } 221 return validateDomain(val) 222 } 223 224 func validateDomain(val string) (string, error) { 225 if alphaRegexp.FindString(val) == "" { 226 return "", fmt.Errorf("%s is not a valid domain", val) 227 } 228 ns := domainRegexp.FindSubmatch([]byte(val)) 229 if len(ns) > 0 && len(ns[1]) < 255 { 230 return string(ns[1]), nil 231 } 232 return "", fmt.Errorf("%s is not a valid domain", val) 233 } 234 235 // ValidateLabel validates that the specified string is a valid label, and returns it. 236 // Labels are in the form on key=value. 237 func ValidateLabel(val string) (string, error) { 238 if strings.Count(val, "=") < 1 { 239 return "", fmt.Errorf("bad attribute format: %s", val) 240 } 241 return val, nil 242 }