mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix --label being env var expanded.
Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
parent
726fb269cf
commit
434d77bc0e
5 changed files with 62 additions and 73 deletions
|
@ -129,47 +129,18 @@ func (b *Builder) dispatch(stepN int, stepTotal int, ast *parser.Node) error {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// count the number of nodes that we are going to traverse first
|
msgList := initMsgList(ast)
|
||||||
// so we can pre-create the argument and message array. This speeds up the
|
|
||||||
// allocation of those list a lot when they have a lot of arguments
|
|
||||||
cursor := ast
|
|
||||||
var n int
|
|
||||||
for cursor.Next != nil {
|
|
||||||
cursor = cursor.Next
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
msgList := make([]string, n)
|
|
||||||
|
|
||||||
var i int
|
|
||||||
// Append build args to runConfig environment variables
|
// Append build args to runConfig environment variables
|
||||||
envs := append(b.runConfig.Env, b.buildArgsWithoutConfigEnv()...)
|
envs := append(b.runConfig.Env, b.buildArgsWithoutConfigEnv()...)
|
||||||
|
|
||||||
for ast.Next != nil {
|
for i := 0; ast.Next != nil; i++ {
|
||||||
ast = ast.Next
|
ast = ast.Next
|
||||||
var str string
|
words, err := b.evaluateEnv(cmd, ast.Value, envs)
|
||||||
str = ast.Value
|
if err != nil {
|
||||||
if replaceEnvAllowed[cmd] {
|
return err
|
||||||
var err error
|
|
||||||
var words []string
|
|
||||||
|
|
||||||
if allowWordExpansion[cmd] {
|
|
||||||
words, err = ProcessWords(str, envs, b.directive.EscapeToken)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
strList = append(strList, words...)
|
|
||||||
} else {
|
|
||||||
str, err = ProcessWord(str, envs, b.directive.EscapeToken)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
strList = append(strList, str)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strList = append(strList, str)
|
|
||||||
}
|
}
|
||||||
|
strList = append(strList, words...)
|
||||||
msgList[i] = ast.Value
|
msgList[i] = ast.Value
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg += " " + strings.Join(msgList, " ")
|
msg += " " + strings.Join(msgList, " ")
|
||||||
|
@ -186,6 +157,29 @@ func (b *Builder) dispatch(stepN int, stepTotal int, ast *parser.Node) error {
|
||||||
return fmt.Errorf("Unknown instruction: %s", upperCasedCmd)
|
return fmt.Errorf("Unknown instruction: %s", upperCasedCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// count the number of nodes that we are going to traverse first
|
||||||
|
// allocation of those list a lot when they have a lot of arguments
|
||||||
|
func initMsgList(cursor *parser.Node) []string {
|
||||||
|
var n int
|
||||||
|
for ; cursor.Next != nil; n++ {
|
||||||
|
cursor = cursor.Next
|
||||||
|
}
|
||||||
|
return make([]string, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Builder) evaluateEnv(cmd string, str string, envs []string) ([]string, error) {
|
||||||
|
if !replaceEnvAllowed[cmd] {
|
||||||
|
return []string{str}, nil
|
||||||
|
}
|
||||||
|
var processFunc func(string, []string, rune) ([]string, error)
|
||||||
|
if allowWordExpansion[cmd] {
|
||||||
|
processFunc = ProcessWords
|
||||||
|
} else {
|
||||||
|
processFunc = ProcessWord
|
||||||
|
}
|
||||||
|
return processFunc(str, envs, b.directive.EscapeToken)
|
||||||
|
}
|
||||||
|
|
||||||
// buildArgsWithoutConfigEnv returns a list of key=value pairs for all the build
|
// buildArgsWithoutConfigEnv returns a list of key=value pairs for all the build
|
||||||
// args that are not overriden by runConfig environment variables.
|
// args that are not overriden by runConfig environment variables.
|
||||||
func (b *Builder) buildArgsWithoutConfigEnv() []string {
|
func (b *Builder) buildArgsWithoutConfigEnv() []string {
|
||||||
|
|
|
@ -220,7 +220,9 @@ func NodeFromLabels(labels map[string]string) *Node {
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
value := labels[key]
|
value := labels[key]
|
||||||
labelPairs = append(labelPairs, fmt.Sprintf("%q='%s'", key, value))
|
labelPairs = append(labelPairs, fmt.Sprintf("%q='%s'", key, value))
|
||||||
node := newKeyValueNode(key, value)
|
// Value must be single quoted to prevent env variable expansion
|
||||||
|
// See https://github.com/docker/docker/issues/26027
|
||||||
|
node := newKeyValueNode(key, "'"+value+"'")
|
||||||
rootNode, prevNode = appendKeyValueNode(node, rootNode, prevNode)
|
rootNode, prevNode = appendKeyValueNode(node, rootNode, prevNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,19 +40,19 @@ func TestParseNameValNewFormat(t *testing.T) {
|
||||||
func TestNodeFromLabels(t *testing.T) {
|
func TestNodeFromLabels(t *testing.T) {
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
"weird": "'first second'",
|
"weird": "first' second",
|
||||||
}
|
}
|
||||||
expected := &Node{
|
expected := &Node{
|
||||||
Value: "label",
|
Value: "label",
|
||||||
Original: `LABEL "foo"='bar' "weird"=''first second''`,
|
Original: `LABEL "foo"='bar' "weird"='first' second'`,
|
||||||
Next: &Node{
|
Next: &Node{
|
||||||
Value: "foo",
|
Value: "foo",
|
||||||
Next: &Node{
|
Next: &Node{
|
||||||
Value: "bar",
|
Value: "'bar'",
|
||||||
Next: &Node{
|
Next: &Node{
|
||||||
Value: "weird",
|
Value: "weird",
|
||||||
Next: &Node{
|
Next: &Node{
|
||||||
Value: "'first second'",
|
Value: "'first' second'",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,16 +24,9 @@ type shellWord struct {
|
||||||
|
|
||||||
// ProcessWord will use the 'env' list of environment variables,
|
// ProcessWord will use the 'env' list of environment variables,
|
||||||
// and replace any env var references in 'word'.
|
// and replace any env var references in 'word'.
|
||||||
func ProcessWord(word string, env []string, escapeToken rune) (string, error) {
|
func ProcessWord(word string, env []string, escapeToken rune) ([]string, error) {
|
||||||
sw := &shellWord{
|
word, _, err := process(word, env, escapeToken)
|
||||||
word: word,
|
return []string{word}, err
|
||||||
envs: env,
|
|
||||||
pos: 0,
|
|
||||||
escapeToken: escapeToken,
|
|
||||||
}
|
|
||||||
sw.scanner.Init(strings.NewReader(word))
|
|
||||||
word, _, err := sw.process()
|
|
||||||
return word, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessWords will use the 'env' list of environment variables,
|
// ProcessWords will use the 'env' list of environment variables,
|
||||||
|
@ -44,6 +37,11 @@ func ProcessWord(word string, env []string, escapeToken rune) (string, error) {
|
||||||
// Note, each one is trimmed to remove leading and trailing spaces (unless
|
// Note, each one is trimmed to remove leading and trailing spaces (unless
|
||||||
// they are quoted", but ProcessWord retains spaces between words.
|
// they are quoted", but ProcessWord retains spaces between words.
|
||||||
func ProcessWords(word string, env []string, escapeToken rune) ([]string, error) {
|
func ProcessWords(word string, env []string, escapeToken rune) ([]string, error) {
|
||||||
|
_, words, err := process(word, env, escapeToken)
|
||||||
|
return words, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(word string, env []string, escapeToken rune) (string, []string, error) {
|
||||||
sw := &shellWord{
|
sw := &shellWord{
|
||||||
word: word,
|
word: word,
|
||||||
envs: env,
|
envs: env,
|
||||||
|
@ -51,8 +49,7 @@ func ProcessWords(word string, env []string, escapeToken rune) ([]string, error)
|
||||||
escapeToken: escapeToken,
|
escapeToken: escapeToken,
|
||||||
}
|
}
|
||||||
sw.scanner.Init(strings.NewReader(word))
|
sw.scanner.Init(strings.NewReader(word))
|
||||||
_, words, err := sw.process()
|
return sw.process()
|
||||||
return words, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sw *shellWord) process() (string, []string, error) {
|
func (sw *shellWord) process() (string, []string, error) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/testutil/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestShellParser4EnvVars(t *testing.T) {
|
func TestShellParser4EnvVars(t *testing.T) {
|
||||||
|
@ -13,9 +15,7 @@ func TestShellParser4EnvVars(t *testing.T) {
|
||||||
lineCount := 0
|
lineCount := 0
|
||||||
|
|
||||||
file, err := os.Open(fn)
|
file, err := os.Open(fn)
|
||||||
if err != nil {
|
assert.NilError(t, err)
|
||||||
t.Fatalf("Can't open '%s': %s", err, fn)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
|
@ -36,29 +36,25 @@ func TestShellParser4EnvVars(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
words := strings.Split(line, "|")
|
words := strings.Split(line, "|")
|
||||||
if len(words) != 3 {
|
assert.Equal(t, len(words), 3)
|
||||||
t.Fatalf("Error in '%s' - should be exactly one | in:%q", fn, line)
|
|
||||||
}
|
|
||||||
|
|
||||||
words[0] = strings.TrimSpace(words[0])
|
platform := strings.TrimSpace(words[0])
|
||||||
words[1] = strings.TrimSpace(words[1])
|
source := strings.TrimSpace(words[1])
|
||||||
words[2] = strings.TrimSpace(words[2])
|
expected := strings.TrimSpace(words[2])
|
||||||
|
|
||||||
// Key W=Windows; A=All; U=Unix
|
// Key W=Windows; A=All; U=Unix
|
||||||
if (words[0] != "W") && (words[0] != "A") && (words[0] != "U") {
|
if platform != "W" && platform != "A" && platform != "U" {
|
||||||
t.Fatalf("Invalid tag %s at line %d of %s. Must be W, A or U", words[0], lineCount, fn)
|
t.Fatalf("Invalid tag %s at line %d of %s. Must be W, A or U", platform, lineCount, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((words[0] == "W" || words[0] == "A") && runtime.GOOS == "windows") ||
|
if ((platform == "W" || platform == "A") && runtime.GOOS == "windows") ||
|
||||||
((words[0] == "U" || words[0] == "A") && runtime.GOOS != "windows") {
|
((platform == "U" || platform == "A") && runtime.GOOS != "windows") {
|
||||||
newWord, err := ProcessWord(words[1], envs, '\\')
|
newWord, err := ProcessWord(source, envs, '\\')
|
||||||
|
if expected == "error" {
|
||||||
if err != nil {
|
assert.Error(t, err, "")
|
||||||
newWord = "error"
|
} else {
|
||||||
}
|
assert.NilError(t, err)
|
||||||
|
assert.DeepEqual(t, newWord, []string{expected})
|
||||||
if newWord != words[2] {
|
|
||||||
t.Fatalf("Error. Src: %s Calc: %s Expected: %s at line %d", words[1], newWord, words[2], lineCount)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue