From bc29091a20104dd3ffadd8ee3e6b248fb70c75ff Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Tue, 14 Sep 2021 12:02:51 +0200 Subject: [PATCH] compose-switch is installed as a Linux "alternative" to docker-compose Signed-off-by: Nicolas De Loof --- Makefile | 3 - README.md | 30 +++++- centos-test.Dockerfile | 24 +++++ go.mod | 4 +- go.sum | 29 ------ install_on_linux.sh | 55 +++++------ main.go | 31 +------ redirect/config.go | 64 ------------- redirect/paths.go | 1 - redirect/paths_windows.go | 1 - redirect/runcompose.go | 18 ---- tests/e2e/redirect_test.go | 44 --------- tests/echostub/main.go | 16 ---- tests/framework.go | 181 ------------------------------------- utuntu-test.Dockerfile | 29 ++++++ 15 files changed, 114 insertions(+), 416 deletions(-) create mode 100644 centos-test.Dockerfile delete mode 100644 redirect/config.go delete mode 100644 tests/e2e/redirect_test.go delete mode 100644 tests/echostub/main.go delete mode 100644 tests/framework.go create mode 100644 utuntu-test.Dockerfile diff --git a/Makefile b/Makefile index 08c2333..e204306 100644 --- a/Makefile +++ b/Makefile @@ -13,9 +13,6 @@ bin: cross: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags=$(LDFLAGS) -o bin/docker-compose-linux-amd64 . CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags=$(LDFLAGS) -o bin/docker-compose-linux-arm64 . - CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags=$(LDFLAGS) -o bin/docker-compose-darwin-amd64 . - CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags=$(LDFLAGS) -o bin/docker-compose-darwin-arm64 . - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags=$(LDFLAGS) -o bin/docker-compose-windows-amd64.exe . test: go test -cover $(shell go list $(TAGS) ./... | grep -vE 'e2e') diff --git a/README.md b/README.md index 748effc..1bd269c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,32 @@ Compose Switch -------------- -This is a thin wrapper to actually run either docker-compose v1 (python) or docker compose v2 (compose CLI plugin) depending on user's configuration +Compose Switch is a replacement to the Compose V1 `docker-compose` (python) executable. It translate the command line info Compose V2 `docker compose` then run the latter. + +## installation + +We provide an install script for automated installtion: + +```console +$ curl -fL https://raw.githubusercontent.com/docker/compose-cli/main/scripts/install/install_linux.sh | sh +``` + +### Manual installation + +1. download compose-switch binary for your architecture +```console +$ curl -fL https://github.com/docker/compose-switch/releases/download/v1.0.1/docker-compose-linux-amd64 -o /usr/local/bin/compose-switch +``` +1. make compose-switch executable +```console +$ chmode +x /usr/local/bin/compose-switch +``` +1. rename docker-compose if you already have it installed as `/usr/local/bin/docker-compose` +```console +$ mv /usr/local/bin/docker-compose /usr/local/bin/docker-compose-v1 +``` +1. define an "alternatives" group for `docker-compose` command: +```console +$ update-alternatives --install /usr/local/bin/docker-compose docker-compose /$(which docker-compose) 1 +$ update-alternatives --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99 +``` \ No newline at end of file diff --git a/centos-test.Dockerfile b/centos-test.Dockerfile new file mode 100644 index 0000000..50efbe5 --- /dev/null +++ b/centos-test.Dockerfile @@ -0,0 +1,24 @@ +FROM centos + +RUN yum install -y curl yum-utils + +# install docker cli +RUN yum-config-manager \ + --add-repo \ + https://download.docker.com/linux/centos/docker-ce.repo +RUN yum install -y docker-ce-cli + +# install compose v1 +RUN curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose +RUN chmod +x /usr/local/bin/docker-compose + +# install compose v2 +RUN mkdir -p /usr/local/lib/docker/cli-plugins +RUN curl -L https://github.com/docker/compose/releases/download/v2.0.0-rc.3/docker-compose-linux-amd64 > /usr/local/lib/docker/cli-plugins/docker-compose +RUN chmod +x /usr/local/lib/docker/cli-plugins/docker-compose + + +COPY install_on_linux.sh /tmp/install_on_linux.sh +RUN /tmp/install_on_linux.sh + +RUN docker-compose --version diff --git a/go.mod b/go.mod index e3b1b64..272375c 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,7 @@ module github.com/docker/compose-switch go 1.16 require ( - github.com/Microsoft/go-winio v0.5.0 - github.com/labstack/echo v3.3.10+incompatible - github.com/labstack/gommon v0.3.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cobra v1.1.3 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c gotest.tools/v3 v3.0.3 diff --git a/go.sum b/go.sum index 1ec1ca7..c36149b 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,6 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= -github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -34,7 +32,6 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -107,23 +104,13 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= -github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= -github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= -github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= @@ -140,7 +127,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -159,7 +145,6 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -177,14 +162,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -196,7 +175,6 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -229,7 +207,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -246,20 +223,16 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -313,9 +286,7 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= diff --git a/install_on_linux.sh b/install_on_linux.sh index fa9da4e..d848a01 100755 --- a/install_on_linux.sh +++ b/install_on_linux.sh @@ -1,21 +1,14 @@ #!/bin/sh -COMPOSE_SWITCH_VERSION="1.0.0" -COMPOSE_SWITCH_URL="https://github.com/docker/compose-switch/releases/download/$COMPOSE_SWITCH_VERSION/docker-compose" -DOCKER_COMPOSE_V1_PATH_ORIG="$(which docker-compose)" -DOCKER_COMPOSE_V1_PATH_NEW="$DOCKER_COMPOSE_V1_PATH_ORIG-v1" +set -x +set -e -if [ ! -f "${DOCKER_COMPOSE_V1_PATH_ORIG}" ]; then - echo "'docker-compose' V1 could not be found in PATH. Aborting..." - exit 1 -fi - -if [ -f "${DOCKER_COMPOSE_V1_PATH_NEW}" ]; then - echo "Looks like docker-compose V1->V2 switch is already installed. 'docker-compose' binary was already moved to '${DOCKER_COMPOSE_V1_PATH_NEW}'." - echo "If you are trying to re-enable Docker Compose V2, please run:" - echo "$ docker-compose enable-v2" - exit 0 -fi +ARCHITECTURE=amd64 +if [ "$(uname -m)" = "aarch64" ]; then + ARCHITECTURE=arm64 +fi +COMPOSE_SWITCH_VERSION="v1.0.1" +COMPOSE_SWITCH_URL="https://github.com/docker/compose-switch/releases/download/${COMPOSE_SWITCH_VERSION}/docker-compose-linux-${ARCHITECTURE}" error=$(docker compose version 2>&1 >/dev/null) if [ $? -ne 0 ]; then @@ -23,19 +16,27 @@ if [ $? -ne 0 ]; then exit 1 fi -TMP_FILE=$(mktemp) -echo "Downloading compose V1->V2 switch into $TMP_FILE..." -curl -L -o "$TMP_FILE" "$COMPOSE_SWITCH_URL" -chmod +x "$TMP_FILE" +curl -fL $COMPOSE_SWITCH_URL -o /usr/local/bin/compose-switch +chmod +x /usr/local/bin/compose-switch -echo "Switching Docker Compose binary" -mv "$DOCKER_COMPOSE_V1_PATH_ORIG" "$DOCKER_COMPOSE_V1_PATH_NEW" -mv "$TMP_FILE" "$DOCKER_COMPOSE_V1_PATH_ORIG" +COMPOSE=$(command -v docker-compose) +if [ "$COMPOSE" = /usr/local/bin/docker-compose ]; then + # This is a manual installation of docker-compose + # so, safe for us to rename binary + mv /usr/local/bin/docker-compose /usr/local/bin/docker-compose-v1 + COMPOSE=/usr/local/bin/docker-compose-v1 +fi -echo "Compose V1->V2 installed" +ALTERNATIVES="update-alternatives" +if ! command -v $ALTERNATIVES; then + ALTERNATIVES=alternatives +fi -$DOCKER_COMPOSE_V1_PATH_ORIG enable-v2 -echo "Docker Compose V2 enabled" -docker-compose version +echo "Configuring `docker-compose` alternatives" +if [ $COMPOSE -ne "" ]; then + $ALTERNATIVES --install /usr/local/bin/docker-compose docker-compose $COMPOSE 1 +fi +$ALTERNATIVES --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99 -echo "To switch back to Compose V1, you can run: `docker-compose disable-v2`" +echo "'docker-compose' is now set to run Compose V2" +echo "use '$ALTERNATIVES --config docker-compose' if you want to switch back to Compose V1" \ No newline at end of file diff --git a/main.go b/main.go index 6460873..9bedee1 100644 --- a/main.go +++ b/main.go @@ -19,48 +19,23 @@ package main import ( "fmt" "os" - "strings" "github.com/docker/compose-switch/redirect" "github.com/spf13/cobra" ) func main() { - configFile := redirect.GetConfigFile() - err := configFile.Load() - if err != nil { - fmt.Fprintf(os.Stderr, "Failed to load docker configuration: %s\n", err) - os.Exit(1) - } - root := &cobra.Command{ DisableFlagParsing: true, Use: "docker-compose", RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 && args[0] == "disable-v2" { - configFile.SetFeature("composeV2", redirect.Disabled) - err := configFile.Write() - return err - } - if len(args) > 0 && args[0] == "enable-v2" { - configFile.SetFeature("composeV2", redirect.Enabled) - err := configFile.Write() - return err - } - - useV2, ok := configFile.GetFeature(redirect.ComposeV2) - - if ok && strings.HasSuffix(useV2, redirect.Enabled) { - compose := redirect.Convert(args) - redirect.RunComposeV2(compose) - return nil - } - redirect.RunComposeV1(args) + compose := redirect.Convert(args) + redirect.RunComposeV2(compose) return nil }, } - err = root.Execute() + err := root.Execute() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/redirect/config.go b/redirect/config.go deleted file mode 100644 index ece4597..0000000 --- a/redirect/config.go +++ /dev/null @@ -1,64 +0,0 @@ -package redirect - -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" -) - -const ( - Enabled = "enabled" - Disabled = "disabled" - ComposeV2 = "composeV2" -) - -type config struct { - path string - data map[string]interface{} -} - -func (config *config) Load() error { - config.data = map[string]interface{}{} - if _, err := os.Stat(config.path); os.IsNotExist(err) { - return nil - } - raw, err := ioutil.ReadFile(config.path) - if err != nil { - return err - } - err = json.Unmarshal(raw, &config.data) - return err -} - -func (config *config) Write() error { - d, err := json.MarshalIndent(config.data, "", "\t") - if err != nil { - return err - } - return ioutil.WriteFile(config.path, d, 0644) -} - -func GetConfigFile() config { - configDir := os.Getenv("DOCKER_CONFIG") - if configDir == "" { - home, _ := os.UserHomeDir() - configDir = filepath.Join(home, ".docker") - } - configFile := filepath.Join(configDir, "features.json") - return config{ - path: configFile, - } -} - -func (config *config) GetFeature(key string) (string, bool) { - v, ok := config.data[key] - if !ok { - return "", false - } - return v.(string), true -} - -func (config *config) SetFeature(key, value string) { - config.data[key] = value -} diff --git a/redirect/paths.go b/redirect/paths.go index 0341dbf..88ea0fe 100644 --- a/redirect/paths.go +++ b/redirect/paths.go @@ -3,6 +3,5 @@ package redirect const ( - ComposeV1Binary = "docker-compose-v1" DockerBinary = "docker" ) diff --git a/redirect/paths_windows.go b/redirect/paths_windows.go index b42cc82..456bb32 100644 --- a/redirect/paths_windows.go +++ b/redirect/paths_windows.go @@ -3,6 +3,5 @@ package redirect const ( - ComposeV1Binary = "docker-compose-v1.exe" DockerBinary = "docker.exe" ) diff --git a/redirect/runcompose.go b/redirect/runcompose.go index cc72567..8adb0a6 100644 --- a/redirect/runcompose.go +++ b/redirect/runcompose.go @@ -8,24 +8,6 @@ import ( composeexec "github.com/docker/compose-switch/exec" ) -func RunComposeV1(args []string) { - execBinary, err := exec.LookPath(ComposeV1Binary) - if err != nil { - fmt.Fprintln(os.Stderr, err) - fmt.Fprintln(os.Stderr, "Current PATH : "+os.Getenv("PATH")) - os.Exit(1) - } - // syscall.Exec for compose v1 will not work if using compose V1 python self-extracting binary, as it belives it's packaged as docker-compose and not docker-compose-v1 - err = composeexec.Shellout(execBinary, append([]string{"docker-compose"}, args...), os.Environ()) - if err != nil { - if exiterr, ok := err.(*exec.ExitError); ok { - os.Exit(exiterr.ExitCode()) - } - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} - func RunComposeV2(args []string) { execBinary, err := exec.LookPath(DockerBinary) if err != nil { diff --git a/tests/e2e/redirect_test.go b/tests/e2e/redirect_test.go deleted file mode 100644 index d8b828c..0000000 --- a/tests/e2e/redirect_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package e2e - -import ( - "fmt" - "os" - "path/filepath" - "testing" - - "github.com/docker/compose-switch/redirect" - . "github.com/docker/compose-switch/tests" - "gotest.tools/v3/icmd" -) - -var binDir string - -const testUUID = `ABCDEFAB-ABCD-1234-5678-ABCDEFABCDEF` - -func TestMain(m *testing.M) { - p, cleanup, err := SetupExistingCLI() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - binDir = p - exitCode := m.Run() - cleanup() - os.Exit(exitCode) -} - -func TestComposeRedirect(t *testing.T) { - c := NewE2eCLI(t, binDir) - - t.Run("disable-v2", func(t *testing.T) { - c.RunNewComposeCmd("disable-v2") - c.RunNewComposeCmd("--version").Assert(t, icmd.Expected{Out: redirect.ComposeV1Binary + " --version"}) - c.RunCmd("cat", filepath.Join(c.ConfigDir, "features.json")).Assert(t, icmd.Expected{Out: `"composeV2": "disabled"`}) - }) - - t.Run("enable-v2", func(t *testing.T) { - c.RunNewComposeCmd("enable-v2") - c.RunNewComposeCmd("--version").Assert(t, icmd.Expected{Out: redirect.DockerBinary + " compose version"}) - c.RunCmd("cat", filepath.Join(c.ConfigDir, "features.json")).Assert(t, icmd.Expected{Out: `"composeV2": "enabled"`}) - }) -} diff --git a/tests/echostub/main.go b/tests/echostub/main.go deleted file mode 100644 index 917ed59..0000000 --- a/tests/echostub/main.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import ( - "fmt" - "os" - "reflect" - "strings" -) - -func main() { - if reflect.DeepEqual(os.Args, []string{"docker", "compose", "version", "--short"}) { - fmt.Println("2.0.0-rc.3") - } else { - fmt.Println(strings.Join(os.Args, " ")) - } -} diff --git a/tests/framework.go b/tests/framework.go deleted file mode 100644 index da54cd5..0000000 --- a/tests/framework.go +++ /dev/null @@ -1,181 +0,0 @@ -package e2e - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/docker/compose-switch/redirect" - "gotest.tools/v3/assert" - is "gotest.tools/v3/assert/cmp" - "gotest.tools/v3/icmd" -) - -// E2eCLI is used to wrap the CLI for end to end testing -// nolint stutter -type E2eCLI struct { - BinDir string - ConfigDir string - Test *testing.T -} - -func getBinExt() string { - if runtime.GOOS == "windows" { - return ".exe" - } - return "" -} - -var dockerCompose = "docker-compose" + getBinExt() - -// NewE2eCLI returns a configured TestE2eCLI -func NewE2eCLI(t *testing.T, binDir string) *E2eCLI { - configDir, err := ioutil.TempDir("", "") - assert.Check(t, is.Nil(err)) - - t.Parallel() - - t.Cleanup(func() { - if t.Failed() { - conf, _ := ioutil.ReadFile(filepath.Join(configDir, "features.json")) - t.Errorf("features.json: %s\n", string(conf)) - } - _ = os.RemoveAll(configDir) - }) - - return &E2eCLI{binDir, configDir, t} -} - -// SetupExistingCLI copies the existing CLI in a temporary directory so that the -// new CLI can be configured to use it -func SetupExistingCLI() (string, func(), error) { - binDir, err := ioutil.TempDir("", "") - if err != nil { - return "", nil, err - } - - bin, err := findExecutable(dockerCompose, []string{"../../bin"}) - if err != nil { - return "", nil, err - } - - if err := CopyFile(bin, filepath.Join(binDir, dockerCompose)); err != nil { - return "", nil, err - } - - echostub, err := findExecutable("echostub"+getBinExt(), []string{"../../bin/test"}) - if err != nil { - return "", nil, err - } - - if err := CopyFile(echostub, filepath.Join(binDir, redirect.ComposeV1Binary)); err != nil { - return "", nil, err - } - - if err := CopyFile(echostub, filepath.Join(binDir, redirect.DockerBinary)); err != nil { - return "", nil, err - } - - cleanup := func() { - _ = os.RemoveAll(binDir) - } - - return binDir, cleanup, nil -} - -func findExecutable(executableName string, paths []string) (string, error) { - for _, p := range paths { - bin, err := filepath.Abs(path.Join(p, executableName)) - if err != nil { - return "", err - } - - if _, err := os.Stat(bin); os.IsNotExist(err) { - continue - } - - return bin, nil - } - - return "", fmt.Errorf("executable not found %q in %s", executableName, strings.Join(paths, ", ")) -} - -// CopyFile copies a file from a sourceFile to a destinationFile setting permissions to 0755 -func CopyFile(sourceFile string, destinationFile string) error { - src, err := os.Open(sourceFile) - if err != nil { - return err - } - // nolint: errcheck - defer src.Close() - - dst, err := os.OpenFile(destinationFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) - if err != nil { - return err - } - // nolint: errcheck - defer dst.Close() - - if _, err = io.Copy(dst, src); err != nil { - return err - } - - return err -} - -// NewCmd creates a cmd object configured with the test environment set -func (c *E2eCLI) NewCmd(command string, args ...string) icmd.Cmd { - testPath := c.PathEnvVar() - env := append(os.Environ(), - "DOCKER_CONFIG="+c.ConfigDir, - "TEST_DESKTOP_SOCKET="+c.DesktopSocket(), - "PATH="+testPath, - ) - return icmd.Cmd{ - Command: append([]string{command}, args...), - Env: env, - } -} - -// RunNewComposeCmd runs a docker-compose cmd -func (c *E2eCLI) RunNewComposeCmd(args ...string) *icmd.Result { - fmt.Printf(" [%s] %s %s\n", c.Test.Name(), filepath.Join(c.BinDir, dockerCompose), strings.Join(args, " ")) - return icmd.RunCmd(c.NewComposeCmd(args...)) -} - -// NewComposeCmd creates a docker-compose cmd without running it -func (c *E2eCLI) NewComposeCmd(args ...string) icmd.Cmd { - return c.NewCmd(filepath.Join(c.BinDir, dockerCompose), args...) -} - -// RunCmd runs a command, expects no error and returns a result -func (c *E2eCLI) RunCmd(args ...string) *icmd.Result { - fmt.Printf(" [%s] %s\n", c.Test.Name(), strings.Join(args, " ")) - assert.Assert(c.Test, len(args) >= 1, "require at least one command in parameters") - res := icmd.RunCmd(c.NewCmd(args[0], args[1:]...)) - res.Assert(c.Test, icmd.Success) - return res -} - -// DesktopSocket get the path where test metrics will be sent -func (c *E2eCLI) DesktopSocket() string { - if runtime.GOOS == "windows" { - return `\\.\pipe\` + filepath.Base(c.ConfigDir) + "_metrics" - } - return filepath.Join(c.ConfigDir, "./docker-cli.sock") -} - -// PathEnvVar returns path (os sensitive) for running test -func (c *E2eCLI) PathEnvVar() string { - path := c.BinDir + ":" + os.Getenv("PATH") - if runtime.GOOS == "windows" { - path = c.BinDir + ";" + os.Getenv("PATH") - } - return path -} diff --git a/utuntu-test.Dockerfile b/utuntu-test.Dockerfile new file mode 100644 index 0000000..3f1d24c --- /dev/null +++ b/utuntu-test.Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu + +# install docker CLI +RUN apt update +RUN apt-get install -y \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + lsb-release +RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg +RUN echo \ + "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null +RUN apt-get update +RUN apt-get install -y docker-ce-cli + +# install compose v1 (ubuntu managed) +RUN apt-get install -y docker-compose + +# install compose v2 +RUN mkdir -p /usr/local/lib/docker/cli-plugins +RUN curl -L https://github.com/docker/compose/releases/download/v2.0.0-rc.3/docker-compose-linux-amd64 > /usr/local/lib/docker/cli-plugins/docker-compose +RUN chmod +x /usr/local/lib/docker/cli-plugins/docker-compose + +COPY install_on_linux.sh /tmp/install_on_linux.sh +RUN /tmp/install_on_linux.sh + +RUN docker-compose --version