-
Notifications
You must be signed in to change notification settings - Fork 18.6k
/
opts.go
151 lines (131 loc) · 3.42 KB
/
opts.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package opts
import (
"fmt"
"github.com/dotcloud/docker/utils"
"os"
"path/filepath"
"regexp"
"strings"
)
// ListOpts type
type ListOpts struct {
values []string
validator ValidatorFctType
}
func NewListOpts(validator ValidatorFctType) ListOpts {
return ListOpts{
validator: validator,
}
}
func (opts *ListOpts) String() string {
return fmt.Sprintf("%v", []string(opts.values))
}
// Set validates if needed the input value and add it to the
// internal slice.
func (opts *ListOpts) Set(value string) error {
if opts.validator != nil {
v, err := opts.validator(value)
if err != nil {
return err
}
value = v
}
opts.values = append(opts.values, value)
return nil
}
// Delete remove the given element from the slice.
func (opts *ListOpts) Delete(key string) {
for i, k := range opts.values {
if k == key {
opts.values = append(opts.values[:i], opts.values[i+1:]...)
return
}
}
}
// GetMap returns the content of values in a map in order to avoid
// duplicates.
// FIXME: can we remove this?
func (opts *ListOpts) GetMap() map[string]struct{} {
ret := make(map[string]struct{})
for _, k := range opts.values {
ret[k] = struct{}{}
}
return ret
}
// GetAll returns the values' slice.
// FIXME: Can we remove this?
func (opts *ListOpts) GetAll() []string {
return opts.values
}
// Get checks the existence of the given key.
func (opts *ListOpts) Get(key string) bool {
for _, k := range opts.values {
if k == key {
return true
}
}
return false
}
// Len returns the amount of element in the slice.
func (opts *ListOpts) Len() int {
return len(opts.values)
}
// Validators
type ValidatorFctType func(val string) (string, error)
func ValidateAttach(val string) (string, error) {
if val != "stdin" && val != "stdout" && val != "stderr" {
return val, fmt.Errorf("Unsupported stream name: %s", val)
}
return val, nil
}
func ValidateLink(val string) (string, error) {
if _, err := utils.PartParser("name:alias", val); err != nil {
return val, err
}
return val, nil
}
func ValidatePath(val string) (string, error) {
var containerPath string
if strings.Count(val, ":") > 2 {
return val, fmt.Errorf("bad format for volumes: %s", val)
}
splited := strings.SplitN(val, ":", 2)
if len(splited) == 1 {
containerPath = splited[0]
val = filepath.Clean(splited[0])
} else {
containerPath = splited[1]
val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1]))
}
if !filepath.IsAbs(containerPath) {
return val, fmt.Errorf("%s is not an absolute path", containerPath)
}
return val, nil
}
func ValidateEnv(val string) (string, error) {
arr := strings.Split(val, "=")
if len(arr) > 1 {
return val, nil
}
return fmt.Sprintf("%s=%s", val, os.Getenv(val)), nil
}
func ValidateIp4Address(val string) (string, error) {
re := regexp.MustCompile(`^(([0-9]+\.){3}([0-9]+))\s*$`)
var ns = re.FindSubmatch([]byte(val))
if len(ns) > 0 {
return string(ns[1]), nil
}
return "", fmt.Errorf("%s is not an ip4 address", val)
}
func ValidateDomain(val string) (string, error) {
alpha := regexp.MustCompile(`[a-zA-Z]`)
if alpha.FindString(val) == "" {
return "", fmt.Errorf("%s is not a valid domain", val)
}
re := 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*$`)
ns := re.FindSubmatch([]byte(val))
if len(ns) > 0 {
return string(ns[1]), nil
}
return "", fmt.Errorf("%s is not a valid domain", val)
}