From bf8a55f590bbd516000a95bd7da9800a7ad3320e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81kos=20Tak=C3=A1cs?= Date: Sun, 20 Mar 2022 17:48:57 +0100 Subject: [PATCH] Fix required env vars ignored except the last one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the variable substitution, if a missing variable was followed by an existing one, the empty "err" variable overwrote the previous non-empty variable. Unlike with Docker Compose v1, the first found error did not guarantee that an actual error would be thrown. Example which would have run before the fix even though var1 is not defined: ```yaml services: bash: image: bash:5.0.18-alpine3.15 environment: var12: "_ ${var1:?Error1} _ ${var2:?Error2} _ " command: - env ``` ```bash # var2=1 docker compose up ``` This change also means that, if multiple variables are missing in one string, the first one will be reported by Docker Compose Signed-off-by: Ákos Takács --- interpolation/interpolation_test.go | 1 + template/template.go | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/interpolation/interpolation_test.go b/interpolation/interpolation_test.go index 592211636..322bfe24a 100644 --- a/interpolation/interpolation_test.go +++ b/interpolation/interpolation_test.go @@ -113,6 +113,7 @@ func TestValidUnexistentInterpolation(t *testing.T) { {test: "{{{ ${FOO:?foo_} }}}", errMsg: "foo_"}, {test: "{{{ ${FOO:?foo-bar-value} }}}", errMsg: "foo-bar-value"}, {test: "{{{ ${FOO:?foo} ${BAR:-DEFAULT_VALUE} }}}", errMsg: "foo"}, + {test: "${FOO:?foo} ${BAR:?bar}", errMsg: "foo"}, {test: "{{{ ${BAR} }}}", expected: "{{{ }}}"}, {test: "${FOO:?baz} }}}", errMsg: "baz"}, {test: "${FOO?baz} }}}", errMsg: "baz"}, diff --git a/template/template.go b/template/template.go index 22e4e95ad..3e62326a1 100644 --- a/template/template.go +++ b/template/template.go @@ -63,8 +63,9 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su if len(subsFuncs) == 0 { subsFuncs = getDefaultSortedSubstitutionFunctions(template) } - var err error + var errReturn error result := pattern.ReplaceAllStringFunc(template, func(substring string) string { + var err error closingBraceIndex := getFirstBraceClosingIndex(substring) rest := "" if closingBraceIndex > -1 { @@ -87,6 +88,9 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su if substitution == "" { err = &InvalidTemplateError{Template: template} + if errReturn == nil { + errReturn = err + } return "" } @@ -98,6 +102,9 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su ) value, applied, err = f(substitution, mapping) if err != nil { + if errReturn == nil { + errReturn = err + } return "" } if !applied { @@ -105,6 +112,9 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su } interpolatedNested, err := SubstituteWith(rest, mapping, pattern, subsFuncs...) if err != nil { + if errReturn == nil { + errReturn = err + } return "" } return value + interpolatedNested @@ -118,7 +128,7 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su return value }) - return result, err + return result, errReturn } func getDefaultSortedSubstitutionFunctions(template string, fns ...SubstituteFunc) []SubstituteFunc {