Skip to content

Commit 60e82c1

Browse files
authored
Merge pull request moby#3199 from thaJeztah/frontend_cleanup
frontend/dockerfile: some minor refactor and optimizations
2 parents 639d33a + 9313bd7 commit 60e82c1

File tree

12 files changed

+108
-126
lines changed

12 files changed

+108
-126
lines changed

frontend/dockerfile/builder/build.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,10 @@ func parseExtraHosts(v string) ([]llb.HostIP, error) {
770770
return nil, err
771771
}
772772
for _, field := range fields {
773-
parts := strings.SplitN(field, "=", 2)
774-
if len(parts) != 2 {
773+
key, val, ok := strings.Cut(strings.ToLower(field), "=")
774+
if !ok {
775775
return nil, errors.Errorf("invalid key-value pair %s", field)
776776
}
777-
key := strings.ToLower(parts[0])
778-
val := strings.ToLower(parts[1])
779777
ip := net.ParseIP(val)
780778
if ip == nil {
781779
return nil, errors.Errorf("failed to parse IP %s", val)

frontend/dockerfile/instructions/bflag.go

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,7 @@ func (bf *BFlags) Parse() error {
156156
return nil
157157
}
158158

159-
arg = arg[2:]
160-
value := ""
161-
162-
index := strings.Index(arg, "=")
163-
if index >= 0 {
164-
value = arg[index+1:]
165-
arg = arg[:index]
166-
}
159+
arg, value, hasValue := strings.Cut(arg[2:], "=")
167160

168161
flag, ok := bf.flags[arg]
169162
if !ok {
@@ -180,27 +173,27 @@ func (bf *BFlags) Parse() error {
180173
switch flag.flagType {
181174
case boolType:
182175
// value == "" is only ok if no "=" was specified
183-
if index >= 0 && value == "" {
176+
if hasValue && value == "" {
184177
return errors.Errorf("missing a value on flag: %s", arg)
185178
}
186179

187-
lower := strings.ToLower(value)
188-
if lower == "" {
180+
switch strings.ToLower(value) {
181+
case "true", "":
189182
flag.Value = "true"
190-
} else if lower == "true" || lower == "false" {
191-
flag.Value = lower
192-
} else {
183+
case "false":
184+
flag.Value = "false"
185+
default:
193186
return errors.Errorf("expecting boolean value for flag %s, not: %s", arg, value)
194187
}
195188

196189
case stringType:
197-
if index < 0 {
190+
if !hasValue {
198191
return errors.Errorf("missing a value on flag: %s", arg)
199192
}
200193
flag.Value = value
201194

202195
case stringsType:
203-
if index < 0 {
196+
if !hasValue {
204197
return errors.Errorf("missing a value on flag: %s", arg)
205198
}
206199
flag.StringValues = append(flag.StringValues, value)

frontend/dockerfile/instructions/commands_runmount.go

Lines changed: 61 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,33 @@ import (
1111
"github.com/pkg/errors"
1212
)
1313

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+
)
1923

20-
var allowedMountTypes = map[string]struct{}{
24+
var allowedMountTypes = map[MountType]struct{}{
2125
MountTypeBind: {},
2226
MountTypeCache: {},
2327
MountTypeTmpfs: {},
2428
MountTypeSecret: {},
2529
MountTypeSSH: {},
2630
}
2731

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+
)
3139

32-
var allowedSharingTypes = map[string]struct{}{
40+
var allowedSharingModes = map[ShareMode]struct{}{
3341
MountSharingShared: {},
3442
MountSharingPrivate: {},
3543
MountSharingLocked: {},
@@ -44,31 +52,18 @@ func init() {
4452
parseRunPostHooks = append(parseRunPostHooks, runMountPostHook)
4553
}
4654

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))
5259
}
53-
if s == "ssh" {
54-
if !isSSHMountsSupported() {
55-
return false
56-
}
57-
}
58-
_, ok := allowedMountTypes[s]
59-
return ok
60+
return types
6061
}
6162

6263
func allMountTypes() []string {
63-
types := make([]string, 0, len(allowedMountTypes)+2)
64+
types := make([]string, 0, len(allowedMountTypes))
6465
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))
7267
}
7368
return types
7469
}
@@ -119,22 +114,22 @@ type mountState struct {
119114
}
120115

121116
type Mount struct {
122-
Type string
117+
Type MountType
123118
From string
124119
Source string
125120
Target string
126121
ReadOnly bool
127122
SizeLimit int64
128123
CacheID string
129-
CacheSharing string
124+
CacheSharing ShareMode
130125
Required bool
131126
Mode *uint64
132127
UID *uint64
133128
GID *uint64
134129
}
135130

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))
138133
fields, err := csvReader.Read()
139134
if err != nil {
140135
return nil, errors.Wrap(err, "failed to parse csv mounts")
@@ -145,10 +140,10 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
145140
roAuto := true
146141

147142
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)
150145

151-
if len(parts) == 1 {
146+
if !ok {
152147
if expander == nil {
153148
continue // evaluate later
154149
}
@@ -162,27 +157,24 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
162157
roAuto = false
163158
continue
164159
case "required":
165-
if m.Type == "secret" || m.Type == "ssh" {
160+
if m.Type == MountTypeSecret || m.Type == MountTypeSSH {
166161
m.Required = true
167162
continue
168163
} else {
169164
return nil, errors.Errorf("unexpected key '%s' for mount type '%s'", key, m.Type)
170165
}
166+
default:
167+
// any other option requires a value.
168+
return nil, errors.Errorf("invalid field '%s' must be a key=value pair", field)
171169
}
172170
}
173171

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]
179172
// check for potential variable
180173
if expander != nil {
181-
processed, err := expander(value)
174+
value, err = expander(value)
182175
if err != nil {
183176
return nil, err
184177
}
185-
value = processed
186178
} else if key == "from" {
187179
if matched, err := regexp.MatchString(`\$.`, value); err != nil { //nolint
188180
return nil, err
@@ -196,10 +188,11 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
196188

197189
switch key {
198190
case "type":
199-
if !isValidMountType(strings.ToLower(value)) {
191+
v := MountType(strings.ToLower(value))
192+
if _, ok := allowedMountTypes[v]; !ok {
200193
return nil, suggest.WrapError(errors.Errorf("unsupported mount type %q", value), value, allMountTypes(), true)
201194
}
202-
m.Type = strings.ToLower(value)
195+
m.Type = v
203196
case "from":
204197
m.From = value
205198
case "source", "src":
@@ -220,17 +213,16 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
220213
m.ReadOnly = !rw
221214
roAuto = false
222215
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)
225218
if err != nil {
226219
return nil, errors.Errorf("invalid value for %s: %s", key, value)
227220
}
228-
m.Required = v
229221
} else {
230222
return nil, errors.Errorf("unexpected key '%s' for mount type '%s'", key, m.Type)
231223
}
232224
case "size":
233-
if m.Type == "tmpfs" {
225+
if m.Type == MountTypeTmpfs {
234226
m.SizeLimit, err = units.RAMInBytes(value)
235227
if err != nil {
236228
return nil, errors.Errorf("invalid value for %s: %s", key, value)
@@ -241,10 +233,11 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
241233
case "id":
242234
m.CacheID = value
243235
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)
246239
}
247-
m.CacheSharing = strings.ToLower(value)
240+
m.CacheSharing = v
248241
case "mode":
249242
mode, err := strconv.ParseUint(value, 8, 32)
250243
if err != nil {
@@ -273,16 +266,16 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
273266

274267
fileInfoAllowed := m.Type == MountTypeSecret || m.Type == MountTypeSSH || m.Type == MountTypeCache
275268

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+
}
286279
}
287280

288281
if roAuto {
@@ -293,10 +286,6 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
293286
}
294287
}
295288

296-
if m.CacheSharing != "" && m.Type != MountTypeCache {
297-
return nil, errors.Errorf("invalid cache sharing set for %v mount", m.Type)
298-
}
299-
300289
if m.Type == MountTypeSecret {
301290
if m.From != "" {
302291
return nil, errors.Errorf("secret mount should not have a from")
@@ -312,5 +301,9 @@ func parseMount(value string, expander SingleWordExpander) (*Mount, error) {
312301
}
313302
}
314303

304+
if m.CacheSharing != "" && m.Type != MountTypeCache {
305+
return nil, errors.Errorf("invalid cache sharing set for %v mount", m.Type)
306+
}
307+
315308
return m, nil
316309
}

frontend/dockerfile/instructions/commands_runnetwork.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import (
44
"github.com/pkg/errors"
55
)
66

7+
type NetworkMode = string
8+
79
const (
8-
NetworkDefault = "default"
9-
NetworkNone = "none"
10-
NetworkHost = "host"
10+
NetworkDefault NetworkMode = "default"
11+
NetworkNone NetworkMode = "none"
12+
NetworkHost NetworkMode = "host"
1113
)
1214

13-
var allowedNetwork = map[string]struct{}{
15+
var allowedNetwork = map[NetworkMode]struct{}{
1416
NetworkDefault: {},
1517
NetworkNone: {},
1618
NetworkHost: {},
@@ -51,7 +53,7 @@ func runNetworkPostHook(cmd *RunCommand, req parseRequest) error {
5153
return nil
5254
}
5355

54-
func GetNetwork(cmd *RunCommand) string {
56+
func GetNetwork(cmd *RunCommand) NetworkMode {
5557
return cmd.getExternalValue(networkKey).(*networkState).networkMode
5658
}
5759

frontend/dockerfile/instructions/commands_secrets.go

Lines changed: 0 additions & 5 deletions
This file was deleted.

frontend/dockerfile/instructions/commands_ssh.go

Lines changed: 0 additions & 5 deletions
This file was deleted.

frontend/dockerfile/instructions/parse.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,12 +357,13 @@ func parseFrom(req parseRequest) (*Stage, error) {
357357
}, nil
358358
}
359359

360-
func parseBuildStageName(args []string) (string, error) {
361-
stageName := ""
360+
var validStageName = regexp.MustCompile("^[a-z][a-z0-9-_.]*$")
361+
362+
func parseBuildStageName(args []string) (stageName string, err error) {
362363
switch {
363364
case len(args) == 3 && strings.EqualFold(args[1], "as"):
364365
stageName = strings.ToLower(args[2])
365-
if ok, _ := regexp.MatchString("^[a-z][a-z0-9-_\\.]*$", stageName); !ok {
366+
if !validStageName.MatchString(stageName) {
366367
return "", errors.Errorf("invalid name for build stage: %q, name can't start with a number or contain symbols", args[2])
367368
}
368369
case len(args) != 1:

0 commit comments

Comments
 (0)