-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathvolume_mount_options.go
127 lines (103 loc) · 2.93 KB
/
volume_mount_options.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
package volume_mount_options
import (
"errors"
"fmt"
"strconv"
"strings"
)
const ValidationFailErrorMessage = "- validation mount options failed: %s"
const NotAllowedErrorMessage = "- Not allowed options: %s"
const MissingOptionErrorMessage = "- Missing mandatory options: %s"
type MountOpts map[string]interface{}
func NewMountOpts(userOpts map[string]interface{}, mask MountOptsMask) (MountOpts, error) {
mountOpts := make(map[string]interface{})
for k, v := range mask.Defaults {
mountOpts[k] = v
}
allowedErrorList := []string{}
for k, v := range userOpts {
var canonicalKey string
var ok bool
if canonicalKey, ok = mask.KeyPerms[k]; !ok {
canonicalKey = k
}
if inArray(mask.Ignored, canonicalKey) {
continue
}
if inArray(mask.Allowed, canonicalKey) {
uv := uniformKeyData(canonicalKey, v)
mountOpts[canonicalKey] = uv
} else if !mask.SloppyMount {
allowedErrorList = append(allowedErrorList, k)
}
}
var validationErrorList []string
if mask.ValidationFunc != nil {
for key, val := range mountOpts {
for _, validationFunc := range mask.ValidationFunc {
err := validationFunc.Validate(key, fmt.Sprintf("%v", val))
if err != nil {
validationErrorList = append(validationErrorList, err.Error())
}
}
}
}
var mandatoryErrorList []string
for _, k := range mask.Mandatory {
if _, ok := mountOpts[k]; !ok {
mandatoryErrorList = append(mandatoryErrorList, k)
}
}
errorString := buildErrorMessage(validationErrorList, ValidationFailErrorMessage)
errorString += buildErrorMessage(allowedErrorList, NotAllowedErrorMessage)
errorString += buildErrorMessage(mandatoryErrorList, MissingOptionErrorMessage)
if hasErrors(allowedErrorList, validationErrorList, mandatoryErrorList) {
return MountOpts{}, errors.New(errorString)
}
return mountOpts, nil
}
func hasErrors(allowedErrorList []string, validationErrorList []string, mandatoryErrorList []string) bool {
return len(allowedErrorList) > 0 || len(validationErrorList) > 0 || len(mandatoryErrorList) > 0
}
func buildErrorMessage(validationErrorList []string, errorDesc string) string {
if len(validationErrorList) > 0 {
return fmt.Sprintln(fmt.Sprintf(errorDesc, strings.Join(validationErrorList, ", ")))
}
return ""
}
func inArray(list []string, key string) bool {
for _, k := range list {
if k == key {
return true
}
}
return false
}
func uniformKeyData(key string, data interface{}) string {
switch key {
case "auto-traverse-mounts":
return uniformData(data, true)
case "dircache":
return uniformData(data, true)
}
return uniformData(data, false)
}
func uniformData(data interface{}, boolAsInt bool) string {
switch t := data.(type) {
case int, int8, int16, int32, int64, float32, float64:
return fmt.Sprintf("%#v", data)
case string:
return t
case bool:
if boolAsInt {
if data.(bool) {
return "1"
} else {
return "0"
}
} else {
return strconv.FormatBool(data.(bool))
}
}
return ""
}