From ae4dc2e0db7ff27b52ce0c21e36948f7d2b2e2d9 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Mon, 18 May 2020 10:53:07 +0200 Subject: [PATCH] Reject compose file with unsupported features Signed-off-by: Nicolas De Loof --- ecs/pkg/amazon/cloudformation.go | 5 +++ ecs/pkg/amazon/cloudformation_test.go | 44 +++++++++---------- .../amazon/testdata/invalid_network_mode.yaml | 5 +++ ecs/pkg/amazon/up.go | 5 --- ecs/pkg/amazon/validate.go | 8 +++- ecs/pkg/amazon/validate_test.go | 13 ++++++ 6 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 ecs/pkg/amazon/testdata/invalid_network_mode.yaml create mode 100644 ecs/pkg/amazon/validate_test.go diff --git a/ecs/pkg/amazon/cloudformation.go b/ecs/pkg/amazon/cloudformation.go index d14b5fafa..93ed2e095 100644 --- a/ecs/pkg/amazon/cloudformation.go +++ b/ecs/pkg/amazon/cloudformation.go @@ -26,6 +26,11 @@ const ( // Convert a compose project into a CloudFormation template func (c client) Convert(project *compose.Project) (*cloudformation.Template, error) { + err := Validate(project) + if err != nil { + return nil, err + } + template := cloudformation.NewTemplate() template.Parameters[ParameterClusterName] = cloudformation.Parameter{ diff --git a/ecs/pkg/amazon/cloudformation_test.go b/ecs/pkg/amazon/cloudformation_test.go index e45073385..456efbd01 100644 --- a/ecs/pkg/amazon/cloudformation_test.go +++ b/ecs/pkg/amazon/cloudformation_test.go @@ -4,46 +4,42 @@ import ( "fmt" "testing" + "gotest.tools/assert" + "github.com/docker/ecs-plugin/pkg/compose" "gotest.tools/v3/golden" ) func TestSimpleConvert(t *testing.T) { - options := compose.ProjectOptions{ - Name: t.Name(), - ConfigPaths: []string{"testdata/input/simple-single-service.yaml"}, - } - result := convertResultAsString(t, options, "TestCluster") + project := load(t, "testdata/input/simple-single-service.yaml") + result := convertResultAsString(t, project, "TestCluster") expected := "simple/simple-cloudformation-conversion.golden" golden.Assert(t, result, expected) } func TestSimpleWithOverrides(t *testing.T) { - options := compose.ProjectOptions{ - Name: t.Name(), - ConfigPaths: []string{"testdata/input/simple-single-service.yaml", "testdata/input/simple-single-service-with-overrides.yaml"}, - } - result := convertResultAsString(t, options, "TestCluster") + project := load(t, "testdata/input/simple-single-service.yaml", "testdata/input/simple-single-service-with-overrides.yaml") + result := convertResultAsString(t, project, "TestCluster") expected := "simple/simple-cloudformation-with-overrides-conversion.golden" golden.Assert(t, result, expected) } -func convertResultAsString(t *testing.T, options compose.ProjectOptions, clusterName string) string { - project, err := compose.ProjectFromOptions(&options) - if err != nil { - t.Error(err) - } +func convertResultAsString(t *testing.T, project *compose.Project, clusterName string) string { client, err := NewClient("", clusterName, "") - if err != nil { - t.Error(err) - } + assert.NilError(t, err) result, err := client.Convert(project) - if err != nil { - t.Error(err) - } + assert.NilError(t, err) resultAsJSON, err := result.JSON() - if err != nil { - t.Error(err) - } + assert.NilError(t, err) return fmt.Sprintf("%s\n", string(resultAsJSON)) } + +func load(t *testing.T, paths ...string) *compose.Project { + options := compose.ProjectOptions{ + Name: t.Name(), + ConfigPaths: paths, + } + project, err := compose.ProjectFromOptions(&options) + assert.NilError(t, err) + return project +} diff --git a/ecs/pkg/amazon/testdata/invalid_network_mode.yaml b/ecs/pkg/amazon/testdata/invalid_network_mode.yaml new file mode 100644 index 000000000..ce8ed8ad5 --- /dev/null +++ b/ecs/pkg/amazon/testdata/invalid_network_mode.yaml @@ -0,0 +1,5 @@ +version: "3" +services: + simple: + image: nginx + network_mode: bridge \ No newline at end of file diff --git a/ecs/pkg/amazon/up.go b/ecs/pkg/amazon/up.go index 2ad74ba8d..e3297249d 100644 --- a/ecs/pkg/amazon/up.go +++ b/ecs/pkg/amazon/up.go @@ -27,11 +27,6 @@ func (c *client) ComposeUp(ctx context.Context, project *compose.Project) error return fmt.Errorf("we do not (yet) support updating an existing CloudFormation stack") } - err = c.Validate(project) - if err != nil { - return err - } - template, err := c.Convert(project) if err != nil { return err diff --git a/ecs/pkg/amazon/validate.go b/ecs/pkg/amazon/validate.go index 551dc7bc7..4e7918fc0 100644 --- a/ecs/pkg/amazon/validate.go +++ b/ecs/pkg/amazon/validate.go @@ -1,12 +1,14 @@ package amazon import ( + "fmt" + "github.com/compose-spec/compose-go/types" "github.com/docker/ecs-plugin/pkg/compose" ) // Validate check the compose model do not use unsupported features and inject sane defaults for ECS deployment -func (c *client) Validate(project *compose.Project) error { +func Validate(project *compose.Project) error { if len(project.Networks) == 0 { // Compose application model implies a default network if none is explicitly set. // FIXME move this to compose-go @@ -22,6 +24,10 @@ func (c *client) Validate(project *compose.Project) error { service.Networks = map[string]*types.ServiceNetworkConfig{"default": nil} project.Services[i] = service } + + if service.NetworkMode != "" && service.NetworkMode != "awsvpc" { + return fmt.Errorf("ECS do not support NetworkMode %q", service.NetworkMode) + } } // Here we can check for incompatible attributes, inject sane defaults, etc diff --git a/ecs/pkg/amazon/validate_test.go b/ecs/pkg/amazon/validate_test.go new file mode 100644 index 000000000..e0cdd6507 --- /dev/null +++ b/ecs/pkg/amazon/validate_test.go @@ -0,0 +1,13 @@ +package amazon + +import ( + "testing" + + "gotest.tools/assert" +) + +func TestInvalidNetworkMode(t *testing.T) { + project := load(t, "testdata/invalid_network_mode.yaml") + err := Validate(project) + assert.Error(t, err, "ECS do not support NetworkMode \"bridge\"") +}