github.com/guilhermebr/docker@v1.4.2-0.20150428121140-67da055cebca/opts/opts.go (about) 1 package opts 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "path" 8 "regexp" 9 "strings" 10 11 flag "github.com/docker/docker/pkg/mflag" 12 "github.com/docker/docker/pkg/parsers" 13 "github.com/docker/docker/pkg/ulimit" 14 ) 15 16 var ( 17 alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) 18 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*$`) 19 DefaultHTTPHost = "127.0.0.1" // Default HTTP Host used if only port is provided to -H flag e.g. docker -d -H tcp://:8080 20 DefaultUnixSocket = "/var/run/docker.sock" // Docker daemon by default always listens on the default unix socket 21 ) 22 23 func ListVar(values *[]string, names []string, usage string) { 24 flag.Var(newListOptsRef(values, nil), names, usage) 25 } 26 27 func HostListVar(values *[]string, names []string, usage string) { 28 flag.Var(newListOptsRef(values, ValidateHost), names, usage) 29 } 30 31 func IPListVar(values *[]string, names []string, usage string) { 32 flag.Var(newListOptsRef(values, ValidateIPAddress), names, usage) 33 } 34 35 func DnsSearchListVar(values *[]string, names []string, usage string) { 36 flag.Var(newListOptsRef(values, ValidateDnsSearch), names, usage) 37 } 38 39 func IPVar(value *net.IP, names []string, defaultValue, usage string) { 40 flag.Var(NewIpOpt(value, defaultValue), names, usage) 41 } 42 43 func LabelListVar(values *[]string, names []string, usage string) { 44 flag.Var(newListOptsRef(values, ValidateLabel), names, usage) 45 } 46 47 func UlimitMapVar(values map[string]*ulimit.Ulimit, names []string, usage string) { 48 flag.Var(NewUlimitOpt(values), names, usage) 49 } 50 51 // ListOpts type 52 type ListOpts struct { 53 values *[]string 54 validator ValidatorFctType 55 } 56 57 func NewListOpts(validator ValidatorFctType) ListOpts { 58 var values []string 59 return *newListOptsRef(&values, validator) 60 } 61 62 func newListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts { 63 return &ListOpts{ 64 values: values, 65 validator: validator, 66 } 67 } 68 69 func (opts *ListOpts) String() string { 70 return fmt.Sprintf("%v", []string((*opts.values))) 71 } 72 73 // Set validates if needed the input value and add it to the 74 // internal slice. 75 func (opts *ListOpts) Set(value string) error { 76 if opts.validator != nil { 77 v, err := opts.validator(value) 78 if err != nil { 79 return err 80 } 81 value = v 82 } 83 (*opts.values) = append((*opts.values), value) 84 return nil 85 } 86 87 // Delete remove the given element from the slice. 88 func (opts *ListOpts) Delete(key string) { 89 for i, k := range *opts.values { 90 if k == key { 91 (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...) 92 return 93 } 94 } 95 } 96 97 // GetMap returns the content of values in a map in order to avoid 98 // duplicates. 99 // FIXME: can we remove this? 100 func (opts *ListOpts) GetMap() map[string]struct{} { 101 ret := make(map[string]struct{}) 102 for _, k := range *opts.values { 103 ret[k] = struct{}{} 104 } 105 return ret 106 } 107 108 // GetAll returns the values' slice. 109 // FIXME: Can we remove this? 110 func (opts *ListOpts) GetAll() []string { 111 return (*opts.values) 112 } 113 114 // Get checks the existence of the given key. 115 func (opts *ListOpts) Get(key string) bool { 116 for _, k := range *opts.values { 117 if k == key { 118 return true 119 } 120 } 121 return false 122 } 123 124 // Len returns the amount of element in the slice. 125 func (opts *ListOpts) Len() int { 126 return len((*opts.values)) 127 } 128 129 // Validators 130 type ValidatorFctType func(val string) (string, error) 131 type ValidatorFctListType func(val string) ([]string, error) 132 133 func ValidateAttach(val string) (string, error) { 134 s := strings.ToLower(val) 135 for _, str := range []string{"stdin", "stdout", "stderr"} { 136 if s == str { 137 return s, nil 138 } 139 } 140 return val, fmt.Errorf("valid streams are STDIN, STDOUT and STDERR.") 141 } 142 143 func ValidateLink(val string) (string, error) { 144 if _, err := parsers.PartParser("name:alias", val); err != nil { 145 return val, err 146 } 147 return val, nil 148 } 149 150 func ValidatePath(val string) (string, error) { 151 var containerPath string 152 153 if strings.Count(val, ":") > 2 { 154 return val, fmt.Errorf("bad format for volumes: %s", val) 155 } 156 157 splited := strings.SplitN(val, ":", 2) 158 if len(splited) == 1 { 159 containerPath = splited[0] 160 val = path.Clean(splited[0]) 161 } else { 162 containerPath = splited[1] 163 val = fmt.Sprintf("%s:%s", splited[0], path.Clean(splited[1])) 164 } 165 166 if !path.IsAbs(containerPath) { 167 return val, fmt.Errorf("%s is not an absolute path", containerPath) 168 } 169 return val, nil 170 } 171 172 func ValidateEnv(val string) (string, error) { 173 arr := strings.Split(val, "=") 174 if len(arr) > 1 { 175 return val, nil 176 } 177 if !doesEnvExist(val) { 178 return val, nil 179 } 180 return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil 181 } 182 183 func ValidateIPAddress(val string) (string, error) { 184 var ip = net.ParseIP(strings.TrimSpace(val)) 185 if ip != nil { 186 return ip.String(), nil 187 } 188 return "", fmt.Errorf("%s is not an ip address", val) 189 } 190 191 func ValidateMACAddress(val string) (string, error) { 192 _, err := net.ParseMAC(strings.TrimSpace(val)) 193 if err != nil { 194 return "", err 195 } 196 return val, nil 197 } 198 199 // Validates domain for resolvconf search configuration. 200 // A zero length domain is represented by . 201 func ValidateDnsSearch(val string) (string, error) { 202 if val = strings.Trim(val, " "); val == "." { 203 return val, nil 204 } 205 return validateDomain(val) 206 } 207 208 func validateDomain(val string) (string, error) { 209 if alphaRegexp.FindString(val) == "" { 210 return "", fmt.Errorf("%s is not a valid domain", val) 211 } 212 ns := domainRegexp.FindSubmatch([]byte(val)) 213 if len(ns) > 0 && len(ns[1]) < 255 { 214 return string(ns[1]), nil 215 } 216 return "", fmt.Errorf("%s is not a valid domain", val) 217 } 218 219 func ValidateExtraHost(val string) (string, error) { 220 // allow for IPv6 addresses in extra hosts by only splitting on first ":" 221 arr := strings.SplitN(val, ":", 2) 222 if len(arr) != 2 || len(arr[0]) == 0 { 223 return "", fmt.Errorf("bad format for add-host: %q", val) 224 } 225 if _, err := ValidateIPAddress(arr[1]); err != nil { 226 return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1]) 227 } 228 return val, nil 229 } 230 231 func ValidateLabel(val string) (string, error) { 232 if strings.Count(val, "=") != 1 { 233 return "", fmt.Errorf("bad attribute format: %s", val) 234 } 235 return val, nil 236 } 237 238 func ValidateHost(val string) (string, error) { 239 host, err := parsers.ParseHost(DefaultHTTPHost, DefaultUnixSocket, val) 240 if err != nil { 241 return val, err 242 } 243 return host, nil 244 } 245 246 func doesEnvExist(name string) bool { 247 for _, entry := range os.Environ() { 248 parts := strings.SplitN(entry, "=", 2) 249 if parts[0] == name { 250 return true 251 } 252 } 253 return false 254 }