Repository: compose-spec/compose-go
Pull request #297 (2022-08-01 14:30:58)

Revert usage of "-" as separator for resource names
As noticed by some users in the original [PR](https://github.com/compose-spec/compose-go/pull/294/files), the changes were breaking ones and unjustified regarding the value offered in counter part.

This reverts commit 56e6c331759dd691e1e33c6b8338ceb4c0ca3c50, reversing
changes made to 0ab97a220d0895c435a88ced3026478e43185c53.


Patch:
diff --git a/cli/options.go b/cli/options.go
index 35e145d..e457b43 100644
--- a/cli/options.go
+++ b/cli/options.go
@@ -350,8 +350,7 @@ func ProjectFromOptions(options *ProjectOptions) (*types.Project, error) {
 
 	options.loadOptions = append(options.loadOptions,
 		withNamePrecedenceLoad(absWorkingDir, options),
-		withConvertWindowsPaths(options),
-		withSeparator(options))
+		withConvertWindowsPaths(options))
 
 	project, err := loader.Load(types.ConfigDetails{
 		ConfigFiles: configs,
@@ -385,15 +384,6 @@ func withConvertWindowsPaths(options *ProjectOptions) func(*loader.Options) {
 	}
 }
 
-// withSeparator defines loader.Options separator used to define resource names
-func withSeparator(options *ProjectOptions) func(*loader.Options) {
-	return func(o *loader.Options) {
-		if utils.StringToBool(options.Environment["COMPOSE_COMPATIBILITY"]) {
-			o.Separator = loader.CompatibilitySeparator
-		}
-	}
-}
-
 // getConfigPathsFromOptions retrieves the config files for project based on project options
 func getConfigPathsFromOptions(options *ProjectOptions) ([]string, error) {
 	if len(options.ConfigPaths) != 0 {
diff --git a/loader/loader.go b/loader/loader.go
index 6b7930a..acf11a9 100644
--- a/loader/loader.go
+++ b/loader/loader.go
@@ -43,11 +43,6 @@ import (
 	"gopkg.in/yaml.v2"
 )
 
-const (
-	DefaultSeparator       = "-"
-	CompatibilitySeparator = "_"
-)
-
 // Options supported by Load
 type Options struct {
 	// Skip schema validation
@@ -72,8 +67,6 @@ type Options struct {
 	projectName string
 	// Indicates when the projectName was imperatively set or guessed from path
 	projectNameImperativelySet bool
-	// Set separator used for naming resources
-	Separator string
 }
 
 func (o *Options) SetProjectName(name string, imperativelySet bool) {
@@ -162,7 +155,6 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
 			LookupValue:     configDetails.LookupEnv,
 			TypeCastMapping: interpolateTypeCastMapping,
 		},
-		Separator: DefaultSeparator,
 	}
 
 	for _, op := range options {
@@ -231,7 +223,7 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
 	}
 
 	if !opts.SkipNormalization {
-		err = normalize(project, opts.ResolvePaths, opts.Separator)
+		err = normalize(project, opts.ResolvePaths)
 		if err != nil {
 			return nil, err
 		}
diff --git a/loader/normalize.go b/loader/normalize.go
index 44498b4..4b98d62 100644
--- a/loader/normalize.go
+++ b/loader/normalize.go
@@ -28,7 +28,7 @@ import (
 )
 
 // normalize compose project by moving deprecated attributes to their canonical position and injecting implicit defaults
-func normalize(project *types.Project, resolvePaths bool, separator string) error {
+func normalize(project *types.Project, resolvePaths bool) error {
 	absWorkingDir, err := filepath.Abs(project.WorkingDir)
 	if err != nil {
 		return err
@@ -110,7 +110,7 @@ func normalize(project *types.Project, resolvePaths bool, separator string) erro
 		project.Services[i] = s
 	}
 
-	setNameFromKey(project, separator)
+	setNameFromKey(project)
 
 	return nil
 }
@@ -143,31 +143,31 @@ func absComposeFiles(composeFiles []string) ([]string, error) {
 }
 
 // Resources with no explicit name are actually named by their key in map
-func setNameFromKey(project *types.Project, separator string) {
+func setNameFromKey(project *types.Project) {
 	for i, n := range project.Networks {
 		if n.Name == "" {
-			n.Name = fmt.Sprintf("%s%s%s", project.Name, separator, i)
+			n.Name = fmt.Sprintf("%s_%s", project.Name, i)
 			project.Networks[i] = n
 		}
 	}
 
 	for i, v := range project.Volumes {
 		if v.Name == "" {
-			v.Name = fmt.Sprintf("%s%s%s", project.Name, separator, i)
+			v.Name = fmt.Sprintf("%s_%s", project.Name, i)
 			project.Volumes[i] = v
 		}
 	}
 
 	for i, c := range project.Configs {
 		if c.Name == "" {
-			c.Name = fmt.Sprintf("%s%s%s", project.Name, separator, i)
+			c.Name = fmt.Sprintf("%s_%s", project.Name, i)
 			project.Configs[i] = c
 		}
 	}
 
 	for i, s := range project.Secrets {
 		if s.Name == "" {
-			s.Name = fmt.Sprintf("%s%s%s", project.Name, separator, i)
+			s.Name = fmt.Sprintf("%s_%s", project.Name, i)
 			project.Secrets[i] = s
 		}
 	}


Test patch:
diff --git a/cli/options_test.go b/cli/options_test.go
index 2859d9d..3836177 100644
--- a/cli/options_test.go
+++ b/cli/options_test.go
@@ -237,28 +237,3 @@ func TestEnvMap(t *testing.T) {
 	m = utils.GetAsEqualsMap(l)
 	assert.Equal(t, m["foo"], "bar")
 }
-
-func TestWithSeparator(t *testing.T) {
-	t.Run("With default separator", func(t *testing.T) {
-		opts, err := NewProjectOptions([]string{
-			"testdata/simple/compose-with-network-and-volume.yaml",
-		}, WithName("my-project"))
-		assert.NilError(t, err)
-		p, err := ProjectFromOptions(opts)
-		assert.NilError(t, err)
-		assert.Equal(t, p.Networks["test-network"].Name, "my-project-test-network")
-
-	})
-
-	t.Run("With compatibility separator", func(t *testing.T) {
-		t.Setenv("COMPOSE_COMPATIBILITY", "true")
-		opts, err := NewProjectOptions([]string{
-			"testdata/simple/compose-with-network-and-volume.yaml",
-		}, WithName("my-project"), WithOsEnv)
-		assert.NilError(t, err)
-		p, err := ProjectFromOptions(opts)
-		assert.NilError(t, err)
-		assert.Equal(t, p.Networks["test-network"].Name, "my-project_test-network")
-
-	})
-}
diff --git a/cli/testdata/simple/compose-with-network-and-volume.yaml b/cli/testdata/simple/compose-with-network-and-volume.yaml
deleted file mode 100644
index 893fb7b..0000000
--- a/cli/testdata/simple/compose-with-network-and-volume.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-services:
-  simple:
-    image: nginx
-    networks:
-      - test-network
-    volumes:
-      - test-volume
-networks:
-  test-network:
-volumes:
-  test-volume:
diff --git a/loader/normalize_test.go b/loader/normalize_test.go
index 0b6aa84..c32a78e 100644
--- a/loader/normalize_test.go
+++ b/loader/normalize_test.go
@@ -73,16 +73,16 @@ services:
       default: null
 networks:
   default:
-    name: myProject-default
+    name: myProject_default
   myExternalnet:
     name: myExternalnet
     external: true
   myNamedNet:
     name: CustomName
   mynet:
-    name: myProject-mynet
+    name: myProject_mynet
 `
-	err := normalize(&project, false, DefaultSeparator)
+	err := normalize(&project, false)
 	assert.NilError(t, err)
 	marshal, err := yaml.Marshal(project)
 	assert.NilError(t, err)
@@ -116,9 +116,9 @@ services:
       default: null
 networks:
   default:
-    name: myProject-default
+    name: myProject_default
 `, filepath.Join(wd, "testdata"))
-	err := normalize(&project, true, DefaultSeparator)
+	err := normalize(&project, true)
 	assert.NilError(t, err)
 	marshal, err := yaml.Marshal(project)
 	assert.NilError(t, err)
@@ -138,11 +138,11 @@ func TestNormalizeAbsolutePaths(t *testing.T) {
 
 	expected := types.Project{
 		Name:         "myProject",
-		Networks:     types.Networks{"default": {Name: "myProject-default"}},
+		Networks:     types.Networks{"default": {Name: "myProject_default"}},
 		WorkingDir:   absWorkingDir,
 		ComposeFiles: []string{absComposeFile, absOverrideFile},
 	}
-	err := normalize(&project, false, DefaultSeparator)
+	err := normalize(&project, false)
 	assert.NilError(t, err)
 	assert.DeepEqual(t, expected, project)
 }
@@ -166,13 +166,13 @@ func TestNormalizeVolumes(t *testing.T) {
 	absCwd, _ := filepath.Abs(".")
 	expected := types.Project{
 		Name:     "myProject",
-		Networks: types.Networks{"default": {Name: "myProject-default"}},
+		Networks: types.Networks{"default": {Name: "myProject_default"}},
 		Volumes: types.Volumes{
 			"myExternalVol": {
 				Name:     "myExternalVol",
 				External: types.External{External: true},
 			},
-			"myvol": {Name: "myProject-myvol"},
+			"myvol": {Name: "myProject_myvol"},
 			"myNamedVol": {
 				Name: "CustomName",
 			},
@@ -180,29 +180,7 @@ func TestNormalizeVolumes(t *testing.T) {
 		WorkingDir:   absCwd,
 		ComposeFiles: []string{},
 	}
-	err := normalize(&project, false, DefaultSeparator)
-	assert.NilError(t, err)
-	assert.DeepEqual(t, expected, project)
-}
-
-func TestNormalizeWithCompatibilitySeparator(t *testing.T) {
-	project := types.Project{
-		Name:         "myProject",
-		WorkingDir:   "testdata",
-		Networks:     types.Networks{},
-		ComposeFiles: []string{filepath.Join("testdata", "simple", "compose.yaml"), filepath.Join("testdata", "simple", "compose-with-overrides.yaml")},
-	}
-	absWorkingDir, _ := filepath.Abs("testdata")
-	absComposeFile, _ := filepath.Abs(filepath.Join("testdata", "simple", "compose.yaml"))
-	absOverrideFile, _ := filepath.Abs(filepath.Join("testdata", "simple", "compose-with-overrides.yaml"))
-
-	expected := types.Project{
-		Name:         "myProject",
-		Networks:     types.Networks{"default": {Name: "myProject_default"}},
-		WorkingDir:   absWorkingDir,
-		ComposeFiles: []string{absComposeFile, absOverrideFile},
-	}
-	err := normalize(&project, false, "_")
+	err := normalize(&project, false)
 	assert.NilError(t, err)
 	assert.DeepEqual(t, expected, project)
 }