Skip to content

Commit

Permalink
Merge pull request #272 from glours/interpolate-compose-name
Browse files Browse the repository at this point in the history
  • Loading branch information
ndeloof committed Jun 15, 2022
2 parents 0056c09 + 2929133 commit 311eaf5
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 15 deletions.
1 change: 1 addition & 0 deletions loader/full-example.yml
Expand Up @@ -25,6 +25,7 @@ services:
tags:
- foo:v1.0.0
- docker.io/username/foo:my-other-tag
- ${COMPOSE_PROJECT_NAME}:1.0.0


cap_add:
Expand Down
6 changes: 4 additions & 2 deletions loader/full-struct_test.go
Expand Up @@ -70,7 +70,7 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
Mode: uint32Ptr(0440),
},
},
Tags: []string{"foo:v1.0.0", "docker.io/username/foo:my-other-tag"},
Tags: []string{"foo:v1.0.0", "docker.io/username/foo:my-other-tag", "full_example_project_name:1.0.0"},
},
CapAdd: []string{"ALL"},
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
Expand Down Expand Up @@ -602,6 +602,7 @@ services:
tags:
- foo:v1.0.0
- docker.io/username/foo:my-other-tag
- full_example_project_name:1.0.0
cap_add:
- ALL
cap_drop:
Expand Down Expand Up @@ -1133,7 +1134,8 @@ func fullExampleJSON(workingDir, homeDir string) string {
],
"tags": [
"foo:v1.0.0",
"docker.io/username/foo:my-other-tag"
"docker.io/username/foo:my-other-tag",
"full_example_project_name:1.0.0"
]
},
"cap_add": [
Expand Down
35 changes: 26 additions & 9 deletions loader/loader.go
Expand Up @@ -160,6 +160,8 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
op(opts)
}

projectName := projectName(configDetails, opts)

var configs []*types.Config
for i, file := range configDetails.ConfigFiles {
configDict := file.Config
Expand Down Expand Up @@ -207,15 +209,6 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
s.EnvFile = newEnvFiles
}

projectName, projectNameImperativelySet := opts.GetProjectName()
model.Name = NormalizeProjectName(model.Name)
if !projectNameImperativelySet && model.Name != "" {
projectName = model.Name
}

if projectName != "" {
configDetails.Environment[consts.ComposeProjectName] = projectName
}
project := &types.Project{
Name: projectName,
WorkingDir: configDetails.WorkingDir,
Expand Down Expand Up @@ -245,6 +238,30 @@ func Load(configDetails types.ConfigDetails, options ...func(*Options)) (*types.
return project, nil
}

func projectName(details types.ConfigDetails, opts *Options) string {
projectName, projectNameImperativelySet := opts.GetProjectName()
var pjNameFromConfigFile string

for _, configFile := range details.ConfigFiles {
yml, err := ParseYAML(configFile.Content)
if err != nil {
return ""
}
if val, ok := yml["name"]; ok && val != "" {
pjNameFromConfigFile = yml["name"].(string)
}
}
pjNameFromConfigFile = NormalizeProjectName(pjNameFromConfigFile)
if !projectNameImperativelySet && pjNameFromConfigFile != "" {
projectName = pjNameFromConfigFile
}

if _, ok := details.Environment[consts.ComposeProjectName]; !ok && projectName != "" {
details.Environment[consts.ComposeProjectName] = projectName
}
return projectName
}

func NormalizeProjectName(s string) string {
r := regexp.MustCompile("[a-z0-9_-]")
s = strings.ToLower(s)
Expand Down
93 changes: 89 additions & 4 deletions loader/loader_test.go
Expand Up @@ -34,20 +34,32 @@ import (
)

func buildConfigDetails(yaml string, env map[string]string) types.ConfigDetails {
return buildConfigDetailsMultipleFiles(env, yaml)
}

func buildConfigDetailsMultipleFiles(env map[string]string, yamls ...string) types.ConfigDetails {
workingDir, err := os.Getwd()
if err != nil {
panic(err)
}

return types.ConfigDetails{
WorkingDir: workingDir,
ConfigFiles: []types.ConfigFile{
{Filename: "filename.yml", Content: []byte(yaml)},
},
WorkingDir: workingDir,
ConfigFiles: buildConfigFiles(yamls),
Environment: env,
}
}

func buildConfigFiles(yamls []string) []types.ConfigFile {
configFiles := []types.ConfigFile{}
for i, yaml := range yamls {
configFiles = append(configFiles, types.ConfigFile{
Filename: fmt.Sprintf("filename%d.yml", i),
Content: []byte(yaml)})
}
return configFiles
}

func loadYAML(yaml string) (*types.Project, error) {
return loadYAMLWithEnv(yaml, nil)
}
Expand Down Expand Up @@ -1951,3 +1963,76 @@ services:
assert.NilError(t, err)
assert.Equal(t, "value2", sshValue)
}

func TestProjectNameInterpolation(t *testing.T) {
t.Run("project name simple interpolation", func(t *testing.T) {
yaml := `
name: interpolated
services:
web:
image: web
container_name: ${COMPOSE_PROJECT_NAME}-web
`
configDetails := buildConfigDetails(yaml, map[string]string{})

actual, err := Load(configDetails)
assert.NilError(t, err)
svc, err := actual.GetService("web")
assert.NilError(t, err)
assert.Equal(t, "interpolated-web", svc.ContainerName)
})

t.Run("project name interpolation with override", func(t *testing.T) {
yaml1 := `
name: interpolated
services:
web:
image: web
container_name: ${COMPOSE_PROJECT_NAME}-web
`
yaml2 := `
name: overrided
services:
db:
image: db
container_name: ${COMPOSE_PROJECT_NAME}-db
`
yaml3 := `
services:
proxy:
image: proxy
container_name: ${COMPOSE_PROJECT_NAME}-proxy
`
configDetails := buildConfigDetailsMultipleFiles(map[string]string{}, yaml1, yaml2, yaml3)

actual, err := Load(configDetails)
assert.NilError(t, err)
svc, err := actual.GetService("web")
assert.NilError(t, err)
assert.Equal(t, "overrided-web", svc.ContainerName)

svc, err = actual.GetService("db")
assert.NilError(t, err)
assert.Equal(t, "overrided-db", svc.ContainerName)

svc, err = actual.GetService("proxy")
assert.NilError(t, err)
assert.Equal(t, "overrided-proxy", svc.ContainerName)
})

t.Run("project name env variable interpolation", func(t *testing.T) {
yaml := `
name: interpolated
services:
web:
image: web
container_name: ${COMPOSE_PROJECT_NAME}-web
`
configDetails := buildConfigDetails(yaml, map[string]string{"COMPOSE_PROJECT_NAME": "env-var"})
actual, err := Load(configDetails)
assert.NilError(t, err)
svc, err := actual.GetService("web")
assert.NilError(t, err)
assert.Equal(t, "env-var-web", svc.ContainerName)
})
}

0 comments on commit 311eaf5

Please sign in to comment.