mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-29 17:05:46 +08:00
Merge pull request #1011 from crazy-max/bake-target-name
bake(compose): allow dot in target name
This commit is contained in:
commit
30d650862d
11
bake/bake.go
11
bake/bake.go
@ -90,6 +90,10 @@ func ReadTargets(ctx context.Context, files []File, targets, overrides []string,
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, t := range targets {
|
||||||
|
targets[i] = sanitizeTargetName(t)
|
||||||
|
}
|
||||||
|
|
||||||
o, err := c.newOverrides(overrides)
|
o, err := c.newOverrides(overrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@ -976,6 +980,13 @@ func validateTargetName(name string) error {
|
|||||||
return nil
|
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 {
|
func sliceEqual(s1, s2 []string) bool {
|
||||||
if len(s1) != len(s2) {
|
if len(s1) != len(s2) {
|
||||||
return false
|
return false
|
||||||
|
@ -307,6 +307,67 @@ services:
|
|||||||
require.Equal(t, []string{"db", "newservice", "webapp"}, g[0].Targets)
|
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) {
|
func TestHCLCwdPrefix(t *testing.T) {
|
||||||
fp := File{
|
fp := File{
|
||||||
Name: "docker-bake.hcl",
|
Name: "docker-bake.hcl",
|
||||||
|
@ -61,8 +61,9 @@ func ParseCompose(dt []byte) (*Config, error) {
|
|||||||
s.Build = &compose.BuildConfig{}
|
s.Build = &compose.BuildConfig{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = validateTargetName(s.Name); err != nil {
|
targetName := sanitizeTargetName(s.Name)
|
||||||
return nil, errors.Wrapf(err, "invalid service name %q", s.Name)
|
if err = validateTargetName(targetName); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "invalid service name %q", targetName)
|
||||||
}
|
}
|
||||||
|
|
||||||
var contextPathP *string
|
var contextPathP *string
|
||||||
@ -85,9 +86,9 @@ func ParseCompose(dt []byte) (*Config, error) {
|
|||||||
secrets = append(secrets, secret)
|
secrets = append(secrets, secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
g.Targets = append(g.Targets, s.Name)
|
g.Targets = append(g.Targets, targetName)
|
||||||
t := &Target{
|
t := &Target{
|
||||||
Name: s.Name,
|
Name: targetName,
|
||||||
Context: contextPathP,
|
Context: contextPathP,
|
||||||
Dockerfile: dockerfilePathP,
|
Dockerfile: dockerfilePathP,
|
||||||
Tags: s.Build.Tags,
|
Tags: s.Build.Tags,
|
||||||
@ -220,13 +221,13 @@ func (t *Target) composeExtTarget(exts map[string]interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// compposeValidate validates a compose file
|
// composeValidate validates a compose file
|
||||||
func composeValidate(project *compose.Project) error {
|
func composeValidate(project *compose.Project) error {
|
||||||
for _, s := range project.Services {
|
for _, s := range project.Services {
|
||||||
if s.Build != nil {
|
if s.Build != nil {
|
||||||
for _, secret := range s.Build.Secrets {
|
for _, secret := range s.Build.Secrets {
|
||||||
if _, ok := project.Secrets[secret.Source]; !ok {
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ func TestServiceName(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
svc: "a.b",
|
svc: "a.b",
|
||||||
wantErr: true,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
svc: "_a",
|
svc: "_a",
|
||||||
|
@ -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{
|
tgts, grps, err := bake.ReadTargets(ctx, files, targets, overrides, map[string]string{
|
||||||
// Don't forget to update documentation if you add a new
|
// don't forget to update documentation if you add a new
|
||||||
// built-in variable: docs/reference/buildx_bake.md#built-in-variables
|
// built-in variable: docs/guides/bake/file-definition.md#built-in-variables
|
||||||
"BAKE_CMD_CONTEXT": cmdContext,
|
"BAKE_CMD_CONTEXT": cmdContext,
|
||||||
"BAKE_LOCAL_PLATFORM": platforms.DefaultString(),
|
"BAKE_LOCAL_PLATFORM": platforms.DefaultString(),
|
||||||
})
|
})
|
||||||
|
@ -36,6 +36,7 @@ $ docker buildx bake webapp-dev
|
|||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
> In the case of compose files, each service corresponds to a target.
|
> 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
|
Complete list of valid target fields available for [HCL](#hcl-definition) and
|
||||||
[JSON](#json-definition) definitions:
|
[JSON](#json-definition) definitions:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user