소스 검색

Use `Project` from compose-go

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 5 년 전
부모
커밋
c5895fe09a

+ 12 - 11
ecs/cmd/commands/compose.go

@@ -7,9 +7,10 @@ import (
 	"os"
 	"strings"
 
+	"github.com/compose-spec/compose-go/cli"
+	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/cli/command"
 	amazon "github.com/docker/ecs-plugin/pkg/amazon/backend"
-	"github.com/docker/ecs-plugin/pkg/compose"
 	"github.com/docker/ecs-plugin/pkg/docker"
 	"github.com/spf13/cobra"
 )
@@ -18,8 +19,8 @@ func ComposeCommand(dockerCli command.Cli) *cobra.Command {
 	cmd := &cobra.Command{
 		Use: "compose",
 	}
-	opts := &compose.ProjectOptions{}
-	opts.AddFlags(cmd.Flags())
+	opts := &cli.ProjectOptions{}
+	AddFlags(opts, cmd.Flags())
 
 	cmd.AddCommand(
 		ConvertCommand(dockerCli, opts),
@@ -42,10 +43,10 @@ func (o upOptions) LoadBalancerArn() *string {
 	return &o.loadBalancerArn
 }
 
-func ConvertCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *cobra.Command {
+func ConvertCommand(dockerCli command.Cli, projectOpts *cli.ProjectOptions) *cobra.Command {
 	cmd := &cobra.Command{
 		Use: "convert",
-		RunE: compose.WithProject(projectOpts, func(project *compose.Project, args []string) error {
+		RunE: WithProject(projectOpts, func(project *types.Project, args []string) error {
 			clusteropts, err := docker.GetAwsContext(dockerCli)
 			if err != nil {
 				return err
@@ -71,7 +72,7 @@ func ConvertCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions)
 	return cmd
 }
 
-func UpCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *cobra.Command {
+func UpCommand(dockerCli command.Cli, projectOpts *cli.ProjectOptions) *cobra.Command {
 	opts := upOptions{}
 	cmd := &cobra.Command{
 		Use: "up",
@@ -87,11 +88,11 @@ func UpCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *cobr
 	return cmd
 }
 
-func PsCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *cobra.Command {
+func PsCommand(dockerCli command.Cli, projectOpts *cli.ProjectOptions) *cobra.Command {
 	opts := upOptions{}
 	cmd := &cobra.Command{
 		Use: "ps",
-		RunE: compose.WithProject(projectOpts, func(project *compose.Project, args []string) error {
+		RunE: WithProject(projectOpts, func(project *types.Project, args []string) error {
 			clusteropts, err := docker.GetAwsContext(dockerCli)
 			if err != nil {
 				return err
@@ -120,7 +121,7 @@ type downOptions struct {
 	DeleteCluster bool
 }
 
-func DownCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *cobra.Command {
+func DownCommand(dockerCli command.Cli, projectOpts *cli.ProjectOptions) *cobra.Command {
 	opts := downOptions{}
 	cmd := &cobra.Command{
 		Use: "down",
@@ -136,7 +137,7 @@ func DownCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *co
 	return cmd
 }
 
-func LogsCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *cobra.Command {
+func LogsCommand(dockerCli command.Cli, projectOpts *cli.ProjectOptions) *cobra.Command {
 	cmd := &cobra.Command{
 		Use: "logs [PROJECT NAME]",
 		RunE: docker.WithAwsContext(dockerCli, func(clusteropts docker.AwsContext, args []string) error {
@@ -147,7 +148,7 @@ func LogsCommand(dockerCli command.Cli, projectOpts *compose.ProjectOptions) *co
 			var name string
 
 			if len(args) == 0 {
-				project, err := compose.ProjectFromOptions(projectOpts)
+				project, err := cli.ProjectFromOptions(projectOpts)
 				if err != nil {
 					return err
 				}

+ 7 - 10
ecs/pkg/compose/opts.go → ecs/cmd/commands/opts.go

@@ -1,26 +1,23 @@
-package compose
+package commands
 
 import (
+	"github.com/compose-spec/compose-go/cli"
+	"github.com/compose-spec/compose-go/types"
 	"github.com/spf13/cobra"
 	"github.com/spf13/pflag"
 )
 
-type ProjectOptions struct {
-	ConfigPaths []string
-	Name        string
-}
-
-func (o *ProjectOptions) AddFlags(flags *pflag.FlagSet) {
+func AddFlags(o *cli.ProjectOptions, flags *pflag.FlagSet) {
 	flags.StringArrayVarP(&o.ConfigPaths, "file", "f", nil, "Specify an alternate compose file")
 	flags.StringVarP(&o.Name, "project-name", "n", "", "Specify an alternate project name (default: directory name)")
 }
 
-type ProjectFunc func(project *Project, args []string) error
+type ProjectFunc func(project *types.Project, args []string) error
 
 // WithProject wrap a ProjectFunc into a cobra command
-func WithProject(options *ProjectOptions, f ProjectFunc) func(cmd *cobra.Command, args []string) error {
+func WithProject(options *cli.ProjectOptions, f ProjectFunc) func(cmd *cobra.Command, args []string) error {
 	return func(cmd *cobra.Command, args []string) error {
-		project, err := ProjectFromOptions(options)
+		project, err := cli.ProjectFromOptions(options)
 		if err != nil {
 			return err
 		}

+ 3 - 3
ecs/cmd/commands/secret.go

@@ -11,7 +11,7 @@ import (
 
 	"github.com/docker/cli/cli/command"
 	amazon "github.com/docker/ecs-plugin/pkg/amazon/backend"
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/docker/ecs-plugin/pkg/compose"
 	"github.com/docker/ecs-plugin/pkg/docker"
 	"github.com/spf13/cobra"
 )
@@ -57,7 +57,7 @@ func CreateSecret(dockerCli command.Cli) *cobra.Command {
 			}
 			name := args[0]
 
-			secret := types.NewSecret(name, opts.Username, opts.Password, opts.Description)
+			secret := compose.NewSecret(name, opts.Username, opts.Password, opts.Description)
 			id, err := backend.CreateSecret(context.Background(), secret)
 			fmt.Println(id)
 			return err
@@ -140,7 +140,7 @@ func DeleteSecret(dockerCli command.Cli) *cobra.Command {
 	return cmd
 }
 
-func printList(out io.Writer, secrets []types.Secret) {
+func printList(out io.Writer, secrets []compose.Secret) {
 	printSection(out, len(secrets), func(w io.Writer) {
 		for _, secret := range secrets {
 			fmt.Fprintf(w, "%s\t%s\t%s\n", secret.ID, secret.Name, secret.Description)

+ 3 - 4
ecs/go.mod

@@ -14,7 +14,7 @@ require (
 	github.com/bugsnag/panicwrap v1.2.0 // indirect
 	github.com/cenkalti/backoff v2.2.1+incompatible // indirect
 	github.com/cloudflare/cfssl v1.4.1 // indirect
-	github.com/compose-spec/compose-go v0.0.0-20200409090215-53c0040c9127
+	github.com/compose-spec/compose-go v0.0.0-20200622094647-0bb9a6c7d89a
 	github.com/containerd/containerd v1.3.2 // indirect
 	github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb // indirect
 	github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
@@ -35,11 +35,11 @@ require (
 	github.com/manifoldco/promptui v0.7.0
 	github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
 	github.com/miekg/pkcs11 v1.0.3 // indirect
-	github.com/mitchellh/mapstructure v1.2.2
+	github.com/mitchellh/mapstructure v1.3.2
 	github.com/morikuni/aec v1.0.0 // indirect
 	github.com/onsi/ginkgo v1.11.0 // indirect
 	github.com/opencontainers/image-spec v1.0.1 // indirect
-	github.com/sirupsen/logrus v1.5.0
+	github.com/sirupsen/logrus v1.6.0
 	github.com/smartystreets/goconvey v1.6.4 // indirect
 	github.com/spf13/cobra v0.0.5
 	github.com/spf13/pflag v1.0.5
@@ -52,7 +52,6 @@ require (
 	gopkg.in/fatih/pool.v2 v2.0.0 // indirect
 	gopkg.in/gorethink/gorethink.v3 v3.0.5 // indirect
 	gopkg.in/ini.v1 v1.55.0
-	gotest.tools v2.2.0+incompatible
 	gotest.tools/v3 v3.0.2
 	vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787 // indirect
 )

+ 21 - 8
ecs/go.sum

@@ -54,8 +54,12 @@ github.com/cloudflare/cfssl v1.4.1 h1:vScfU2DrIUI9VPHBVeeAQ0q5A+9yshO1Gz+3QoUQiK
 github.com/cloudflare/cfssl v1.4.1/go.mod h1:KManx/OJPb5QY+y0+o/898AMcM128sF0bURvoVUSjTo=
 github.com/cloudflare/go-metrics v0.0.0-20151117154305-6a9aea36fb41/go.mod h1:eaZPlJWD+G9wseg1BuRXlHnjntPMrywMsyxf+LTOdP4=
 github.com/cloudflare/redoctober v0.0.0-20171127175943-746a508df14c/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo=
-github.com/compose-spec/compose-go v0.0.0-20200409090215-53c0040c9127 h1:mAsQN3s19glh3KBOQjiRYBhqaX1SdzNqhB3/cuqgSbE=
-github.com/compose-spec/compose-go v0.0.0-20200409090215-53c0040c9127/go.mod h1:1PUpzRF1O/65VOqXZuwpCuYY7pJxbIq1jbAvAf62FGM=
+github.com/compose-spec/compose-go v0.0.0-20200616184722-5b8dc203fd7f h1:XE6hHZdPjxN8uGaRlvdCB8YwXbz1PXnQ0CboNygdL2o=
+github.com/compose-spec/compose-go v0.0.0-20200616184722-5b8dc203fd7f/go.mod h1:d3Vb4tH01Pr4YKD3RvfwguRcezDBUYJTVYgpCSRYSVg=
+github.com/compose-spec/compose-go v0.0.0-20200617133919-fca3bb55c5cc h1:jZfF+HzxW+c8Em308MvcK7j5+ZqIAWqFjN1RZnVFzck=
+github.com/compose-spec/compose-go v0.0.0-20200617133919-fca3bb55c5cc/go.mod h1:d3Vb4tH01Pr4YKD3RvfwguRcezDBUYJTVYgpCSRYSVg=
+github.com/compose-spec/compose-go v0.0.0-20200622094647-0bb9a6c7d89a h1:FmEuebUePUA0Kd/NSiCmdPG/n6eKdZdBtIbfejVtRS8=
+github.com/compose-spec/compose-go v0.0.0-20200622094647-0bb9a6c7d89a/go.mod h1:ih9anT8po+49hrb+1j3ldIJ/YRAaBH52ErlQLTKE2Yo=
 github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
 github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
 github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
@@ -134,9 +138,12 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
 github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
 github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -151,6 +158,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
 github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
 github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
@@ -183,6 +191,8 @@ github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49/go.mod h1:yyMNCy
 github.com/kisom/goutils v1.1.0/go.mod h1:+UBTfd78habUYWFbNWTJNG+jNG/i/lGURakr4A/yNRw=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -218,8 +228,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc35r0TV4=
-github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
@@ -282,8 +292,8 @@ github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvH
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
-github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q=
-github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
+github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
@@ -330,6 +340,7 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
+github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56 h1:yhqBHs09SmmUoNOHc9jgK4a60T3XFRtPAkYxVnqgY50=
 github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
 github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
@@ -450,6 +461,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
 gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=

+ 44 - 21
ecs/pkg/amazon/backend/cloudformation.go

@@ -5,14 +5,9 @@ import (
 	"regexp"
 	"strings"
 
-	"github.com/compose-spec/compose-go/types"
-
-	"github.com/sirupsen/logrus"
-
+	ecsapi "github.com/aws/aws-sdk-go/service/ecs"
 	"github.com/aws/aws-sdk-go/service/elbv2"
 	cloudmapapi "github.com/aws/aws-sdk-go/service/servicediscovery"
-
-	ecsapi "github.com/aws/aws-sdk-go/service/ecs"
 	"github.com/awslabs/goformation/v4/cloudformation"
 	"github.com/awslabs/goformation/v4/cloudformation/ec2"
 	"github.com/awslabs/goformation/v4/cloudformation/ecs"
@@ -21,10 +16,11 @@ import (
 	"github.com/awslabs/goformation/v4/cloudformation/logs"
 	cloudmap "github.com/awslabs/goformation/v4/cloudformation/servicediscovery"
 	"github.com/awslabs/goformation/v4/cloudformation/tags"
-	"github.com/docker/ecs-plugin/pkg/amazon/compatibility"
+	"github.com/compose-spec/compose-go/compatibility"
+	"github.com/compose-spec/compose-go/types"
 	sdk "github.com/docker/ecs-plugin/pkg/amazon/sdk"
-	btypes "github.com/docker/ecs-plugin/pkg/amazon/types"
 	"github.com/docker/ecs-plugin/pkg/compose"
+	"github.com/sirupsen/logrus"
 )
 
 const (
@@ -35,11 +31,38 @@ const (
 	ParameterLoadBalancerARN = "ParameterLoadBalancerARN"
 )
 
+type FargateCompatibilityChecker struct {
+	*compatibility.AllowList
+}
+
 // Convert a compose project into a CloudFormation template
-func (b Backend) Convert(project *compose.Project) (*cloudformation.Template, error) {
-	warnings := compatibility.Check(project)
-	for _, w := range warnings {
-		logrus.Warn(w)
+func (b Backend) Convert(project *types.Project) (*cloudformation.Template, error) {
+	var checker compatibility.Checker = FargateCompatibilityChecker{
+		&compatibility.AllowList{
+			Supported: []string{
+				"services.command",
+				"services.container_name",
+				"services.depends_on",
+				"services.entrypoint",
+				"services.environment",
+				"services.healthcheck",
+				"services.healthcheck.interval",
+				"services.healthcheck.start_period",
+				"services.healthcheck.test",
+				"services.healthcheck.timeout",
+				"services.networks",
+				"services.ports",
+				"services.ports.mode",
+				"services.ports.target",
+				"services.ports.protocol",
+				"services.user",
+				"services.working_dir",
+			},
+		},
+	}
+	compatibility.Check(project, checker)
+	for _, err := range checker.Errors() {
+		logrus.Warn(err.Error())
 	}
 
 	template := cloudformation.NewTemplate()
@@ -188,7 +211,7 @@ func (b Backend) Convert(project *compose.Project) (*cloudformation.Template, er
 	return template, nil
 }
 
-func getLoadBalancerType(project *compose.Project) string {
+func getLoadBalancerType(project *types.Project) string {
 	for _, service := range project.Services {
 		for _, port := range service.Ports {
 			if port.Published != 80 && port.Published != 443 {
@@ -199,7 +222,7 @@ func getLoadBalancerType(project *compose.Project) string {
 	return elbv2.LoadBalancerTypeEnumApplication
 }
 
-func getLoadBalancerSecurityGroups(project *compose.Project, template *cloudformation.Template) []string {
+func getLoadBalancerSecurityGroups(project *types.Project, template *cloudformation.Template) []string {
 	securityGroups := []string{}
 	for _, network := range project.Networks {
 		if !network.Internal {
@@ -210,7 +233,7 @@ func getLoadBalancerSecurityGroups(project *compose.Project, template *cloudform
 	return uniqueStrings(securityGroups)
 }
 
-func createLoadBalancer(project *compose.Project, template *cloudformation.Template) string {
+func createLoadBalancer(project *types.Project, template *cloudformation.Template) string {
 	loadBalancerName := fmt.Sprintf("%sLoadBalancer", strings.Title(project.Name))
 	// Create LoadBalancer if `ParameterLoadBalancerName` is not set
 	template.Conditions["CreateLoadBalancer"] = cloudformation.Equals("", cloudformation.Ref(ParameterLoadBalancerARN))
@@ -270,7 +293,7 @@ func createListener(service types.ServiceConfig, port types.ServicePortConfig, t
 	return listenerName
 }
 
-func createTargetGroup(project *compose.Project, service types.ServiceConfig, port types.ServicePortConfig, template *cloudformation.Template, protocol string) string {
+func createTargetGroup(project *types.Project, service types.ServiceConfig, port types.ServicePortConfig, template *cloudformation.Template, protocol string) string {
 	targetGroupName := fmt.Sprintf(
 		"%s%s%dTargetGroup",
 		normalizeResourceName(service.Name),
@@ -345,7 +368,7 @@ func createTaskExecutionRole(service types.ServiceConfig, err error, definition
 	return taskExecutionRole, nil
 }
 
-func createCluster(project *compose.Project, template *cloudformation.Template) string {
+func createCluster(project *types.Project, template *cloudformation.Template) string {
 	template.Resources["Cluster"] = &ecs.Cluster{
 		ClusterName: project.Name,
 		Tags: []tags.Tag{
@@ -360,7 +383,7 @@ func createCluster(project *compose.Project, template *cloudformation.Template)
 	return cluster
 }
 
-func createCloudMap(project *compose.Project, template *cloudformation.Template) {
+func createCloudMap(project *types.Project, template *cloudformation.Template) {
 	template.Resources["CloudMap"] = &cloudmap.PrivateDnsNamespace{
 		Description: fmt.Sprintf("Service Map for Docker Compose project %s", project.Name),
 		Name:        fmt.Sprintf("%s.local", project.Name),
@@ -368,8 +391,8 @@ func createCloudMap(project *compose.Project, template *cloudformation.Template)
 	}
 }
 
-func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc string, template *cloudformation.Template) string {
-	if sg, ok := net.Extras[btypes.ExtensionSecurityGroup]; ok {
+func convertNetwork(project *types.Project, net types.NetworkConfig, vpc string, template *cloudformation.Template) string {
+	if sg, ok := net.Extensions[compose.ExtensionSecurityGroup]; ok {
 		logrus.Debugf("Security Group for network %q set by user to %q", net.Name, sg)
 		return sg.(string)
 	}
@@ -420,7 +443,7 @@ func convertNetwork(project *compose.Project, net types.NetworkConfig, vpc strin
 	return cloudformation.Ref(securityGroup)
 }
 
-func networkResourceName(project *compose.Project, network string) string {
+func networkResourceName(project *types.Project, network string) string {
 	return fmt.Sprintf("%s%sNetwork", normalizeResourceName(project.Name), normalizeResourceName(network))
 }
 

+ 13 - 14
ecs/pkg/amazon/backend/cloudformation_test.go

@@ -7,13 +7,11 @@ import (
 	"github.com/aws/aws-sdk-go/service/elbv2"
 	"github.com/awslabs/goformation/v4/cloudformation"
 	"github.com/awslabs/goformation/v4/cloudformation/ec2"
-	"github.com/awslabs/goformation/v4/cloudformation/iam"
-
 	"github.com/awslabs/goformation/v4/cloudformation/elasticloadbalancingv2"
+	"github.com/awslabs/goformation/v4/cloudformation/iam"
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/compose-spec/compose-go/loader"
 	"github.com/compose-spec/compose-go/types"
-	"github.com/docker/ecs-plugin/pkg/compose"
-
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/golden"
 )
@@ -58,6 +56,10 @@ version: "3"
 services:
   test:
     image: hello_world
+    networks:
+      - front-tier 
+      - back-tier 
+
 networks:
   front-tier:
     name: public
@@ -103,7 +105,7 @@ services:
 	assert.Check(t, lb.Type == elbv2.LoadBalancerTypeEnumNetwork)
 }
 
-func convertResultAsString(t *testing.T, project *compose.Project, clusterName string) string {
+func convertResultAsString(t *testing.T, project *types.Project, clusterName string) string {
 	client, err := NewBackend("", clusterName, "")
 	assert.NilError(t, err)
 	result, err := client.Convert(project)
@@ -113,12 +115,12 @@ func convertResultAsString(t *testing.T, project *compose.Project, clusterName s
 	return fmt.Sprintf("%s\n", string(resultAsJSON))
 }
 
-func load(t *testing.T, paths ...string) *compose.Project {
-	options := compose.ProjectOptions{
+func load(t *testing.T, paths ...string) *types.Project {
+	options := cli.ProjectOptions{
 		Name:        t.Name(),
 		ConfigPaths: paths,
 	}
-	project, err := compose.ProjectFromOptions(&options)
+	project, err := cli.ProjectFromOptions(&options)
 	assert.NilError(t, err)
 	return project
 }
@@ -130,14 +132,11 @@ func convertYaml(t *testing.T, yaml string) *cloudformation.Template {
 		ConfigFiles: []types.ConfigFile{
 			{Config: dict},
 		},
+	}, func(options *loader.Options) {
+		options.Name = "Test"
 	})
 	assert.NilError(t, err)
-	err = compose.Normalize(model)
-	assert.NilError(t, err)
-	template, err := Backend{}.Convert(&compose.Project{
-		Config: *model,
-		Name:   "test",
-	})
+	template, err := Backend{}.Convert(model)
 	assert.NilError(t, err)
 	return template
 }

+ 4 - 4
ecs/pkg/amazon/backend/down.go

@@ -3,14 +3,14 @@ package backend
 import (
 	"context"
 
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/docker/ecs-plugin/pkg/compose"
 )
 
-func (b *Backend) Down(ctx context.Context, options compose.ProjectOptions) error {
+func (b *Backend) Down(ctx context.Context, options cli.ProjectOptions) error {
 	name := options.Name
 	if name == "" {
-		project, err := compose.ProjectFromOptions(&options)
+		project, err := cli.ProjectFromOptions(&options)
 		if err != nil {
 			return err
 		}
@@ -22,7 +22,7 @@ func (b *Backend) Down(ctx context.Context, options compose.ProjectOptions) erro
 		return err
 	}
 
-	err = b.WaitStackCompletion(ctx, name, types.StackDelete)
+	err = b.WaitStackCompletion(ctx, name, compose.StackDelete)
 	if err != nil {
 		return err
 	}

+ 3 - 3
ecs/pkg/amazon/backend/down_test.go

@@ -4,8 +4,8 @@ import (
 	"context"
 	"testing"
 
+	"github.com/compose-spec/compose-go/cli"
 	"github.com/docker/ecs-plugin/pkg/amazon/sdk"
-	btypes "github.com/docker/ecs-plugin/pkg/amazon/types"
 	"github.com/docker/ecs-plugin/pkg/compose"
 	"github.com/golang/mock/gomock"
 )
@@ -23,10 +23,10 @@ func TestDown(t *testing.T) {
 	recorder := m.EXPECT()
 	recorder.DeleteStack(ctx, "test_project").Return(nil)
 	recorder.GetStackID(ctx, "test_project").Return("stack-123", nil)
-	recorder.WaitStackComplete(ctx, "stack-123", btypes.StackDelete).Return(nil)
+	recorder.WaitStackComplete(ctx, "stack-123", compose.StackDelete).Return(nil)
 	recorder.DescribeStackEvents(ctx, "stack-123").Return(nil, nil)
 
-	c.Down(ctx, compose.ProjectOptions{
+	c.Down(ctx, cli.ProjectOptions{
 		ConfigPaths: []string{},
 		Name:        "test_project",
 	})

+ 10 - 10
ecs/pkg/amazon/backend/list.go

@@ -6,11 +6,11 @@ import (
 	"sort"
 	"strings"
 
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/ecs-plugin/pkg/compose"
 )
 
-func (b *Backend) Ps(ctx context.Context, project *compose.Project) ([]types.TaskStatus, error) {
+func (b *Backend) Ps(ctx context.Context, project *types.Project) ([]compose.TaskStatus, error) {
 	cluster := b.Cluster
 	if cluster == "" {
 		cluster = project.Name
@@ -19,17 +19,17 @@ func (b *Backend) Ps(ctx context.Context, project *compose.Project) ([]types.Tas
 	for _, service := range project.Services {
 		tasks, err := b.api.ListTasks(ctx, cluster, service.Name)
 		if err != nil {
-			return []types.TaskStatus{}, err
+			return []compose.TaskStatus{}, err
 		}
 		arns = append(arns, tasks...)
 	}
 	if len(arns) == 0 {
-		return []types.TaskStatus{}, nil
+		return []compose.TaskStatus{}, nil
 	}
 
 	tasks, err := b.api.DescribeTasks(ctx, cluster, arns...)
 	if err != nil {
-		return []types.TaskStatus{}, err
+		return []compose.TaskStatus{}, err
 	}
 
 	networkInterfaces := []string{}
@@ -40,21 +40,21 @@ func (b *Backend) Ps(ctx context.Context, project *compose.Project) ([]types.Tas
 	}
 	publicIps, err := b.api.GetPublicIPs(ctx, networkInterfaces...)
 	if err != nil {
-		return []types.TaskStatus{}, err
+		return []compose.TaskStatus{}, err
 	}
 
 	sort.Slice(tasks, func(i, j int) bool {
 		return strings.Compare(tasks[i].Service, tasks[j].Service) < 0
 	})
 
-	for i, t := range tasks {
+	for i, task := range tasks {
 		ports := []string{}
-		s, err := project.GetService(t.Service)
+		s, err := project.GetService(task.Service)
 		if err != nil {
-			return []types.TaskStatus{}, err
+			return []compose.TaskStatus{}, err
 		}
 		for _, p := range s.Ports {
-			ports = append(ports, fmt.Sprintf("%s:%d->%d/%s", publicIps[t.NetworkInterface], p.Published, p.Target, p.Protocol))
+			ports = append(ports, fmt.Sprintf("%s:%d->%d/%s", publicIps[task.NetworkInterface], p.Published, p.Target, p.Protocol))
 		}
 		tasks[i].Name = s.Name
 		tasks[i].Ports = ports

+ 4 - 4
ecs/pkg/amazon/backend/secrets.go

@@ -3,18 +3,18 @@ package backend
 import (
 	"context"
 
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/docker/ecs-plugin/pkg/compose"
 )
 
-func (b Backend) CreateSecret(ctx context.Context, secret types.Secret) (string, error) {
+func (b Backend) CreateSecret(ctx context.Context, secret compose.Secret) (string, error) {
 	return b.api.CreateSecret(ctx, secret)
 }
 
-func (b Backend) InspectSecret(ctx context.Context, id string) (types.Secret, error) {
+func (b Backend) InspectSecret(ctx context.Context, id string) (compose.Secret, error) {
 	return b.api.InspectSecret(ctx, id)
 }
 
-func (b Backend) ListSecrets(ctx context.Context) ([]types.Secret, error) {
+func (b Backend) ListSecrets(ctx context.Context) ([]compose.Secret, error) {
 	return b.api.ListSecrets(ctx)
 }
 

+ 9 - 8
ecs/pkg/amazon/backend/up.go

@@ -4,12 +4,13 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/compose-spec/compose-go/cli"
+	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/ecs-plugin/pkg/compose"
 )
 
-func (b *Backend) Up(ctx context.Context, options compose.ProjectOptions) error {
-	project, err := compose.ProjectFromOptions(&options)
+func (b *Backend) Up(ctx context.Context, options cli.ProjectOptions) error {
+	project, err := cli.ProjectFromOptions(&options)
 	if err != nil {
 		return err
 	}
@@ -66,12 +67,12 @@ func (b *Backend) Up(ctx context.Context, options compose.ProjectOptions) error
 	}
 
 	fmt.Println()
-	return b.WaitStackCompletion(ctx, project.Name, types.StackCreate)
+	return b.WaitStackCompletion(ctx, project.Name, compose.StackCreate)
 }
 
-func (b Backend) GetVPC(ctx context.Context, project *compose.Project) (string, error) {
+func (b Backend) GetVPC(ctx context.Context, project *types.Project) (string, error) {
 	//check compose file for custom VPC selected
-	if vpc, ok := project.Extras[types.ExtensionVPC]; ok {
+	if vpc, ok := project.Extensions[compose.ExtensionVPC]; ok {
 		vpcID := vpc.(string)
 		ok, err := b.api.VpcExists(ctx, vpcID)
 		if err != nil {
@@ -88,9 +89,9 @@ func (b Backend) GetVPC(ctx context.Context, project *compose.Project) (string,
 	return defaultVPC, nil
 }
 
-func (b Backend) GetLoadBalancer(ctx context.Context, project *compose.Project) (string, error) {
+func (b Backend) GetLoadBalancer(ctx context.Context, project *types.Project) (string, error) {
 	//check compose file for custom VPC selected
-	if lb, ok := project.Extras[types.ExtensionLB]; ok {
+	if lb, ok := project.Extensions[compose.ExtensionLB]; ok {
 		lbName := lb.(string)
 		ok, err := b.api.LoadBalancerExists(ctx, lbName)
 		if err != nil {

+ 0 - 41
ecs/pkg/amazon/compatibility/check.go

@@ -1,41 +0,0 @@
-package compatibility
-
-import (
-	"github.com/compose-spec/compose-go/types"
-	"github.com/docker/ecs-plugin/pkg/compose"
-)
-
-type Warning string
-type Warnings []string
-
-type Checker interface {
-	CheckService(service *types.ServiceConfig)
-	CheckCapAdd(service *types.ServiceConfig)
-	CheckDNS(service *types.ServiceConfig)
-	CheckDNSOpts(service *types.ServiceConfig)
-	CheckDNSSearch(service *types.ServiceConfig)
-	CheckDomainName(service *types.ServiceConfig)
-	CheckExtraHosts(service *types.ServiceConfig)
-	CheckHostname(service *types.ServiceConfig)
-	CheckIpc(service *types.ServiceConfig)
-	CheckLabels(service *types.ServiceConfig)
-	CheckLinks(service *types.ServiceConfig)
-	CheckLogging(service *types.ServiceConfig)
-	CheckMacAddress(service *types.ServiceConfig)
-	CheckNetworkMode(service *types.ServiceConfig)
-	CheckPid(service *types.ServiceConfig)
-	CheckSysctls(service *types.ServiceConfig)
-	CheckTmpfs(service *types.ServiceConfig)
-	CheckUserNSMode(service *types.ServiceConfig)
-	Errors() []error
-}
-
-// Check the compose model do not use unsupported features and inject sane defaults for ECS deployment
-func Check(project *compose.Project) []error {
-	c := FargateCompatibilityChecker{}
-	for i, service := range project.Services {
-		c.CheckService(&service)
-		project.Services[i] = service
-	}
-	return c.errors
-}

+ 0 - 23
ecs/pkg/amazon/compatibility/check_test.go

@@ -1,23 +0,0 @@
-package compatibility
-
-import (
-	"testing"
-
-	"github.com/docker/ecs-plugin/pkg/compose"
-	"gotest.tools/v3/assert"
-)
-
-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
-}
-func TestInvalidNetworkMode(t *testing.T) {
-	project := load(t, "../backend/testdata/invalid_network_mode.yaml")
-	err := Check(project)
-	assert.Error(t, err[0], "'network_mode' \"bridge\" is not supported")
-}

+ 0 - 171
ecs/pkg/amazon/compatibility/compatibility.go

@@ -1,171 +0,0 @@
-package compatibility
-
-import (
-	"fmt"
-
-	"github.com/aws/aws-sdk-go/service/ecs"
-	"github.com/compose-spec/compose-go/types"
-)
-
-type FargateCompatibilityChecker struct {
-	errors []error
-}
-
-func (c *FargateCompatibilityChecker) error(message string, args ...interface{}) {
-	c.errors = append(c.errors, fmt.Errorf(message, args...))
-}
-
-func (c *FargateCompatibilityChecker) Errors() []error {
-	return c.errors
-}
-
-func (c *FargateCompatibilityChecker) CheckService(service *types.ServiceConfig) {
-	c.CheckCapAdd(service)
-	c.CheckDNS(service)
-	c.CheckDNSOpts(service)
-	c.CheckDNSSearch(service)
-	c.CheckDomainName(service)
-	c.CheckExtraHosts(service)
-	c.CheckHostname(service)
-	c.CheckIpc(service)
-	c.CheckLabels(service)
-	c.CheckLinks(service)
-	c.CheckLogging(service)
-	c.CheckMacAddress(service)
-	c.CheckNetworkMode(service)
-	c.CheckPid(service)
-	c.CheckSysctls(service)
-	c.CheckTmpfs(service)
-	c.CheckUserNSMode(service)
-}
-
-func (c *FargateCompatibilityChecker) CheckNetworkMode(service *types.ServiceConfig) {
-	if service.NetworkMode != "" && service.NetworkMode != ecs.NetworkModeAwsvpc {
-		c.error("'network_mode' %q is not supported", service.NetworkMode)
-	}
-	service.NetworkMode = ecs.NetworkModeAwsvpc
-}
-
-func (c *FargateCompatibilityChecker) CheckLinks(service *types.ServiceConfig) {
-	if len(service.Links) != 0 {
-		c.error("'links' is not supported")
-		service.Links = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckLogging(service *types.ServiceConfig) {
-	c.CheckLoggingDriver(service)
-}
-
-func (c *FargateCompatibilityChecker) CheckLoggingDriver(service *types.ServiceConfig) {
-	if service.LogDriver != "" && service.LogDriver != ecs.LogDriverAwslogs {
-		c.error("'log_driver' %q is not supported", service.LogDriver)
-		service.LogDriver = ecs.LogDriverAwslogs
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckPid(service *types.ServiceConfig) {
-	if service.Pid != "" {
-		c.error("'pid' is not supported")
-		service.Pid = ""
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckUserNSMode(service *types.ServiceConfig) {
-	if service.UserNSMode != "" {
-		c.error("'userns_mode' is not supported")
-		service.UserNSMode = ""
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckIpc(service *types.ServiceConfig) {
-	if service.Ipc != "" {
-		c.error("'ipc' is not supported")
-		service.Ipc = ""
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckMacAddress(service *types.ServiceConfig) {
-	if service.MacAddress != "" {
-		c.error("'mac_address' is not supported")
-		service.MacAddress = ""
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckHostname(service *types.ServiceConfig) {
-	if service.Hostname != "" {
-		c.error("'hostname' is not supported")
-		service.Hostname = ""
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckDomainName(service *types.ServiceConfig) {
-	if service.DomainName != "" {
-		c.error("'domainname' is not supported")
-		service.DomainName = ""
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckDNSSearch(service *types.ServiceConfig) {
-	if len(service.DNSSearch) > 0 {
-		c.error("'dns_search' is not supported")
-		service.DNSSearch = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckDNS(service *types.ServiceConfig) {
-	if len(service.DNS) > 0 {
-		c.error("'dns' is not supported")
-		service.DNS = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckDNSOpts(service *types.ServiceConfig) {
-	if len(service.DNSOpts) > 0 {
-		c.error("'dns_opt' is not supported")
-		service.DNSOpts = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckExtraHosts(service *types.ServiceConfig) {
-	if len(service.ExtraHosts) > 0 {
-		c.error("'extra_hosts' is not supported")
-		service.ExtraHosts = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckCapAdd(service *types.ServiceConfig) {
-	for i, v := range service.CapAdd {
-		if v != "SYS_PTRACE" {
-			c.error("'cap_add' %s is not supported", v)
-			l := len(service.CapAdd)
-			service.CapAdd[i] = service.CapAdd[l-1]
-			service.CapAdd = service.CapAdd[:l-1]
-		}
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckTmpfs(service *types.ServiceConfig) {
-	if len(service.Tmpfs) > 0 {
-		c.error("'tmpfs' is not supported")
-		service.Tmpfs = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckSysctls(service *types.ServiceConfig) {
-	if len(service.Sysctls) > 0 {
-		c.error("'sysctls' is not supported")
-		service.Sysctls = nil
-	}
-}
-
-func (c *FargateCompatibilityChecker) CheckLabels(service *types.ServiceConfig) {
-	for k, v := range service.Labels {
-		if v == "" {
-			c.error("'labels' with an empty value is not supported")
-			delete(service.Labels, k)
-		}
-	}
-}
-
-var _ Checker = &FargateCompatibilityChecker{}

+ 6 - 6
ecs/pkg/amazon/sdk/api.go

@@ -5,7 +5,7 @@ import (
 
 	cf "github.com/aws/aws-sdk-go/service/cloudformation"
 	"github.com/awslabs/goformation/v4/cloudformation"
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/docker/ecs-plugin/pkg/compose"
 )
 
 //go:generate mockgen -destination=./api_mock.go -self_package "github.com/docker/ecs-plugin/pkg/amazon" -package=amazon . API
@@ -38,19 +38,19 @@ type downAPI interface {
 }
 
 type logsAPI interface {
-	GetLogs(ctx context.Context, name string, consumer types.LogConsumer) error
+	GetLogs(ctx context.Context, name string, consumer compose.LogConsumer) error
 }
 
 type secretsAPI interface {
-	CreateSecret(ctx context.Context, secret types.Secret) (string, error)
-	InspectSecret(ctx context.Context, id string) (types.Secret, error)
-	ListSecrets(ctx context.Context) ([]types.Secret, error)
+	CreateSecret(ctx context.Context, secret compose.Secret) (string, error)
+	InspectSecret(ctx context.Context, id string) (compose.Secret, error)
+	ListSecrets(ctx context.Context) ([]compose.Secret, error)
 	DeleteSecret(ctx context.Context, id string, recover bool) error
 }
 
 type listAPI interface {
 	ListTasks(ctx context.Context, cluster string, name string) ([]string, error)
-	DescribeTasks(ctx context.Context, cluster string, arns ...string) ([]types.TaskStatus, error)
+	DescribeTasks(ctx context.Context, cluster string, arns ...string) ([]compose.TaskStatus, error)
 	GetPublicIPs(ctx context.Context, interfaces ...string) (map[string]string, error)
 }
 

+ 10 - 9
ecs/pkg/amazon/sdk/api_mock.go

@@ -8,9 +8,10 @@ import (
 	context "context"
 	reflect "reflect"
 
+	"github.com/docker/ecs-plugin/pkg/compose"
+
 	cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
 	cloudformation0 "github.com/awslabs/goformation/v4/cloudformation"
-	btypes "github.com/docker/ecs-plugin/pkg/amazon/types"
 	gomock "github.com/golang/mock/gomock"
 )
 
@@ -53,7 +54,7 @@ func (mr *MockAPIMockRecorder) ClusterExists(arg0, arg1 interface{}) *gomock.Cal
 }
 
 // CreateSecret mocks base method
-func (m *MockAPI) CreateSecret(arg0 context.Context, arg1 btypes.Secret) (string, error) {
+func (m *MockAPI) CreateSecret(arg0 context.Context, arg1 compose.Secret) (string, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateSecret", arg0, arg1)
 	ret0, _ := ret[0].(string)
@@ -139,14 +140,14 @@ func (mr *MockAPIMockRecorder) DescribeStackEvents(arg0, arg1 interface{}) *gomo
 }
 
 // DescribeTasks mocks base method
-func (m *MockAPI) DescribeTasks(arg0 context.Context, arg1 string, arg2 ...string) ([]btypes.TaskStatus, error) {
+func (m *MockAPI) DescribeTasks(arg0 context.Context, arg1 string, arg2 ...string) ([]compose.TaskStatus, error) {
 	m.ctrl.T.Helper()
 	varargs := []interface{}{arg0, arg1}
 	for _, a := range arg2 {
 		varargs = append(varargs, a)
 	}
 	ret := m.ctrl.Call(m, "DescribeTasks", varargs...)
-	ret0, _ := ret[0].([]btypes.TaskStatus)
+	ret0, _ := ret[0].([]compose.TaskStatus)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -174,7 +175,7 @@ func (mr *MockAPIMockRecorder) GetDefaultVPC(arg0 interface{}) *gomock.Call {
 }
 
 // GetLogs mocks base method
-func (m *MockAPI) GetLogs(arg0 context.Context, arg1 string, arg2 btypes.LogConsumer) error {
+func (m *MockAPI) GetLogs(arg0 context.Context, arg1 string, arg2 compose.LogConsumer) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetLogs", arg0, arg1, arg2)
 	ret0, _ := ret[0].(error)
@@ -238,10 +239,10 @@ func (mr *MockAPIMockRecorder) GetSubNets(arg0, arg1 interface{}) *gomock.Call {
 }
 
 // InspectSecret mocks base method
-func (m *MockAPI) InspectSecret(arg0 context.Context, arg1 string) (btypes.Secret, error) {
+func (m *MockAPI) InspectSecret(arg0 context.Context, arg1 string) (compose.Secret, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "InspectSecret", arg0, arg1)
-	ret0, _ := ret[0].(btypes.Secret)
+	ret0, _ := ret[0].(compose.Secret)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -253,10 +254,10 @@ func (mr *MockAPIMockRecorder) InspectSecret(arg0, arg1 interface{}) *gomock.Cal
 }
 
 // ListSecrets mocks base method
-func (m *MockAPI) ListSecrets(arg0 context.Context) ([]btypes.Secret, error) {
+func (m *MockAPI) ListSecrets(arg0 context.Context) ([]compose.Secret, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ListSecrets", arg0)
-	ret0, _ := ret[0].([]btypes.Secret)
+	ret0, _ := ret[0].([]compose.Secret)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }

+ 3 - 4
ecs/pkg/amazon/sdk/convert.go

@@ -13,11 +13,10 @@ import (
 	"github.com/awslabs/goformation/v4/cloudformation/tags"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/opts"
-	t "github.com/docker/ecs-plugin/pkg/amazon/types"
 	"github.com/docker/ecs-plugin/pkg/compose"
 )
 
-func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.TaskDefinition, error) {
+func Convert(project *types.Project, service types.ServiceConfig) (*ecs.TaskDefinition, error) {
 	cpu, mem, err := toLimits(service)
 	if err != nil {
 		return nil, err
@@ -318,8 +317,8 @@ func getImage(image string) string {
 
 func getRepoCredentials(service types.ServiceConfig) *ecs.TaskDefinition_RepositoryCredentials {
 	// extract registry and namespace string from image name
-	for key, value := range service.Extras {
-		if key == t.ExtensionPullCredentials {
+	for key, value := range service.Extensions {
+		if key == compose.ExtensionPullCredentials {
 			return &ecs.TaskDefinition_RepositoryCredentials{CredentialsParameter: value.(string)}
 		}
 	}

+ 15 - 17
ecs/pkg/amazon/sdk/sdk.go

@@ -23,10 +23,8 @@ import (
 	"github.com/aws/aws-sdk-go/service/secretsmanager"
 	"github.com/aws/aws-sdk-go/service/secretsmanager/secretsmanageriface"
 	cf "github.com/awslabs/goformation/v4/cloudformation"
+	"github.com/docker/ecs-plugin/pkg/compose"
 	"github.com/sirupsen/logrus"
-
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
-	t "github.com/docker/ecs-plugin/pkg/amazon/types"
 )
 
 type sdk struct {
@@ -189,9 +187,9 @@ func (s sdk) WaitStackComplete(ctx context.Context, name string, operation int)
 		StackName: aws.String(name),
 	}
 	switch operation {
-	case t.StackCreate:
+	case compose.StackCreate:
 		return s.CF.WaitUntilStackCreateCompleteWithContext(ctx, input)
-	case t.StackDelete:
+	case compose.StackDelete:
 		return s.CF.WaitUntilStackDeleteCompleteWithContext(ctx, input)
 	default:
 		return fmt.Errorf("internal error: unexpected stack operation %d", operation)
@@ -236,7 +234,7 @@ func (s sdk) DeleteStack(ctx context.Context, name string) error {
 	return err
 }
 
-func (s sdk) CreateSecret(ctx context.Context, secret t.Secret) (string, error) {
+func (s sdk) CreateSecret(ctx context.Context, secret compose.Secret) (string, error) {
 	logrus.Debug("Create secret " + secret.Name)
 	secretStr, err := secret.GetCredString()
 	if err != nil {
@@ -254,17 +252,17 @@ func (s sdk) CreateSecret(ctx context.Context, secret t.Secret) (string, error)
 	return *response.ARN, nil
 }
 
-func (s sdk) InspectSecret(ctx context.Context, id string) (t.Secret, error) {
+func (s sdk) InspectSecret(ctx context.Context, id string) (compose.Secret, error) {
 	logrus.Debug("Inspect secret " + id)
 	response, err := s.SM.DescribeSecret(&secretsmanager.DescribeSecretInput{SecretId: &id})
 	if err != nil {
-		return t.Secret{}, err
+		return compose.Secret{}, err
 	}
 	labels := map[string]string{}
 	for _, tag := range response.Tags {
 		labels[*tag.Key] = *tag.Value
 	}
-	secret := t.Secret{
+	secret := compose.Secret{
 		ID:     *response.ARN,
 		Name:   *response.Name,
 		Labels: labels,
@@ -275,14 +273,14 @@ func (s sdk) InspectSecret(ctx context.Context, id string) (t.Secret, error) {
 	return secret, nil
 }
 
-func (s sdk) ListSecrets(ctx context.Context) ([]t.Secret, error) {
+func (s sdk) ListSecrets(ctx context.Context) ([]compose.Secret, error) {
 
 	logrus.Debug("List secrets ...")
 	response, err := s.SM.ListSecrets(&secretsmanager.ListSecretsInput{})
 	if err != nil {
-		return []t.Secret{}, err
+		return []compose.Secret{}, err
 	}
-	var secrets []t.Secret
+	var secrets []compose.Secret
 
 	for _, sec := range response.SecretList {
 
@@ -294,7 +292,7 @@ func (s sdk) ListSecrets(ctx context.Context) ([]t.Secret, error) {
 		if sec.Description != nil {
 			description = *sec.Description
 		}
-		secrets = append(secrets, t.Secret{
+		secrets = append(secrets, compose.Secret{
 			ID:          *sec.ARN,
 			Name:        *sec.Name,
 			Labels:      labels,
@@ -311,7 +309,7 @@ func (s sdk) DeleteSecret(ctx context.Context, id string, recover bool) error {
 	return err
 }
 
-func (s sdk) GetLogs(ctx context.Context, name string, consumer types.LogConsumer) error {
+func (s sdk) GetLogs(ctx context.Context, name string, consumer compose.LogConsumer) error {
 	logGroup := fmt.Sprintf("/docker-compose/%s", name)
 	var startTime int64
 	for {
@@ -357,7 +355,7 @@ func (s sdk) ListTasks(ctx context.Context, cluster string, service string) ([]s
 	return arns, nil
 }
 
-func (s sdk) DescribeTasks(ctx context.Context, cluster string, arns ...string) ([]t.TaskStatus, error) {
+func (s sdk) DescribeTasks(ctx context.Context, cluster string, arns ...string) ([]compose.TaskStatus, error) {
 	tasks, err := s.ECS.DescribeTasksWithContext(ctx, &ecs.DescribeTasksInput{
 		Cluster: aws.String(cluster),
 		Tasks:   aws.StringSlice(arns),
@@ -365,7 +363,7 @@ func (s sdk) DescribeTasks(ctx context.Context, cluster string, arns ...string)
 	if err != nil {
 		return nil, err
 	}
-	result := []t.TaskStatus{}
+	result := []compose.TaskStatus{}
 	for _, task := range tasks.Tasks {
 		var networkInterface string
 		for _, attachement := range task.Attachments {
@@ -377,7 +375,7 @@ func (s sdk) DescribeTasks(ctx context.Context, cluster string, arns ...string)
 				}
 			}
 		}
-		result = append(result, t.TaskStatus{
+		result = append(result, compose.TaskStatus{
 			State:            *task.LastStatus,
 			Service:          strings.Replace(*task.Group, "service:", "", 1),
 			NetworkInterface: networkInterface,

+ 9 - 8
ecs/pkg/compose/api.go

@@ -4,19 +4,20 @@ import (
 	"context"
 
 	"github.com/awslabs/goformation/v4/cloudformation"
-	"github.com/docker/ecs-plugin/pkg/amazon/types"
+	"github.com/compose-spec/compose-go/cli"
+	"github.com/compose-spec/compose-go/types"
 )
 
 type API interface {
-	Up(ctx context.Context, options ProjectOptions) error
-	Down(ctx context.Context, options ProjectOptions) error
+	Up(ctx context.Context, options cli.ProjectOptions) error
+	Down(ctx context.Context, options cli.ProjectOptions) error
 
-	Convert(project *Project) (*cloudformation.Template, error)
+	Convert(project *types.Project) (*cloudformation.Template, error)
 	Logs(ctx context.Context, projectName string) error
-	Ps(background context.Context, project *Project) ([]types.TaskStatus, error)
+	Ps(background context.Context, project *types.Project) ([]TaskStatus, error)
 
-	CreateSecret(ctx context.Context, secret types.Secret) (string, error)
-	InspectSecret(ctx context.Context, id string) (types.Secret, error)
-	ListSecrets(ctx context.Context) ([]types.Secret, error)
+	CreateSecret(ctx context.Context, secret Secret) (string, error)
+	InspectSecret(ctx context.Context, id string) (Secret, error)
+	ListSecrets(ctx context.Context) ([]Secret, error)
 	DeleteSecret(ctx context.Context, id string, recover bool) error
 }

+ 0 - 89
ecs/pkg/compose/normalize.go

@@ -1,89 +0,0 @@
-package compose
-
-import (
-	"fmt"
-
-	"github.com/compose-spec/compose-go/types"
-	"github.com/sirupsen/logrus"
-)
-
-// Normalize a compose-go model to move deprecated attributes to canonical position, and introduce implicit defaults
-// FIXME move this to compose-go
-func Normalize(model *types.Config) error {
-	if len(model.Networks) == 0 {
-		// Compose application model implies a default network if none is explicitly set.
-		model.Networks["default"] = types.NetworkConfig{
-			Name: "default",
-		}
-	}
-
-	for i, s := range model.Services {
-		if len(s.Networks) == 0 {
-			// Service without explicit network attachment are implicitly exposed on default network
-			s.Networks = map[string]*types.ServiceNetworkConfig{"default": nil}
-		}
-
-		for i, p := range s.Ports {
-			if p.Published == 0 {
-				p.Published = p.Target
-				s.Ports[i] = p
-			}
-		}
-
-		if s.LogDriver != "" {
-			logrus.Warn("`log_driver` is deprecated. Use the `logging` attribute")
-			if s.Logging == nil {
-				s.Logging = &types.LoggingConfig{}
-			}
-			if s.Logging.Driver == "" {
-				s.Logging.Driver = s.LogDriver
-			} else {
-				return fmt.Errorf("can't use both 'log_driver' (deprecated) and 'logging.driver'")
-			}
-		}
-		if len(s.LogOpt) != 0 {
-			logrus.Warn("`log_opts` is deprecated. Use the `logging` attribute")
-			if s.Logging == nil {
-				s.Logging = &types.LoggingConfig{}
-			}
-			for k, v := range s.LogOpt {
-				if _, ok := s.Logging.Options[k]; !ok {
-					s.Logging.Options[k] = v
-				} else {
-					return fmt.Errorf("can't use both 'log_opt' (deprecated) and 'logging.options'")
-				}
-			}
-		}
-		model.Services[i] = s
-	}
-
-	for i, n := range model.Networks {
-		if n.Name == "" {
-			n.Name = i
-			model.Networks[i] = n
-		}
-	}
-
-	for i, v := range model.Volumes {
-		if v.Name == "" {
-			v.Name = i
-			model.Volumes[i] = v
-		}
-	}
-
-	for i, c := range model.Configs {
-		if c.Name == "" {
-			c.Name = i
-			model.Configs[i] = c
-		}
-	}
-
-	for i, s := range model.Secrets {
-		if s.Name == "" {
-			s.Name = i
-			model.Secrets[i] = s
-		}
-	}
-
-	return nil
-}

+ 0 - 170
ecs/pkg/compose/project.go

@@ -1,170 +0,0 @@
-package compose
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strings"
-
-	"github.com/compose-spec/compose-go/loader"
-	"github.com/compose-spec/compose-go/types"
-	"github.com/sirupsen/logrus"
-)
-
-type Project struct {
-	types.Config
-	projectDir string
-	Name       string `yaml:"-" json:"-"`
-}
-
-func NewProject(config types.ConfigDetails, name string) (*Project, error) {
-	model, err := loader.Load(config)
-	if err != nil {
-		return nil, err
-	}
-
-	err = Normalize(model)
-	if err != nil {
-		return nil, err
-	}
-
-	p := Project{
-		Config:     *model,
-		projectDir: config.WorkingDir,
-		Name:       name,
-	}
-	return &p, nil
-}
-
-// projectFromOptions load a compose project based on command line options
-func ProjectFromOptions(options *ProjectOptions) (*Project, error) {
-	configPath, err := getConfigPathFromOptions(options)
-	if err != nil {
-		return nil, err
-	}
-
-	name := options.Name
-	if name == "" {
-		name = os.Getenv("COMPOSE_PROJECT_NAME")
-	}
-
-	workingDir := filepath.Dir(configPath[0])
-
-	if name == "" {
-		r := regexp.MustCompile(`[^a-z0-9\\-_]+`)
-		name = r.ReplaceAllString(strings.ToLower(filepath.Base(workingDir)), "")
-	}
-
-	configs, err := parseConfigs(configPath)
-	if err != nil {
-		return nil, err
-	}
-
-	return NewProject(types.ConfigDetails{
-		WorkingDir:  workingDir,
-		ConfigFiles: configs,
-		Environment: environment(),
-	}, name)
-}
-
-func getConfigPathFromOptions(options *ProjectOptions) ([]string, error) {
-	paths := []string{}
-	pwd, err := os.Getwd()
-	if err != nil {
-		return nil, err
-	}
-
-	if len(options.ConfigPaths) != 0 {
-		for _, f := range options.ConfigPaths {
-			if f == "-" {
-				paths = append(paths, f)
-				continue
-			}
-			if !filepath.IsAbs(f) {
-				f = filepath.Join(pwd, f)
-			}
-			if _, err := os.Stat(f); err != nil {
-				return nil, err
-			}
-			paths = append(paths, f)
-		}
-		return paths, nil
-	}
-
-	sep := os.Getenv("COMPOSE_FILE_SEPARATOR")
-	if sep == "" {
-		sep = string(os.PathListSeparator)
-	}
-	f := os.Getenv("COMPOSE_FILE")
-	if f != "" {
-		return strings.Split(f, sep), nil
-	}
-
-	for {
-		candidates := []string{}
-		for _, n := range SupportedFilenames {
-			f := filepath.Join(pwd, n)
-			if _, err := os.Stat(f); err == nil {
-				candidates = append(candidates, f)
-			}
-		}
-		if len(candidates) > 0 {
-			winner := candidates[0]
-			if len(candidates) > 1 {
-				logrus.Warnf("Found multiple config files with supported names: %s", strings.Join(candidates, ", "))
-				logrus.Warnf("Using %s\n", winner)
-			}
-			return []string{winner}, nil
-		}
-		parent := filepath.Dir(pwd)
-		if parent == pwd {
-			return nil, fmt.Errorf("Can't find a suitable configuration file in this directory or any parent. Are you in the right directory?")
-		}
-		pwd = parent
-	}
-}
-
-var SupportedFilenames = []string{"compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml"}
-
-func parseConfigs(configPaths []string) ([]types.ConfigFile, error) {
-	files := []types.ConfigFile{}
-	for _, f := range configPaths {
-		var (
-			b   []byte
-			err error
-		)
-		if f == "-" {
-			b, err = ioutil.ReadAll(os.Stdin)
-		} else {
-			if _, err := os.Stat(f); err != nil {
-				return nil, err
-			}
-			b, err = ioutil.ReadFile(f)
-		}
-		if err != nil {
-			return nil, err
-		}
-		config, err := loader.ParseYAML(b)
-		if err != nil {
-			return nil, err
-		}
-		files = append(files, types.ConfigFile{Filename: f, Config: config})
-	}
-	return files, nil
-}
-
-func environment() map[string]string {
-	return getAsEqualsMap(os.Environ())
-}
-
-// getAsEqualsMap split key=value formatted strings into a key : value map
-func getAsEqualsMap(em []string) map[string]string {
-	m := make(map[string]string)
-	for _, v := range em {
-		kv := strings.SplitN(v, "=", 2)
-		m[kv[0]] = kv[1]
-	}
-	return m
-}

+ 0 - 46
ecs/pkg/compose/project_test.go

@@ -1,46 +0,0 @@
-package compose
-
-import (
-	"os"
-	"testing"
-
-	"gotest.tools/v3/assert"
-)
-
-func Test_project_name(t *testing.T) {
-	p, err := ProjectFromOptions(&ProjectOptions{
-		Name:        "my_project",
-		ConfigPaths: []string{"testdata/simple/compose.yaml"},
-	})
-	assert.NilError(t, err)
-	assert.Equal(t, p.Name, "my_project")
-
-	p, err = ProjectFromOptions(&ProjectOptions{
-		Name:        "",
-		ConfigPaths: []string{"testdata/simple/compose.yaml"},
-	})
-	assert.NilError(t, err)
-	assert.Equal(t, p.Name, "simple")
-
-	os.Setenv("COMPOSE_PROJECT_NAME", "my_project_from_env")
-	p, err = ProjectFromOptions(&ProjectOptions{
-		Name:        "",
-		ConfigPaths: []string{"testdata/simple/compose.yaml"},
-	})
-	assert.NilError(t, err)
-	assert.Equal(t, p.Name, "my_project_from_env")
-}
-
-func Test_project_from_set_of_files(t *testing.T) {
-	p, err := ProjectFromOptions(&ProjectOptions{
-		Name: "my_project",
-		ConfigPaths: []string{
-			"testdata/simple/compose.yaml",
-			"testdata/simple/compose-with-overrides.yaml",
-		},
-	})
-	assert.NilError(t, err)
-	service, err := p.GetService("simple")
-	assert.NilError(t, err)
-	assert.Equal(t, service.Image, "haproxy")
-}

+ 1 - 1
ecs/pkg/amazon/types/types.go → ecs/pkg/compose/types.go

@@ -1,4 +1,4 @@
-package types
+package compose
 
 import "encoding/json"
 

+ 1 - 1
ecs/pkg/amazon/types/x.go → ecs/pkg/compose/x.go

@@ -1,4 +1,4 @@
-package types
+package compose
 
 const (
 	ExtensionSecurityGroup   = "x-aws-securitygroup"