mirror of
https://github.com/docker/compose.git
synced 2025-07-13 16:54:25 +02:00
Implement --domainname flag on compose up, also defining compose extension "x-aci-domain-name" to store ACI DNSLabelName.
Signed-off-by: Guillaume Tardif <guillaume.tardif@docker.com>
This commit is contained in:
parent
268c02523a
commit
334ebf5f75
@ -43,8 +43,10 @@ const (
|
|||||||
StatusRunning = "Running"
|
StatusRunning = "Running"
|
||||||
// ComposeDNSSidecarName name of the dns sidecar container
|
// ComposeDNSSidecarName name of the dns sidecar container
|
||||||
ComposeDNSSidecarName = "aci--dns--sidecar"
|
ComposeDNSSidecarName = "aci--dns--sidecar"
|
||||||
dnsSidecarImage = "busybox:1.31.1"
|
// ExtensionDomainName compose extension to set ACI DNS label name
|
||||||
|
ExtensionDomainName = "x-aci-domain-name"
|
||||||
|
|
||||||
|
dnsSidecarImage = "busybox:1.31.1"
|
||||||
azureFileDriverName = "azure_file"
|
azureFileDriverName = "azure_file"
|
||||||
volumeDriveroptsShareNameKey = "share_name"
|
volumeDriveroptsShareNameKey = "share_name"
|
||||||
volumeDriveroptsAccountNameKey = "storage_account_name"
|
volumeDriveroptsAccountNameKey = "storage_account_name"
|
||||||
@ -103,26 +105,16 @@ func ToContainerGroup(ctx context.Context, aciContext store.AciContext, p types.
|
|||||||
return containerinstance.ContainerGroup{}, errors.New("ACI integration does not support labels in compose applications")
|
return containerinstance.ContainerGroup{}, errors.New("ACI integration does not support labels in compose applications")
|
||||||
}
|
}
|
||||||
if service.Ports != nil {
|
if service.Ports != nil {
|
||||||
var containerPorts []containerinstance.ContainerPort
|
containerPorts, serviceGroupPorts, dnsLabelName, err := convertPortsToAci(service, p)
|
||||||
for _, portConfig := range service.Ports {
|
if err != nil {
|
||||||
if portConfig.Published != 0 && portConfig.Published != portConfig.Target {
|
return groupDefinition, err
|
||||||
msg := fmt.Sprintf("Port mapping is not supported with ACI, cannot map port %d to %d for container %s",
|
|
||||||
portConfig.Published, portConfig.Target, service.Name)
|
|
||||||
return groupDefinition, errors.New(msg)
|
|
||||||
}
|
|
||||||
portNumber := int32(portConfig.Target)
|
|
||||||
containerPorts = append(containerPorts, containerinstance.ContainerPort{
|
|
||||||
Port: to.Int32Ptr(portNumber),
|
|
||||||
})
|
|
||||||
groupPorts = append(groupPorts, containerinstance.Port{
|
|
||||||
Port: to.Int32Ptr(portNumber),
|
|
||||||
Protocol: containerinstance.TCP,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
containerDefinition.ContainerProperties.Ports = &containerPorts
|
containerDefinition.ContainerProperties.Ports = &containerPorts
|
||||||
|
groupPorts = append(groupPorts, serviceGroupPorts...)
|
||||||
groupDefinition.ContainerGroupProperties.IPAddress = &containerinstance.IPAddress{
|
groupDefinition.ContainerGroupProperties.IPAddress = &containerinstance.IPAddress{
|
||||||
Type: containerinstance.Public,
|
Type: containerinstance.Public,
|
||||||
Ports: &groupPorts,
|
Ports: &groupPorts,
|
||||||
|
DNSNameLabel: dnsLabelName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +129,35 @@ func ToContainerGroup(ctx context.Context, aciContext store.AciContext, p types.
|
|||||||
return groupDefinition, nil
|
return groupDefinition, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertPortsToAci(service serviceConfigAciHelper, p types.Project) ([]containerinstance.ContainerPort, []containerinstance.Port, *string, error) {
|
||||||
|
var groupPorts []containerinstance.Port
|
||||||
|
var containerPorts []containerinstance.ContainerPort
|
||||||
|
for _, portConfig := range service.Ports {
|
||||||
|
if portConfig.Published != 0 && portConfig.Published != portConfig.Target {
|
||||||
|
msg := fmt.Sprintf("Port mapping is not supported with ACI, cannot map port %d to %d for container %s",
|
||||||
|
portConfig.Published, portConfig.Target, service.Name)
|
||||||
|
return nil, nil, nil, errors.New(msg)
|
||||||
|
}
|
||||||
|
portNumber := int32(portConfig.Target)
|
||||||
|
containerPorts = append(containerPorts, containerinstance.ContainerPort{
|
||||||
|
Port: to.Int32Ptr(portNumber),
|
||||||
|
})
|
||||||
|
groupPorts = append(groupPorts, containerinstance.Port{
|
||||||
|
Port: to.Int32Ptr(portNumber),
|
||||||
|
Protocol: containerinstance.TCP,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
var dnsLabelName *string = nil
|
||||||
|
if extension, ok := p.Extensions[ExtensionDomainName]; ok {
|
||||||
|
domain, ok := extension.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, nil, fmt.Errorf("could not read %s compose extension as string", ExtensionDomainName)
|
||||||
|
}
|
||||||
|
dnsLabelName = &domain
|
||||||
|
}
|
||||||
|
return containerPorts, groupPorts, dnsLabelName, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getDNSSidecar(containers []containerinstance.Container) containerinstance.Container {
|
func getDNSSidecar(containers []containerinstance.Container) containerinstance.Container {
|
||||||
var commands []string
|
var commands []string
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
|
|
||||||
type composeOptions struct {
|
type composeOptions struct {
|
||||||
Name string
|
Name string
|
||||||
|
DomainName string
|
||||||
WorkingDir string
|
WorkingDir string
|
||||||
ConfigPaths []string
|
ConfigPaths []string
|
||||||
Environment []string
|
Environment []string
|
||||||
@ -60,7 +61,7 @@ func (o *composeOptions) toProjectOptions() (*cli.ProjectOptions, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the compose command with its child commands
|
// Command returns the compose command with its child commands
|
||||||
func Command() *cobra.Command {
|
func Command(contextType string) *cobra.Command {
|
||||||
command := &cobra.Command{
|
command := &cobra.Command{
|
||||||
Short: "Docker Compose",
|
Short: "Docker Compose",
|
||||||
Use: "compose",
|
Use: "compose",
|
||||||
@ -70,7 +71,7 @@ func Command() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command.AddCommand(
|
command.AddCommand(
|
||||||
upCommand(),
|
upCommand(contextType),
|
||||||
downCommand(),
|
downCommand(),
|
||||||
psCommand(),
|
psCommand(),
|
||||||
listCommand(),
|
listCommand(),
|
||||||
|
@ -20,14 +20,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
aciconvert "github.com/docker/compose-cli/aci/convert"
|
||||||
"github.com/docker/compose-cli/api/client"
|
"github.com/docker/compose-cli/api/client"
|
||||||
|
"github.com/docker/compose-cli/context/store"
|
||||||
"github.com/docker/compose-cli/progress"
|
"github.com/docker/compose-cli/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
func upCommand() *cobra.Command {
|
func upCommand(contextType string) *cobra.Command {
|
||||||
opts := composeOptions{}
|
opts := composeOptions{}
|
||||||
upCmd := &cobra.Command{
|
upCmd := &cobra.Command{
|
||||||
Use: "up",
|
Use: "up",
|
||||||
@ -40,6 +41,11 @@ func upCommand() *cobra.Command {
|
|||||||
upCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files")
|
upCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files")
|
||||||
upCmd.Flags().StringArrayVarP(&opts.Environment, "environment", "e", []string{}, "Environment variables")
|
upCmd.Flags().StringArrayVarP(&opts.Environment, "environment", "e", []string{}, "Environment variables")
|
||||||
upCmd.Flags().BoolP("detach", "d", true, " Detached mode: Run containers in the background")
|
upCmd.Flags().BoolP("detach", "d", true, " Detached mode: Run containers in the background")
|
||||||
|
|
||||||
|
if contextType == store.AciContextType {
|
||||||
|
upCmd.Flags().StringVar(&opts.DomainName, "domainname", "", "Container NIS domain name")
|
||||||
|
}
|
||||||
|
|
||||||
return upCmd
|
return upCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,6 +61,9 @@ func runUp(ctx context.Context, opts composeOptions) error {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
project, err := cli.ProjectFromOptions(options)
|
project, err := cli.ProjectFromOptions(options)
|
||||||
|
if opts.DomainName != "" {
|
||||||
|
project.Extensions = map[string]interface{}{aciconvert.ExtensionDomainName: opts.DomainName}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,6 @@ func main() {
|
|||||||
cmd.StopCommand(),
|
cmd.StopCommand(),
|
||||||
cmd.KillCommand(),
|
cmd.KillCommand(),
|
||||||
cmd.SecretCommand(),
|
cmd.SecretCommand(),
|
||||||
compose.Command(),
|
|
||||||
|
|
||||||
// Place holders
|
// Place holders
|
||||||
cmd.EcsCommand(),
|
cmd.EcsCommand(),
|
||||||
@ -179,7 +178,10 @@ func main() {
|
|||||||
ctype = cc.Type()
|
ctype = cc.Type()
|
||||||
}
|
}
|
||||||
|
|
||||||
root.AddCommand(run.Command(ctype))
|
root.AddCommand(
|
||||||
|
run.Command(ctype),
|
||||||
|
compose.Command(ctype),
|
||||||
|
)
|
||||||
|
|
||||||
if ctype == store.AciContextType {
|
if ctype == store.AciContextType {
|
||||||
// we can also pass ctype as a parameter to the volume command and customize subcommands, flags, etc. when we have other backend implementations
|
// we can also pass ctype as a parameter to the volume command and customize subcommands, flags, etc. when we have other backend implementations
|
||||||
|
@ -453,7 +453,7 @@ func TestContainerRunAttached(t *testing.T) {
|
|||||||
|
|
||||||
func TestComposeUpUpdate(t *testing.T) {
|
func TestComposeUpUpdate(t *testing.T) {
|
||||||
c := NewParallelE2eCLI(t, binDir)
|
c := NewParallelE2eCLI(t, binDir)
|
||||||
_, _ = setupTestResourceGroup(t, c)
|
_, groupID := setupTestResourceGroup(t, c)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
composeFile = "../composefiles/aci-demo/aci_demo_port.yaml"
|
composeFile = "../composefiles/aci-demo/aci_demo_port.yaml"
|
||||||
@ -465,8 +465,11 @@ func TestComposeUpUpdate(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
t.Run("compose up", func(t *testing.T) {
|
t.Run("compose up", func(t *testing.T) {
|
||||||
|
dnsLabelName := "nginx-" + groupID
|
||||||
|
fqdn := dnsLabelName + "." + location + ".azurecontainer.io"
|
||||||
// Name of Compose project is taken from current folder "acie2e"
|
// Name of Compose project is taken from current folder "acie2e"
|
||||||
c.RunDockerCmd("compose", "up", "-f", composeFile)
|
c.RunDockerCmd("compose", "up", "-f", composeFile, "--domainname", dnsLabelName)
|
||||||
|
|
||||||
res := c.RunDockerCmd("ps")
|
res := c.RunDockerCmd("ps")
|
||||||
out := lines(res.Stdout())
|
out := lines(res.Stdout())
|
||||||
// Check three containers are running
|
// Check three containers are running
|
||||||
@ -493,6 +496,11 @@ func TestComposeUpUpdate(t *testing.T) {
|
|||||||
b, err := ioutil.ReadAll(r.Body)
|
b, err := ioutil.ReadAll(r.Body)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Assert(t, strings.Contains(string(b), `"word":`))
|
assert.Assert(t, strings.Contains(string(b), `"word":`))
|
||||||
|
|
||||||
|
endpoint = fmt.Sprintf("http://%s:%d", fqdn, containerInspect.Ports[0].HostPort)
|
||||||
|
r, err = HTTPGetWithRetry(endpoint+"/words/noun", 3)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
assert.Equal(t, r.StatusCode, http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("compose ps", func(t *testing.T) {
|
t.Run("compose ps", func(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user