diff --git a/frontend/dockerfile/instructions/bflag.go b/frontend/dockerfile/instructions/bflag.go index d8bf74739499..66c53add055a 100644 --- a/frontend/dockerfile/instructions/bflag.go +++ b/frontend/dockerfile/instructions/bflag.go @@ -108,6 +108,15 @@ func (fl *Flag) IsUsed() bool { return false } +// Used returns a slice of flag names that are set +func (bf *BFlags) Used() []string { + used := make([]string, 0, len(bf.used)) + for f := range bf.used { + used = append(used, f) + } + return used +} + // IsTrue checks if a bool flag is true func (fl *Flag) IsTrue() bool { if fl.flagType != boolType { diff --git a/frontend/dockerfile/instructions/bflag_test.go b/frontend/dockerfile/instructions/bflag_test.go index 0e880e619066..f7c180d8e7da 100644 --- a/frontend/dockerfile/instructions/bflag_test.go +++ b/frontend/dockerfile/instructions/bflag_test.go @@ -1,6 +1,8 @@ package instructions import ( + "sort" + "strings" "testing" ) @@ -184,4 +186,30 @@ func TestBuilderFlags(t *testing.T) { if !flBool1.IsTrue() { t.Fatalf("Test %s, bool1 should be true", bf.Args) } + + // --- + + bf = NewBFlags() + _ = bf.AddBool("bool1", false) + _ = bf.AddBool("bool2", false) + _ = bf.AddBool("bool3", false) + _ = bf.AddBool("bool4", true) + _ = bf.AddBool("bool5", true) + _ = bf.AddString("str1", "") + _ = bf.AddString("str2", "") + _ = bf.AddString("str3", "def3") + _ = bf.AddString("str4", "def4") + + bf.Args = []string{`--bool2=false`, `--bool3`, `--bool4=true`, `--bool5`, `--str2= `, `--str3=def3`, `--str4=my-val`} + + if err = bf.Parse(); err != nil { + t.Fatalf("Test %q was supposed to work: %s", bf.Args, err) + } + used := bf.Used() + sort.Strings(used) + expected = "bool2, bool3, bool4, bool5, str2, str3, str4" + actual := strings.Join(used, ", ") + if actual != expected { + t.Fatalf("Test %s, expected '%s', got '%s'", bf.Args, expected, actual) + } } diff --git a/frontend/dockerfile/instructions/commands.go b/frontend/dockerfile/instructions/commands.go index e6027445ac1d..b900ad771151 100644 --- a/frontend/dockerfile/instructions/commands.go +++ b/frontend/dockerfile/instructions/commands.go @@ -269,6 +269,7 @@ type RunCommand struct { withNameAndCode withExternalData ShellDependantCmdLine + FlagsUsed []string } // CmdCommand : CMD foo diff --git a/frontend/dockerfile/instructions/parse.go b/frontend/dockerfile/instructions/parse.go index 83cab66944dd..18e727229c95 100644 --- a/frontend/dockerfile/instructions/parse.go +++ b/frontend/dockerfile/instructions/parse.go @@ -375,7 +375,7 @@ func parseRun(req parseRequest) (*RunCommand, error) { if err := req.flags.Parse(); err != nil { return nil, err } - + cmd.FlagsUsed = req.flags.Used() cmd.ShellDependantCmdLine = parseShellDependentCommand(req, false) cmd.withNameAndCode = newWithNameAndCode(req) diff --git a/frontend/dockerfile/instructions/parse_test.go b/frontend/dockerfile/instructions/parse_test.go index ed543effd2fa..b059654c6cce 100644 --- a/frontend/dockerfile/instructions/parse_test.go +++ b/frontend/dockerfile/instructions/parse_test.go @@ -226,3 +226,16 @@ func TestErrorCases(t *testing.T) { require.Contains(t, err.Error(), c.expectedError) } } + +func TestRunCmdFlagsUsed(t *testing.T) { + dockerfile := "RUN --mount=type=tmpfs,target=/foo/ echo hello" + r := strings.NewReader(dockerfile) + ast, err := parser.Parse(r) + require.NoError(t, err) + + n := ast.AST.Children[0] + c, err := ParseInstruction(n) + require.NoError(t, err) + require.IsType(t, c, &RunCommand{}) + require.Equal(t, []string{"mount"}, c.(*RunCommand).FlagsUsed) +}