diff --git a/loader/validate.go b/loader/validate.go index 455e48c4..b4c42c7f 100644 --- a/loader/validate.go +++ b/loader/validate.go @@ -51,6 +51,9 @@ func checkConsistency(project *types.Project) error { } } + if s.NetworkMode != "" && len(s.Networks) > 0 { + return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %s declares mutually exclusive `network_mode` and `networks`", s.Name)) + } for network := range s.Networks { if _, ok := project.Networks[network]; !ok { return errors.Wrap(errdefs.ErrInvalid, fmt.Sprintf("service %q refers to undefined network %s", s.Name, network)) diff --git a/loader/validate_test.go b/loader/validate_test.go index 577d4076..959f7a31 100644 --- a/loader/validate_test.go +++ b/loader/validate_test.go @@ -138,6 +138,24 @@ func TestValidateNetworkMode(t *testing.T) { err := checkConsistency(project) assert.NilError(t, err) }) + + t.Run("network_mode & networks can't both be defined", func(t *testing.T) { + project := &types.Project{ + Networks: types.Networks{"mynetwork": types.NetworkConfig{}}, + Services: types.Services([]types.ServiceConfig{ + { + Name: "myservice1", + Image: "scratch", + NetworkMode: "host", + Networks: map[string]*types.ServiceNetworkConfig{ + "mynetwork": {}, + }, + }, + }), + } + err := checkConsistency(project) + assert.Error(t, err, "service myservice1 declares mutually exclusive `network_mode` and `networks`: invalid compose project") + }) } func TestValidateSecret(t *testing.T) {