github.com/clcy1243/docker@v1.6.0-rc3/opts/opts.go (about) 1 package opts 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "path" 8 "regexp" 9 "strings" 10 11 "github.com/docker/docker/api" 12 flag "github.com/docker/docker/pkg/mflag" 13 "github.com/docker/docker/pkg/parsers" 14 "github.com/docker/docker/pkg/ulimit" 15 "github.com/docker/docker/utils" 16 ) 17 18 var ( 19 alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) 20 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*$`) 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, api.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 !utils.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 } else { 196 return val, nil 197 } 198 } 199 200 // Validates domain for resolvconf search configuration. 201 // A zero length domain is represented by . 202 func ValidateDnsSearch(val string) (string, error) { 203 if val = strings.Trim(val, " "); val == "." { 204 return val, nil 205 } 206 return validateDomain(val) 207 } 208 209 func validateDomain(val string) (string, error) { 210 if alphaRegexp.FindString(val) == "" { 211 return "", fmt.Errorf("%s is not a valid domain", val) 212 } 213 ns := domainRegexp.FindSubmatch([]byte(val)) 214 if len(ns) > 0 && len(ns[1]) < 255 { 215 return string(ns[1]), nil 216 } 217 return "", fmt.Errorf("%s is not a valid domain", val) 218 } 219 220 func ValidateExtraHost(val string) (string, error) { 221 // allow for IPv6 addresses in extra hosts by only splitting on first ":" 222 arr := strings.SplitN(val, ":", 2) 223 if len(arr) != 2 || len(arr[0]) == 0 { 224 return "", fmt.Errorf("bad format for add-host: %q", val) 225 } 226 if _, err := ValidateIPAddress(arr[1]); err != nil { 227 return "", fmt.Errorf("invalid IP address in add-host: %q", arr[1]) 228 } 229 return val, nil 230 } 231 232 func ValidateLabel(val string) (string, error) { 233 if strings.Count(val, "=") != 1 { 234 return "", fmt.Errorf("bad attribute format: %s", val) 235 } 236 return val, nil 237 }