github.com/mizzy/docker@v1.5.0/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/utils" 15 ) 16 17 var ( 18 alphaRegexp = regexp.MustCompile(`[a-zA-Z]`) 19 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*$`) 20 ) 21 22 func ListVar(values *[]string, names []string, usage string) { 23 flag.Var(newListOptsRef(values, nil), names, usage) 24 } 25 26 func HostListVar(values *[]string, names []string, usage string) { 27 flag.Var(newListOptsRef(values, api.ValidateHost), names, usage) 28 } 29 30 func IPListVar(values *[]string, names []string, usage string) { 31 flag.Var(newListOptsRef(values, ValidateIPAddress), names, usage) 32 } 33 34 func DnsSearchListVar(values *[]string, names []string, usage string) { 35 flag.Var(newListOptsRef(values, ValidateDnsSearch), names, usage) 36 } 37 38 func IPVar(value *net.IP, names []string, defaultValue, usage string) { 39 flag.Var(NewIpOpt(value, defaultValue), names, usage) 40 } 41 42 func LabelListVar(values *[]string, names []string, usage string) { 43 flag.Var(newListOptsRef(values, ValidateLabel), names, usage) 44 } 45 46 // ListOpts type 47 type ListOpts struct { 48 values *[]string 49 validator ValidatorFctType 50 } 51 52 func NewListOpts(validator ValidatorFctType) ListOpts { 53 var values []string 54 return *newListOptsRef(&values, validator) 55 } 56 57 func newListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts { 58 return &ListOpts{ 59 values: values, 60 validator: validator, 61 } 62 } 63 64 func (opts *ListOpts) String() string { 65 return fmt.Sprintf("%v", []string((*opts.values))) 66 } 67 68 // Set validates if needed the input value and add it to the 69 // internal slice. 70 func (opts *ListOpts) Set(value string) error { 71 if opts.validator != nil { 72 v, err := opts.validator(value) 73 if err != nil { 74 return err 75 } 76 value = v 77 } 78 (*opts.values) = append((*opts.values), value) 79 return nil 80 } 81 82 // Delete remove the given element from the slice. 83 func (opts *ListOpts) Delete(key string) { 84 for i, k := range *opts.values { 85 if k == key { 86 (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...) 87 return 88 } 89 } 90 } 91 92 // GetMap returns the content of values in a map in order to avoid 93 // duplicates. 94 // FIXME: can we remove this? 95 func (opts *ListOpts) GetMap() map[string]struct{} { 96 ret := make(map[string]struct{}) 97 for _, k := range *opts.values { 98 ret[k] = struct{}{} 99 } 100 return ret 101 } 102 103 // GetAll returns the values' slice. 104 // FIXME: Can we remove this? 105 func (opts *ListOpts) GetAll() []string { 106 return (*opts.values) 107 } 108 109 // Get checks the existence of the given key. 110 func (opts *ListOpts) Get(key string) bool { 111 for _, k := range *opts.values { 112 if k == key { 113 return true 114 } 115 } 116 return false 117 } 118 119 // Len returns the amount of element in the slice. 120 func (opts *ListOpts) Len() int { 121 return len((*opts.values)) 122 } 123 124 // Validators 125 type ValidatorFctType func(val string) (string, error) 126 type ValidatorFctListType func(val string) ([]string, error) 127 128 func ValidateAttach(val string) (string, error) { 129 s := strings.ToLower(val) 130 for _, str := range []string{"stdin", "stdout", "stderr"} { 131 if s == str { 132 return s, nil 133 } 134 } 135 return val, fmt.Errorf("valid streams are STDIN, STDOUT and STDERR.") 136 } 137 138 func ValidateLink(val string) (string, error) { 139 if _, err := parsers.PartParser("name:alias", val); err != nil { 140 return val, err 141 } 142 return val, nil 143 } 144 145 func ValidatePath(val string) (string, error) { 146 var containerPath string 147 148 if strings.Count(val, ":") > 2 { 149 return val, fmt.Errorf("bad format for volumes: %s", val) 150 } 151 152 splited := strings.SplitN(val, ":", 2) 153 if len(splited) == 1 { 154 containerPath = splited[0] 155 val = path.Clean(splited[0]) 156 } else { 157 containerPath = splited[1] 158 val = fmt.Sprintf("%s:%s", splited[0], path.Clean(splited[1])) 159 } 160 161 if !path.IsAbs(containerPath) { 162 return val, fmt.Errorf("%s is not an absolute path", containerPath) 163 } 164 return val, nil 165 } 166 167 func ValidateEnv(val string) (string, error) { 168 arr := strings.Split(val, "=") 169 if len(arr) > 1 { 170 return val, nil 171 } 172 if !utils.DoesEnvExist(val) { 173 return val, nil 174 } 175 return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil 176 } 177 178 func ValidateIPAddress(val string) (string, error) { 179 var ip = net.ParseIP(strings.TrimSpace(val)) 180 if ip != nil { 181 return ip.String(), nil 182 } 183 return "", fmt.Errorf("%s is not an ip address", val) 184 } 185 186 // Validates domain for resolvconf search configuration. 187 // A zero length domain is represented by . 188 func ValidateDnsSearch(val string) (string, error) { 189 if val = strings.Trim(val, " "); val == "." { 190 return val, nil 191 } 192 return validateDomain(val) 193 } 194 195 func validateDomain(val string) (string, error) { 196 if alphaRegexp.FindString(val) == "" { 197 return "", fmt.Errorf("%s is not a valid domain", val) 198 } 199 ns := domainRegexp.FindSubmatch([]byte(val)) 200 if len(ns) > 0 { 201 return string(ns[1]), nil 202 } 203 return "", fmt.Errorf("%s is not a valid domain", val) 204 } 205 206 func ValidateExtraHost(val string) (string, error) { 207 arr := strings.Split(val, ":") 208 if len(arr) != 2 || len(arr[0]) == 0 { 209 return "", fmt.Errorf("bad format for add-host: %s", val) 210 } 211 if _, err := ValidateIPAddress(arr[1]); err != nil { 212 return "", fmt.Errorf("bad format for add-host: %s", val) 213 } 214 return val, nil 215 } 216 217 func ValidateLabel(val string) (string, error) { 218 if strings.Count(val, "=") != 1 { 219 return "", fmt.Errorf("bad attribute format: %s", val) 220 } 221 return val, nil 222 }