mirror of https://github.com/docker/compose.git
Use docker/api progress writer
Signed-off-by: aiordache <anca.iordache@docker.com> Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
83d65c02a0
commit
de99add26b
|
@ -12,6 +12,7 @@ import (
|
||||||
amazon "github.com/docker/ecs-plugin/pkg/amazon/backend"
|
amazon "github.com/docker/ecs-plugin/pkg/amazon/backend"
|
||||||
"github.com/docker/ecs-plugin/pkg/amazon/cloudformation"
|
"github.com/docker/ecs-plugin/pkg/amazon/cloudformation"
|
||||||
"github.com/docker/ecs-plugin/pkg/docker"
|
"github.com/docker/ecs-plugin/pkg/docker"
|
||||||
|
"github.com/docker/ecs-plugin/pkg/progress"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,7 +80,11 @@ func UpCommand(dockerCli command.Cli, options *composeOptions) *cobra.Command {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return backend.Up(context.Background(), opts)
|
|
||||||
|
return progress.Run(context.Background(), func(ctx context.Context) error {
|
||||||
|
backend.SetWriter(ctx)
|
||||||
|
return backend.Up(ctx, opts)
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
cmd.Flags().StringVar(&opts.loadBalancerArn, "load-balancer", "", "")
|
cmd.Flags().StringVar(&opts.loadBalancerArn, "load-balancer", "", "")
|
||||||
|
@ -124,7 +129,10 @@ func DownCommand(dockerCli command.Cli, options *composeOptions) *cobra.Command
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return backend.Down(context.Background(), opts)
|
return progress.Run(context.Background(), func(ctx context.Context) error {
|
||||||
|
backend.SetWriter(ctx)
|
||||||
|
return backend.Down(ctx, opts)
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
cmd.Flags().BoolVar(&opts.DeleteCluster, "delete-cluster", false, "Delete cluster")
|
cmd.Flags().BoolVar(&opts.DeleteCluster, "delete-cluster", false, "Delete cluster")
|
||||||
|
@ -139,7 +147,7 @@ func LogsCommand(dockerCli command.Cli, options *composeOptions) *cobra.Command
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return backend.Logs(context.Background(), opts)
|
return backend.Logs(context.Background(), opts, os.Stdout)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module github.com/docker/ecs-plugin
|
module github.com/docker/ecs-plugin
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
|
||||||
github.com/Microsoft/hcsshim v0.8.7 // indirect
|
github.com/Microsoft/hcsshim v0.8.7 // indirect
|
||||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect
|
||||||
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
|
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
|
||||||
|
@ -10,11 +9,13 @@ require (
|
||||||
github.com/bitly/go-hostpool v0.1.0 // indirect
|
github.com/bitly/go-hostpool v0.1.0 // indirect
|
||||||
github.com/bitly/go-simplejson v0.5.0 // indirect
|
github.com/bitly/go-simplejson v0.5.0 // indirect
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||||
|
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129
|
||||||
github.com/bugsnag/bugsnag-go v1.5.3 // indirect
|
github.com/bugsnag/bugsnag-go v1.5.3 // indirect
|
||||||
github.com/bugsnag/panicwrap v1.2.0 // indirect
|
github.com/bugsnag/panicwrap v1.2.0 // indirect
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||||
github.com/cloudflare/cfssl v1.4.1 // indirect
|
github.com/cloudflare/cfssl v1.4.1 // indirect
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200811091145-837f8f4de457
|
github.com/compose-spec/compose-go v0.0.0-20200811091145-837f8f4de457
|
||||||
|
github.com/containerd/console v1.0.0
|
||||||
github.com/containerd/containerd v1.3.2 // indirect
|
github.com/containerd/containerd v1.3.2 // indirect
|
||||||
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb // indirect
|
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb // indirect
|
||||||
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
|
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492
|
||||||
|
@ -36,16 +37,17 @@ require (
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||||
github.com/miekg/pkcs11 v1.0.3 // indirect
|
github.com/miekg/pkcs11 v1.0.3 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.3.3
|
github.com/mitchellh/mapstructure v1.3.3
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/moby/term v0.0.0-20200611042045-63b9a826fb74
|
||||||
|
github.com/morikuni/aec v1.0.0
|
||||||
github.com/onsi/ginkgo v1.11.0 // indirect
|
github.com/onsi/ginkgo v1.11.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/sirupsen/logrus v1.6.0
|
github.com/sirupsen/logrus v1.6.0
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/spf13/cobra v0.0.5
|
github.com/spf13/cobra v0.0.5
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/theupdateframework/notary v0.6.1 // indirect
|
github.com/theupdateframework/notary v0.6.1 // indirect
|
||||||
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // indirect
|
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||||
google.golang.org/grpc v1.27.0 // indirect
|
google.golang.org/grpc v1.27.0 // indirect
|
||||||
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
|
||||||
|
|
24
ecs/go.sum
24
ecs/go.sum
|
@ -34,6 +34,8 @@ github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngE
|
||||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
|
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129 h1:gfAMKE626QEuKG3si0pdTRcr/YEbBoxY+3GOH3gWvl4=
|
||||||
|
github.com/buger/goterm v0.0.0-20200322175922-2f3e71b85129/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U=
|
||||||
github.com/bugsnag/bugsnag-go v1.5.3 h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04=
|
github.com/bugsnag/bugsnag-go v1.5.3 h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04=
|
||||||
github.com/bugsnag/bugsnag-go v1.5.3/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
github.com/bugsnag/bugsnag-go v1.5.3/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||||
github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA=
|
github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA=
|
||||||
|
@ -54,12 +56,13 @@ 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/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/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/cloudflare/redoctober v0.0.0-20171127175943-746a508df14c/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo=
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200716130117-e87e4f7839e3 h1:+ntlMTrEcScJjlnEOP8P1IIrusJaR93Eazr66YgUueA=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200716130117-e87e4f7839e3/go.mod h1:ArodJ6gsEB7iWKrbV3fSHZ08LlBvSVB0Oqg04fX86t4=
|
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200811091145-837f8f4de457 h1:8ely1LF7H02sIWz6QjgU53YBCiRpYlM9F9u1MeE1ZPk=
|
github.com/compose-spec/compose-go v0.0.0-20200811091145-837f8f4de457 h1:8ely1LF7H02sIWz6QjgU53YBCiRpYlM9F9u1MeE1ZPk=
|
||||||
github.com/compose-spec/compose-go v0.0.0-20200811091145-837f8f4de457/go.mod h1:cS0vAvM6u9yjJgKWIH2yiqYMWO7WGJb+c0Irw+RefqU=
|
github.com/compose-spec/compose-go v0.0.0-20200811091145-837f8f4de457/go.mod h1:cS0vAvM6u9yjJgKWIH2yiqYMWO7WGJb+c0Irw+RefqU=
|
||||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||||
|
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 h1:uict5mhHFTzKLUCufdSLym7z/J0CbBJT59lYbP9wtbg=
|
||||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||||
|
github.com/containerd/console v1.0.0 h1:fU3UuQapBs+zLJu82NhR11Rif1ny2zfMMAyPJzSN5tQ=
|
||||||
|
github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
||||||
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/containerd v1.3.2 h1:ForxmXkA6tPIvffbrDAcPUIB32QgXkt2XFj+F0UxetA=
|
github.com/containerd/containerd v1.3.2 h1:ForxmXkA6tPIvffbrDAcPUIB32QgXkt2XFj+F0UxetA=
|
||||||
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
|
@ -76,6 +79,8 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
|
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
@ -137,8 +142,7 @@ github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
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 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
@ -157,8 +161,6 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
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 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
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/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc=
|
github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc=
|
||||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
|
@ -229,11 +231,11 @@ 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/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 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
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/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
||||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mjibson/esc v0.2.0/go.mod h1:9Hw9gxxfHulMF5OJKCyhYD7PzlSdhzXyaGEBRPH1OPs=
|
github.com/mjibson/esc v0.2.0/go.mod h1:9Hw9gxxfHulMF5OJKCyhYD7PzlSdhzXyaGEBRPH1OPs=
|
||||||
|
github.com/moby/term v0.0.0-20200611042045-63b9a826fb74 h1:kvRIeqJNICemq2UFLx8q/Pj+1IRNZS0XPTaMFkuNsvg=
|
||||||
|
github.com/moby/term v0.0.0-20200611042045-63b9a826fb74/go.mod h1:pJ0Ot5YGdTcMdxnPMyGCfAr6fKXe0g9cDlz16MuFEBE=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
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/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
@ -401,7 +403,9 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -419,8 +423,8 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdO
|
||||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
|
||||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/docker/ecs-plugin/pkg/amazon/sdk"
|
"github.com/docker/ecs-plugin/pkg/amazon/sdk"
|
||||||
|
"github.com/docker/ecs-plugin/pkg/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBackend(profile string, region string) (*Backend, error) {
|
func NewBackend(profile string, region string) (*Backend, error) {
|
||||||
|
@ -17,6 +20,7 @@ func NewBackend(profile string, region string) (*Backend, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Backend{
|
return &Backend{
|
||||||
Region: region,
|
Region: region,
|
||||||
api: sdk.NewAPI(sess),
|
api: sdk.NewAPI(sess),
|
||||||
|
@ -26,4 +30,9 @@ func NewBackend(profile string, region string) (*Backend, error) {
|
||||||
type Backend struct {
|
type Backend struct {
|
||||||
Region string
|
Region string
|
||||||
api sdk.API
|
api sdk.API
|
||||||
|
writer progress.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Backend) SetWriter(context context.Context) {
|
||||||
|
b.writer = progress.ContextWriter(context)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
"github.com/docker/ecs-plugin/pkg/compose"
|
"github.com/docker/ecs-plugin/pkg/compose"
|
||||||
"github.com/docker/ecs-plugin/pkg/console"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Down(ctx context.Context, options *cli.ProjectOptions) error {
|
func (b *Backend) Down(ctx context.Context, options *cli.ProjectOptions) error {
|
||||||
|
@ -18,13 +17,7 @@ func (b *Backend) Down(ctx context.Context, options *cli.ProjectOptions) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return b.WaitStackCompletion(ctx, name, compose.StackDelete)
|
||||||
w := console.NewProgressWriter()
|
|
||||||
err = b.WaitStackCompletion(ctx, name, compose.StackDelete, w)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) projectName(options *cli.ProjectOptions) (string, error) {
|
func (b *Backend) projectName(options *cli.ProjectOptions) (string, error) {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -13,7 +15,7 @@ import (
|
||||||
"github.com/docker/ecs-plugin/pkg/console"
|
"github.com/docker/ecs-plugin/pkg/console"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Logs(ctx context.Context, options *cli.ProjectOptions) error {
|
func (b *Backend) Logs(ctx context.Context, options *cli.ProjectOptions, writer io.Writer) error {
|
||||||
name := options.Name
|
name := options.Name
|
||||||
if name == "" {
|
if name == "" {
|
||||||
project, err := cli.ProjectFromOptions(options)
|
project, err := cli.ProjectFromOptions(options)
|
||||||
|
@ -26,6 +28,7 @@ func (b *Backend) Logs(ctx context.Context, options *cli.ProjectOptions) error {
|
||||||
err := b.api.GetLogs(ctx, name, &logConsumer{
|
err := b.api.GetLogs(ctx, name, &logConsumer{
|
||||||
colors: map[string]console.ColorFunc{},
|
colors: map[string]console.ColorFunc{},
|
||||||
width: 0,
|
width: 0,
|
||||||
|
writer: writer,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -45,8 +48,10 @@ func (l *logConsumer) Log(service, container, message string) {
|
||||||
l.computeWidth()
|
l.computeWidth()
|
||||||
}
|
}
|
||||||
prefix := fmt.Sprintf("%-"+strconv.Itoa(l.width)+"s |", service)
|
prefix := fmt.Sprintf("%-"+strconv.Itoa(l.width)+"s |", service)
|
||||||
|
|
||||||
for _, line := range strings.Split(message, "\n") {
|
for _, line := range strings.Split(message, "\n") {
|
||||||
fmt.Printf("%s %s\n", cf(prefix), line)
|
buf := bytes.NewBufferString(fmt.Sprintf("%s %s\n", cf(prefix), line))
|
||||||
|
l.writer.Write(buf.Bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,4 +68,5 @@ func (l *logConsumer) computeWidth() {
|
||||||
type logConsumer struct {
|
type logConsumer struct {
|
||||||
colors map[string]console.ColorFunc
|
colors map[string]console.ColorFunc
|
||||||
width int
|
width int
|
||||||
|
writer io.Writer
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
"github.com/docker/ecs-plugin/pkg/compose"
|
"github.com/docker/ecs-plugin/pkg/compose"
|
||||||
"github.com/docker/ecs-plugin/pkg/console"
|
"github.com/docker/ecs-plugin/pkg/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Up(ctx context.Context, options *cli.ProjectOptions) error {
|
func (b *Backend) Up(ctx context.Context, options *cli.ProjectOptions) error {
|
||||||
|
@ -82,10 +83,12 @@ func (b *Backend) Up(ctx context.Context, options *cli.ProjectOptions) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
w := console.NewProgressWriter()
|
|
||||||
for k := range template.Resources {
|
for k := range template.Resources {
|
||||||
w.ResourceEvent(k, "PENDING", "")
|
b.writer.Event(progress.Event{
|
||||||
|
ID: k,
|
||||||
|
Status: progress.Working,
|
||||||
|
StatusText: "Pending",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
signalChan := make(chan os.Signal, 1)
|
signalChan := make(chan os.Signal, 1)
|
||||||
|
@ -96,7 +99,29 @@ func (b *Backend) Up(ctx context.Context, options *cli.ProjectOptions) error {
|
||||||
b.Down(ctx, options)
|
b.Down(ctx, options)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return b.WaitStackCompletion(ctx, project.Name, operation, w)
|
err = b.WaitStackCompletion(ctx, project.Name, operation)
|
||||||
|
// update status for external resources (LB and cluster)
|
||||||
|
loadBalancerName := fmt.Sprintf("%.32s", fmt.Sprintf("%sLoadBalancer", strings.Title(project.Name)))
|
||||||
|
for k := range template.Resources {
|
||||||
|
switch k {
|
||||||
|
case "Cluster":
|
||||||
|
if cluster == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case loadBalancerName:
|
||||||
|
if lb == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b.writer.Event(progress.Event{
|
||||||
|
ID: k,
|
||||||
|
Status: progress.Done,
|
||||||
|
StatusText: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Backend) GetVPC(ctx context.Context, project *types.Project) (string, error) {
|
func (b Backend) GetVPC(ctx context.Context, project *types.Project) (string, error) {
|
||||||
|
|
|
@ -8,10 +8,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/docker/ecs-plugin/pkg/console"
|
"github.com/docker/ecs-plugin/pkg/compose"
|
||||||
|
"github.com/docker/ecs-plugin/pkg/progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) WaitStackCompletion(ctx context.Context, name string, operation int, w console.ProgressWriter) error {
|
func (b *Backend) WaitStackCompletion(ctx context.Context, name string, operation int) error {
|
||||||
knownEvents := map[string]struct{}{}
|
knownEvents := map[string]struct{}{}
|
||||||
|
|
||||||
// Get the unique Stack ID so we can collect events without getting some from previous deployments with same name
|
// Get the unique Stack ID so we can collect events without getting some from previous deployments with same name
|
||||||
|
@ -22,7 +23,6 @@ func (b *Backend) WaitStackCompletion(ctx context.Context, name string, operatio
|
||||||
|
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
b.api.WaitStackComplete(ctx, stackID, operation) //nolint:errcheck
|
b.api.WaitStackComplete(ctx, stackID, operation) //nolint:errcheck
|
||||||
ticker.Stop()
|
ticker.Stop()
|
||||||
|
@ -55,11 +55,38 @@ func (b *Backend) WaitStackCompletion(ctx context.Context, name string, operatio
|
||||||
resource := aws.StringValue(event.LogicalResourceId)
|
resource := aws.StringValue(event.LogicalResourceId)
|
||||||
reason := aws.StringValue(event.ResourceStatusReason)
|
reason := aws.StringValue(event.ResourceStatusReason)
|
||||||
status := aws.StringValue(event.ResourceStatus)
|
status := aws.StringValue(event.ResourceStatus)
|
||||||
w.ResourceEvent(resource, status, reason)
|
progressStatus := progress.Working
|
||||||
if stackErr == nil && strings.HasSuffix(status, "_FAILED") {
|
|
||||||
stackErr = fmt.Errorf(reason)
|
switch status {
|
||||||
|
case "CREATE_COMPLETE":
|
||||||
|
if operation == compose.StackCreate {
|
||||||
|
progressStatus = progress.Done
|
||||||
|
|
||||||
|
}
|
||||||
|
case "UPDATE_COMPLETE":
|
||||||
|
if operation == compose.StackUpdate {
|
||||||
|
progressStatus = progress.Done
|
||||||
|
}
|
||||||
|
case "DELETE_COMPLETE":
|
||||||
|
if operation == compose.StackDelete {
|
||||||
|
progressStatus = progress.Done
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if strings.HasSuffix(status, "_FAILED") {
|
||||||
|
progressStatus = progress.Error
|
||||||
|
if stackErr == nil {
|
||||||
|
operation = compose.StackDelete
|
||||||
|
stackErr = fmt.Errorf(reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
b.writer.Event(progress.Event{
|
||||||
|
ID: resource,
|
||||||
|
Status: progressStatus,
|
||||||
|
StatusText: status,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stackErr
|
return stackErr
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package compose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/awslabs/goformation/v4/cloudformation"
|
"github.com/awslabs/goformation/v4/cloudformation"
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
|
@ -15,8 +16,8 @@ type API interface {
|
||||||
CreateContextData(ctx context.Context, params map[string]string) (contextData interface{}, description string, err error)
|
CreateContextData(ctx context.Context, params map[string]string) (contextData interface{}, description string, err error)
|
||||||
|
|
||||||
Convert(project *types.Project) (*cloudformation.Template, error)
|
Convert(project *types.Project) (*cloudformation.Template, error)
|
||||||
Logs(ctx context.Context, options *cli.ProjectOptions) error
|
Logs(ctx context.Context, options *cli.ProjectOptions, writer io.Writer) error
|
||||||
Ps(background context.Context, options *cli.ProjectOptions) ([]ServiceStatus, error)
|
Ps(ctx context.Context, options *cli.ProjectOptions) ([]ServiceStatus, error)
|
||||||
|
|
||||||
CreateSecret(ctx context.Context, secret Secret) (string, error)
|
CreateSecret(ctx context.Context, secret Secret) (string, error)
|
||||||
InspectSecret(ctx context.Context, id string) (Secret, error)
|
InspectSecret(ctx context.Context, id string) (Secret, error)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package console
|
package console
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,6 +25,14 @@ var Monochrome = func(s string) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ansiColor(code, s string) string {
|
||||||
|
return fmt.Sprintf("%s%s%s", ansi(code), s, ansi("0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ansi(code string) string {
|
||||||
|
return fmt.Sprintf("\033[%sm", code)
|
||||||
|
}
|
||||||
|
|
||||||
func makeColorFunc(code string) ColorFunc {
|
func makeColorFunc(code string) ColorFunc {
|
||||||
return func(s string) string {
|
return func(s string) string {
|
||||||
return ansiColor(code, s)
|
return ansiColor(code, s)
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
package console
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type resource struct {
|
|
||||||
name string
|
|
||||||
status string
|
|
||||||
details string
|
|
||||||
}
|
|
||||||
|
|
||||||
type progress struct {
|
|
||||||
console console
|
|
||||||
resources []*resource
|
|
||||||
}
|
|
||||||
|
|
||||||
type ProgressWriter interface {
|
|
||||||
ResourceEvent(name string, status string, details string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewProgressWriter() ProgressWriter {
|
|
||||||
return &progress{
|
|
||||||
console: ansiConsole{os.Stdout},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
blue = "36;2"
|
|
||||||
red = "31;1"
|
|
||||||
green = "32;1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (p *progress) ResourceEvent(name string, status string, details string) {
|
|
||||||
if logrus.IsLevelEnabled(logrus.DebugLevel) {
|
|
||||||
logrus.Debugf("> %s : %s %s\n", name, status, details)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.console.MoveUp(len(p.resources))
|
|
||||||
|
|
||||||
newResource := true
|
|
||||||
for _, r := range p.resources {
|
|
||||||
if r.name == name {
|
|
||||||
newResource = false
|
|
||||||
r.status = status
|
|
||||||
r.details = details
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if newResource {
|
|
||||||
p.resources = append(p.resources, &resource{name, status, details})
|
|
||||||
}
|
|
||||||
|
|
||||||
var width int
|
|
||||||
for _, r := range p.resources {
|
|
||||||
l := len(r.name)
|
|
||||||
if width < l {
|
|
||||||
width = l
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range p.resources {
|
|
||||||
s := r.status
|
|
||||||
if strings.HasSuffix(s, "_IN_PROGRESS") {
|
|
||||||
s = p.console.WiP(s)
|
|
||||||
} else if strings.HasSuffix(s, "_COMPLETE") {
|
|
||||||
s = p.console.OK(s)
|
|
||||||
} else if strings.HasSuffix(s, "_FAILED") {
|
|
||||||
s = p.console.KO(s)
|
|
||||||
}
|
|
||||||
p.console.ClearLine()
|
|
||||||
p.console.Printf("%-"+strconv.Itoa(width)+"s ... %s %s", r.name, s, r.details) // nolint:errcheck
|
|
||||||
p.console.MoveDown(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type console interface {
|
|
||||||
Printf(format string, a ...interface{})
|
|
||||||
MoveUp(int)
|
|
||||||
MoveDown(int)
|
|
||||||
ClearLine()
|
|
||||||
OK(string) string
|
|
||||||
KO(string) string
|
|
||||||
WiP(string) string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ansiConsole struct {
|
|
||||||
out io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) Printf(format string, a ...interface{}) {
|
|
||||||
fmt.Fprintf(c.out, format, a...) // nolint:errcheck
|
|
||||||
fmt.Fprintf(c.out, "\r")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) MoveUp(i int) {
|
|
||||||
fmt.Fprintf(c.out, "\033[%dA", i) // nolint:errcheck
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) MoveDown(i int) {
|
|
||||||
fmt.Fprintf(c.out, "\033[%dB", i) // nolint:errcheck
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) ClearLine() {
|
|
||||||
fmt.Fprint(c.out, "\033[2K\r") // nolint:errcheck
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) OK(s string) string {
|
|
||||||
return ansiColor(green, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) KO(s string) string {
|
|
||||||
return ansiColor(red, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c ansiConsole) WiP(s string) string {
|
|
||||||
return ansiColor(blue, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ansiColor(code, s string) string {
|
|
||||||
return fmt.Sprintf("%s%s%s", ansi(code), s, ansi("0"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ansi(code string) string {
|
|
||||||
return fmt.Sprintf("\033[%sm", code)
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package console
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestProgressWriter(t *testing.T) {
|
|
||||||
c := &bufferConsole{}
|
|
||||||
p := progress{
|
|
||||||
console: c,
|
|
||||||
}
|
|
||||||
p.ResourceEvent("resource1", "CREATE_IN_PROGRESS", "")
|
|
||||||
assert.Equal(t, c.lines[0], "resource1 ... CREATE_IN_PROGRESS ")
|
|
||||||
|
|
||||||
p.ResourceEvent("resource2_long_name", "CREATE_IN_PROGRESS", "ok")
|
|
||||||
assert.Equal(t, c.lines[0], "resource1 ... CREATE_IN_PROGRESS ")
|
|
||||||
assert.Equal(t, c.lines[1], "resource2_long_name ... CREATE_IN_PROGRESS ok")
|
|
||||||
|
|
||||||
p.ResourceEvent("resource2_long_name", "CREATE_COMPLETE", "done")
|
|
||||||
assert.Equal(t, c.lines[0], "resource1 ... CREATE_IN_PROGRESS ")
|
|
||||||
assert.Equal(t, c.lines[1], "resource2_long_name ... CREATE_COMPLETE done")
|
|
||||||
|
|
||||||
p.ResourceEvent("resource1", "CREATE_FAILED", "oups")
|
|
||||||
assert.Equal(t, c.lines[0], "resource1 ... CREATE_FAILED oups")
|
|
||||||
assert.Equal(t, c.lines[1], "resource2_long_name ... CREATE_COMPLETE done")
|
|
||||||
}
|
|
||||||
|
|
||||||
type bufferConsole struct {
|
|
||||||
pos int
|
|
||||||
lines []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) Printf(format string, a ...interface{}) {
|
|
||||||
b.lines[b.pos] = fmt.Sprintf(format, a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) MoveUp(i int) {
|
|
||||||
b.pos -= i
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) MoveDown(i int) {
|
|
||||||
b.pos += i
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) ClearLine() {
|
|
||||||
if len(b.lines) <= b.pos {
|
|
||||||
b.lines = append(b.lines, "")
|
|
||||||
}
|
|
||||||
b.lines[b.pos] = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) OK(s string) string {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) KO(s string) string {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bufferConsole) WiP(s string) string {
|
|
||||||
return s
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package progress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type plainWriter struct {
|
||||||
|
out io.Writer
|
||||||
|
done chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plainWriter) Start(ctx context.Context) error {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-p.done:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plainWriter) Event(e Event) {
|
||||||
|
fmt.Println(e.ID, e.Text, e.StatusText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *plainWriter) Stop() {
|
||||||
|
p.done <- true
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package progress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type spinner struct {
|
||||||
|
time time.Time
|
||||||
|
index int
|
||||||
|
chars []string
|
||||||
|
stop bool
|
||||||
|
done string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSpinner() *spinner {
|
||||||
|
chars := []string{
|
||||||
|
"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏",
|
||||||
|
}
|
||||||
|
done := "⠿"
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
chars = []string{"-"}
|
||||||
|
done = "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
return &spinner{
|
||||||
|
index: 0,
|
||||||
|
time: time.Now(),
|
||||||
|
chars: chars,
|
||||||
|
done: done,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *spinner) String() string {
|
||||||
|
if s.stop {
|
||||||
|
return s.done
|
||||||
|
}
|
||||||
|
|
||||||
|
d := time.Since(s.time)
|
||||||
|
if d.Milliseconds() > 100 {
|
||||||
|
s.index = (s.index + 1) % len(s.chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.chars[s.index]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *spinner) Stop() {
|
||||||
|
s.stop = true
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
package progress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/buger/goterm"
|
||||||
|
"github.com/morikuni/aec"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ttyWriter struct {
|
||||||
|
out io.Writer
|
||||||
|
events map[string]Event
|
||||||
|
eventIDs []string
|
||||||
|
repeated bool
|
||||||
|
numLines int
|
||||||
|
done chan bool
|
||||||
|
mtx *sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ttyWriter) Start(ctx context.Context) error {
|
||||||
|
ticker := time.NewTicker(100 * time.Millisecond)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
w.print()
|
||||||
|
return ctx.Err()
|
||||||
|
case <-w.done:
|
||||||
|
w.print()
|
||||||
|
return nil
|
||||||
|
case <-ticker.C:
|
||||||
|
w.print()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ttyWriter) Stop() {
|
||||||
|
w.done <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ttyWriter) Event(e Event) {
|
||||||
|
w.mtx.Lock()
|
||||||
|
defer w.mtx.Unlock()
|
||||||
|
if !StringContains(w.eventIDs, e.ID) {
|
||||||
|
w.eventIDs = append(w.eventIDs, e.ID)
|
||||||
|
}
|
||||||
|
if _, ok := w.events[e.ID]; ok {
|
||||||
|
last := w.events[e.ID]
|
||||||
|
switch e.Status {
|
||||||
|
case Done, Error:
|
||||||
|
if last.Status != e.Status {
|
||||||
|
last.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last.Status = e.Status
|
||||||
|
last.Text = e.Text
|
||||||
|
last.StatusText = e.StatusText
|
||||||
|
w.events[e.ID] = last
|
||||||
|
} else {
|
||||||
|
e.startTime = time.Now()
|
||||||
|
e.spinner = newSpinner()
|
||||||
|
w.events[e.ID] = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ttyWriter) print() {
|
||||||
|
w.mtx.Lock()
|
||||||
|
defer w.mtx.Unlock()
|
||||||
|
if len(w.eventIDs) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
terminalWidth := goterm.Width()
|
||||||
|
b := aec.EmptyBuilder
|
||||||
|
for i := 0; i <= w.numLines; i++ {
|
||||||
|
b = b.Up(1)
|
||||||
|
}
|
||||||
|
if !w.repeated {
|
||||||
|
b = b.Down(1)
|
||||||
|
}
|
||||||
|
w.repeated = true
|
||||||
|
fmt.Fprint(w.out, b.Column(0).ANSI)
|
||||||
|
|
||||||
|
// Hide the cursor while we are printing
|
||||||
|
fmt.Fprint(w.out, aec.Hide)
|
||||||
|
defer fmt.Fprint(w.out, aec.Show)
|
||||||
|
|
||||||
|
firstLine := fmt.Sprintf("[+] Running %d/%d", numDone(w.events), w.numLines)
|
||||||
|
if w.numLines != 0 && numDone(w.events) == w.numLines {
|
||||||
|
firstLine = aec.Apply(firstLine, aec.BlueF)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w.out, firstLine)
|
||||||
|
|
||||||
|
var statusPadding int
|
||||||
|
for _, v := range w.eventIDs {
|
||||||
|
l := len(fmt.Sprintf("%s %s", w.events[v].ID, w.events[v].Text))
|
||||||
|
if statusPadding < l {
|
||||||
|
statusPadding = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
numLines := 0
|
||||||
|
for _, v := range w.eventIDs {
|
||||||
|
line := lineText(w.events[v], terminalWidth, statusPadding, runtime.GOOS != "windows")
|
||||||
|
// nolint: errcheck
|
||||||
|
fmt.Fprint(w.out, line)
|
||||||
|
numLines++
|
||||||
|
}
|
||||||
|
|
||||||
|
w.numLines = numLines
|
||||||
|
}
|
||||||
|
|
||||||
|
func lineText(event Event, terminalWidth, statusPadding int, color bool) string {
|
||||||
|
endTime := time.Now()
|
||||||
|
if event.Status != Working {
|
||||||
|
endTime = event.endTime
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed := endTime.Sub(event.startTime).Seconds()
|
||||||
|
|
||||||
|
textLen := len(fmt.Sprintf("%s %s", event.ID, event.Text))
|
||||||
|
padding := statusPadding - textLen
|
||||||
|
if padding < 0 {
|
||||||
|
padding = 0
|
||||||
|
}
|
||||||
|
text := fmt.Sprintf(" %s %s %s%s %s",
|
||||||
|
event.spinner.String(),
|
||||||
|
event.ID,
|
||||||
|
event.Text,
|
||||||
|
strings.Repeat(" ", padding),
|
||||||
|
event.StatusText,
|
||||||
|
)
|
||||||
|
timer := fmt.Sprintf("%.1fs\n", elapsed)
|
||||||
|
o := align(text, timer, terminalWidth)
|
||||||
|
|
||||||
|
if color {
|
||||||
|
color := aec.WhiteF
|
||||||
|
if event.Status == Done {
|
||||||
|
color = aec.BlueF
|
||||||
|
}
|
||||||
|
if event.Status == Error {
|
||||||
|
color = aec.RedF
|
||||||
|
}
|
||||||
|
return aec.Apply(o, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
func numDone(events map[string]Event) int {
|
||||||
|
i := 0
|
||||||
|
for _, e := range events {
|
||||||
|
if e.Status == Done {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func align(l, r string, w int) string {
|
||||||
|
return fmt.Sprintf("%-[2]*[1]s %[3]s", l, w-len(r)-1, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringContains check if an array contains a specific value
|
||||||
|
func StringContains(array []string, needle string) bool {
|
||||||
|
for _, val := range array {
|
||||||
|
if val == needle {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
package progress
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/console"
|
||||||
|
"github.com/moby/term"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EventStatus indicates the status of an action
|
||||||
|
type EventStatus int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Working means that the current task is working
|
||||||
|
Working EventStatus = iota
|
||||||
|
// Done means that the current task is done
|
||||||
|
Done
|
||||||
|
// Error means that the current task has errored
|
||||||
|
Error
|
||||||
|
)
|
||||||
|
|
||||||
|
// Event reprensents a progress event
|
||||||
|
type Event struct {
|
||||||
|
ID string
|
||||||
|
Text string
|
||||||
|
Status EventStatus
|
||||||
|
StatusText string
|
||||||
|
Done bool
|
||||||
|
|
||||||
|
startTime time.Time
|
||||||
|
endTime time.Time
|
||||||
|
spinner *spinner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Event) stop() {
|
||||||
|
e.endTime = time.Now()
|
||||||
|
e.spinner.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writer can write multiple progress events
|
||||||
|
type Writer interface {
|
||||||
|
Start(context.Context) error
|
||||||
|
Stop()
|
||||||
|
Event(Event)
|
||||||
|
}
|
||||||
|
|
||||||
|
type writerKey struct{}
|
||||||
|
|
||||||
|
// WithContextWriter adds the writer to the context
|
||||||
|
func WithContextWriter(ctx context.Context, writer Writer) context.Context {
|
||||||
|
return context.WithValue(ctx, writerKey{}, writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContextWriter returns the writer from the context
|
||||||
|
func ContextWriter(ctx context.Context) Writer {
|
||||||
|
s, _ := ctx.Value(writerKey{}).(Writer)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type progressFunc func(context.Context) error
|
||||||
|
|
||||||
|
// Run will run a writer and the progress function
|
||||||
|
// in parallel
|
||||||
|
func Run(ctx context.Context, pf progressFunc) error {
|
||||||
|
eg, _ := errgroup.WithContext(ctx)
|
||||||
|
w, err := NewWriter(os.Stderr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
eg.Go(func() error {
|
||||||
|
return w.Start(context.Background())
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx = WithContextWriter(ctx, w)
|
||||||
|
|
||||||
|
eg.Go(func() error {
|
||||||
|
defer w.Stop()
|
||||||
|
return pf(ctx)
|
||||||
|
})
|
||||||
|
|
||||||
|
return eg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWriter returns a new multi-progress writer
|
||||||
|
func NewWriter(out console.File) (Writer, error) {
|
||||||
|
_, isTerminal := term.GetFdInfo(out)
|
||||||
|
|
||||||
|
if isTerminal {
|
||||||
|
con, err := console.ConsoleFromFile(out)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ttyWriter{
|
||||||
|
out: con,
|
||||||
|
eventIDs: []string{},
|
||||||
|
events: map[string]Event{},
|
||||||
|
repeated: false,
|
||||||
|
done: make(chan bool),
|
||||||
|
mtx: &sync.RWMutex{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &plainWriter{
|
||||||
|
out: out,
|
||||||
|
done: make(chan bool),
|
||||||
|
}, nil
|
||||||
|
}
|
Loading…
Reference in New Issue