Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 7f8bb03

Browse files
committed
Introduce ECS emulation mode
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
1 parent ed1776f commit 7f8bb03

10 files changed

Lines changed: 146 additions & 9 deletions

File tree

aci/backend.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ func (cs *aciComposeService) Up(ctx context.Context, project *types.Project) err
396396
return createOrUpdateACIContainers(ctx, cs.ctx, groupDefinition)
397397
}
398398

399+
func (cs *aciComposeService) Emulate(context.Context, *cli.ProjectOptions) error {
400+
return errdefs.ErrNotImplemented
401+
}
402+
399403
func (cs *aciComposeService) Down(ctx context.Context, project string) error {
400404
logrus.Debugf("Down on project with name %q\n", project)
401405

cli/cmd/compose/compose.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (o *composeOptions) toProjectOptions() (*cli.ProjectOptions, error) {
6060
}
6161

6262
// Command returns the compose command with its child commands
63-
func Command() *cobra.Command {
63+
func Command(contextType string) *cobra.Command {
6464
command := &cobra.Command{
6565
Short: "Docker Compose",
6666
Use: "compose",
@@ -70,7 +70,7 @@ func Command() *cobra.Command {
7070
}
7171

7272
command.AddCommand(
73-
upCommand(),
73+
upCommand(contextType),
7474
downCommand(),
7575
psCommand(),
7676
logsCommand(),

cli/cmd/compose/up.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,32 @@ import (
2424
"github.com/spf13/cobra"
2525

2626
"github.com/docker/compose-cli/client"
27+
"github.com/docker/compose-cli/context/store"
2728
"github.com/docker/compose-cli/progress"
2829
)
2930

30-
func upCommand() *cobra.Command {
31+
func upCommand(contextType string) *cobra.Command {
3132
opts := composeOptions{}
33+
var simulation bool
3234
upCmd := &cobra.Command{
3335
Use: "up",
3436
RunE: func(cmd *cobra.Command, args []string) error {
35-
return runUp(cmd.Context(), opts)
37+
return runUp(cmd.Context(), opts, simulation)
3638
},
3739
}
3840
upCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name")
3941
upCmd.Flags().StringVar(&opts.WorkingDir, "workdir", "", "Work dir")
4042
upCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files")
4143
upCmd.Flags().StringArrayVarP(&opts.Environment, "environment", "e", []string{}, "Environment variables")
4244
upCmd.Flags().BoolP("detach", "d", true, " Detached mode: Run containers in the background")
45+
if contextType == store.EcsContextType {
46+
upCmd.Flags().BoolVar(&simulation, "simulate", false, " Simulation mode: run compose app with ECS local container endpoints")
47+
}
4348

4449
return upCmd
4550
}
4651

47-
func runUp(ctx context.Context, opts composeOptions) error {
52+
func runUp(ctx context.Context, opts composeOptions, simulation bool) error {
4853
c, err := client.New(ctx)
4954
if err != nil {
5055
return err
@@ -60,6 +65,9 @@ func runUp(ctx context.Context, opts composeOptions) error {
6065
return err
6166
}
6267

68+
if simulation {
69+
return c.ComposeService().Emulate(ctx, options)
70+
}
6371
return c.ComposeService().Up(ctx, project)
6472
})
6573
}

cli/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ func main() {
121121
cmd.RmCommand(),
122122
cmd.StartCommand(),
123123
cmd.InspectCommand(),
124-
compose.Command(),
125124
login.Command(),
126125
logout.Command(),
127126
cmd.VersionCommand(version),
@@ -184,6 +183,8 @@ func main() {
184183
$ docker context create %s <name>`, cc.Type(), store.EcsContextType))
185184
}
186185

186+
root.AddCommand(compose.Command(ctype))
187+
187188
metrics.Track(ctype, os.Args[1:], root.PersistentFlags())
188189

189190
ctx = apicontext.WithCurrentContext(ctx, currentContext)

client/compose.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ func (c *composeService) Up(context.Context, *types.Project) error {
3434
return errdefs.ErrNotImplemented
3535
}
3636

37+
// Emulate executes the equivalent to a `compose up` in platform emulation mode
38+
func (c *composeService) Emulate(context.Context, *cli.ProjectOptions) error {
39+
return errdefs.ErrNotImplemented
40+
}
41+
3742
// Down executes the equivalent to a `compose down`
3843
func (c *composeService) Down(context.Context, string) error {
3944
return errdefs.ErrNotImplemented

compose/api.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ type Service interface {
3535
Ps(ctx context.Context, projectName string) ([]ServiceStatus, error)
3636
// Convert translate compose model into backend's native format
3737
Convert(ctx context.Context, project *types.Project) ([]byte, error)
38+
// Emulate executes the equivalent to a `compose up` in platform emulation mode
39+
Emulate(ctx context.Context, options *cli.ProjectOptions) error
3840
}
3941

4042
// PortPublisher hold status about published port

ecs/emulate.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
Copyright 2020 Docker, Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package ecs
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"os"
23+
"os/exec"
24+
"path/filepath"
25+
"strings"
26+
27+
"github.com/aws/aws-sdk-go/aws"
28+
"github.com/compose-spec/compose-go/types"
29+
"github.com/sanathkr/go-yaml"
30+
31+
"github.com/compose-spec/compose-go/cli"
32+
)
33+
34+
func (c *ecsAPIService) Emulate(ctx context.Context, options *cli.ProjectOptions) error {
35+
project, err := cli.ProjectFromOptions(options)
36+
if err != nil {
37+
return err
38+
}
39+
project.Networks["credentials_network"] = types.NetworkConfig{
40+
Driver: "bridge",
41+
Ipam: types.IPAMConfig{
42+
Config: []*types.IPAMPool{
43+
{
44+
Subnet: "169.254.170.0/24",
45+
Gateway: "169.254.170.1",
46+
},
47+
},
48+
},
49+
}
50+
51+
// On Windows, this directory can be found at "%UserProfile%\.aws"
52+
home, err := os.UserHomeDir()
53+
if err != nil {
54+
return err
55+
}
56+
57+
for i, service := range project.Services {
58+
service.Networks["credentials_network"] = &types.ServiceNetworkConfig{
59+
Ipv4Address: fmt.Sprintf("169.254.170.%d", i+3),
60+
}
61+
service.DependsOn = append(service.DependsOn, "ecs-local-endpoints")
62+
service.Environment["AWS_DEFAULT_REGION"] = aws.String(c.ctx.Region)
63+
service.Environment["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"] = aws.String("/creds")
64+
service.Environment["ECS_CONTAINER_METADATA_URI"] = aws.String("http://169.254.170.2/v3")
65+
project.Services[i] = service
66+
}
67+
68+
project.Services = append(project.Services, types.ServiceConfig{
69+
Name: "ecs-local-endpoints",
70+
Image: "amazon/amazon-ecs-local-container-endpoints",
71+
Volumes: []types.ServiceVolumeConfig{
72+
{
73+
Type: types.VolumeTypeBind,
74+
Source: "/var/run",
75+
Target: "/var/run",
76+
},
77+
{
78+
Type: types.VolumeTypeBind,
79+
Source: filepath.Join(home, ".aws"),
80+
Target: "/home/.aws",
81+
},
82+
},
83+
Environment: map[string]*string{
84+
"HOME": aws.String("/home"),
85+
"AWS_PROFILE": aws.String("default"),
86+
},
87+
Networks: map[string]*types.ServiceNetworkConfig{
88+
"credentials_network": {
89+
Ipv4Address: "169.254.170.2",
90+
},
91+
},
92+
})
93+
94+
delete(project.Networks, "default")
95+
config := map[string]interface{}{
96+
"services": project.Services,
97+
"networks": project.Networks,
98+
"volumes": project.Volumes,
99+
"secrets": project.Secrets,
100+
"configs": project.Configs,
101+
}
102+
marshal, err := yaml.Marshal(config)
103+
if err != nil {
104+
return err
105+
}
106+
107+
cmd := exec.Command("docker-compose", "--context", "default", "--project-directory", project.WorkingDir, "--project-name", project.Name, "-f", "-", "up")
108+
cmd.Stdin = strings.NewReader(string(marshal))
109+
cmd.Stdout = os.Stdout
110+
cmd.Stderr = os.Stderr
111+
return cmd.Run()
112+
}

example/backend.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ func (cs *composeService) Down(ctx context.Context, project string) error {
132132
return nil
133133
}
134134

135+
func (cs *composeService) Emulate(context.Context, *cli.ProjectOptions) error {
136+
return errdefs.ErrNotImplemented
137+
}
138+
135139
func (cs *composeService) Ps(ctx context.Context, project string) ([]compose.ServiceStatus, error) {
136140
return nil, errdefs.ErrNotImplemented
137141
}

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ require (
2222
github.com/aws/aws-sdk-go v1.34.8
2323
github.com/awslabs/goformation/v4 v4.14.0
2424
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
25-
github.com/compose-spec/compose-go v0.0.0-20200818070525-eb1188aae4a2
25+
github.com/compose-spec/compose-go v0.0.0-20200824075806-a70cd5945c25
2626
github.com/containerd/console v1.0.0
2727
github.com/containerd/containerd v1.3.5 // indirect
2828
github.com/docker/cli v0.0.0-20200528204125-dd360c7c0de8
@@ -46,6 +46,7 @@ require (
4646
github.com/opencontainers/go-digest v1.0.0
4747
github.com/opencontainers/runc v0.1.1 // indirect
4848
github.com/pkg/errors v0.9.1
49+
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b
4950
github.com/sirupsen/logrus v1.6.0
5051
github.com/smartystreets/goconvey v1.6.4 // indirect
5152
github.com/spf13/cobra v1.0.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
8787
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
8888
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
8989
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
90-
github.com/compose-spec/compose-go v0.0.0-20200818070525-eb1188aae4a2 h1:b3JmHJVJt8zXy112yGtRq74G32sPQ8XLJxfHKaP/DOg=
91-
github.com/compose-spec/compose-go v0.0.0-20200818070525-eb1188aae4a2/go.mod h1:P7PZ0svgjrZ8nv/XvxObbl8o0DCIE9ZbL8pllg6uL4w=
90+
github.com/compose-spec/compose-go v0.0.0-20200824075806-a70cd5945c25 h1:mVlGrHJuNGPJNEvCCIrDIZX5FYtNTwFd++y+fJaGTXM=
91+
github.com/compose-spec/compose-go v0.0.0-20200824075806-a70cd5945c25/go.mod h1:P7PZ0svgjrZ8nv/XvxObbl8o0DCIE9ZbL8pllg6uL4w=
9292
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
9393
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
9494
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=

0 commit comments

Comments
 (0)