2016-12-20 16:26:49 -05:00
|
|
|
package interpolation
|
|
|
|
|
|
|
|
import (
|
2017-10-03 18:03:20 -04:00
|
|
|
"strconv"
|
2022-09-22 10:31:28 -04:00
|
|
|
"testing"
|
2017-10-03 18:03:20 -04:00
|
|
|
|
2020-02-22 12:12:14 -05:00
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
is "gotest.tools/v3/assert/cmp"
|
2016-12-20 16:26:49 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
var defaults = map[string]string{
|
2017-10-03 18:03:20 -04:00
|
|
|
"USER": "jenny",
|
|
|
|
"FOO": "bar",
|
|
|
|
"count": "5",
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func defaultMapping(name string) (string, bool) {
|
|
|
|
val, ok := defaults[name]
|
|
|
|
return val, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestInterpolate(t *testing.T) {
|
2017-03-22 10:42:03 -04:00
|
|
|
services := map[string]interface{}{
|
|
|
|
"servicea": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"image": "example:${USER}",
|
|
|
|
"volumes": []interface{}{"$FOO:/target"},
|
2017-03-22 10:42:03 -04:00
|
|
|
"logging": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"driver": "${FOO}",
|
2017-03-22 10:42:03 -04:00
|
|
|
"options": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"user": "$USER",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-03-22 10:42:03 -04:00
|
|
|
expected := map[string]interface{}{
|
|
|
|
"servicea": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"image": "example:jenny",
|
|
|
|
"volumes": []interface{}{"bar:/target"},
|
2017-03-22 10:42:03 -04:00
|
|
|
"logging": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"driver": "bar",
|
2017-03-22 10:42:03 -04:00
|
|
|
"options": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"user": "jenny",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2017-10-04 16:51:48 -04:00
|
|
|
result, err := Interpolate(services, Options{LookupValue: defaultMapping})
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.DeepEqual(expected, result))
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestInvalidInterpolation(t *testing.T) {
|
2017-03-22 10:42:03 -04:00
|
|
|
services := map[string]interface{}{
|
|
|
|
"servicea": map[string]interface{}{
|
2016-12-20 16:26:49 -05:00
|
|
|
"image": "${",
|
|
|
|
},
|
|
|
|
}
|
2017-10-04 16:51:48 -04:00
|
|
|
_, err := Interpolate(services, Options{LookupValue: defaultMapping})
|
linting: fix incorrectly formatted errors (revive)
cli/compose/interpolation/interpolation.go:102:4: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
"invalid interpolation format for %s: %#v. You may need to escape any $ with another $.",
^
cli/command/stack/loader/loader.go:30:30: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
return nil, errors.Errorf("Compose file contains unsupported options:\n\n%s\n",
^
cli/command/formatter/formatter.go:76:30: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
return tmpl, errors.Errorf("Template parsing error: %v\n", err)
^
cli/command/formatter/formatter.go:97:24: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
return errors.Errorf("Template parsing error: %v\n", err)
^
cli/command/image/build.go:257:25: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
return errors.Errorf("error checking context: '%s'.", err)
^
cli/command/volume/create.go:35:27: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
return errors.Errorf("Conflicting options: either specify --name or provide positional arg, not both\n")
^
cli/command/container/create.go:160:24: error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
return errors.Errorf("failed to remove the CID file '%s': %s \n", cid.path, err)
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-03-27 15:13:03 -04:00
|
|
|
assert.Error(t, err, `invalid interpolation format for servicea.image: "${"; you may need to escape any $ with another $`)
|
2016-12-20 16:26:49 -05:00
|
|
|
}
|
2017-10-03 16:22:02 -04:00
|
|
|
|
|
|
|
func TestInterpolateWithDefaults(t *testing.T) {
|
2022-09-22 10:31:28 -04:00
|
|
|
t.Setenv("FOO", "BARZ")
|
2017-10-03 16:22:02 -04:00
|
|
|
|
|
|
|
config := map[string]interface{}{
|
|
|
|
"networks": map[string]interface{}{
|
|
|
|
"foo": "thing_${FOO}",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
expected := map[string]interface{}{
|
|
|
|
"networks": map[string]interface{}{
|
|
|
|
"foo": "thing_BARZ",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
result, err := Interpolate(config, Options{})
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.DeepEqual(expected, result))
|
2017-10-03 16:22:02 -04:00
|
|
|
}
|
2017-10-03 18:03:20 -04:00
|
|
|
|
|
|
|
func TestInterpolateWithCast(t *testing.T) {
|
|
|
|
config := map[string]interface{}{
|
|
|
|
"foo": map[string]interface{}{
|
|
|
|
"replicas": "$count",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
toInt := func(value string) (interface{}, error) {
|
|
|
|
return strconv.Atoi(value)
|
|
|
|
}
|
|
|
|
result, err := Interpolate(config, Options{
|
|
|
|
LookupValue: defaultMapping,
|
2017-10-04 16:51:48 -04:00
|
|
|
TypeCastMapping: map[Path]Cast{NewPath(PathMatchAll, "replicas"): toInt},
|
2017-10-03 18:03:20 -04:00
|
|
|
})
|
2018-03-06 14:44:13 -05:00
|
|
|
assert.NilError(t, err)
|
2017-10-03 18:03:20 -04:00
|
|
|
expected := map[string]interface{}{
|
|
|
|
"foo": map[string]interface{}{
|
|
|
|
"replicas": 5,
|
|
|
|
},
|
|
|
|
}
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.DeepEqual(expected, result))
|
2017-10-03 18:03:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPathMatches(t *testing.T) {
|
|
|
|
var testcases = []struct {
|
|
|
|
doc string
|
|
|
|
path Path
|
|
|
|
pattern Path
|
|
|
|
expected bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
doc: "pattern too short",
|
|
|
|
path: NewPath("one", "two", "three"),
|
|
|
|
pattern: NewPath("one", "two"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
doc: "pattern too long",
|
|
|
|
path: NewPath("one", "two"),
|
|
|
|
pattern: NewPath("one", "two", "three"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
doc: "pattern mismatch",
|
|
|
|
path: NewPath("one", "three", "two"),
|
|
|
|
pattern: NewPath("one", "two", "three"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
doc: "pattern mismatch with match-all part",
|
|
|
|
path: NewPath("one", "three", "two"),
|
|
|
|
pattern: NewPath(PathMatchAll, "two", "three"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
doc: "pattern match with match-all part",
|
|
|
|
path: NewPath("one", "two", "three"),
|
|
|
|
pattern: NewPath("one", "*", "three"),
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
doc: "pattern match",
|
|
|
|
path: NewPath("one", "two", "three"),
|
|
|
|
pattern: NewPath("one", "two", "three"),
|
|
|
|
expected: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, testcase := range testcases {
|
2018-03-05 18:53:52 -05:00
|
|
|
assert.Check(t, is.Equal(testcase.expected, testcase.path.matches(testcase.pattern)))
|
2017-10-03 18:03:20 -04:00
|
|
|
}
|
|
|
|
}
|