mirror of https://github.com/docker/compose.git
Adopt CloudFormation to create ECS app from compose.yaml
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
4e72d1892a
commit
b70f01d2f4
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli-plugins/plugin"
|
||||
"github.com/docker/cli/cli/command"
|
||||
|
@ -70,6 +71,7 @@ func ComposeCommand(clusteropts *clusterOptions) *cobra.Command {
|
|||
opts.AddFlags(cmd.Flags())
|
||||
|
||||
cmd.AddCommand(
|
||||
ConvertCommand(clusteropts, opts),
|
||||
UpCommand(clusteropts, opts),
|
||||
DownCommand(clusteropts, opts),
|
||||
)
|
||||
|
@ -87,6 +89,32 @@ func (o upOptions) LoadBalancerArn() *string {
|
|||
return &o.loadBalancerArn
|
||||
}
|
||||
|
||||
func ConvertCommand(clusteropts *clusterOptions, projectOpts *compose.ProjectOptions) *cobra.Command {
|
||||
opts := upOptions{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "convert",
|
||||
RunE: compose.WithProject(projectOpts, func(project *compose.Project, args []string) error {
|
||||
client, err := amazon.NewClient(clusteropts.profile, clusteropts.cluster, clusteropts.region)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
template, err := client.Convert(project, opts.LoadBalancerArn())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
j, err := template.JSON()
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to generate JSON: %s\n", err)
|
||||
} else {
|
||||
fmt.Printf("%s\n", string(j))
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func UpCommand(clusteropts *clusterOptions, projectOpts *compose.ProjectOptions) *cobra.Command {
|
||||
opts := upOptions{}
|
||||
cmd := &cobra.Command{
|
||||
|
@ -107,7 +135,6 @@ type downOptions struct {
|
|||
KeepLoadBalancer bool
|
||||
}
|
||||
|
||||
|
||||
func DownCommand(clusteropts *clusterOptions, projectOpts *compose.ProjectOptions) *cobra.Command {
|
||||
opts := downOptions{}
|
||||
cmd := &cobra.Command{
|
||||
|
@ -122,4 +149,4 @@ func DownCommand(clusteropts *clusterOptions, projectOpts *compose.ProjectOption
|
|||
}
|
||||
cmd.Flags().BoolVar(&opts.KeepLoadBalancer, "keep-load-balancer", false, "Keep Load Balancer for further use")
|
||||
return cmd
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ require (
|
|||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
|
||||
github.com/aws/aws-sdk-go v1.28.9
|
||||
github.com/awslabs/goformation/v4 v4.8.0
|
||||
github.com/bitly/go-hostpool v0.1.0 // indirect
|
||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||
|
|
26
ecs/go.sum
26
ecs/go.sum
|
@ -21,6 +21,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
|
|||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.28.9 h1:grIuBQc+p3dTRXerh5+2OxSuWFi0iXuxbFdTSg0jaW0=
|
||||
github.com/aws/aws-sdk-go v1.28.9/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/awslabs/goformation/v4 v4.8.0 h1:UiUhyokRy3suEqBXTnipvY8klqY3Eyl4GCH17brraEc=
|
||||
github.com/awslabs/goformation/v4 v4.8.0/go.mod h1:GcJULxCJfloT+3pbqCluXftdEK2AD/UqpS3hkaaBntg=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
@ -46,8 +48,6 @@ 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-20200131085702-0b38cc2d8e6b h1:VK0c2Hfrg9FHjvJpWfGwiHPP2UeU0QZ6/5/dN0ehbSQ=
|
||||
github.com/compose-spec/compose-go v0.0.0-20200131085702-0b38cc2d8e6b/go.mod h1:KoJjdV81vERSyYVuQD63nryyt8ZTlqTWe8JuJIMhRo4=
|
||||
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/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
|
@ -139,7 +139,9 @@ github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:
|
|||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
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/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=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
|
@ -180,7 +182,6 @@ github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
|||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-shellwords v1.0.9/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
|
||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
|
@ -205,8 +206,12 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
|
|||
github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||
github.com/onsi/ginkgo v1.5.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.2.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
|
@ -244,12 +249,14 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
|
|||
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b h1:jUK33OXuZP/l6babJtnLo1qsGvq6G9so9KMflGAm4YA=
|
||||
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b/go.mod h1:8458kAagoME2+LN5//WxE71ysZ3B7r22fdgb7qVmXSY=
|
||||
github.com/sanathkr/yaml v0.0.0-20170819201035-0056894fa522 h1:fOCp11H0yuyAt2wqlbJtbyPzSgaxHTv8uN1pMpkG1t8=
|
||||
github.com/sanathkr/yaml v0.0.0-20170819201035-0056894fa522/go.mod h1:tQTYKOQgxoH3v6dEmdHiz4JG+nbxWwM5fgPQUpSZqVQ=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
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.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
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/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
|
@ -285,9 +292,12 @@ github.com/weppos/publicsuffix-go v0.5.0 h1:rutRtjBJViU/YjcI5d80t4JAVvDltS6bciJg
|
|||
github.com/weppos/publicsuffix-go v0.5.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
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/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=
|
||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 h1:j2hhcujLRHAg872RWAV5yaUrEjHEObwDv3aImCaNLek=
|
||||
|
@ -327,6 +337,8 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 h1:KaQtG+aDELoNmXYas3TVkGNYR
|
|||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -385,10 +397,12 @@ gopkg.in/dancannon/gorethink.v3 v3.0.5 h1:/g7PWP7zUS6vSNmHSDbjCHQh1Rqn8Jy6zSMQxA
|
|||
gopkg.in/dancannon/gorethink.v3 v3.0.5/go.mod h1:GXsi1e3N2OcKhcP6nsYABTiUejbWMFO4GY5a4pEaeEc=
|
||||
gopkg.in/fatih/pool.v2 v2.0.0 h1:xIFeWtxifuQJGk/IEPKsTduEKcKvPmhoiVDGpC40nKg=
|
||||
gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/gorethink/gorethink.v3 v3.0.5 h1:e2Uc/Xe+hpcVQFsj6MuHlYog3r0JYpnTzwDj/y2O4MU=
|
||||
gopkg.in/gorethink/gorethink.v3 v3.0.5/go.mod h1:+3yIIHJUGMBK+wyPH+iN5TP+88ikFDfZdqTlK3Y9q8I=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
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=
|
||||
|
@ -396,8 +410,6 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
|||
gopkg.in/yaml.v2 v2.2.8/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.0 h1:d+tVGRu6X0ZBQ+kyAR8JKi6AXhTP2gmQaoIYaGFz634=
|
||||
gotest.tools/v3 v3.0.0/go.mod h1:TUP+/YtXl/dp++T+SZ5v2zUmLVBHmptSb/ajDLCJ+3c=
|
||||
gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
)
|
||||
|
||||
|
||||
const (
|
||||
ProjectTag = "com.docker.compose.project"
|
||||
)
|
||||
|
@ -35,27 +34,27 @@ func NewClient(profile string, cluster string, region string) (compose.API, erro
|
|||
}
|
||||
return &client{
|
||||
Cluster: cluster,
|
||||
Region: region,
|
||||
sess: sess,
|
||||
ECS: ecs.New(sess),
|
||||
EC2: ec2.New(sess),
|
||||
ELB: elbv2.New(sess),
|
||||
CW: cloudwatchlogs.New(sess),
|
||||
IAM: iam.New(sess),
|
||||
CF: cloudformation.New(sess),
|
||||
Region: region,
|
||||
sess: sess,
|
||||
ECS: ecs.New(sess),
|
||||
EC2: ec2.New(sess),
|
||||
ELB: elbv2.New(sess),
|
||||
CW: cloudwatchlogs.New(sess),
|
||||
IAM: iam.New(sess),
|
||||
CF: cloudformation.New(sess),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type client struct {
|
||||
Cluster string
|
||||
Region string
|
||||
sess *session.Session
|
||||
ECS ecsiface.ECSAPI
|
||||
EC2 ec2iface.EC2API
|
||||
ELB elbv2iface.ELBV2API
|
||||
CW cloudwatchlogsiface.CloudWatchLogsAPI
|
||||
IAM iamiface.IAMAPI
|
||||
CF cloudformationiface.CloudFormationAPI
|
||||
Region string
|
||||
sess *session.Session
|
||||
ECS ecsiface.ECSAPI
|
||||
EC2 ec2iface.EC2API
|
||||
ELB elbv2iface.ELBV2API
|
||||
CW cloudwatchlogsiface.CloudWatchLogsAPI
|
||||
IAM iamiface.IAMAPI
|
||||
CF cloudformationiface.CloudFormationAPI
|
||||
}
|
||||
|
||||
var _ compose.API = &client{}
|
||||
|
|
|
@ -1 +1,81 @@
|
|||
package amazon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
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"
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
"github.com/docker/ecs-plugin/pkg/convert"
|
||||
)
|
||||
|
||||
func (c client) Convert(project *compose.Project, loadBalancerArn *string) (*cloudformation.Template, error) {
|
||||
template := cloudformation.NewTemplate()
|
||||
|
||||
vpc, err := c.GetDefaultVPC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subnets, err := c.GetSubNets(vpc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ingresses = []ec2.SecurityGroup_Ingress{}
|
||||
for _, service := range project.Services {
|
||||
for _, port := range service.Ports {
|
||||
ingresses = append(ingresses, ec2.SecurityGroup_Ingress{
|
||||
CidrIp: "0.0.0.0/0",
|
||||
Description: fmt.Sprintf("%d/%s", port.Target, port.Protocol),
|
||||
FromPort: int(port.Target),
|
||||
IpProtocol: strings.ToUpper(port.Protocol),
|
||||
ToPort: int(port.Target),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
securityGroup := fmt.Sprintf("%s Security Group", project.Name)
|
||||
template.Resources["SecurityGroup"] = &ec2.SecurityGroup{
|
||||
GroupDescription: securityGroup,
|
||||
GroupName: securityGroup,
|
||||
SecurityGroupIngress: ingresses,
|
||||
VpcId: *vpc,
|
||||
}
|
||||
|
||||
for _, service := range project.Services {
|
||||
definition, err := convert.Convert(project, service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
role, err := c.GetEcsTaskExecutionRole(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
definition.TaskRoleArn = *role
|
||||
|
||||
taskDefinition := fmt.Sprintf("%sTaskDefinition", service.Name)
|
||||
template.Resources[taskDefinition] = definition
|
||||
|
||||
template.Resources[service.Name] = &ecs.Service{
|
||||
Cluster: c.Cluster,
|
||||
DesiredCount: 1,
|
||||
LaunchType: ecsapi.LaunchTypeFargate,
|
||||
NetworkConfiguration: &ecs.Service_NetworkConfiguration{
|
||||
AwsvpcConfiguration: &ecs.Service_AwsVpcConfiguration{
|
||||
AssignPublicIp: ecsapi.AssignPublicIpEnabled,
|
||||
SecurityGroups: []string{cloudformation.Ref("SecurityGroup")},
|
||||
Subnets: subnets,
|
||||
},
|
||||
},
|
||||
SchedulingStrategy: ecsapi.SchedulingStrategyReplica,
|
||||
ServiceName: service.Name,
|
||||
TaskDefinition: cloudformation.Ref(taskDefinition),
|
||||
}
|
||||
}
|
||||
return template, nil
|
||||
}
|
||||
|
|
|
@ -1,64 +1,18 @@
|
|||
package amazon
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/ecs"
|
||||
"github.com/aws/aws-sdk-go/service/cloudformation"
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (c *client) ComposeDown(project *compose.Project, keepLoadBalancer bool) error {
|
||||
err := c.DeleteLoadBalancer(project, keepLoadBalancer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
services := []*string{}
|
||||
// FIXME we should be able to retrieve services by tags, so we don't need the initial compose file to run "down"
|
||||
for _, service := range project.Services {
|
||||
logrus.Debugf("Deleting service %q\n", service.Name)
|
||||
out, err := c.ECS.DeleteService(&ecs.DeleteServiceInput{
|
||||
// Force to true so that we don't have to scale down to 0
|
||||
// before deleting
|
||||
Force: aws.Bool(true),
|
||||
Cluster: aws.String(c.Cluster),
|
||||
Service: aws.String(service.Name),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
services = append(services, out.Service.ServiceArn)
|
||||
}
|
||||
|
||||
logrus.Info("Stopping services...")
|
||||
err = c.ECS.WaitUntilServicesInactive(&ecs.DescribeServicesInput{
|
||||
Services: services,
|
||||
_, err := c.CF.DeleteStack(&cloudformation.DeleteStackInput{
|
||||
StackName: &project.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Info("All services stopped")
|
||||
|
||||
logrus.Debug("Deleting security groups")
|
||||
groups, err := c.EC2.DescribeSecurityGroups(&ec2.DescribeSecurityGroupsInput{
|
||||
Filters: []*ec2.Filter{
|
||||
{
|
||||
Name: aws.String("tag:" + ProjectTag),
|
||||
Values: aws.StringSlice([]string{project.Name}),
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, g := range groups.SecurityGroups {
|
||||
_, err = c.EC2.DeleteSecurityGroup(&ec2.DeleteSecurityGroupInput{
|
||||
GroupId: g.GroupId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// TODO monitor progress
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
||||
func (c client) RegisterTaskDefinition(task *ecs.RegisterTaskDefinitionInput) (*string, error) {
|
||||
logrus.Debug("Register Task Definition")
|
||||
def, err := c.ECS.RegisterTaskDefinition(task)
|
||||
|
|
|
@ -2,9 +2,10 @@ package amazon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/elbv2"
|
||||
|
@ -132,4 +133,4 @@ func (c client) DeleteListeners(loadBalancer *string) error {
|
|||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package amazon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
|
|
|
@ -2,12 +2,13 @@ package amazon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetDefaultVPC retrieve the default VPC for AWS account
|
||||
|
@ -30,9 +31,8 @@ func (c client) GetDefaultVPC() (*string, error) {
|
|||
return vpcs.Vpcs[0].VpcId, nil
|
||||
}
|
||||
|
||||
|
||||
// GetSubNets retrieve default subnets for a VPC
|
||||
func (c client) GetSubNets(vpc *string) ([]*string, error) {
|
||||
func (c client) GetSubNets(vpc *string) ([]string, error) {
|
||||
logrus.Debug("Retrieve SubNets")
|
||||
subnets, err := c.EC2.DescribeSubnets(&ec2.DescribeSubnetsInput{
|
||||
DryRun: nil,
|
||||
|
@ -51,9 +51,9 @@ func (c client) GetSubNets(vpc *string) ([]*string, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ids := []*string{}
|
||||
ids := []string{}
|
||||
for _, subnet := range subnets.Subnets {
|
||||
ids = append(ids, subnet.SubnetId)
|
||||
ids = append(ids, *subnet.SubnetId)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
@ -91,7 +91,6 @@ func (c client) CreateSecurityGroup(project *compose.Project, vpc *string) (*str
|
|||
return securityGroup.GroupId, nil
|
||||
}
|
||||
|
||||
|
||||
func (c *client) ExposePort(securityGroup *string, port types.ServicePortConfig) error {
|
||||
logrus.Debugf("Authorize ingress port %d/%s\n", port.Published, port.Protocol)
|
||||
_, err := c.EC2.AuthorizeSecurityGroupIngress(&ec2.AuthorizeSecurityGroupIngressInput{
|
||||
|
@ -110,4 +109,4 @@ func (c *client) ExposePort(securityGroup *string, port types.ServicePortConfig)
|
|||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package amazon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
|
@ -13,7 +14,7 @@ const ECSTaskExecutionPolicy = "arn:aws:iam::aws:policy/service-role/AmazonECSTa
|
|||
var defaultTaskExecutionRole *string
|
||||
|
||||
// GetEcsTaskExecutionRole retrieve the role ARN to apply for task execution
|
||||
func (c client) GetEcsTaskExecutionRole(spec *types.ServiceConfig) (*string, error) {
|
||||
func (c client) GetEcsTaskExecutionRole(spec types.ServiceConfig) (*string, error) {
|
||||
if arn, ok := spec.Extras["x-ecs-TaskExecutionRole"]; ok {
|
||||
s := arn.(string)
|
||||
return &s, nil
|
||||
|
|
|
@ -2,128 +2,54 @@ package amazon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ecs"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/aws/aws-sdk-go/service/cloudformation"
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
"github.com/docker/ecs-plugin/pkg/convert"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (c *client) ComposeUp(project *compose.Project, loadBalancerArn *string) error {
|
||||
type mapping struct {
|
||||
service *types.ServiceConfig
|
||||
task *ecs.RegisterTaskDefinitionInput
|
||||
}
|
||||
mappings := []mapping{}
|
||||
for _, service := range project.Services {
|
||||
task, err := convert.Convert(project, service)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mappings = append(mappings, mapping{
|
||||
service: &service,
|
||||
task: task,
|
||||
})
|
||||
}
|
||||
|
||||
vpc, err := c.GetDefaultVPC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
subnets, err := c.GetSubNets(vpc)
|
||||
template, err := c.Convert(project, loadBalancerArn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
securityGroup, err := c.CreateSecurityGroup(project, vpc)
|
||||
json, err := template.JSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if loadBalancerArn == nil {
|
||||
loadBalancerArn, err = c.CreateLoadBalancer(project, subnets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logGroup, err := c.GetOrCreateLogGroup(project)
|
||||
_, err = c.CF.ValidateTemplate(&cloudformation.ValidateTemplateInput{
|
||||
TemplateBody: aws.String(string(json)),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, mapping := range mappings {
|
||||
ingress := []*ecs.LoadBalancer{}
|
||||
for _, port := range mapping.service.Ports {
|
||||
name := fmt.Sprintf("%s-%s-%d-%s", project.Name, mapping.service.Name, port.Target, port.Protocol)
|
||||
targetgroup, err := c.CreateTargetGroup(name, vpc, port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ingress = append(ingress, &ecs.LoadBalancer{
|
||||
ContainerName: aws.String(mapping.service.Name),
|
||||
ContainerPort: aws.Int64(int64(port.Target)),
|
||||
TargetGroupArn: targetgroup,
|
||||
})
|
||||
_, err = c.CF.CreateStack(&cloudformation.CreateStackInput{
|
||||
OnFailure: aws.String("DELETE"),
|
||||
StackName: aws.String(project.Name),
|
||||
TemplateBody: aws.String(string(json)),
|
||||
TimeoutInMinutes: aws.Int64(10),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.CreateListener(port, loadBalancerArn, targetgroup)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = c.CreateService(project, mapping.service, mapping.task, securityGroup, subnets, logGroup, ingress)
|
||||
if err != nil {
|
||||
return err
|
||||
events, err := c.CF.DescribeStackEvents(&cloudformation.DescribeStackEventsInput{
|
||||
StackName: aws.String(project.Name),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, event := range events.StackEvents {
|
||||
fmt.Printf("%s %s\n", *event.LogicalResourceId, *event.ResourceStatus)
|
||||
if *event.ResourceStatus == "CREATE_FAILED" {
|
||||
fmt.Fprintln(os.Stderr, event.ResourceStatusReason)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO monitor progress
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *client) CreateService(project *compose.Project, service *types.ServiceConfig, task *ecs.RegisterTaskDefinitionInput, securityGroup *string, subnets []*string, logGroup *string, ingress []*ecs.LoadBalancer) (*string, error) {
|
||||
role, err := c.GetEcsTaskExecutionRole(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
task.ExecutionRoleArn = role
|
||||
|
||||
for _, def := range task.ContainerDefinitions {
|
||||
def.LogConfiguration.Options["awslogs-group"] = logGroup
|
||||
def.LogConfiguration.Options["awslogs-stream-prefix"] = aws.String(service.Name)
|
||||
def.LogConfiguration.Options["awslogs-region"] = aws.String(c.Region)
|
||||
}
|
||||
|
||||
arn, err := c.RegisterTaskDefinition(task)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logrus.Debug("Create Service")
|
||||
created, err := c.ECS.CreateService(&ecs.CreateServiceInput{
|
||||
Cluster: aws.String(c.Cluster),
|
||||
DesiredCount: aws.Int64(1), // FIXME get from deploy options
|
||||
LaunchType: aws.String(ecs.LaunchTypeFargate), //FIXME use service.Isolation tro select EC2 vs Fargate
|
||||
NetworkConfiguration: &ecs.NetworkConfiguration{
|
||||
AwsvpcConfiguration: &ecs.AwsVpcConfiguration{
|
||||
AssignPublicIp: aws.String(ecs.AssignPublicIpEnabled),
|
||||
SecurityGroups: []*string{securityGroup},
|
||||
Subnets: subnets,
|
||||
},
|
||||
},
|
||||
ServiceName: aws.String(service.Name),
|
||||
SchedulingStrategy: aws.String(ecs.SchedulingStrategyReplica),
|
||||
TaskDefinition: arn,
|
||||
LoadBalancers: ingress,
|
||||
})
|
||||
|
||||
for _, port := range service.Ports {
|
||||
err = c.ExposePort(securityGroup, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return created.Service.ServiceArn, err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package compose
|
||||
|
||||
import "github.com/awslabs/goformation/v4/cloudformation"
|
||||
|
||||
type API interface {
|
||||
Convert(project *Project, loadBalancerArn *string) (*cloudformation.Template, error)
|
||||
ComposeUp(project *Project, loadBalancerArn *string) error
|
||||
ComposeDown(project *Project, keepLoadBalancer bool) error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ func (o *ProjectOptions) AddFlags(flags *pflag.FlagSet) {
|
|||
flags.StringVarP(&o.name, "project-name", "n", "", "Specify an alternate project name (default: directory name)")
|
||||
}
|
||||
|
||||
|
||||
type ProjectFunc func(project *Project, args []string) error
|
||||
|
||||
// WithProject wrap a ProjectFunc into a cobra command
|
||||
|
|
|
@ -2,14 +2,15 @@ package compose
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/compose-spec/compose-go/loader"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/sirupsen/logrus"
|
||||
"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 {
|
||||
|
@ -32,7 +33,6 @@ func NewProject(config types.ConfigDetails, name string) (*Project, error) {
|
|||
return &p, nil
|
||||
}
|
||||
|
||||
|
||||
// projectFromOptions load a compose project based on command line options
|
||||
func projectFromOptions(options *ProjectOptions) (*Project, error) {
|
||||
configPath, err := getConfigPathFromOptions(options)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package compose
|
||||
|
||||
import (
|
||||
"gotest.tools/v3/assert"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func Test_project_name(t *testing.T) {
|
||||
|
|
|
@ -1,118 +1,87 @@
|
|||
package convert
|
||||
|
||||
import (
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ecs"
|
||||
ecsapi "github.com/aws/aws-sdk-go/service/ecs"
|
||||
"github.com/awslabs/goformation/v4/cloudformation/ecs"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/docker/ecs-plugin/pkg/compose"
|
||||
)
|
||||
|
||||
func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.RegisterTaskDefinitionInput, error) {
|
||||
func Convert(project *compose.Project, service types.ServiceConfig) (*ecs.TaskDefinition, error) {
|
||||
_, err := toCPULimits(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
foo := int64(256)
|
||||
logDriver := "awslogs" // FIXME could be set by service.Logging, especially to enable use of firelens
|
||||
return &ecs.RegisterTaskDefinitionInput{
|
||||
ContainerDefinitions: []*ecs.ContainerDefinition{
|
||||
return &ecs.TaskDefinition{
|
||||
ContainerDefinitions: []ecs.TaskDefinition_ContainerDefinition{
|
||||
// Here we can declare sidecars and init-containers using https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_dependson
|
||||
{
|
||||
Command: toStringPtrSlice(service.Command),
|
||||
Cpu: &foo,
|
||||
DependsOn: nil,
|
||||
DisableNetworking: toBoolPtr(service.NetworkMode == "none"),
|
||||
DnsSearchDomains: toStringPtrSlice(service.DNSSearch),
|
||||
DnsServers: toStringPtrSlice(service.DNS),
|
||||
DockerLabels: nil,
|
||||
DockerSecurityOptions: toStringPtrSlice(service.SecurityOpt),
|
||||
EntryPoint: toStringPtrSlice(service.Entrypoint),
|
||||
Environment: toKeyValuePairPtr(service.Environment),
|
||||
Essential: toBoolPtr(true),
|
||||
ExtraHosts: toHostEntryPtr(service.ExtraHosts),
|
||||
FirelensConfiguration: nil,
|
||||
HealthCheck: toHealthCheck(service.HealthCheck),
|
||||
Hostname: toStringPtr(service.Hostname),
|
||||
Image: toStringPtr(service.Image),
|
||||
Interactive: nil,
|
||||
Links: nil,
|
||||
LinuxParameters: toLinuxParameters(service),
|
||||
LogConfiguration: &ecs.LogConfiguration{
|
||||
LogDriver: &logDriver,
|
||||
Options: map[string]*string{},
|
||||
SecretOptions: nil,
|
||||
},
|
||||
Command: service.Command,
|
||||
Cpu: 256,
|
||||
DisableNetworking: service.NetworkMode == "none",
|
||||
DnsSearchDomains: service.DNSSearch,
|
||||
DnsServers: service.DNS,
|
||||
DockerLabels: nil,
|
||||
DockerSecurityOptions: service.SecurityOpt,
|
||||
EntryPoint: service.Entrypoint,
|
||||
Environment: toKeyValuePair(service.Environment),
|
||||
Essential: true,
|
||||
ExtraHosts: toHostEntryPtr(service.ExtraHosts),
|
||||
FirelensConfiguration: nil,
|
||||
HealthCheck: toHealthCheck(service.HealthCheck),
|
||||
Hostname: service.Hostname,
|
||||
Image: service.Image,
|
||||
Interactive: false,
|
||||
Links: nil,
|
||||
LinuxParameters: toLinuxParameters(service),
|
||||
Memory: toMemoryLimits(service.Deploy),
|
||||
MemoryReservation: toMemoryReservation(service.Deploy),
|
||||
MountPoints: nil,
|
||||
Name: toStringPtr(service.Name),
|
||||
Name: service.Name,
|
||||
PortMappings: toPortMappings(service.Ports),
|
||||
Privileged: toBoolPtr(service.Privileged),
|
||||
PseudoTerminal: toBoolPtr(service.Tty),
|
||||
ReadonlyRootFilesystem: toBoolPtr(service.ReadOnly),
|
||||
Privileged: service.Privileged,
|
||||
PseudoTerminal: service.Tty,
|
||||
ReadonlyRootFilesystem: service.ReadOnly,
|
||||
RepositoryCredentials: nil,
|
||||
ResourceRequirements: nil,
|
||||
Secrets: nil,
|
||||
StartTimeout: nil,
|
||||
StopTimeout: durationToInt64Ptr(service.StopGracePeriod),
|
||||
StartTimeout: 0,
|
||||
StopTimeout: durationToInt(service.StopGracePeriod),
|
||||
SystemControls: nil,
|
||||
Ulimits: toUlimits(service.Ulimits),
|
||||
User: toStringPtr(service.User),
|
||||
User: service.User,
|
||||
VolumesFrom: nil,
|
||||
WorkingDirectory: toStringPtr(service.WorkingDir),
|
||||
WorkingDirectory: service.WorkingDir,
|
||||
},
|
||||
},
|
||||
Cpu: toCPU(service),
|
||||
ExecutionRoleArn: nil,
|
||||
Family: toStringPtr(project.Name),
|
||||
IpcMode: toStringPtr(service.Ipc),
|
||||
Family: project.Name,
|
||||
IpcMode: service.Ipc,
|
||||
Memory: toMemory(service),
|
||||
NetworkMode: toStringPtr("awsvpc"), // FIXME could be set by service.NetworkMode, Fargate only supports network mode ‘awsvpc’.
|
||||
PidMode: toStringPtr(service.Pid),
|
||||
NetworkMode: ecsapi.NetworkModeAwsvpc, // FIXME could be set by service.NetworkMode, Fargate only supports network mode ‘awsvpc’.
|
||||
PidMode: service.Pid,
|
||||
PlacementConstraints: toPlacementConstraints(service.Deploy),
|
||||
ProxyConfiguration: nil,
|
||||
RequiresCompatibilities: toRequiresCompatibilities(ecs.LaunchTypeFargate),
|
||||
RequiresCompatibilities: []string{ecsapi.LaunchTypeFargate},
|
||||
Tags: nil,
|
||||
Volumes: []*ecs.Volume{
|
||||
{
|
||||
/* ONLY supported when using EC2 launch type
|
||||
DockerVolumeConfiguration: {
|
||||
Autoprovision: nil,
|
||||
Driver: nil,
|
||||
DriverOpts: nil,
|
||||
Labels: nil,
|
||||
Scope: nil,
|
||||
}, */
|
||||
/* Beta and ONLY supported when using EC2 launch type
|
||||
EfsVolumeConfiguration: {
|
||||
FileSystemId: nil,
|
||||
RootDirectory: nil,
|
||||
}, */
|
||||
/* Bind mount host volume
|
||||
Host: {
|
||||
SourcePath:
|
||||
}, */
|
||||
Name: aws.String("MyVolume"),
|
||||
},
|
||||
},
|
||||
Volumes: []ecs.TaskDefinition_Volume{},
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func toCPU(service types.ServiceConfig) *string {
|
||||
func toCPU(service types.ServiceConfig) string {
|
||||
// FIXME based on service's memory/cpu requirements, select the adequate Fargate CPU
|
||||
v := "256"
|
||||
return &v
|
||||
return "256"
|
||||
}
|
||||
|
||||
func toMemory(service types.ServiceConfig) *string {
|
||||
func toMemory(service types.ServiceConfig) string {
|
||||
// FIXME based on service's memory/cpu requirements, select the adequate Fargate CPU
|
||||
v := "512"
|
||||
return &v
|
||||
return "512"
|
||||
}
|
||||
|
||||
func toCPULimits(service types.ServiceConfig) (*int64, error) {
|
||||
|
@ -153,45 +122,45 @@ func hasMemoryOrMemoryReservation(service types.ServiceConfig) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func toPlacementConstraints(deploy *types.DeployConfig) []*ecs.TaskDefinitionPlacementConstraint {
|
||||
func toPlacementConstraints(deploy *types.DeployConfig) []ecs.TaskDefinition_TaskDefinitionPlacementConstraint {
|
||||
if deploy == nil || deploy.Placement.Constraints == nil || len(deploy.Placement.Constraints) == 0 {
|
||||
return nil
|
||||
}
|
||||
pl := []*ecs.TaskDefinitionPlacementConstraint{}
|
||||
pl := []ecs.TaskDefinition_TaskDefinitionPlacementConstraint{}
|
||||
for _, c := range deploy.Placement.Constraints {
|
||||
pl = append(pl, &ecs.TaskDefinitionPlacementConstraint{
|
||||
Expression: toStringPtr(c),
|
||||
Type: nil,
|
||||
pl = append(pl, ecs.TaskDefinition_TaskDefinitionPlacementConstraint{
|
||||
Expression: c,
|
||||
Type: "",
|
||||
})
|
||||
}
|
||||
return pl
|
||||
}
|
||||
|
||||
func toPortMappings(ports []types.ServicePortConfig) []*ecs.PortMapping {
|
||||
func toPortMappings(ports []types.ServicePortConfig) []ecs.TaskDefinition_PortMapping {
|
||||
if len(ports) == 0 {
|
||||
return nil
|
||||
}
|
||||
m := []*ecs.PortMapping{}
|
||||
m := []ecs.TaskDefinition_PortMapping{}
|
||||
for _, p := range ports {
|
||||
m = append(m, &ecs.PortMapping{
|
||||
ContainerPort: uint32Toint64Ptr(p.Target),
|
||||
HostPort: uint32Toint64Ptr(p.Published),
|
||||
Protocol: toStringPtr(p.Protocol),
|
||||
m = append(m, ecs.TaskDefinition_PortMapping{
|
||||
ContainerPort: int(p.Target),
|
||||
HostPort: int(p.Published),
|
||||
Protocol: p.Protocol,
|
||||
})
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func toUlimits(ulimits map[string]*types.UlimitsConfig) []*ecs.Ulimit {
|
||||
func toUlimits(ulimits map[string]*types.UlimitsConfig) []ecs.TaskDefinition_Ulimit {
|
||||
if len(ulimits) == 0 {
|
||||
return nil
|
||||
}
|
||||
u := []*ecs.Ulimit{}
|
||||
u := []ecs.TaskDefinition_Ulimit{}
|
||||
for k, v := range ulimits {
|
||||
u = append(u, &ecs.Ulimit{
|
||||
Name: toStringPtr(k),
|
||||
SoftLimit: intToInt64Ptr(v.Soft),
|
||||
HardLimit: intToInt64Ptr(v.Hard),
|
||||
u = append(u, ecs.TaskDefinition_Ulimit{
|
||||
Name: k,
|
||||
SoftLimit: v.Soft,
|
||||
HardLimit: v.Hard,
|
||||
})
|
||||
}
|
||||
return u
|
||||
|
@ -209,79 +178,82 @@ func intToInt64Ptr(i int) *int64 {
|
|||
|
||||
const Mb = 1024 * 1024
|
||||
|
||||
func toMemoryLimits(deploy *types.DeployConfig) *int64 {
|
||||
func toMemoryLimits(deploy *types.DeployConfig) int {
|
||||
if deploy == nil {
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
res := deploy.Resources.Limits
|
||||
if res == nil {
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
v := int64(res.MemoryBytes) / Mb
|
||||
return &v
|
||||
v := int(res.MemoryBytes) / Mb
|
||||
return v
|
||||
}
|
||||
|
||||
func toMemoryReservation(deploy *types.DeployConfig) *int64 {
|
||||
func toMemoryReservation(deploy *types.DeployConfig) int {
|
||||
if deploy == nil {
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
res := deploy.Resources.Reservations
|
||||
if res == nil {
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
v := int64(res.MemoryBytes) / Mb
|
||||
return &v
|
||||
v := int(res.MemoryBytes) / Mb
|
||||
return v
|
||||
}
|
||||
|
||||
func toLinuxParameters(service types.ServiceConfig) *ecs.LinuxParameters {
|
||||
return &ecs.LinuxParameters{
|
||||
func toLinuxParameters(service types.ServiceConfig) *ecs.TaskDefinition_LinuxParameters {
|
||||
return &ecs.TaskDefinition_LinuxParameters{
|
||||
Capabilities: toKernelCapabilities(service.CapAdd, service.CapDrop),
|
||||
Devices: nil,
|
||||
InitProcessEnabled: service.Init,
|
||||
MaxSwap: nil,
|
||||
InitProcessEnabled: service.Init != nil && *service.Init,
|
||||
MaxSwap: 0,
|
||||
// FIXME SharedMemorySize: service.ShmSize,
|
||||
Swappiness: nil,
|
||||
Swappiness: 0,
|
||||
Tmpfs: toTmpfs(service.Tmpfs),
|
||||
}
|
||||
}
|
||||
|
||||
func toTmpfs(tmpfs types.StringList) []*ecs.Tmpfs {
|
||||
func toTmpfs(tmpfs types.StringList) []ecs.TaskDefinition_Tmpfs {
|
||||
if tmpfs == nil || len(tmpfs) == 0 {
|
||||
return nil
|
||||
}
|
||||
o := []*ecs.Tmpfs{}
|
||||
for _, t := range tmpfs {
|
||||
path := t
|
||||
o = append(o, &ecs.Tmpfs{
|
||||
ContainerPath: &path,
|
||||
o := []ecs.TaskDefinition_Tmpfs{}
|
||||
for _, path := range tmpfs {
|
||||
o = append(o, ecs.TaskDefinition_Tmpfs{
|
||||
ContainerPath: path,
|
||||
MountOptions: nil,
|
||||
Size: nil,
|
||||
Size: 0,
|
||||
})
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func toKernelCapabilities(add []string, drop []string) *ecs.KernelCapabilities {
|
||||
func toKernelCapabilities(add []string, drop []string) *ecs.TaskDefinition_KernelCapabilities {
|
||||
if len(add) == 0 && len(drop) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &ecs.KernelCapabilities{
|
||||
Add: toStringPtrSlice(add),
|
||||
Drop: toStringPtrSlice(drop),
|
||||
return &ecs.TaskDefinition_KernelCapabilities{
|
||||
Add: add,
|
||||
Drop: drop,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func toHealthCheck(check *types.HealthCheckConfig) *ecs.HealthCheck {
|
||||
func toHealthCheck(check *types.HealthCheckConfig) *ecs.TaskDefinition_HealthCheck {
|
||||
if check == nil {
|
||||
return nil
|
||||
}
|
||||
return &ecs.HealthCheck{
|
||||
Command: toStringPtrSlice(check.Test),
|
||||
Interval: durationToInt64Ptr(check.Interval),
|
||||
Retries: uint64ToInt64Ptr(check.Retries),
|
||||
StartPeriod: durationToInt64Ptr(check.StartPeriod),
|
||||
Timeout: durationToInt64Ptr(check.Timeout),
|
||||
retries := 0
|
||||
if check.Retries != nil {
|
||||
retries = int(*check.Retries)
|
||||
}
|
||||
return &ecs.TaskDefinition_HealthCheck{
|
||||
Command: check.Test,
|
||||
Interval: durationToInt(check.Interval),
|
||||
Retries: retries,
|
||||
StartPeriod: durationToInt(check.StartPeriod),
|
||||
Timeout: durationToInt(check.Timeout),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,66 +265,44 @@ func uint64ToInt64Ptr(i *uint64) *int64 {
|
|||
return &v
|
||||
}
|
||||
|
||||
func durationToInt64Ptr(interval *types.Duration) *int64 {
|
||||
func durationToInt(interval *types.Duration) int {
|
||||
if interval == nil {
|
||||
return nil
|
||||
return 0
|
||||
}
|
||||
v := int64(time.Duration(*interval).Seconds())
|
||||
return &v
|
||||
v := int(time.Duration(*interval).Seconds())
|
||||
return v
|
||||
}
|
||||
|
||||
func toHostEntryPtr(hosts types.HostsList) []*ecs.HostEntry {
|
||||
func toHostEntryPtr(hosts types.HostsList) []ecs.TaskDefinition_HostEntry {
|
||||
if hosts == nil || len(hosts) == 0 {
|
||||
return nil
|
||||
}
|
||||
e := []*ecs.HostEntry{}
|
||||
e := []ecs.TaskDefinition_HostEntry{}
|
||||
for _, h := range hosts {
|
||||
host := h
|
||||
e = append(e, &ecs.HostEntry{
|
||||
Hostname: &host,
|
||||
parts := strings.SplitN(h, ":", 2) // FIXME this should be handled by compose-go
|
||||
e = append(e, ecs.TaskDefinition_HostEntry{
|
||||
Hostname: parts[0],
|
||||
IpAddress: parts[1],
|
||||
})
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func toKeyValuePairPtr(environment types.MappingWithEquals) []*ecs.KeyValuePair {
|
||||
func toKeyValuePair(environment types.MappingWithEquals) []ecs.TaskDefinition_KeyValuePair {
|
||||
if environment == nil || len(environment) == 0 {
|
||||
return nil
|
||||
}
|
||||
pairs := []*ecs.KeyValuePair{}
|
||||
pairs := []ecs.TaskDefinition_KeyValuePair{}
|
||||
for k, v := range environment {
|
||||
name := k
|
||||
value := v
|
||||
pairs = append(pairs, &ecs.KeyValuePair{
|
||||
Name: &name,
|
||||
var value string
|
||||
if v != nil {
|
||||
value = *v
|
||||
}
|
||||
pairs = append(pairs, ecs.TaskDefinition_KeyValuePair{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return pairs
|
||||
}
|
||||
|
||||
func toStringPtr(s string) *string {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
func toStringPtrSlice(s []string) []*string {
|
||||
if len(s) == 0 {
|
||||
return nil
|
||||
}
|
||||
v := []*string{}
|
||||
for _, x := range s {
|
||||
value := x
|
||||
v = append(v, &value)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func toBoolPtr(b bool) *bool {
|
||||
if !b {
|
||||
return nil
|
||||
}
|
||||
return &b
|
||||
}
|
Loading…
Reference in New Issue