Skip to content

Commit

Permalink
bake(compose): allow dot in target name
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <[email protected]>
  • Loading branch information
crazy-max committed Jul 31, 2022
1 parent 480bf2e commit 7ef679d
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 9 deletions.
11 changes: 11 additions & 0 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string,
return nil, nil, err
}

for i, t := range targets {
targets[i] = sanitizeTargetName(t)
}

o, err := c.newOverrides(overrides)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -976,6 +980,13 @@ func validateTargetName(name string) error {
return nil
}

func sanitizeTargetName(target string) string {
// as stipulated in compose spec, service name can contain a dot so as
// best-effort and to avoid any potential ambiguity, we replace the dot
// with an underscore.
return strings.ReplaceAll(target, ".", "_")
}

func sliceEqual(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
Expand Down
61 changes: 61 additions & 0 deletions bake/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,67 @@ services:
require.Equal(t, []string{"db", "newservice", "webapp"}, g[0].Targets)
}

func TestReadTargetsWithDotCompose(t *testing.T) {
t.Parallel()

fp := File{
Name: "docker-compose.yml",
Data: []byte(
`version: "3"
services:
web.app:
build:
dockerfile: Dockerfile.webapp
args:
buildno: 1
`),
}

fp2 := File{
Name: "docker-compose2.yml",
Data: []byte(
`version: "3"
services:
web_app:
build:
args:
buildno2: 12
`),
}

ctx := context.TODO()

m, _, err := ReadTargets(ctx, []File{fp}, []string{"web.app"}, nil, nil)
require.NoError(t, err)
require.Equal(t, 1, len(m))
_, ok := m["web_app"]
require.True(t, ok)
require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile)
require.Equal(t, "1", m["web_app"].Args["buildno"])

m, _, err = ReadTargets(ctx, []File{fp2}, []string{"web_app"}, nil, nil)
require.NoError(t, err)
require.Equal(t, 1, len(m))
_, ok = m["web_app"]
require.True(t, ok)
require.Equal(t, "Dockerfile", *m["web_app"].Dockerfile)
require.Equal(t, "12", m["web_app"].Args["buildno2"])

m, g, err := ReadTargets(ctx, []File{fp, fp2}, []string{"default"}, nil, nil)
require.NoError(t, err)
require.Equal(t, 1, len(m))
_, ok = m["web_app"]
require.True(t, ok)
require.Equal(t, "Dockerfile.webapp", *m["web_app"].Dockerfile)
require.Equal(t, ".", *m["web_app"].Context)
require.Equal(t, "1", m["web_app"].Args["buildno"])
require.Equal(t, "12", m["web_app"].Args["buildno2"])

require.Equal(t, 1, len(g))
sort.Strings(g[0].Targets)
require.Equal(t, []string{"web_app"}, g[0].Targets)
}

func TestHCLCwdPrefix(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Expand Down
13 changes: 7 additions & 6 deletions bake/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ func ParseCompose(dt []byte) (*Config, error) {
s.Build = &compose.BuildConfig{}
}

if err = validateTargetName(s.Name); err != nil {
return nil, errors.Wrapf(err, "invalid service name %q", s.Name)
targetName := sanitizeTargetName(s.Name)
if err = validateTargetName(targetName); err != nil {
return nil, errors.Wrapf(err, "invalid service name %q", targetName)
}

var contextPathP *string
Expand All @@ -85,9 +86,9 @@ func ParseCompose(dt []byte) (*Config, error) {
secrets = append(secrets, secret)
}

g.Targets = append(g.Targets, s.Name)
g.Targets = append(g.Targets, targetName)
t := &Target{
Name: s.Name,
Name: targetName,
Context: contextPathP,
Dockerfile: dockerfilePathP,
Tags: s.Build.Tags,
Expand Down Expand Up @@ -220,13 +221,13 @@ func (t *Target) composeExtTarget(exts map[string]interface{}) error {
return nil
}

// compposeValidate validates a compose file
// composeValidate validates a compose file
func composeValidate(project *compose.Project) error {
for _, s := range project.Services {
if s.Build != nil {
for _, secret := range s.Build.Secrets {
if _, ok := project.Secrets[secret.Source]; !ok {
return errors.Wrap(errComposeInvalid, fmt.Sprintf("service %q refers to undefined build secret %s", s.Name, secret.Source))
return errors.Wrap(errComposeInvalid, fmt.Sprintf("service %q refers to undefined build secret %s", sanitizeTargetName(s.Name), secret.Source))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion bake/compose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ func TestServiceName(t *testing.T) {
},
{
svc: "a.b",
wantErr: true,
wantErr: false,
},
{
svc: "_a",
Expand Down
4 changes: 2 additions & 2 deletions commands/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions) (err error
}

tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, map[string]string{
// Don't forget to update documentation if you add a new
// built-in variable: docs/reference/buildx_bake.md#built-in-variables
// don't forget to update documentation if you add a new
// built-in variable: docs/guides/bake/file-definition.md#built-in-variables
"BAKE_CMD_CONTEXT": cmdContext,
"BAKE_LOCAL_PLATFORM": platforms.DefaultString(),
})
Expand Down
1 change: 1 addition & 0 deletions docs/guides/bake/file-definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ $ docker buildx bake webapp-dev
> **Note**
>
> In the case of compose files, each service corresponds to a target.
> If compose service name contains a dot it will be replaced with an underscore.
Complete list of valid target fields available for [HCL](#hcl-definition) and
[JSON](#json-definition) definitions:
Expand Down

0 comments on commit 7ef679d

Please sign in to comment.