diff --git a/cli/compose/loader/loader.go b/cli/compose/loader/loader.go index 7629477519..1afc112999 100644 --- a/cli/compose/loader/loader.go +++ b/cli/compose/loader/loader.go @@ -337,7 +337,9 @@ func LoadService(name string, serviceDict map[string]interface{}, workingDir str return nil, err } - resolveVolumePaths(serviceConfig.Volumes, workingDir, lookupEnv) + if err := resolveVolumePaths(serviceConfig.Volumes, workingDir, lookupEnv); err != nil { + return nil, err + } return serviceConfig, nil } @@ -376,12 +378,16 @@ func resolveEnvironment(serviceConfig *types.ServiceConfig, workingDir string, l return nil } -func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) { +func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string, lookupEnv template.Mapping) error { for i, volume := range volumes { if volume.Type != "bind" { continue } + if volume.Source == "" { + return errors.New(`invalid mount config for type "bind": field Source must not be empty`) + } + filePath := expandUser(volume.Source, lookupEnv) // Check for a Unix absolute path first, to handle a Windows client // with a Unix daemon. This handles a Windows client connecting to a @@ -394,6 +400,7 @@ func resolveVolumePaths(volumes []types.ServiceVolumeConfig, workingDir string, volume.Source = filePath volumes[i] = volume } + return nil } // TODO: make this more robust diff --git a/cli/compose/loader/loader_test.go b/cli/compose/loader/loader_test.go index 75fdce2c2a..b1df2adcf0 100644 --- a/cli/compose/loader/loader_test.go +++ b/cli/compose/loader/loader_test.go @@ -1266,6 +1266,46 @@ services: assert.Contains(t, err.Error(), "services.tmpfs.volumes.0 Additional property tmpfs is not allowed") } +func TestLoadBindMountSourceMustNotBeEmpty(t *testing.T) { + _, err := loadYAML(` +version: "3.5" +services: + tmpfs: + image: nginx:latest + volumes: + - type: bind + target: /app +`) + require.EqualError(t, err, `invalid mount config for type "bind": field Source must not be empty`) +} + +func TestLoadBindMountWithSource(t *testing.T) { + config, err := loadYAML(` +version: "3.5" +services: + bind: + image: nginx:latest + volumes: + - type: bind + target: /app + source: "." +`) + require.NoError(t, err) + + workingDir, err := os.Getwd() + require.NoError(t, err) + + expected := types.ServiceVolumeConfig{ + Type: "bind", + Source: workingDir, + Target: "/app", + } + + require.Len(t, config.Services, 1) + assert.Len(t, config.Services[0].Volumes, 1) + assert.Equal(t, expected, config.Services[0].Volumes[0]) +} + func TestLoadTmpfsVolumeSizeCanBeZero(t *testing.T) { config, err := loadYAML(` version: "3.6"