mirror of
https://github.com/docker/compose.git
synced 2025-07-25 22:54:54 +02:00
Add e2e test deploying a compose application to an ECS cluster
Signed-off-by: Guillaume Lours <guillaume.lours@docker.com> Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
08bd18231d
commit
e9fe3b2864
@ -7,10 +7,13 @@ build:
|
|||||||
test: build ## Run tests
|
test: build ## Run tests
|
||||||
go test ./... -v
|
go test ./... -v
|
||||||
|
|
||||||
|
e2e: build ## Run tests
|
||||||
|
go test ./... -v -tags=e2e
|
||||||
|
|
||||||
dev: build
|
dev: build
|
||||||
ln -f -s "${PWD}/dist/docker-ecs" "${HOME}/.docker/cli-plugins/docker-ecs"
|
ln -f -s "${PWD}/dist/docker-ecs" "${HOME}/.docker/cli-plugins/docker-ecs"
|
||||||
|
|
||||||
lint: ## Verify Go files
|
lint: ## Verify Go files
|
||||||
golangci-lint run --config ./golangci.yaml ./...
|
golangci-lint run --config ./golangci.yaml ./...
|
||||||
|
|
||||||
.PHONY: clean build test dev lint
|
.PHONY: clean build test dev lint e2e
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package amazon
|
package amazon
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
//go:generate mockgen -destination=./mock/api.go -package=mock . API
|
//go:generate mockgen -destination=./mock/api.go -package=mock . API
|
||||||
|
|
||||||
type API interface {
|
type API interface {
|
||||||
@ -7,4 +9,7 @@ type API interface {
|
|||||||
upAPI
|
upAPI
|
||||||
logsAPI
|
logsAPI
|
||||||
secretsAPI
|
secretsAPI
|
||||||
|
GetTasks(ctx context.Context, cluster string, name string) ([]string, error)
|
||||||
|
GetNetworkInterfaces(ctx context.Context, cluster string, arns ...string) ([]string, error)
|
||||||
|
GetPublicIPs(ctx context.Context, interfaces ...string) ([]string, error)
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,11 @@ package mock
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
reflect "reflect"
|
|
||||||
|
|
||||||
cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
|
cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
|
||||||
cloudformation0 "github.com/awslabs/goformation/v4/cloudformation"
|
cloudformation0 "github.com/awslabs/goformation/v4/cloudformation"
|
||||||
docker "github.com/docker/ecs-plugin/pkg/docker"
|
docker "github.com/docker/ecs-plugin/pkg/docker"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockAPI is a mock of API interface
|
// MockAPI is a mock of API interface
|
||||||
@ -52,21 +51,6 @@ func (mr *MockAPIMockRecorder) ClusterExists(arg0, arg1 interface{}) *gomock.Cal
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClusterExists", reflect.TypeOf((*MockAPI)(nil).ClusterExists), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClusterExists", reflect.TypeOf((*MockAPI)(nil).ClusterExists), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateCluster mocks base method
|
|
||||||
func (m *MockAPI) CreateCluster(arg0 context.Context, arg1 string) (string, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "CreateCluster", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(string)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateCluster indicates an expected call of CreateCluster
|
|
||||||
func (mr *MockAPIMockRecorder) CreateCluster(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateCluster", reflect.TypeOf((*MockAPI)(nil).CreateCluster), arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateSecret mocks base method
|
// CreateSecret mocks base method
|
||||||
func (m *MockAPI) CreateSecret(arg0 context.Context, arg1 docker.Secret) (string, error) {
|
func (m *MockAPI) CreateSecret(arg0 context.Context, arg1 docker.Secret) (string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -168,6 +152,60 @@ func (mr *MockAPIMockRecorder) GetDefaultVPC(arg0 interface{}) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultVPC", reflect.TypeOf((*MockAPI)(nil).GetDefaultVPC), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultVPC", reflect.TypeOf((*MockAPI)(nil).GetDefaultVPC), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLogs mocks base method
|
||||||
|
func (m *MockAPI) GetLogs(arg0 context.Context, arg1 string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetLogs", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLogs indicates an expected call of GetLogs
|
||||||
|
func (mr *MockAPIMockRecorder) GetLogs(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockAPI)(nil).GetLogs), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkInterfaces mocks base method
|
||||||
|
func (m *MockAPI) GetNetworkInterfaces(arg0 context.Context, arg1 string, arg2 ...string) ([]string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{arg0, arg1}
|
||||||
|
for _, a := range arg2 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "GetNetworkInterfaces", varargs...)
|
||||||
|
ret0, _ := ret[0].([]string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNetworkInterfaces indicates an expected call of GetNetworkInterfaces
|
||||||
|
func (mr *MockAPIMockRecorder) GetNetworkInterfaces(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkInterfaces", reflect.TypeOf((*MockAPI)(nil).GetNetworkInterfaces), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublicIPs mocks base method
|
||||||
|
func (m *MockAPI) GetPublicIPs(arg0 context.Context, arg1 ...string) ([]string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{arg0}
|
||||||
|
for _, a := range arg1 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "GetPublicIPs", varargs...)
|
||||||
|
ret0, _ := ret[0].([]string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPublicIPs indicates an expected call of GetPublicIPs
|
||||||
|
func (mr *MockAPIMockRecorder) GetPublicIPs(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]interface{}{arg0}, arg1...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPublicIPs", reflect.TypeOf((*MockAPI)(nil).GetPublicIPs), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
// GetStackID mocks base method
|
// GetStackID mocks base method
|
||||||
func (m *MockAPI) GetStackID(arg0 context.Context, arg1 string) (string, error) {
|
func (m *MockAPI) GetStackID(arg0 context.Context, arg1 string) (string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -198,6 +236,21 @@ func (mr *MockAPIMockRecorder) GetSubNets(arg0, arg1 interface{}) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubNets", reflect.TypeOf((*MockAPI)(nil).GetSubNets), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubNets", reflect.TypeOf((*MockAPI)(nil).GetSubNets), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTasks mocks base method
|
||||||
|
func (m *MockAPI) GetTasks(arg0 context.Context, arg1, arg2 string) ([]string, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetTasks", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].([]string)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTasks indicates an expected call of GetTasks
|
||||||
|
func (mr *MockAPIMockRecorder) GetTasks(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTasks", reflect.TypeOf((*MockAPI)(nil).GetTasks), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
// InspectSecret mocks base method
|
// InspectSecret mocks base method
|
||||||
func (m *MockAPI) InspectSecret(arg0 context.Context, arg1 string) (docker.Secret, error) {
|
func (m *MockAPI) InspectSecret(arg0 context.Context, arg1 string) (docker.Secret, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -271,17 +324,3 @@ func (mr *MockAPIMockRecorder) WaitStackComplete(arg0, arg1, arg2 interface{}) *
|
|||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitStackComplete", reflect.TypeOf((*MockAPI)(nil).WaitStackComplete), arg0, arg1, arg2)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitStackComplete", reflect.TypeOf((*MockAPI)(nil).WaitStackComplete), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogs mocks base method
|
|
||||||
func (m *MockAPI) GetLogs(arg0 context.Context, arg1 string) error {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "GetLogs", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(error)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetLogs mocks base method
|
|
||||||
func (mr *MockAPIMockRecorder) GetLogs(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogs", reflect.TypeOf((*MockAPI)(nil).GetLogs), arg0, arg1)
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestExitErrorCode(t *testing.T) {
|
func TestExitErrorCode(t *testing.T) {
|
||||||
cmd, cleanup := dockerCli.createTestCmd()
|
cmd, cleanup, _ := dockerCli.createTestCmd()
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
cmd.Command = dockerCli.Command("ecs", "unknown_command")
|
cmd.Command = dockerCli.Command("ecs", "unknown_command")
|
||||||
|
65
ecs/tests/e2e_deploy_services_test.go
Normal file
65
ecs/tests/e2e_deploy_services_test.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// +build e2e
|
||||||
|
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
|
"github.com/docker/ecs-plugin/pkg/amazon"
|
||||||
|
"github.com/docker/ecs-plugin/pkg/docker"
|
||||||
|
"gotest.tools/assert"
|
||||||
|
"gotest.tools/v3/fs"
|
||||||
|
"gotest.tools/v3/golden"
|
||||||
|
"gotest.tools/v3/icmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
composeFileName = "compose.yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestE2eDeployServices(t *testing.T) {
|
||||||
|
cmd, cleanup, awsContext := dockerCli.createTestCmd()
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
composeUpSimpleService(t, cmd, awsContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeUpSimpleService(t *testing.T, cmd icmd.Cmd, awsContext docker.AwsContext) {
|
||||||
|
bgContext := context.Background()
|
||||||
|
composeYAML := golden.Get(t, "input/simple-single-service.yaml")
|
||||||
|
tmpDir := fs.NewDir(t, t.Name(),
|
||||||
|
fs.WithFile(composeFileName, "", fs.WithBytes(composeYAML)),
|
||||||
|
)
|
||||||
|
// We can't use the file added in the tmp directory because it will drop if an assertion fails
|
||||||
|
defer composeDown(t, cmd, golden.Path("input/simple-single-service.yaml"))
|
||||||
|
defer tmpDir.Remove()
|
||||||
|
|
||||||
|
cmd.Command = dockerCli.Command("ecs", "compose", "--file="+tmpDir.Join(composeFileName), "--project-name", t.Name(), "up")
|
||||||
|
icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||||
|
|
||||||
|
session, err := session.NewSessionWithOptions(session.Options{
|
||||||
|
Profile: awsContext.Profile,
|
||||||
|
Config: aws.Config{
|
||||||
|
Region: aws.String(awsContext.Region),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.NilError(t, err)
|
||||||
|
sdk := amazon.NewAPI(session)
|
||||||
|
arns, err := sdk.GetTasks(bgContext, t.Name(), "simple")
|
||||||
|
assert.NilError(t, err)
|
||||||
|
networkInterfaces, err := sdk.GetNetworkInterfaces(bgContext, t.Name(), arns...)
|
||||||
|
publicIps, err := sdk.GetPublicIPs(context.Background(), networkInterfaces...)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
for _, ip := range publicIps {
|
||||||
|
icmd.RunCommand("curl", "-I", "http://"+ip).Assert(t, icmd.Success)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeDown(t *testing.T, cmd icmd.Cmd, composeFile string) {
|
||||||
|
cmd.Command = dockerCli.Command("ecs", "compose", "--file="+composeFile, "--project-name", t.Name(), "down")
|
||||||
|
icmd.RunCmd(cmd).Assert(t, icmd.Success)
|
||||||
|
}
|
@ -29,7 +29,7 @@ type dockerCliCommand struct {
|
|||||||
|
|
||||||
type ConfigFileOperator func(configFile *dockerConfigFile.ConfigFile)
|
type ConfigFileOperator func(configFile *dockerConfigFile.ConfigFile)
|
||||||
|
|
||||||
func (d dockerCliCommand) createTestCmd(ops ...ConfigFileOperator) (icmd.Cmd, func()) {
|
func (d dockerCliCommand) createTestCmd(ops ...ConfigFileOperator) (icmd.Cmd, func(), docker.AwsContext) {
|
||||||
configDir, err := ioutil.TempDir("", "config")
|
configDir, err := ioutil.TempDir("", "config")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -55,9 +55,8 @@ func (d dockerCliCommand) createTestCmd(ops ...ConfigFileOperator) (icmd.Cmd, fu
|
|||||||
}
|
}
|
||||||
|
|
||||||
awsContext := docker.AwsContext{
|
awsContext := docker.AwsContext{
|
||||||
Profile: "TestProfile",
|
Profile: "sandbox.devtools.developer",
|
||||||
Cluster: "TestCluster",
|
Region: "eu-west-3",
|
||||||
Region: "TestRegion",
|
|
||||||
}
|
}
|
||||||
testStore, err := docker.NewContextWithStore(testContextName, &awsContext, filepath.Join(configDir, "contexts"))
|
testStore, err := docker.NewContextWithStore(testContextName, &awsContext, filepath.Join(configDir, "contexts"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -71,7 +70,7 @@ func (d dockerCliCommand) createTestCmd(ops ...ConfigFileOperator) (icmd.Cmd, fu
|
|||||||
env := append(os.Environ(),
|
env := append(os.Environ(),
|
||||||
"DOCKER_CONFIG="+configDir,
|
"DOCKER_CONFIG="+configDir,
|
||||||
"DOCKER_CLI_EXPERIMENTAL=enabled") // TODO: Remove this once docker ecs plugin is no more experimental
|
"DOCKER_CLI_EXPERIMENTAL=enabled") // TODO: Remove this once docker ecs plugin is no more experimental
|
||||||
return icmd.Cmd{Env: env}, cleanup
|
return icmd.Cmd{Env: env}, cleanup, awsContext
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d dockerCliCommand) Command(args ...string) []string {
|
func (d dockerCliCommand) Command(args ...string) []string {
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestInvokePluginFromCLI(t *testing.T) {
|
func TestInvokePluginFromCLI(t *testing.T) {
|
||||||
cmd, cleanup := dockerCli.createTestCmd()
|
cmd, cleanup, _ := dockerCli.createTestCmd()
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
// docker --help should list app as a top command
|
// docker --help should list app as a top command
|
||||||
cmd.Command = dockerCli.Command("--help")
|
cmd.Command = dockerCli.Command("--help")
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDefaultAwsContextName(t *testing.T) {
|
func TestDefaultAwsContextName(t *testing.T) {
|
||||||
cmd, cleanup := dockerCli.createTestCmd()
|
cmd, cleanup, _ := dockerCli.createTestCmd()
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
cmd.Command = dockerCli.Command("ecs", "setup", "--cluster", "clusterName", "--profile", "profileName",
|
cmd.Command = dockerCli.Command("ecs", "setup", "--cluster", "clusterName", "--profile", "profileName",
|
||||||
|
6
ecs/tests/testdata/input/simple-single-service.yaml
vendored
Normal file
6
ecs/tests/testdata/input/simple-single-service.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
simple:
|
||||||
|
image: nginx
|
||||||
|
ports:
|
||||||
|
- 80:80
|
Loading…
x
Reference in New Issue
Block a user