bake(compose): allow dot in target name

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2022-07-31 16:53:39 +02:00
parent 480bf2e123
commit 7ef679d945
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
6 changed files with 83 additions and 9 deletions

View File

@ -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
@ -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

View File

@ -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",

View File

@ -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
@ -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,
@ -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))
}
}
}

View File

@ -418,7 +418,7 @@ func TestServiceName(t *testing.T) {
},
{
svc: "a.b",
wantErr: true,
wantErr: false,
},
{
svc: "_a",

View File

@ -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(),
})

View File

@ -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: