@@ -11,25 +11,33 @@ import (
11
11
"github.com/pkg/errors"
12
12
)
13
13
14
- const MountTypeBind = "bind"
15
- const MountTypeCache = "cache"
16
- const MountTypeTmpfs = "tmpfs"
17
- const MountTypeSecret = "secret"
18
- const MountTypeSSH = "ssh"
14
+ type MountType string
15
+
16
+ const (
17
+ MountTypeBind MountType = "bind"
18
+ MountTypeCache MountType = "cache"
19
+ MountTypeTmpfs MountType = "tmpfs"
20
+ MountTypeSecret MountType = "secret"
21
+ MountTypeSSH MountType = "ssh"
22
+ )
19
23
20
- var allowedMountTypes = map [string ]struct {}{
24
+ var allowedMountTypes = map [MountType ]struct {}{
21
25
MountTypeBind : {},
22
26
MountTypeCache : {},
23
27
MountTypeTmpfs : {},
24
28
MountTypeSecret : {},
25
29
MountTypeSSH : {},
26
30
}
27
31
28
- const MountSharingShared = "shared"
29
- const MountSharingPrivate = "private"
30
- const MountSharingLocked = "locked"
32
+ type ShareMode string
33
+
34
+ const (
35
+ MountSharingShared ShareMode = "shared"
36
+ MountSharingPrivate ShareMode = "private"
37
+ MountSharingLocked ShareMode = "locked"
38
+ )
31
39
32
- var allowedSharingTypes = map [string ]struct {}{
40
+ var allowedSharingModes = map [ShareMode ]struct {}{
33
41
MountSharingShared : {},
34
42
MountSharingPrivate : {},
35
43
MountSharingLocked : {},
@@ -44,31 +52,18 @@ func init() {
44
52
parseRunPostHooks = append (parseRunPostHooks , runMountPostHook )
45
53
}
46
54
47
- func isValidMountType (s string ) bool {
48
- if s == "secret" {
49
- if ! isSecretMountsSupported () {
50
- return false
51
- }
55
+ func allShareModes () []string {
56
+ types := make ([]string , 0 , len (allowedSharingModes ))
57
+ for k := range allowedSharingModes {
58
+ types = append (types , string (k ))
52
59
}
53
- if s == "ssh" {
54
- if ! isSSHMountsSupported () {
55
- return false
56
- }
57
- }
58
- _ , ok := allowedMountTypes [s ]
59
- return ok
60
+ return types
60
61
}
61
62
62
63
func allMountTypes () []string {
63
- types := make ([]string , 0 , len (allowedMountTypes )+ 2 )
64
+ types := make ([]string , 0 , len (allowedMountTypes ))
64
65
for k := range allowedMountTypes {
65
- types = append (types , k )
66
- }
67
- if isSecretMountsSupported () {
68
- types = append (types , "secret" )
69
- }
70
- if isSSHMountsSupported () {
71
- types = append (types , "ssh" )
66
+ types = append (types , string (k ))
72
67
}
73
68
return types
74
69
}
@@ -119,22 +114,22 @@ type mountState struct {
119
114
}
120
115
121
116
type Mount struct {
122
- Type string
117
+ Type MountType
123
118
From string
124
119
Source string
125
120
Target string
126
121
ReadOnly bool
127
122
SizeLimit int64
128
123
CacheID string
129
- CacheSharing string
124
+ CacheSharing ShareMode
130
125
Required bool
131
126
Mode * uint64
132
127
UID * uint64
133
128
GID * uint64
134
129
}
135
130
136
- func parseMount (value string , expander SingleWordExpander ) (* Mount , error ) {
137
- csvReader := csv .NewReader (strings .NewReader (value ))
131
+ func parseMount (val string , expander SingleWordExpander ) (* Mount , error ) {
132
+ csvReader := csv .NewReader (strings .NewReader (val ))
138
133
fields , err := csvReader .Read ()
139
134
if err != nil {
140
135
return nil , errors .Wrap (err , "failed to parse csv mounts" )
@@ -145,10 +140,10 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
145
140
roAuto := true
146
141
147
142
for _ , field := range fields {
148
- parts := strings .SplitN (field , "=" , 2 )
149
- key : = strings .ToLower (parts [ 0 ] )
143
+ key , value , ok := strings .Cut (field , "=" )
144
+ key = strings .ToLower (key )
150
145
151
- if len ( parts ) == 1 {
146
+ if ! ok {
152
147
if expander == nil {
153
148
continue // evaluate later
154
149
}
@@ -162,27 +157,24 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
162
157
roAuto = false
163
158
continue
164
159
case "required" :
165
- if m .Type == "secret" || m .Type == "ssh" {
160
+ if m .Type == MountTypeSecret || m .Type == MountTypeSSH {
166
161
m .Required = true
167
162
continue
168
163
} else {
169
164
return nil , errors .Errorf ("unexpected key '%s' for mount type '%s'" , key , m .Type )
170
165
}
166
+ default :
167
+ // any other option requires a value.
168
+ return nil , errors .Errorf ("invalid field '%s' must be a key=value pair" , field )
171
169
}
172
170
}
173
171
174
- if len (parts ) != 2 {
175
- return nil , errors .Errorf ("invalid field '%s' must be a key=value pair" , field )
176
- }
177
-
178
- value := parts [1 ]
179
172
// check for potential variable
180
173
if expander != nil {
181
- processed , err : = expander (value )
174
+ value , err = expander (value )
182
175
if err != nil {
183
176
return nil , err
184
177
}
185
- value = processed
186
178
} else if key == "from" {
187
179
if matched , err := regexp .MatchString (`\$.` , value ); err != nil { //nolint
188
180
return nil , err
@@ -196,10 +188,11 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
196
188
197
189
switch key {
198
190
case "type" :
199
- if ! isValidMountType (strings .ToLower (value )) {
191
+ v := MountType (strings .ToLower (value ))
192
+ if _ , ok := allowedMountTypes [v ]; ! ok {
200
193
return nil , suggest .WrapError (errors .Errorf ("unsupported mount type %q" , value ), value , allMountTypes (), true )
201
194
}
202
- m .Type = strings . ToLower ( value )
195
+ m .Type = v
203
196
case "from" :
204
197
m .From = value
205
198
case "source" , "src" :
@@ -220,17 +213,16 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
220
213
m .ReadOnly = ! rw
221
214
roAuto = false
222
215
case "required" :
223
- if m .Type == "secret" || m .Type == "ssh" {
224
- v , err : = strconv .ParseBool (value )
216
+ if m .Type == MountTypeSecret || m .Type == MountTypeSSH {
217
+ m . Required , err = strconv .ParseBool (value )
225
218
if err != nil {
226
219
return nil , errors .Errorf ("invalid value for %s: %s" , key , value )
227
220
}
228
- m .Required = v
229
221
} else {
230
222
return nil , errors .Errorf ("unexpected key '%s' for mount type '%s'" , key , m .Type )
231
223
}
232
224
case "size" :
233
- if m .Type == "tmpfs" {
225
+ if m .Type == MountTypeTmpfs {
234
226
m .SizeLimit , err = units .RAMInBytes (value )
235
227
if err != nil {
236
228
return nil , errors .Errorf ("invalid value for %s: %s" , key , value )
@@ -241,10 +233,11 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
241
233
case "id" :
242
234
m .CacheID = value
243
235
case "sharing" :
244
- if _ , ok := allowedSharingTypes [strings .ToLower (value )]; ! ok {
245
- return nil , errors .Errorf ("unsupported sharing value %q" , value )
236
+ v := ShareMode (strings .ToLower (value ))
237
+ if _ , ok := allowedSharingModes [v ]; ! ok {
238
+ return nil , suggest .WrapError (errors .Errorf ("unsupported sharing value %q" , value ), value , allShareModes (), true )
246
239
}
247
- m .CacheSharing = strings . ToLower ( value )
240
+ m .CacheSharing = v
248
241
case "mode" :
249
242
mode , err := strconv .ParseUint (value , 8 , 32 )
250
243
if err != nil {
@@ -273,16 +266,16 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
273
266
274
267
fileInfoAllowed := m .Type == MountTypeSecret || m .Type == MountTypeSSH || m .Type == MountTypeCache
275
268
276
- if m . Mode != nil && ! fileInfoAllowed {
277
- return nil , errors . Errorf ( "mode not allowed for %q type mounts" , m . Type )
278
- }
279
-
280
- if m .UID != nil && ! fileInfoAllowed {
281
- return nil , errors .Errorf ("uid not allowed for %q type mounts" , m .Type )
282
- }
283
-
284
- if m . GID != nil && ! fileInfoAllowed {
285
- return nil , errors . Errorf ( "gid not allowed for %q type mounts" , m . Type )
269
+ if ! fileInfoAllowed {
270
+ if m . Mode != nil {
271
+ return nil , errors . Errorf ( "mode not allowed for %q type mounts" , m . Type )
272
+ }
273
+ if m .UID != nil {
274
+ return nil , errors .Errorf ("uid not allowed for %q type mounts" , m .Type )
275
+ }
276
+ if m . GID != nil {
277
+ return nil , errors . Errorf ( "gid not allowed for %q type mounts" , m . Type )
278
+ }
286
279
}
287
280
288
281
if roAuto {
@@ -293,10 +286,6 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
293
286
}
294
287
}
295
288
296
- if m .CacheSharing != "" && m .Type != MountTypeCache {
297
- return nil , errors .Errorf ("invalid cache sharing set for %v mount" , m .Type )
298
- }
299
-
300
289
if m .Type == MountTypeSecret {
301
290
if m .From != "" {
302
291
return nil , errors .Errorf ("secret mount should not have a from" )
@@ -312,5 +301,9 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
312
301
}
313
302
}
314
303
304
+ if m .CacheSharing != "" && m .Type != MountTypeCache {
305
+ return nil , errors .Errorf ("invalid cache sharing set for %v mount" , m .Type )
306
+ }
307
+
315
308
return m , nil
316
309
}
0 commit comments