1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Fix environment resolving.

Load from env should only happen if the value is unset.
Extract a buildEnvironment function and revert some changes to tests.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2017-03-14 12:39:26 -04:00
parent ea43c33330
commit a9c86b63c0
9 changed files with 147 additions and 118 deletions

View file

@ -27,6 +27,19 @@ func buildConfigDetails(source types.Dict, env map[string]string) types.ConfigDe
}
}
func loadYAML(yaml string) (*types.Config, error) {
return loadYAMLWithEnv(yaml, nil)
}
func loadYAMLWithEnv(yaml string, env map[string]string) (*types.Config, error) {
dict, err := ParseYAML([]byte(yaml))
if err != nil {
return nil, err
}
return Load(buildConfigDetails(dict, env))
}
var sampleYAML = `
version: "3"
services:
@ -98,12 +111,16 @@ var sampleDict = types.Dict{
},
}
func strPtr(val string) *string {
return &val
}
var sampleConfig = types.Config{
Services: []types.ServiceConfig{
{
Name: "foo",
Image: "busybox",
Environment: map[string]string{},
Environment: map[string]*string{},
Networks: map[string]*types.ServiceNetworkConfig{
"with_me": nil,
},
@ -111,7 +128,7 @@ var sampleConfig = types.Config{
{
Name: "bar",
Image: "busybox",
Environment: map[string]string{"FOO": "1"},
Environment: map[string]*string{"FOO": strPtr("1")},
Networks: map[string]*types.ServiceNetworkConfig{
"with_ipam": nil,
},
@ -173,7 +190,7 @@ services:
secrets:
super:
external: true
`, nil)
`)
if !assert.NoError(t, err) {
return
}
@ -182,7 +199,7 @@ secrets:
}
func TestParseAndLoad(t *testing.T) {
actual, err := loadYAML(sampleYAML, nil)
actual, err := loadYAML(sampleYAML)
if !assert.NoError(t, err) {
return
}
@ -192,15 +209,15 @@ func TestParseAndLoad(t *testing.T) {
}
func TestInvalidTopLevelObjectType(t *testing.T) {
_, err := loadYAML("1", nil)
_, err := loadYAML("1")
assert.Error(t, err)
assert.Contains(t, err.Error(), "Top-level object must be a mapping")
_, err = loadYAML("\"hello\"", nil)
_, err = loadYAML("\"hello\"")
assert.Error(t, err)
assert.Contains(t, err.Error(), "Top-level object must be a mapping")
_, err = loadYAML("[\"hello\"]", nil)
_, err = loadYAML("[\"hello\"]")
assert.Error(t, err)
assert.Contains(t, err.Error(), "Top-level object must be a mapping")
}
@ -211,7 +228,7 @@ version: "3"
123:
foo:
image: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key at top level: 123")
@ -222,7 +239,7 @@ services:
image: busybox
123:
image: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key in services: 123")
@ -236,7 +253,7 @@ networks:
ipam:
config:
- 123: oh dear
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key in networks.default.ipam.config[0]: 123")
@ -247,7 +264,7 @@ services:
image: busybox
environment:
1: FOO
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Non-string key in services.dict-env.environment: 1")
}
@ -258,7 +275,7 @@ version: "3"
services:
foo:
image: busybox
`, nil)
`)
assert.NoError(t, err)
_, err = loadYAML(`
@ -266,7 +283,7 @@ version: "3.0"
services:
foo:
image: busybox
`, nil)
`)
assert.NoError(t, err)
}
@ -276,7 +293,7 @@ version: "2"
services:
foo:
image: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "version")
@ -285,7 +302,7 @@ version: "2.0"
services:
foo:
image: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "version")
}
@ -296,7 +313,7 @@ version: 3
services:
foo:
image: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "version must be a string")
}
@ -305,7 +322,7 @@ func TestV1Unsupported(t *testing.T) {
_, err := loadYAML(`
foo:
image: busybox
`, nil)
`)
assert.Error(t, err)
}
@ -315,7 +332,7 @@ version: "3"
services:
- foo:
image: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "services must be a mapping")
@ -323,7 +340,7 @@ services:
version: "3"
services:
foo: busybox
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "services.foo must be a mapping")
@ -332,7 +349,7 @@ version: "3"
networks:
- default:
driver: bridge
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "networks must be a mapping")
@ -340,7 +357,7 @@ networks:
version: "3"
networks:
default: bridge
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "networks.default must be a mapping")
@ -349,7 +366,7 @@ version: "3"
volumes:
- data:
driver: local
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "volumes must be a mapping")
@ -357,7 +374,7 @@ volumes:
version: "3"
volumes:
data: local
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "volumes.data must be a mapping")
}
@ -368,13 +385,13 @@ version: "3"
services:
foo:
image: ["busybox", "latest"]
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "services.foo.image must be a string")
}
func TestValidEnvironment(t *testing.T) {
config, err := loadYAML(`
func TestLoadWithEnvironment(t *testing.T) {
config, err := loadYAMLWithEnv(`
version: "3"
services:
dict-env:
@ -391,17 +408,17 @@ services:
- FOO=1
- BAR=2
- BAZ=2.5
- QUX
- QUUX=
- QUX=
- QUUX
`, map[string]string{"QUX": "qux"})
assert.NoError(t, err)
expected := types.MappingWithEquals{
"FOO": "1",
"BAR": "2",
"BAZ": "2.5",
"QUX": "qux",
"QUUX": "",
"FOO": strPtr("1"),
"BAR": strPtr("2"),
"BAZ": strPtr("2.5"),
"QUX": strPtr("qux"),
"QUUX": nil,
}
assert.Equal(t, 2, len(config.Services))
@ -419,7 +436,7 @@ services:
image: busybox
environment:
FOO: ["1"]
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "services.dict-env.environment.FOO must be a string, number or null")
}
@ -431,14 +448,14 @@ services:
dict-env:
image: busybox
environment: "FOO=1"
`, nil)
`)
assert.Error(t, err)
assert.Contains(t, err.Error(), "services.dict-env.environment must be a mapping")
}
func TestEnvironmentInterpolation(t *testing.T) {
home := "/home/foo"
config, err := loadYAML(`
config, err := loadYAMLWithEnv(`
version: "3"
services:
test:
@ -461,7 +478,7 @@ volumes:
assert.NoError(t, err)
expectedLabels := types.MappingWithEquals{
expectedLabels := types.Labels{
"home1": home,
"home2": home,
"nonexistent": "",
@ -534,7 +551,7 @@ services:
bar:
extends:
service: foo
`, nil)
`)
assert.Error(t, err)
assert.IsType(t, &ForbiddenPropertiesError{}, err)
@ -607,7 +624,8 @@ func TestFullExample(t *testing.T) {
assert.NoError(t, err)
homeDir := "/home/foo"
config, err := loadYAML(string(bytes), map[string]string{"HOME": homeDir, "QUX": "2"})
env := map[string]string{"HOME": homeDir, "QUX": "qux_from_environment"}
config, err := loadYAMLWithEnv(string(bytes), env)
if !assert.NoError(t, err) {
return
}
@ -662,14 +680,11 @@ func TestFullExample(t *testing.T) {
DNSSearch: []string{"dc1.example.com", "dc2.example.com"},
DomainName: "foo.com",
Entrypoint: []string{"/code/entrypoint.sh", "-p", "3000"},
Environment: map[string]string{
"RACK_ENV": "development",
"SHOW": "true",
"SESSION_SECRET": "",
"FOO": "1",
"BAR": "2",
"BAZ": "3",
"QUX": "2",
Environment: map[string]*string{
"FOO": strPtr("foo_from_env_file"),
"BAR": strPtr("bar_from_env_file_2"),
"BAZ": strPtr("baz_from_service_def"),
"QUX": strPtr("qux_from_environment"),
},
EnvFile: []string{
"./example1.env",
@ -961,15 +976,6 @@ func TestFullExample(t *testing.T) {
assert.Equal(t, expectedVolumeConfig, config.Volumes)
}
func loadYAML(yaml string, env map[string]string) (*types.Config, error) {
dict, err := ParseYAML([]byte(yaml))
if err != nil {
return nil, err
}
return Load(buildConfigDetails(dict, env))
}
func serviceSort(services []types.ServiceConfig) []types.ServiceConfig {
sort.Sort(servicesByName(services))
return services