Fix substitution with non-empty env-var

Due to a typo, substitution would not work if the given
environment-variable was set.

Given the following docker compose file;

```yaml
version: "3.7"

services:
  app:
    image: nginx:${version:-latest}
```

Deploying a stack with `$version` set would ignore the `$version`
environment variable, and use the default value instead;

```bash
version=alpine docker stack deploy -c docker-compose.yml foobar

Creating network foobar_default
Creating service foobar_app

docker service ls

ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
rskkjxe6sm0w        foobar_app          replicated          1/1                 nginx:latest
```

This patch also fixes "soft default" not detecting empty environment variables,
only non-set environment variables.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2018-09-25 18:35:39 +02:00
parent 54c19e67f6
commit ec3daea021
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
2 changed files with 17 additions and 5 deletions

View File

@ -176,15 +176,21 @@ func extractVariable(value interface{}, pattern *regexp.Regexp) ([]extractedValu
// Soft default (fall back if unset or empty) // Soft default (fall back if unset or empty)
func softDefault(substitution string, mapping Mapping) (string, bool, error) { func softDefault(substitution string, mapping Mapping) (string, bool, error) {
return withDefault(substitution, mapping, "-:") sep := ":-"
if !strings.Contains(substitution, sep) {
return "", false, nil
}
name, defaultValue := partition(substitution, sep)
value, ok := mapping(name)
if !ok || value == "" {
return defaultValue, true, nil
}
return value, true, nil
} }
// Hard default (fall back if-and-only-if empty) // Hard default (fall back if-and-only-if empty)
func hardDefault(substitution string, mapping Mapping) (string, bool, error) { func hardDefault(substitution string, mapping Mapping) (string, bool, error) {
return withDefault(substitution, mapping, "-") sep := "-"
}
func withDefault(substitution string, mapping Mapping, sep string) (string, bool, error) {
if !strings.Contains(substitution, sep) { if !strings.Contains(substitution, sep) {
return "", false, nil return "", false, nil
} }

View File

@ -78,6 +78,12 @@ func TestEmptyValueWithSoftDefault(t *testing.T) {
assert.Check(t, is.Equal("ok def", result)) assert.Check(t, is.Equal("ok def", result))
} }
func TestValueWithSoftDefault(t *testing.T) {
result, err := Substitute("ok ${FOO:-def}", defaultMapping)
assert.NilError(t, err)
assert.Check(t, is.Equal("ok first", result))
}
func TestEmptyValueWithHardDefault(t *testing.T) { func TestEmptyValueWithHardDefault(t *testing.T) {
result, err := Substitute("ok ${BAR-def}", defaultMapping) result, err := Substitute("ok ${BAR-def}", defaultMapping)
assert.NilError(t, err) assert.NilError(t, err)