mirror of
https://github.com/docker/compose.git
synced 2025-04-08 17:05:13 +02:00
Merge pull request #1539 from docker/inject
This commit is contained in:
commit
fa05d4397a
@ -73,7 +73,7 @@ RUN --mount=target=. \
|
||||
GOARCH=${TARGETARCH} \
|
||||
BUILD_TAGS=${BUILD_TAGS} \
|
||||
GIT_TAG=${GIT_TAG} \
|
||||
make BINARY=/out/docker -f builder.Makefile cli
|
||||
make BINARY=/out/docker COMPOSE_BINARY=/out/docker-compose -f builder.Makefile cli
|
||||
|
||||
FROM base AS make-cross
|
||||
ARG BUILD_TAGS
|
||||
@ -83,7 +83,7 @@ RUN --mount=target=. \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
BUILD_TAGS=${BUILD_TAGS} \
|
||||
GIT_TAG=${GIT_TAG} \
|
||||
make BINARY=/out/docker -f builder.Makefile cross
|
||||
make BINARY=/out/docker COMPOSE_BINARY=/out/docker-compose -f builder.Makefile cross
|
||||
|
||||
FROM scratch AS protos
|
||||
COPY --from=make-protos /compose-cli/cli/server/protos .
|
||||
|
143
api/compose/delegator.go
Normal file
143
api/compose/delegator.go
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
)
|
||||
|
||||
// ServiceDelegator implements Service by delegating to another implementation. This allows lazy init
|
||||
type ServiceDelegator struct {
|
||||
Delegate Service
|
||||
}
|
||||
|
||||
//Build implements Service interface
|
||||
func (s *ServiceDelegator) Build(ctx context.Context, project *types.Project, options BuildOptions) error {
|
||||
return s.Delegate.Build(ctx, project, options)
|
||||
}
|
||||
|
||||
//Push implements Service interface
|
||||
func (s *ServiceDelegator) Push(ctx context.Context, project *types.Project, options PushOptions) error {
|
||||
return s.Delegate.Push(ctx, project, options)
|
||||
}
|
||||
|
||||
//Pull implements Service interface
|
||||
func (s *ServiceDelegator) Pull(ctx context.Context, project *types.Project, options PullOptions) error {
|
||||
return s.Delegate.Pull(ctx, project, options)
|
||||
}
|
||||
|
||||
//Create implements Service interface
|
||||
func (s *ServiceDelegator) Create(ctx context.Context, project *types.Project, options CreateOptions) error {
|
||||
return s.Delegate.Create(ctx, project, options)
|
||||
}
|
||||
|
||||
//Start implements Service interface
|
||||
func (s *ServiceDelegator) Start(ctx context.Context, project *types.Project, options StartOptions) error {
|
||||
return s.Delegate.Start(ctx, project, options)
|
||||
}
|
||||
|
||||
//Restart implements Service interface
|
||||
func (s *ServiceDelegator) Restart(ctx context.Context, project *types.Project, options RestartOptions) error {
|
||||
return s.Delegate.Restart(ctx, project, options)
|
||||
}
|
||||
|
||||
//Stop implements Service interface
|
||||
func (s *ServiceDelegator) Stop(ctx context.Context, project *types.Project, options StopOptions) error {
|
||||
return s.Delegate.Stop(ctx, project, options)
|
||||
}
|
||||
|
||||
//Up implements Service interface
|
||||
func (s *ServiceDelegator) Up(ctx context.Context, project *types.Project, options UpOptions) error {
|
||||
return s.Delegate.Up(ctx, project, options)
|
||||
}
|
||||
|
||||
//Down implements Service interface
|
||||
func (s *ServiceDelegator) Down(ctx context.Context, project string, options DownOptions) error {
|
||||
return s.Delegate.Down(ctx, project, options)
|
||||
}
|
||||
|
||||
//Logs implements Service interface
|
||||
func (s *ServiceDelegator) Logs(ctx context.Context, project string, consumer LogConsumer, options LogOptions) error {
|
||||
return s.Delegate.Logs(ctx, project, consumer, options)
|
||||
}
|
||||
|
||||
//Ps implements Service interface
|
||||
func (s *ServiceDelegator) Ps(ctx context.Context, project string, options PsOptions) ([]ContainerSummary, error) {
|
||||
return s.Delegate.Ps(ctx, project, options)
|
||||
}
|
||||
|
||||
//List implements Service interface
|
||||
func (s *ServiceDelegator) List(ctx context.Context, options ListOptions) ([]Stack, error) {
|
||||
return s.Delegate.List(ctx, options)
|
||||
}
|
||||
|
||||
//Convert implements Service interface
|
||||
func (s *ServiceDelegator) Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error) {
|
||||
return s.Delegate.Convert(ctx, project, options)
|
||||
}
|
||||
|
||||
//Kill implements Service interface
|
||||
func (s *ServiceDelegator) Kill(ctx context.Context, project *types.Project, options KillOptions) error {
|
||||
return s.Delegate.Kill(ctx, project, options)
|
||||
}
|
||||
|
||||
//RunOneOffContainer implements Service interface
|
||||
func (s *ServiceDelegator) RunOneOffContainer(ctx context.Context, project *types.Project, options RunOptions) (int, error) {
|
||||
return s.Delegate.RunOneOffContainer(ctx, project, options)
|
||||
}
|
||||
|
||||
//Remove implements Service interface
|
||||
func (s *ServiceDelegator) Remove(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error) {
|
||||
return s.Delegate.Remove(ctx, project, options)
|
||||
}
|
||||
|
||||
//Exec implements Service interface
|
||||
func (s *ServiceDelegator) Exec(ctx context.Context, project *types.Project, options RunOptions) error {
|
||||
return s.Delegate.Exec(ctx, project, options)
|
||||
}
|
||||
|
||||
//Pause implements Service interface
|
||||
func (s *ServiceDelegator) Pause(ctx context.Context, project string, options PauseOptions) error {
|
||||
return s.Delegate.Pause(ctx, project, options)
|
||||
}
|
||||
|
||||
//UnPause implements Service interface
|
||||
func (s *ServiceDelegator) UnPause(ctx context.Context, project string, options PauseOptions) error {
|
||||
return s.Delegate.UnPause(ctx, project, options)
|
||||
}
|
||||
|
||||
//Top implements Service interface
|
||||
func (s *ServiceDelegator) Top(ctx context.Context, project string, services []string) ([]ContainerProcSummary, error) {
|
||||
return s.Delegate.Top(ctx, project, services)
|
||||
}
|
||||
|
||||
//Events implements Service interface
|
||||
func (s *ServiceDelegator) Events(ctx context.Context, project string, options EventsOptions) error {
|
||||
return s.Delegate.Events(ctx, project, options)
|
||||
}
|
||||
|
||||
//Port implements Service interface
|
||||
func (s *ServiceDelegator) Port(ctx context.Context, project string, service string, port int, options PortOptions) (string, int, error) {
|
||||
return s.Delegate.Port(ctx, project, service, port, options)
|
||||
}
|
||||
|
||||
//Images implements Service interface
|
||||
func (s *ServiceDelegator) Images(ctx context.Context, project string, options ImagesOptions) ([]ImageSummary, error) {
|
||||
return s.Delegate.Images(ctx, project, options)
|
||||
}
|
143
api/compose/noimpl.go
Normal file
143
api/compose/noimpl.go
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
|
||||
"github.com/docker/compose-cli/api/errdefs"
|
||||
)
|
||||
|
||||
// NoImpl implements Service to return ErrNotImplemented
|
||||
type NoImpl struct{}
|
||||
|
||||
//Build implements Service interface
|
||||
func (s NoImpl) Build(ctx context.Context, project *types.Project, options BuildOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Push implements Service interface
|
||||
func (s NoImpl) Push(ctx context.Context, project *types.Project, options PushOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Pull implements Service interface
|
||||
func (s NoImpl) Pull(ctx context.Context, project *types.Project, options PullOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Create implements Service interface
|
||||
func (s NoImpl) Create(ctx context.Context, project *types.Project, options CreateOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Start implements Service interface
|
||||
func (s NoImpl) Start(ctx context.Context, project *types.Project, options StartOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Restart implements Service interface
|
||||
func (s NoImpl) Restart(ctx context.Context, project *types.Project, options RestartOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Stop implements Service interface
|
||||
func (s NoImpl) Stop(ctx context.Context, project *types.Project, options StopOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Up implements Service interface
|
||||
func (s NoImpl) Up(ctx context.Context, project *types.Project, options UpOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Down implements Service interface
|
||||
func (s NoImpl) Down(ctx context.Context, project string, options DownOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Logs implements Service interface
|
||||
func (s NoImpl) Logs(ctx context.Context, project string, consumer LogConsumer, options LogOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Ps implements Service interface
|
||||
func (s NoImpl) Ps(ctx context.Context, project string, options PsOptions) ([]ContainerSummary, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//List implements Service interface
|
||||
func (s NoImpl) List(ctx context.Context, options ListOptions) ([]Stack, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Convert implements Service interface
|
||||
func (s NoImpl) Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Kill implements Service interface
|
||||
func (s NoImpl) Kill(ctx context.Context, project *types.Project, options KillOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//RunOneOffContainer implements Service interface
|
||||
func (s NoImpl) RunOneOffContainer(ctx context.Context, project *types.Project, options RunOptions) (int, error) {
|
||||
return 0, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Remove implements Service interface
|
||||
func (s NoImpl) Remove(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Exec implements Service interface
|
||||
func (s NoImpl) Exec(ctx context.Context, project *types.Project, options RunOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Pause implements Service interface
|
||||
func (s NoImpl) Pause(ctx context.Context, project string, options PauseOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//UnPause implements Service interface
|
||||
func (s NoImpl) UnPause(ctx context.Context, project string, options PauseOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Top implements Service interface
|
||||
func (s NoImpl) Top(ctx context.Context, project string, services []string) ([]ContainerProcSummary, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Events implements Service interface
|
||||
func (s NoImpl) Events(ctx context.Context, project string, options EventsOptions) error {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Port implements Service interface
|
||||
func (s NoImpl) Port(ctx context.Context, project string, service string, port int, options PortOptions) (string, int, error) {
|
||||
return "", 0, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
||||
//Images implements Service interface
|
||||
func (s NoImpl) Images(ctx context.Context, project string, options ImagesOptions) ([]ImageSummary, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
}
|
@ -34,6 +34,9 @@ GO_BUILD=$(STATIC_FLAGS) go build -trimpath -ldflags=$(LDFLAGS)
|
||||
BINARY?=bin/docker
|
||||
BINARY_WITH_EXTENSION=$(BINARY)$(EXTENSION)
|
||||
|
||||
COMPOSE_BINARY?=bin/docker-compose
|
||||
COMPOSE_BINARY_WITH_EXTENSION=$(COMPOSE_BINARY)$(EXTENSION)
|
||||
|
||||
WORK_DIR:=$(shell mktemp -d)
|
||||
|
||||
TAGS:=
|
||||
@ -42,9 +45,22 @@ ifdef BUILD_TAGS
|
||||
LINT_TAGS=--build-tags $(BUILD_TAGS)
|
||||
endif
|
||||
|
||||
TAR_TRANSFORM:=--transform s/packaging/docker/ --transform s/bin/docker/ --transform s/docker-linux-amd64/docker/ --transform s/docker-darwin-amd64/docker/ --transform s/docker-linux-arm64/docker/ --transform s/docker-linux-armv6/docker/ --transform s/docker-linux-armv7/docker/ --transform s/docker-darwin-arm64/docker/
|
||||
TAR_TRANSFORM:=--transform s/packaging/docker/ --transform s/bin/docker/ \
|
||||
--transform s/docker-linux-amd64/docker/ --transform s/docker-linux-arm64/docker/ \
|
||||
--transform s/docker-linux-armv6/docker/ --transform s/docker-linux-armv7/docker/ \
|
||||
--transform s/docker-darwin-amd64/docker/ --transform s/docker-darwin-arm64/docker/ \
|
||||
--transform s/docker-compose-linux-amd64/docker-compose/ --transform s/docker-compose-linux-arm64/docker-compose/ \
|
||||
--transform s/docker-compose-linux-armv6/docker-compose/ --transform s/docker-compose-linux-armv7/docker-compose/ \
|
||||
--transform s/docker-compose-darwin-amd64/docker-compose/ --transform s/docker-compose-darwin-arm64/docker-compose/
|
||||
|
||||
ifneq ($(findstring bsd,$(shell tar --version)),)
|
||||
TAR_TRANSFORM=-s /packaging/docker/ -s /bin/docker/ -s /docker-linux-amd64/docker/ -s /docker-darwin-amd64/docker/ -s /docker-linux-arm64/docker/ -s /docker-linux-armv6/docker/ -s /docker-linux-armv7/docker/ -s /docker-darwin-arm64/docker/
|
||||
TAR_TRANSFORM=-s /packaging/docker/ -s /bin/docker/ \
|
||||
-s /docker-linux-amd64/docker/ -s /docker-linux-arm64/docker/ \
|
||||
-s /docker-linux-armv6/docker/ -s /docker-linux-armv7/docker/ \
|
||||
-s /docker-darwin-amd64/docker/ -s /docker-darwin-arm64/docker/ \
|
||||
-s /docker-compose-linux-amd64/docker-compose/ -s /docker-compose-linux-arm64/docker-compose/ \
|
||||
-s /docker-compose-linux-armv6/docker-compose/ -s /docker-compose-linux-armv7/docker-compose/ \
|
||||
-s /docker-compose-darwin-amd64/docker-compose/ -s /docker-compose-darwin-arm64/docker-compose/
|
||||
endif
|
||||
|
||||
all: cli
|
||||
@ -54,11 +70,15 @@ protos:
|
||||
protoc -I. --go_out=plugins=grpc,paths=source_relative:. ${PROTOS}
|
||||
|
||||
.PHONY: cli
|
||||
cli:
|
||||
cli: compose-plugin
|
||||
GOOS=${GOOS} GOARCH=${GOARCH} $(GO_BUILD) $(TAGS) -o $(BINARY_WITH_EXTENSION) ./cli
|
||||
|
||||
.PHONY: compose-plugin
|
||||
compose-plugin:
|
||||
GOOS=${GOOS} GOARCH=${GOARCH} $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY_WITH_EXTENSION) .
|
||||
|
||||
.PHONY: cross
|
||||
cross:
|
||||
cross: cross-compose-plugin
|
||||
GOOS=linux GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(BINARY)-linux-amd64 ./cli
|
||||
GOOS=linux GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(BINARY)-linux-arm64 ./cli
|
||||
GOOS=linux GOARM=6 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(BINARY)-linux-armv6 ./cli
|
||||
@ -67,6 +87,16 @@ cross:
|
||||
GOOS=darwin GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(BINARY)-darwin-arm64 ./cli
|
||||
GOOS=windows GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(BINARY)-windows-amd64.exe ./cli
|
||||
|
||||
.PHONY: cross-compose-plugin
|
||||
cross-compose-plugin:
|
||||
GOOS=linux GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-amd64 .
|
||||
GOOS=linux GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-arm64 .
|
||||
GOOS=linux GOARM=6 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-armv6 .
|
||||
GOOS=linux GOARM=7 GOARCH=arm $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-linux-armv7 .
|
||||
GOOS=darwin GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-darwin-amd64 .
|
||||
GOOS=darwin GOARCH=arm64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-darwin-arm64 .
|
||||
GOOS=windows GOARCH=amd64 $(GO_BUILD) $(TAGS) -o $(COMPOSE_BINARY)-windows-amd64.exe .
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test $(TAGS) -cover $(shell go list $(TAGS) ./... | grep -vE 'e2e')
|
||||
@ -90,14 +120,15 @@ check-go-mod:
|
||||
.PHONY: package
|
||||
package: cross
|
||||
mkdir -p dist
|
||||
tar -czf dist/docker-linux-amd64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-amd64
|
||||
tar -czf dist/docker-linux-arm64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-arm64
|
||||
tar -czf dist/docker-linux-armv6.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-armv6
|
||||
tar -czf dist/docker-linux-armv7.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-armv7
|
||||
tar -czf dist/docker-darwin-amd64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-darwin-amd64
|
||||
tar -czf dist/docker-darwin-arm64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-darwin-arm64
|
||||
tar -czf dist/docker-linux-amd64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-amd64 $(COMPOSE_BINARY)-linux-amd64
|
||||
tar -czf dist/docker-linux-arm64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-arm64 $(COMPOSE_BINARY)-linux-arm64
|
||||
tar -czf dist/docker-linux-armv6.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-armv6 $(COMPOSE_BINARY)-linux-armv6
|
||||
tar -czf dist/docker-linux-armv7.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-linux-armv7 $(COMPOSE_BINARY)-linux-armv7
|
||||
tar -czf dist/docker-darwin-amd64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-darwin-amd64 $(COMPOSE_BINARY)-darwin-amd64
|
||||
tar -czf dist/docker-darwin-arm64.tar.gz $(TAR_TRANSFORM) packaging/LICENSE $(BINARY)-darwin-arm64 $(COMPOSE_BINARY)-darwin-arm64
|
||||
cp $(BINARY)-windows-amd64.exe $(WORK_DIR)/docker.exe
|
||||
rm -f dist/docker-windows-amd64.zip && zip dist/docker-windows-amd64.zip -j packaging/LICENSE $(WORK_DIR)/docker.exe
|
||||
cp $(COMPOSE_BINARY)-windows-amd64.exe $(WORK_DIR)/docker-compose.exe
|
||||
rm -f dist/docker-windows-amd64.zip && zip dist/docker-windows-amd64.zip -j packaging/LICENSE $(WORK_DIR)/docker.exe $(WORK_DIR)/docker-compose.exe
|
||||
rm -r $(WORK_DIR)
|
||||
|
||||
.PHONY: yamldocs
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
)
|
||||
@ -40,14 +39,14 @@ type buildOptions struct {
|
||||
memory string
|
||||
}
|
||||
|
||||
func buildCommand(p *projectOptions) *cobra.Command {
|
||||
func buildCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := buildOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "build [SERVICE...]",
|
||||
Short: "Build or rebuild services",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.memory != "" {
|
||||
fmt.Println("WARNING --memory is ignored as not supported in buildkit.")
|
||||
}
|
||||
@ -58,8 +57,8 @@ func buildCommand(p *projectOptions) *cobra.Command {
|
||||
}
|
||||
os.Stdout = devnull
|
||||
}
|
||||
return runBuild(cmd.Context(), opts, args)
|
||||
},
|
||||
return runBuild(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Don't print anything to STDOUT")
|
||||
cmd.Flags().BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image.")
|
||||
@ -80,19 +79,14 @@ func buildCommand(p *projectOptions) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runBuild(ctx context.Context, opts buildOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runBuild(ctx context.Context, backend compose.Service, opts buildOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Build(ctx, project, compose.BuildOptions{
|
||||
return "", backend.Build(ctx, project, compose.BuildOptions{
|
||||
Pull: opts.pull,
|
||||
Progress: opts.progress,
|
||||
Args: types.NewMapping(opts.args),
|
||||
|
@ -17,22 +17,64 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
dockercli "github.com/docker/cli/cli"
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/context/store"
|
||||
"github.com/docker/compose-cli/api/errdefs"
|
||||
"github.com/docker/compose-cli/cli/formatter"
|
||||
"github.com/docker/compose-cli/cli/metrics"
|
||||
)
|
||||
|
||||
//Command defines a compose CLI command as a func with args
|
||||
type Command func(context.Context, []string) error
|
||||
|
||||
//Adapt a Command func to cobra library
|
||||
func Adapt(fn Command) func(cmd *cobra.Command, args []string) error {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
contextString := fmt.Sprintf("%s", ctx)
|
||||
if !strings.HasSuffix(contextString, ".WithCancel") { // need to handle cancel
|
||||
cancellableCtx, cancel := context.WithCancel(cmd.Context())
|
||||
ctx = cancellableCtx
|
||||
s := make(chan os.Signal, 1)
|
||||
signal.Notify(s, syscall.SIGTERM, syscall.SIGINT)
|
||||
go func() {
|
||||
<-s
|
||||
cancel()
|
||||
}()
|
||||
}
|
||||
err := fn(ctx, args)
|
||||
var composeErr metrics.ComposeError
|
||||
if errdefs.IsErrCanceled(err) || errors.Is(ctx.Err(), context.Canceled) {
|
||||
err = dockercli.StatusError{
|
||||
StatusCode: 130,
|
||||
Status: metrics.CanceledStatus,
|
||||
}
|
||||
}
|
||||
if errors.As(err, &composeErr) {
|
||||
err = dockercli.StatusError{
|
||||
StatusCode: composeErr.GetMetricsFailureCategory().ExitCode,
|
||||
Status: err.Error(),
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Warning is a global warning to be displayed to user on command failure
|
||||
var Warning string
|
||||
|
||||
@ -104,8 +146,8 @@ func (o *projectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.Proj
|
||||
cli.WithName(o.ProjectName))...)
|
||||
}
|
||||
|
||||
// Command returns the compose command with its child commands
|
||||
func Command(contextType string) *cobra.Command {
|
||||
// RootCommand returns the compose command with its child commands
|
||||
func RootCommand(contextType string, backend compose.Service) *cobra.Command {
|
||||
opts := projectOptions{}
|
||||
var ansi string
|
||||
var noAnsi bool
|
||||
@ -119,9 +161,20 @@ func Command(contextType string) *cobra.Command {
|
||||
return cmd.Help()
|
||||
}
|
||||
_ = cmd.Help()
|
||||
return fmt.Errorf("unknown docker command: %q", "compose "+args[0])
|
||||
return dockercli.StatusError{
|
||||
StatusCode: metrics.CommandSyntaxFailure.ExitCode,
|
||||
Status: fmt.Sprintf("unknown docker command: %q", "compose "+args[0]),
|
||||
}
|
||||
},
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
parent := cmd.Root()
|
||||
parentPrerun := parent.PersistentPreRunE
|
||||
if parentPrerun != nil {
|
||||
err := parentPrerun(cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if noAnsi {
|
||||
if ansi != "auto" {
|
||||
return errors.New(`cannot specify DEPRECATED "--no-ansi" and "--ansi". Please use only "--ansi"`)
|
||||
@ -146,34 +199,34 @@ func Command(contextType string) *cobra.Command {
|
||||
}
|
||||
|
||||
command.AddCommand(
|
||||
upCommand(&opts, contextType),
|
||||
downCommand(&opts, contextType),
|
||||
startCommand(&opts),
|
||||
restartCommand(&opts),
|
||||
stopCommand(&opts),
|
||||
psCommand(&opts),
|
||||
listCommand(contextType),
|
||||
logsCommand(&opts, contextType),
|
||||
convertCommand(&opts),
|
||||
killCommand(&opts),
|
||||
runCommand(&opts),
|
||||
removeCommand(&opts),
|
||||
execCommand(&opts),
|
||||
pauseCommand(&opts),
|
||||
unpauseCommand(&opts),
|
||||
topCommand(&opts),
|
||||
eventsCommand(&opts),
|
||||
portCommand(&opts),
|
||||
imagesCommand(&opts),
|
||||
upCommand(&opts, contextType, backend),
|
||||
downCommand(&opts, contextType, backend),
|
||||
startCommand(&opts, backend),
|
||||
restartCommand(&opts, backend),
|
||||
stopCommand(&opts, backend),
|
||||
psCommand(&opts, backend),
|
||||
listCommand(contextType, backend),
|
||||
logsCommand(&opts, contextType, backend),
|
||||
convertCommand(&opts, backend),
|
||||
killCommand(&opts, backend),
|
||||
runCommand(&opts, backend),
|
||||
removeCommand(&opts, backend),
|
||||
execCommand(&opts, backend),
|
||||
pauseCommand(&opts, backend),
|
||||
unpauseCommand(&opts, backend),
|
||||
topCommand(&opts, backend),
|
||||
eventsCommand(&opts, backend),
|
||||
portCommand(&opts, backend),
|
||||
imagesCommand(&opts, backend),
|
||||
versionCommand(),
|
||||
)
|
||||
|
||||
if contextType == store.LocalContextType || contextType == store.DefaultContextType {
|
||||
command.AddCommand(
|
||||
buildCommand(&opts),
|
||||
pushCommand(&opts),
|
||||
pullCommand(&opts),
|
||||
createCommand(&opts),
|
||||
buildCommand(&opts, backend),
|
||||
pushCommand(&opts, backend),
|
||||
pullCommand(&opts, backend),
|
||||
createCommand(&opts, backend),
|
||||
)
|
||||
}
|
||||
command.Flags().SetInterspersed(false)
|
||||
|
@ -31,9 +31,7 @@ import (
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/config"
|
||||
"github.com/docker/compose-cli/utils"
|
||||
)
|
||||
|
||||
@ -52,7 +50,7 @@ type convertOptions struct {
|
||||
|
||||
var addFlagsFuncs []func(cmd *cobra.Command, opts *convertOptions)
|
||||
|
||||
func convertCommand(p *projectOptions) *cobra.Command {
|
||||
func convertCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := convertOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
@ -60,7 +58,7 @@ func convertCommand(p *projectOptions) *cobra.Command {
|
||||
Aliases: []string{"config"},
|
||||
Use: "convert SERVICES",
|
||||
Short: "Converts the compose file to platform's canonical format",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.quiet {
|
||||
devnull, err := os.Open(os.DevNull)
|
||||
if err != nil {
|
||||
@ -81,8 +79,8 @@ func convertCommand(p *projectOptions) *cobra.Command {
|
||||
return runProfiles(opts, args)
|
||||
}
|
||||
|
||||
return runConvert(cmd.Context(), opts, args)
|
||||
},
|
||||
return runConvert(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.StringVar(&opts.Format, "format", "yaml", "Format the output. Values: [yaml | json]")
|
||||
@ -102,23 +100,15 @@ func convertCommand(p *projectOptions) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runConvert(ctx context.Context, opts convertOptions, services []string) error {
|
||||
func runConvert(ctx context.Context, backend compose.Service, opts convertOptions, services []string) error {
|
||||
var json []byte
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project, err := opts.toProject(services, cli.WithInterpolation(!opts.noInterpolate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.resolve {
|
||||
configFile, err := cliconfig.Load(config.Dir())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
configFile := cliconfig.LoadDefaultConfigFile(os.Stderr)
|
||||
|
||||
resolver := remotes.CreateResolver(configFile)
|
||||
err = project.ResolveImages(func(named reference.Named) (digest.Digest, error) {
|
||||
@ -130,7 +120,7 @@ func runConvert(ctx context.Context, opts convertOptions, services []string) err
|
||||
}
|
||||
}
|
||||
|
||||
json, err = c.ComposeService().Convert(ctx, project, compose.ConvertOptions{
|
||||
json, err = backend.Convert(ctx, project, compose.ConvertOptions{
|
||||
Format: opts.Format,
|
||||
Output: opts.Output,
|
||||
})
|
||||
|
@ -17,9 +17,12 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
)
|
||||
|
||||
type createOptions struct {
|
||||
@ -28,21 +31,21 @@ type createOptions struct {
|
||||
noRecreate bool
|
||||
}
|
||||
|
||||
func createCommand(p *projectOptions) *cobra.Command {
|
||||
func createCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := createOptions{
|
||||
composeOptions: &composeOptions{},
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "create [SERVICE...]",
|
||||
Short: "Creates containers for a service.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.Build && opts.noBuild {
|
||||
return fmt.Errorf("--build and --no-build are incompatible")
|
||||
}
|
||||
if opts.forceRecreate && opts.noRecreate {
|
||||
return fmt.Errorf("--force-recreate and --no-recreate are incompatible")
|
||||
}
|
||||
return runCreateStart(cmd.Context(), upOptions{
|
||||
return runCreateStart(ctx, backend, upOptions{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
Build: opts.Build,
|
||||
@ -52,7 +55,7 @@ func createCommand(p *projectOptions) *cobra.Command {
|
||||
forceRecreate: opts.forceRecreate,
|
||||
noRecreate: opts.noRecreate,
|
||||
}, args)
|
||||
},
|
||||
}),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.")
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/context/store"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
@ -39,22 +38,24 @@ type downOptions struct {
|
||||
images string
|
||||
}
|
||||
|
||||
func downCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
func downCommand(p *projectOptions, contextType string, backend compose.Service) *cobra.Command {
|
||||
opts := downOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
downCmd := &cobra.Command{
|
||||
Use: "down",
|
||||
Short: "Stop and remove containers, networks",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.images != "" {
|
||||
if opts.images != "all" && opts.images != "local" {
|
||||
return fmt.Errorf("invalid value for --rmi: %q", opts.images)
|
||||
}
|
||||
}
|
||||
return runDown(cmd.Context(), opts)
|
||||
},
|
||||
return runDown(ctx, backend, opts)
|
||||
}),
|
||||
}
|
||||
flags := downCmd.Flags()
|
||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
|
||||
@ -68,13 +69,8 @@ func downCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
return downCmd
|
||||
}
|
||||
|
||||
func runDown(ctx context.Context, opts downOptions) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
func runDown(ctx context.Context, backend compose.Service, opts downOptions) error {
|
||||
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
name := opts.ProjectName
|
||||
var project *types.Project
|
||||
if opts.ProjectName == "" {
|
||||
@ -91,7 +87,7 @@ func runDown(ctx context.Context, opts downOptions) error {
|
||||
timeoutValue := time.Duration(opts.timeout) * time.Second
|
||||
timeout = &timeoutValue
|
||||
}
|
||||
return name, c.ComposeService().Down(ctx, name, compose.DownOptions{
|
||||
return name, backend.Down(ctx, name, compose.DownOptions{
|
||||
RemoveOrphans: opts.removeOrphans,
|
||||
Project: project,
|
||||
Timeout: timeout,
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@ -32,7 +31,7 @@ type eventsOpts struct {
|
||||
json bool
|
||||
}
|
||||
|
||||
func eventsCommand(p *projectOptions) *cobra.Command {
|
||||
func eventsCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := eventsOpts{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
@ -41,27 +40,22 @@ func eventsCommand(p *projectOptions) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "events [options] [--] [SERVICE...]",
|
||||
Short: "Receive real time events from containers.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runEvents(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runEvents(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&opts.json, "json", false, "Output events as a stream of json objects")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runEvents(ctx context.Context, opts eventsOpts, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runEvents(ctx context.Context, backend compose.Service, opts eventsOpts, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.ComposeService().Events(ctx, project, compose.EventsOptions{
|
||||
return backend.Events(ctx, project, compose.EventsOptions{
|
||||
Services: services,
|
||||
Consumer: func(event compose.Event) error {
|
||||
if opts.json {
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"github.com/containerd/console"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
)
|
||||
|
||||
@ -43,7 +42,7 @@ type execOpts struct {
|
||||
privileged bool
|
||||
}
|
||||
|
||||
func execCommand(p *projectOptions) *cobra.Command {
|
||||
func execCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := execOpts{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
@ -53,13 +52,13 @@ func execCommand(p *projectOptions) *cobra.Command {
|
||||
Use: "exec [options] [-e KEY=VAL...] [--] SERVICE COMMAND [ARGS...]",
|
||||
Short: "Execute a command in a running container.",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if len(args) > 1 {
|
||||
opts.command = args[1:]
|
||||
}
|
||||
opts.service = args[0]
|
||||
return runExec(cmd.Context(), opts)
|
||||
},
|
||||
return runExec(ctx, backend, opts)
|
||||
}),
|
||||
}
|
||||
|
||||
runCmd.Flags().BoolVarP(&opts.detach, "detach", "d", false, "Detached mode: Run command in the background.")
|
||||
@ -74,12 +73,7 @@ func execCommand(p *projectOptions) *cobra.Command {
|
||||
return runCmd
|
||||
}
|
||||
|
||||
func runExec(ctx context.Context, opts execOpts) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runExec(ctx context.Context, backend compose.Service, opts execOpts) error {
|
||||
project, err := opts.toProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -114,5 +108,5 @@ func runExec(ctx context.Context, opts execOpts) error {
|
||||
execOpts.Writer = con
|
||||
execOpts.Reader = con
|
||||
}
|
||||
return c.ComposeService().Exec(ctx, project, execOpts)
|
||||
return backend.Exec(ctx, project, execOpts)
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/cli/formatter"
|
||||
"github.com/docker/compose-cli/utils"
|
||||
@ -40,33 +39,28 @@ type imageOptions struct {
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
func imagesCommand(p *projectOptions) *cobra.Command {
|
||||
func imagesCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := imageOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
imgCmd := &cobra.Command{
|
||||
Use: "images [SERVICE...]",
|
||||
Short: "List images used by the created containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runImages(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runImages(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
imgCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
|
||||
return imgCmd
|
||||
}
|
||||
|
||||
func runImages(ctx context.Context, opts imageOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runImages(ctx context.Context, backend compose.Service, opts imageOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
images, err := c.ComposeService().Images(ctx, projectName, compose.ImagesOptions{
|
||||
images, err := backend.Images(ctx, projectName, compose.ImagesOptions{
|
||||
Services: services,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
)
|
||||
|
||||
@ -30,16 +29,16 @@ type killOptions struct {
|
||||
Signal string
|
||||
}
|
||||
|
||||
func killCommand(p *projectOptions) *cobra.Command {
|
||||
func killCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := killOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "kill [options] [SERVICE...]",
|
||||
Short: "Force stop service containers.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runKill(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runKill(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
@ -48,16 +47,12 @@ func killCommand(p *projectOptions) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runKill(ctx context.Context, opts killOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func runKill(ctx context.Context, backend compose.Service, opts killOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.ComposeService().Kill(ctx, project, compose.KillOptions{
|
||||
return backend.Kill(ctx, project, compose.KillOptions{
|
||||
Signal: opts.Signal,
|
||||
})
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/context/store"
|
||||
"github.com/docker/compose-cli/cli/formatter"
|
||||
@ -39,14 +38,14 @@ type lsOptions struct {
|
||||
Filter opts.FilterOpt
|
||||
}
|
||||
|
||||
func listCommand(contextType string) *cobra.Command {
|
||||
func listCommand(contextType string, backend compose.Service) *cobra.Command {
|
||||
opts := lsOptions{Filter: opts.NewFilterOpt()}
|
||||
lsCmd := &cobra.Command{
|
||||
Use: "ls",
|
||||
Short: "List running compose projects",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runList(cmd.Context(), opts)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runList(ctx, backend, opts)
|
||||
}),
|
||||
}
|
||||
lsCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
|
||||
lsCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs.")
|
||||
@ -62,18 +61,14 @@ var acceptedListFilters = map[string]bool{
|
||||
"name": true,
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, opts lsOptions) error {
|
||||
func runList(ctx context.Context, backend compose.Service, opts lsOptions) error {
|
||||
filters := opts.Filter.Value()
|
||||
err := filters.Validate(acceptedListFilters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stackList, err := c.ComposeService().List(ctx, compose.ListOptions{All: opts.All})
|
||||
stackList, err := backend.List(ctx, compose.ListOptions{All: opts.All})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/context/store"
|
||||
"github.com/docker/compose-cli/cli/formatter"
|
||||
@ -38,16 +37,16 @@ type logsOptions struct {
|
||||
timestamps bool
|
||||
}
|
||||
|
||||
func logsCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
func logsCommand(p *projectOptions, contextType string, backend compose.Service) *cobra.Command {
|
||||
opts := logsOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
logsCmd := &cobra.Command{
|
||||
Use: "logs [service...]",
|
||||
Short: "View output from containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runLogs(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runLogs(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
flags := logsCmd.Flags()
|
||||
flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output.")
|
||||
@ -61,18 +60,13 @@ func logsCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
return logsCmd
|
||||
}
|
||||
|
||||
func runLogs(ctx context.Context, opts logsOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runLogs(ctx context.Context, backend compose.Service, opts logsOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
consumer := formatter.NewLogConsumer(ctx, os.Stdout, !opts.noColor, !opts.noPrefix)
|
||||
return c.ComposeService().Logs(ctx, projectName, consumer, compose.LogOptions{
|
||||
return backend.Logs(ctx, projectName, consumer, compose.LogOptions{
|
||||
Services: services,
|
||||
Follow: opts.follow,
|
||||
Tail: opts.tail,
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
)
|
||||
@ -30,33 +29,28 @@ type pauseOptions struct {
|
||||
*projectOptions
|
||||
}
|
||||
|
||||
func pauseCommand(p *projectOptions) *cobra.Command {
|
||||
func pauseCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := pauseOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "pause [SERVICE...]",
|
||||
Short: "pause services",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runPause(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPause(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPause(ctx context.Context, opts pauseOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runPause(ctx context.Context, backend compose.Service, opts pauseOptions, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Pause(ctx, project, compose.PauseOptions{
|
||||
return "", backend.Pause(ctx, project, compose.PauseOptions{
|
||||
Services: services,
|
||||
})
|
||||
})
|
||||
@ -67,33 +61,28 @@ type unpauseOptions struct {
|
||||
*projectOptions
|
||||
}
|
||||
|
||||
func unpauseCommand(p *projectOptions) *cobra.Command {
|
||||
func unpauseCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := unpauseOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "unpause [SERVICE...]",
|
||||
Short: "unpause services",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runUnPause(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runUnPause(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runUnPause(ctx context.Context, opts unpauseOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runUnPause(ctx context.Context, backend compose.Service, opts unpauseOptions, services []string) error {
|
||||
project, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().UnPause(ctx, project, compose.PauseOptions{
|
||||
return "", backend.UnPause(ctx, project, compose.PauseOptions{
|
||||
Services: services,
|
||||
})
|
||||
})
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
)
|
||||
|
||||
@ -33,7 +32,7 @@ type portOptions struct {
|
||||
index int
|
||||
}
|
||||
|
||||
func portCommand(p *projectOptions) *cobra.Command {
|
||||
func portCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := portOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
@ -41,30 +40,25 @@ func portCommand(p *projectOptions) *cobra.Command {
|
||||
Use: "port [options] [--] SERVICE PRIVATE_PORT",
|
||||
Short: "Print the public port for a port binding.",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
port, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runPort(cmd.Context(), opts, args[0], port)
|
||||
},
|
||||
return runPort(ctx, backend, opts, args[0], port)
|
||||
}),
|
||||
}
|
||||
cmd.Flags().StringVar(&opts.protocol, "protocol", "tcp", "tcp or udp")
|
||||
cmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if service has multiple replicas")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPort(ctx context.Context, opts portOptions, service string, port int) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runPort(ctx context.Context, backend compose.Service, opts portOptions, service string, port int) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip, port, err := c.ComposeService().Port(ctx, projectName, service, port, compose.PortOptions{
|
||||
ip, port, err := backend.Port(ctx, projectName, service, port, compose.PortOptions{
|
||||
Protocol: opts.protocol,
|
||||
Index: opts.index,
|
||||
})
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/cli/formatter"
|
||||
"github.com/docker/compose-cli/utils"
|
||||
@ -40,16 +39,16 @@ type psOptions struct {
|
||||
Services bool
|
||||
}
|
||||
|
||||
func psCommand(p *projectOptions) *cobra.Command {
|
||||
func psCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := psOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
psCmd := &cobra.Command{
|
||||
Use: "ps",
|
||||
Short: "List containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runPs(cmd.Context(), opts)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPs(ctx, backend, opts)
|
||||
}),
|
||||
}
|
||||
psCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
|
||||
psCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
|
||||
@ -58,17 +57,12 @@ func psCommand(p *projectOptions) *cobra.Command {
|
||||
return psCmd
|
||||
}
|
||||
|
||||
func runPs(ctx context.Context, opts psOptions) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runPs(ctx context.Context, backend compose.Service, opts psOptions) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := c.ComposeService().Ps(ctx, projectName, compose.PsOptions{
|
||||
containers, err := backend.Ps(ctx, projectName, compose.PsOptions{
|
||||
All: opts.All,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
"github.com/docker/compose-cli/utils"
|
||||
@ -40,19 +39,19 @@ type pullOptions struct {
|
||||
ignorePullFailures bool
|
||||
}
|
||||
|
||||
func pullCommand(p *projectOptions) *cobra.Command {
|
||||
func pullCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := pullOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "pull [SERVICE...]",
|
||||
Short: "Pull service images",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.noParallel {
|
||||
fmt.Fprint(os.Stderr, aec.Apply("option '--no-parallel' is DEPRECATED and will be ignored.\n", aec.RedF))
|
||||
}
|
||||
return runPull(cmd.Context(), opts, args)
|
||||
},
|
||||
return runPull(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Pull without printing progress information")
|
||||
@ -65,12 +64,7 @@ func pullCommand(p *projectOptions) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPull(ctx context.Context, opts pullOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runPull(ctx context.Context, backend compose.Service, opts pullOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -94,11 +88,11 @@ func runPull(ctx context.Context, opts pullOptions, services []string) error {
|
||||
}
|
||||
|
||||
if opts.quiet {
|
||||
return c.ComposeService().Pull(ctx, project, apiOpts)
|
||||
return backend.Pull(ctx, project, apiOpts)
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Pull(ctx, project, apiOpts)
|
||||
return "", backend.Pull(ctx, project, apiOpts)
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
)
|
||||
@ -33,35 +32,30 @@ type pushOptions struct {
|
||||
Ignorefailures bool
|
||||
}
|
||||
|
||||
func pushCommand(p *projectOptions) *cobra.Command {
|
||||
func pushCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := pushOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
pushCmd := &cobra.Command{
|
||||
Use: "push [SERVICE...]",
|
||||
Short: "Push service images",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runPush(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPush(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
pushCmd.Flags().BoolVar(&opts.Ignorefailures, "ignore-push-failures", false, "Push what it can and ignores images with push failures")
|
||||
|
||||
return pushCmd
|
||||
}
|
||||
|
||||
func runPush(ctx context.Context, opts pushOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runPush(ctx context.Context, backend compose.Service, opts pushOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Push(ctx, project, compose.PushOptions{
|
||||
return "", backend.Push(ctx, project, compose.PushOptions{
|
||||
IgnoreFailures: opts.Ignorefailures,
|
||||
})
|
||||
})
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
"github.com/docker/compose-cli/utils/prompt"
|
||||
@ -36,7 +35,7 @@ type removeOptions struct {
|
||||
volumes bool
|
||||
}
|
||||
|
||||
func removeCommand(p *projectOptions) *cobra.Command {
|
||||
func removeCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := removeOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
@ -49,9 +48,9 @@ By default, anonymous volumes attached to containers will not be removed. You
|
||||
can override this with -v. To list all volumes, use "docker volume ls".
|
||||
|
||||
Any data which is not in a volume will be lost.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRemove(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runRemove(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
f := cmd.Flags()
|
||||
f.BoolVarP(&opts.force, "force", "f", false, "Don't ask to confirm removal")
|
||||
@ -60,12 +59,7 @@ Any data which is not in a volume will be lost.`,
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runRemove(ctx context.Context, opts removeOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runRemove(ctx context.Context, backend compose.Service, opts removeOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -73,7 +67,7 @@ func runRemove(ctx context.Context, opts removeOptions, services []string) error
|
||||
|
||||
if opts.stop {
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
err := c.ComposeService().Stop(ctx, project, compose.StopOptions{
|
||||
err := backend.Stop(ctx, project, compose.StopOptions{
|
||||
Services: services,
|
||||
})
|
||||
return "", err
|
||||
@ -83,7 +77,7 @@ func runRemove(ctx context.Context, opts removeOptions, services []string) error
|
||||
}
|
||||
}
|
||||
|
||||
reosurces, err := c.ComposeService().Remove(ctx, project, compose.RemoveOptions{
|
||||
reosurces, err := backend.Remove(ctx, project, compose.RemoveOptions{
|
||||
DryRun: true,
|
||||
Services: services,
|
||||
})
|
||||
@ -109,7 +103,7 @@ func runRemove(ctx context.Context, opts removeOptions, services []string) error
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
_, err = c.ComposeService().Remove(ctx, project, compose.RemoveOptions{
|
||||
_, err = backend.Remove(ctx, project, compose.RemoveOptions{
|
||||
Volumes: opts.volumes,
|
||||
Force: opts.force,
|
||||
})
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
)
|
||||
@ -32,16 +31,16 @@ type restartOptions struct {
|
||||
timeout int
|
||||
}
|
||||
|
||||
func restartCommand(p *projectOptions) *cobra.Command {
|
||||
func restartCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := restartOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
restartCmd := &cobra.Command{
|
||||
Use: "restart",
|
||||
Short: "Restart containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runRestart(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runRestart(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
flags := restartCmd.Flags()
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||
@ -49,12 +48,7 @@ func restartCommand(p *projectOptions) *cobra.Command {
|
||||
return restartCmd
|
||||
}
|
||||
|
||||
func runRestart(ctx context.Context, opts restartOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runRestart(ctx context.Context, backend compose.Service, opts restartOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -62,7 +56,7 @@ func runRestart(ctx context.Context, opts restartOptions, services []string) err
|
||||
|
||||
timeout := time.Duration(opts.timeout) * time.Second
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Restart(ctx, project, compose.RestartOptions{
|
||||
return "", backend.Restart(ctx, project, compose.RestartOptions{
|
||||
Timeout: &timeout,
|
||||
})
|
||||
})
|
||||
|
@ -28,7 +28,6 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
)
|
||||
@ -100,7 +99,7 @@ func (opts runOptions) apply(project *types.Project) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCommand(p *projectOptions) *cobra.Command {
|
||||
func runCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := runOptions{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
@ -110,7 +109,7 @@ func runCommand(p *projectOptions) *cobra.Command {
|
||||
Use: "run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]",
|
||||
Short: "Run a one-off command on a service.",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if len(args) > 1 {
|
||||
opts.Command = args[1:]
|
||||
}
|
||||
@ -118,8 +117,8 @@ func runCommand(p *projectOptions) *cobra.Command {
|
||||
if len(opts.publish) > 0 && opts.servicePorts {
|
||||
return fmt.Errorf("--service-ports and --publish are incompatible")
|
||||
}
|
||||
return runRun(cmd.Context(), opts)
|
||||
},
|
||||
return runRun(ctx, backend, opts)
|
||||
}),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
|
||||
@ -141,8 +140,8 @@ func runCommand(p *projectOptions) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runRun(ctx context.Context, opts runOptions) error {
|
||||
c, project, err := setup(ctx, *opts.composeOptions, []string{opts.Service})
|
||||
func runRun(ctx context.Context, backend compose.Service, opts runOptions) error {
|
||||
project, err := setup(*opts.composeOptions, []string{opts.Service})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -153,7 +152,7 @@ func runRun(ctx context.Context, opts runOptions) error {
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", startDependencies(ctx, c, *project, opts.Service)
|
||||
return "", startDependencies(ctx, backend, *project, opts.Service)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@ -194,7 +193,7 @@ func runRun(ctx context.Context, opts runOptions) error {
|
||||
UseNetworkAliases: opts.useAliases,
|
||||
Index: 0,
|
||||
}
|
||||
exitCode, err := c.ComposeService().RunOneOffContainer(ctx, project, runOpts)
|
||||
exitCode, err := backend.RunOneOffContainer(ctx, project, runOpts)
|
||||
if exitCode != 0 {
|
||||
errMsg := ""
|
||||
if err != nil {
|
||||
@ -205,7 +204,7 @@ func runRun(ctx context.Context, opts runOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func startDependencies(ctx context.Context, c *client.Client, project types.Project, requestedServiceName string) error {
|
||||
func startDependencies(ctx context.Context, backend compose.Service, project types.Project, requestedServiceName string) error {
|
||||
dependencies := types.Services{}
|
||||
var requestedService types.ServiceConfig
|
||||
for _, service := range project.Services {
|
||||
@ -218,10 +217,10 @@ func startDependencies(ctx context.Context, c *client.Client, project types.Proj
|
||||
|
||||
project.Services = dependencies
|
||||
project.DisabledServices = append(project.DisabledServices, requestedService)
|
||||
if err := c.ComposeService().Create(ctx, &project, compose.CreateOptions{}); err != nil {
|
||||
if err := backend.Create(ctx, &project, compose.CreateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.ComposeService().Start(ctx, &project, compose.StartOptions{}); err != nil {
|
||||
if err := backend.Start(ctx, &project, compose.StartOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -19,7 +19,6 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
|
||||
@ -30,33 +29,28 @@ type startOptions struct {
|
||||
*projectOptions
|
||||
}
|
||||
|
||||
func startCommand(p *projectOptions) *cobra.Command {
|
||||
func startCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := startOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
startCmd := &cobra.Command{
|
||||
Use: "start [SERVICE...]",
|
||||
Short: "Start services",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runStart(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runStart(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
return startCmd
|
||||
}
|
||||
|
||||
func runStart(ctx context.Context, opts startOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runStart(ctx context.Context, backend compose.Service, opts startOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Start(ctx, project, compose.StartOptions{})
|
||||
return "", backend.Start(ctx, project, compose.StartOptions{})
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
)
|
||||
@ -33,17 +32,19 @@ type stopOptions struct {
|
||||
timeout int
|
||||
}
|
||||
|
||||
func stopCommand(p *projectOptions) *cobra.Command {
|
||||
func stopCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := stopOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "stop [SERVICE...]",
|
||||
Short: "Stop services",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
return runStop(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runStop(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||
@ -51,12 +52,7 @@ func stopCommand(p *projectOptions) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runStop(ctx context.Context, opts stopOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func runStop(ctx context.Context, backend compose.Service, opts stopOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -68,7 +64,7 @@ func runStop(ctx context.Context, opts stopOptions, services []string) error {
|
||||
timeout = &timeoutValue
|
||||
}
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Stop(ctx, project, compose.StopOptions{
|
||||
return "", backend.Stop(ctx, project, compose.StopOptions{
|
||||
Timeout: timeout,
|
||||
Services: services,
|
||||
})
|
||||
|
@ -27,37 +27,33 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
)
|
||||
|
||||
type topOptions struct {
|
||||
*projectOptions
|
||||
}
|
||||
|
||||
func topCommand(p *projectOptions) *cobra.Command {
|
||||
func topCommand(p *projectOptions, backend compose.Service) *cobra.Command {
|
||||
opts := topOptions{
|
||||
projectOptions: p,
|
||||
}
|
||||
topCmd := &cobra.Command{
|
||||
Use: "top",
|
||||
Short: "Display the running processes",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runTop(cmd.Context(), opts, args)
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runTop(ctx, backend, opts, args)
|
||||
}),
|
||||
}
|
||||
return topCmd
|
||||
}
|
||||
|
||||
func runTop(ctx context.Context, opts topOptions, services []string) error {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func runTop(ctx context.Context, backend compose.Service, opts topOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, err := c.ComposeService().Top(ctx, projectName, services)
|
||||
containers, err := backend.Top(ctx, projectName, services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/context/store"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
@ -140,7 +139,7 @@ func (opts upOptions) apply(project *types.Project, services []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func upCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
func upCommand(p *projectOptions, contextType string, backend compose.Service) *cobra.Command {
|
||||
opts := upOptions{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
@ -149,8 +148,10 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
upCmd := &cobra.Command{
|
||||
Use: "up [SERVICE...]",
|
||||
Short: "Create and start containers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
switch contextType {
|
||||
case store.LocalContextType, store.DefaultContextType, store.EcsLocalSimulationContextType:
|
||||
if opts.exitCodeFrom != "" {
|
||||
@ -168,11 +169,11 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
if opts.recreateDeps && opts.noRecreate {
|
||||
return fmt.Errorf("--always-recreate-deps and --no-recreate are incompatible")
|
||||
}
|
||||
return runCreateStart(cmd.Context(), opts, args)
|
||||
return runCreateStart(ctx, backend, opts, args)
|
||||
default:
|
||||
return runUp(cmd.Context(), opts, args)
|
||||
return runUp(ctx, backend, opts, args)
|
||||
}
|
||||
},
|
||||
}),
|
||||
}
|
||||
flags := upCmd.Flags()
|
||||
flags.StringArrayVarP(&opts.Environment, "environment", "e", []string{}, "Environment variables")
|
||||
@ -204,8 +205,8 @@ func upCommand(p *projectOptions, contextType string) *cobra.Command {
|
||||
return upCmd
|
||||
}
|
||||
|
||||
func runUp(ctx context.Context, opts upOptions, services []string) error {
|
||||
c, project, err := setup(ctx, *opts.composeOptions, services)
|
||||
func runUp(ctx context.Context, backend compose.Service, opts upOptions, services []string) error {
|
||||
project, err := setup(*opts.composeOptions, services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -216,7 +217,7 @@ func runUp(ctx context.Context, opts upOptions, services []string) error {
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
return "", c.ComposeService().Up(ctx, project, compose.UpOptions{
|
||||
return "", backend.Up(ctx, project, compose.UpOptions{
|
||||
Detach: opts.Detach,
|
||||
QuietPull: opts.quietPull,
|
||||
})
|
||||
@ -224,8 +225,8 @@ func runUp(ctx context.Context, opts upOptions, services []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func runCreateStart(ctx context.Context, opts upOptions, services []string) error {
|
||||
c, project, err := setup(ctx, *opts.composeOptions, services)
|
||||
func runCreateStart(ctx context.Context, backend compose.Service, opts upOptions, services []string) error {
|
||||
project, err := setup(*opts.composeOptions, services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -240,7 +241,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
|
||||
}
|
||||
|
||||
_, err = progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
err := c.ComposeService().Create(ctx, project, compose.CreateOptions{
|
||||
err := backend.Create(ctx, project, compose.CreateOptions{
|
||||
Services: services,
|
||||
RemoveOrphans: opts.removeOrphans,
|
||||
Recreate: opts.recreateStrategy(),
|
||||
@ -253,7 +254,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
|
||||
return "", err
|
||||
}
|
||||
if opts.Detach {
|
||||
err = c.ComposeService().Start(ctx, project, compose.StartOptions{})
|
||||
err = backend.Start(ctx, project, compose.StartOptions{})
|
||||
}
|
||||
return "", err
|
||||
})
|
||||
@ -285,10 +286,10 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
|
||||
_, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||
go func() {
|
||||
<-signalChan
|
||||
c.ComposeService().Kill(ctx, project, compose.KillOptions{}) // nolint:errcheck
|
||||
backend.Kill(ctx, project, compose.KillOptions{}) // nolint:errcheck
|
||||
}()
|
||||
|
||||
return "", c.ComposeService().Stop(ctx, project, compose.StopOptions{})
|
||||
return "", backend.Stop(ctx, project, compose.StopOptions{})
|
||||
})
|
||||
return err
|
||||
}
|
||||
@ -311,7 +312,7 @@ func runCreateStart(ctx context.Context, opts upOptions, services []string) erro
|
||||
return err
|
||||
})
|
||||
|
||||
err = c.ComposeService().Start(ctx, project, compose.StartOptions{
|
||||
err = backend.Start(ctx, project, compose.StartOptions{
|
||||
Attach: func(event compose.ContainerEvent) {
|
||||
queue <- event
|
||||
},
|
||||
@ -351,15 +352,10 @@ func setServiceScale(project *types.Project, name string, replicas int) error {
|
||||
return fmt.Errorf("unknown service %q", name)
|
||||
}
|
||||
|
||||
func setup(ctx context.Context, opts composeOptions, services []string) (*client.Client, *types.Project, error) {
|
||||
c, err := client.New(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
func setup(opts composeOptions, services []string) (*types.Project, error) {
|
||||
project, err := opts.toProject(services)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.DomainName != "" {
|
||||
@ -397,7 +393,7 @@ func setup(ctx context.Context, opts composeOptions, services []string) (*client
|
||||
project.Services = services
|
||||
}
|
||||
|
||||
return c, project, nil
|
||||
return project, nil
|
||||
}
|
||||
|
||||
type printer struct {
|
||||
|
@ -17,9 +17,11 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/docker/compose-cli/api/config"
|
||||
@ -44,3 +46,36 @@ func confDir() string {
|
||||
home, _ := os.UserHomeDir()
|
||||
return filepath.Join(home, config.ConfigFileDir)
|
||||
}
|
||||
|
||||
// GetCurrentContext get current context based on opts, env vars
|
||||
func GetCurrentContext(contextOpt string, configDir string, hosts []string) string {
|
||||
// host and context flags cannot be both set at the same time -- the local backend enforces this when resolving hostname
|
||||
// -H flag disables context --> set default as current
|
||||
if len(hosts) > 0 {
|
||||
return "default"
|
||||
}
|
||||
// DOCKER_HOST disables context --> set default as current
|
||||
if _, present := os.LookupEnv("DOCKER_HOST"); present {
|
||||
return "default"
|
||||
}
|
||||
res := contextOpt
|
||||
if res == "" {
|
||||
// check if DOCKER_CONTEXT env variable was set
|
||||
if _, present := os.LookupEnv("DOCKER_CONTEXT"); present {
|
||||
res = os.Getenv("DOCKER_CONTEXT")
|
||||
}
|
||||
|
||||
if res == "" {
|
||||
config, err := config.LoadFile(configDir)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, errors.Wrap(err, "WARNING"))
|
||||
return "default"
|
||||
}
|
||||
res = config.CurrentContext
|
||||
}
|
||||
}
|
||||
if res == "" {
|
||||
res = "default"
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
61
cli/config/flags_test.go
Normal file
61
cli/config/flags_test.go
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
"github.com/docker/compose-cli/api/config"
|
||||
)
|
||||
|
||||
var contextSetConfig = []byte(`{
|
||||
"currentContext": "some-context"
|
||||
}`)
|
||||
|
||||
func TestDetermineCurrentContext(t *testing.T) {
|
||||
d, err := ioutil.TempDir("", "")
|
||||
// nolint errcheck
|
||||
defer os.RemoveAll(d)
|
||||
assert.NilError(t, err)
|
||||
err = ioutil.WriteFile(filepath.Join(d, config.ConfigFileName), contextSetConfig, 0644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// If nothing set, fallback to default
|
||||
c := GetCurrentContext("", "", []string{})
|
||||
assert.Equal(t, c, "default")
|
||||
|
||||
// If context flag set, use that
|
||||
c = GetCurrentContext("other-context", "", []string{})
|
||||
assert.Equal(t, c, "other-context")
|
||||
|
||||
// If no context flag, use config
|
||||
c = GetCurrentContext("", d, []string{})
|
||||
assert.Equal(t, c, "some-context")
|
||||
|
||||
// Ensure context flag overrides config
|
||||
c = GetCurrentContext("other-context", d, []string{})
|
||||
assert.Equal(t, "other-context", c)
|
||||
|
||||
// Ensure host flag overrides context
|
||||
c = GetCurrentContext("other-context", d, []string{"hostname"})
|
||||
assert.Equal(t, "default", c)
|
||||
}
|
64
cli/main.go
64
cli/main.go
@ -29,9 +29,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
cliflags "github.com/docker/cli/cli/flags"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
@ -48,6 +45,7 @@ import (
|
||||
"github.com/docker/compose-cli/cli/cmd/logout"
|
||||
"github.com/docker/compose-cli/cli/cmd/run"
|
||||
"github.com/docker/compose-cli/cli/cmd/volume"
|
||||
cliconfig "github.com/docker/compose-cli/cli/config"
|
||||
"github.com/docker/compose-cli/cli/metrics"
|
||||
"github.com/docker/compose-cli/cli/mobycli"
|
||||
cliopts "github.com/docker/compose-cli/cli/options"
|
||||
@ -62,7 +60,6 @@ import (
|
||||
|
||||
var (
|
||||
contextAgnosticCommands = map[string]struct{}{
|
||||
"compose": {},
|
||||
"context": {},
|
||||
"login": {},
|
||||
"logout": {},
|
||||
@ -198,7 +195,7 @@ func main() {
|
||||
configDir := opts.Config
|
||||
config.WithDir(configDir)
|
||||
|
||||
currentContext := determineCurrentContext(opts.Context, configDir, opts.Hosts)
|
||||
currentContext := cliconfig.GetCurrentContext(opts.Context, configDir, opts.Hosts)
|
||||
apicontext.WithCurrentContext(currentContext)
|
||||
|
||||
s, err := store.New(configDir)
|
||||
@ -221,7 +218,7 @@ func main() {
|
||||
|
||||
root.AddCommand(
|
||||
run.Command(ctype),
|
||||
compose.Command(ctype),
|
||||
compose.RootCommand(ctype, service.ComposeService()),
|
||||
volume.Command(ctype),
|
||||
)
|
||||
|
||||
@ -234,27 +231,7 @@ func main() {
|
||||
func getBackend(ctype string, configDir string, opts cliopts.GlobalOpts) (backend.Service, error) {
|
||||
switch ctype {
|
||||
case store.DefaultContextType, store.LocalContextType:
|
||||
configFile, err := cliconfig.Load(configDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options := cliflags.CommonOptions{
|
||||
Context: opts.Context,
|
||||
Debug: opts.Debug,
|
||||
Hosts: opts.Hosts,
|
||||
LogLevel: opts.LogLevel,
|
||||
}
|
||||
|
||||
if opts.TLSVerify {
|
||||
options.TLS = opts.TLS
|
||||
options.TLSVerify = opts.TLSVerify
|
||||
options.TLSOptions = opts.TLSOptions
|
||||
}
|
||||
apiClient, err := command.NewAPIClientFromFlags(&options, configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return local.NewService(apiClient), nil
|
||||
return local.GetLocalBackend(configDir, opts)
|
||||
}
|
||||
service, err := backend.Get(ctype)
|
||||
if errdefs.IsNotFoundError(err) {
|
||||
@ -311,6 +288,7 @@ func exit(ctx string, err error, ctype string) {
|
||||
}
|
||||
|
||||
if compose.Warning != "" {
|
||||
logrus.Warn(err)
|
||||
fmt.Fprintln(os.Stderr, compose.Warning)
|
||||
}
|
||||
|
||||
@ -354,38 +332,6 @@ func newSigContext() (context.Context, func()) {
|
||||
return ctx, cancel
|
||||
}
|
||||
|
||||
func determineCurrentContext(flag string, configDir string, hosts []string) string {
|
||||
// host and context flags cannot be both set at the same time -- the local backend enforces this when resolving hostname
|
||||
// -H flag disables context --> set default as current
|
||||
if len(hosts) > 0 {
|
||||
return "default"
|
||||
}
|
||||
// DOCKER_HOST disables context --> set default as current
|
||||
if _, present := os.LookupEnv("DOCKER_HOST"); present {
|
||||
return "default"
|
||||
}
|
||||
res := flag
|
||||
if res == "" {
|
||||
// check if DOCKER_CONTEXT env variable was set
|
||||
if _, present := os.LookupEnv("DOCKER_CONTEXT"); present {
|
||||
res = os.Getenv("DOCKER_CONTEXT")
|
||||
}
|
||||
|
||||
if res == "" {
|
||||
config, err := config.LoadFile(configDir)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, errors.Wrap(err, "WARNING"))
|
||||
return "default"
|
||||
}
|
||||
res = config.CurrentContext
|
||||
}
|
||||
}
|
||||
if res == "" {
|
||||
res = "default"
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func walk(c *cobra.Command, f func(*cobra.Command)) {
|
||||
f(c)
|
||||
for _, c := range c.Commands() {
|
||||
|
@ -17,53 +17,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
"github.com/docker/compose-cli/api/config"
|
||||
"github.com/docker/compose-cli/cli/cmd"
|
||||
"github.com/docker/compose-cli/cli/cmd/context"
|
||||
"github.com/docker/compose-cli/cli/cmd/login"
|
||||
"github.com/docker/compose-cli/cli/cmd/run"
|
||||
)
|
||||
|
||||
var contextSetConfig = []byte(`{
|
||||
"currentContext": "some-context"
|
||||
}`)
|
||||
|
||||
func TestDetermineCurrentContext(t *testing.T) {
|
||||
d, err := ioutil.TempDir("", "")
|
||||
// nolint errcheck
|
||||
defer os.RemoveAll(d)
|
||||
assert.NilError(t, err)
|
||||
err = ioutil.WriteFile(filepath.Join(d, config.ConfigFileName), contextSetConfig, 0644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// If nothing set, fallback to default
|
||||
c := determineCurrentContext("", "", []string{})
|
||||
assert.Equal(t, c, "default")
|
||||
|
||||
// If context flag set, use that
|
||||
c = determineCurrentContext("other-context", "", []string{})
|
||||
assert.Equal(t, c, "other-context")
|
||||
|
||||
// If no context flag, use config
|
||||
c = determineCurrentContext("", d, []string{})
|
||||
assert.Equal(t, c, "some-context")
|
||||
|
||||
// Ensure context flag overrides config
|
||||
c = determineCurrentContext("other-context", d, []string{})
|
||||
assert.Equal(t, "other-context", c)
|
||||
|
||||
// Ensure host flag overrides context
|
||||
c = determineCurrentContext("other-context", d, []string{"hostname"})
|
||||
assert.Equal(t, "default", c)
|
||||
}
|
||||
|
||||
func TestCheckOwnCommand(t *testing.T) {
|
||||
assert.Assert(t, isContextAgnosticCommand(login.Command()))
|
||||
assert.Assert(t, isContextAgnosticCommand(context.Command()))
|
||||
|
@ -55,3 +55,26 @@ var (
|
||||
// PullFailure failure while pulling image
|
||||
PullFailure = FailureCategory{MetricsStatus: PullFailureStatus, ExitCode: 18}
|
||||
)
|
||||
|
||||
//ByExitCode retrieve FailureCategory based on command exit code
|
||||
func ByExitCode(exitCode int) FailureCategory {
|
||||
switch exitCode {
|
||||
case 0:
|
||||
return FailureCategory{MetricsStatus: SuccessStatus, ExitCode: 0}
|
||||
case 14:
|
||||
return FileNotFoundFailure
|
||||
case 15:
|
||||
return ComposeParseFailure
|
||||
case 16:
|
||||
return CommandSyntaxFailure
|
||||
case 17:
|
||||
return BuildFailure
|
||||
case 18:
|
||||
return PullFailure
|
||||
case 130:
|
||||
return FailureCategory{MetricsStatus: CanceledStatus, ExitCode: exitCode}
|
||||
default:
|
||||
return FailureCategory{MetricsStatus: FailureStatus, ExitCode: exitCode}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -68,12 +68,8 @@ func Exec(root *cobra.Command) {
|
||||
if err != nil {
|
||||
if exiterr, ok := err.(*exec.ExitError); ok {
|
||||
exitCode := exiterr.ExitCode()
|
||||
if exitCode == 130 {
|
||||
metrics.Track(store.DefaultContextType, os.Args[1:], metrics.CanceledStatus)
|
||||
} else {
|
||||
metrics.Track(store.DefaultContextType, os.Args[1:], metrics.FailureStatus)
|
||||
}
|
||||
os.Exit(exiterr.ExitCode())
|
||||
metrics.Track(store.DefaultContextType, os.Args[1:], metrics.ByExitCode(exitCode).MetricsStatus)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
metrics.Track(store.DefaultContextType, os.Args[1:], metrics.FailureStatus)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
|
@ -35,7 +35,7 @@ const descriptionSourcePath = "docs/reference/"
|
||||
|
||||
func generateCliYaml(opts *options) error {
|
||||
cmd := &cobra.Command{Use: "docker"}
|
||||
cmd.AddCommand(compose.Command("local"))
|
||||
cmd.AddCommand(compose.RootCommand("local", nil))
|
||||
disableFlagsInUseLine(cmd)
|
||||
source := filepath.Join(opts.source, descriptionSourcePath)
|
||||
if err := loadLongDescription(cmd, source); err != nil {
|
||||
|
@ -17,8 +17,9 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
local_compose "github.com/docker/compose-cli/local/compose"
|
||||
"os"
|
||||
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
"github.com/docker/docker/client"
|
||||
|
||||
"github.com/docker/compose-cli/api/backend"
|
||||
@ -29,6 +30,7 @@ import (
|
||||
"github.com/docker/compose-cli/api/resources"
|
||||
"github.com/docker/compose-cli/api/secrets"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
local_compose "github.com/docker/compose-cli/local/compose"
|
||||
)
|
||||
|
||||
const backendType = store.EcsLocalSimulationContextType
|
||||
@ -50,7 +52,7 @@ func service() (backend.Service, error) {
|
||||
|
||||
return &ecsLocalSimulation{
|
||||
moby: apiClient,
|
||||
compose: local_compose.NewComposeService(apiClient),
|
||||
compose: local_compose.NewComposeService(apiClient, cliconfig.LoadDefaultConfigFile(os.Stderr)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,11 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
cliflags "github.com/docker/cli/cli/flags"
|
||||
"github.com/docker/docker/client"
|
||||
|
||||
"github.com/docker/compose-cli/api/backend"
|
||||
@ -25,6 +30,7 @@ import (
|
||||
"github.com/docker/compose-cli/api/resources"
|
||||
"github.com/docker/compose-cli/api/secrets"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
cliopts "github.com/docker/compose-cli/cli/options"
|
||||
local_compose "github.com/docker/compose-cli/local/compose"
|
||||
)
|
||||
|
||||
@ -36,13 +42,39 @@ type local struct {
|
||||
|
||||
// NewService build a backend for "local" context, using Docker API client
|
||||
func NewService(apiClient client.APIClient) backend.Service {
|
||||
file := cliconfig.LoadDefaultConfigFile(os.Stderr)
|
||||
return &local{
|
||||
containerService: &containerService{apiClient},
|
||||
volumeService: &volumeService{apiClient},
|
||||
composeService: local_compose.NewComposeService(apiClient),
|
||||
composeService: local_compose.NewComposeService(apiClient, file),
|
||||
}
|
||||
}
|
||||
|
||||
// GetLocalBackend initialize local backend
|
||||
func GetLocalBackend(configDir string, opts cliopts.GlobalOpts) (backend.Service, error) {
|
||||
configFile, err := cliconfig.Load(configDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
options := cliflags.CommonOptions{
|
||||
Context: opts.Context,
|
||||
Debug: opts.Debug,
|
||||
Hosts: opts.Hosts,
|
||||
LogLevel: opts.LogLevel,
|
||||
}
|
||||
|
||||
if opts.TLSVerify {
|
||||
options.TLS = opts.TLS
|
||||
options.TLSVerify = opts.TLSVerify
|
||||
options.TLSOptions = opts.TLSOptions
|
||||
}
|
||||
apiClient, err := command.NewAPIClientFromFlags(&options, configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewService(apiClient), nil
|
||||
}
|
||||
|
||||
func (s *local) ContainerService() containers.Service {
|
||||
return s.containerService
|
||||
}
|
||||
|
@ -28,13 +28,11 @@ import (
|
||||
"github.com/docker/buildx/driver"
|
||||
_ "github.com/docker/buildx/driver/docker" // required to get default driver registered
|
||||
"github.com/docker/buildx/util/progress"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
bclient "github.com/moby/buildkit/client"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/config"
|
||||
composeprogress "github.com/docker/compose-cli/api/progress"
|
||||
"github.com/docker/compose-cli/cli/metrics"
|
||||
"github.com/docker/compose-cli/utils"
|
||||
@ -195,12 +193,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opts
|
||||
}
|
||||
const drivername = "default"
|
||||
|
||||
configFile, err := cliconfig.Load(config.Dir())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient, configFile, nil, nil, "", nil, nil, project.WorkingDir)
|
||||
d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient, s.configFile, nil, nil, "", nil, nil, project.WorkingDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -26,20 +26,23 @@ import (
|
||||
"github.com/docker/compose-cli/api/errdefs"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/sanathkr/go-yaml"
|
||||
)
|
||||
|
||||
// NewComposeService create a local implementation of the compose.Service API
|
||||
func NewComposeService(apiClient client.APIClient) compose.Service {
|
||||
func NewComposeService(apiClient client.APIClient, configFile *configfile.ConfigFile) compose.Service {
|
||||
return &composeService{
|
||||
apiClient: apiClient,
|
||||
apiClient: apiClient,
|
||||
configFile: configFile,
|
||||
}
|
||||
}
|
||||
|
||||
type composeService struct {
|
||||
apiClient client.APIClient
|
||||
apiClient client.APIClient
|
||||
configFile *configfile.ConfigFile
|
||||
}
|
||||
|
||||
func (s *composeService) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
|
||||
|
@ -27,23 +27,17 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/distribution/distribution/v3/reference"
|
||||
"github.com/docker/buildx/driver"
|
||||
cliconfig "github.com/docker/cli/cli/config"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
"github.com/docker/docker/registry"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/config"
|
||||
"github.com/docker/compose-cli/api/progress"
|
||||
"github.com/docker/compose-cli/cli/metrics"
|
||||
)
|
||||
|
||||
func (s *composeService) Pull(ctx context.Context, project *types.Project, opts compose.PullOptions) error {
|
||||
configFile, err := cliconfig.Load(config.Dir())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := s.apiClient.Info(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -67,7 +61,7 @@ func (s *composeService) Pull(ctx context.Context, project *types.Project, opts
|
||||
continue
|
||||
}
|
||||
eg.Go(func() error {
|
||||
err := s.pullServiceImage(ctx, service, info, configFile, w)
|
||||
err := s.pullServiceImage(ctx, service, info, s.configFile, w)
|
||||
if err != nil {
|
||||
if !opts.IgnoreFailures {
|
||||
return err
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -131,6 +132,26 @@ func TestLocalComposeUp(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestComposeUsingCliPlugin(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
|
||||
err := os.Remove(filepath.Join(c.ConfigDir, "cli-plugins", "docker-compose"))
|
||||
assert.NilError(t, err)
|
||||
res := c.RunDockerOrExitError("compose", "ls")
|
||||
res.Assert(t, icmd.Expected{Err: "'compose' is not a docker command", ExitCode: 1})
|
||||
}
|
||||
|
||||
func TestComposeCliPluginWithoutCloudIntegration(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
|
||||
err := os.Remove(filepath.Join(binDir, "docker"))
|
||||
assert.NilError(t, err)
|
||||
err = os.Rename(filepath.Join(binDir, "com.docker.cli"), filepath.Join(binDir, "docker"))
|
||||
assert.NilError(t, err)
|
||||
res := c.RunDockerOrExitError("compose", "ls")
|
||||
res.Assert(t, icmd.Expected{Out: "NAME STATUS", ExitCode: 0})
|
||||
}
|
||||
|
||||
func TestComposePull(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
services:
|
||||
service1:
|
||||
build: service1
|
@ -0,0 +1,17 @@
|
||||
# Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM busybox
|
||||
|
||||
RUN sleep infinity
|
@ -17,7 +17,11 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -84,3 +88,69 @@ func TestComposeMetrics(t *testing.T) {
|
||||
}, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func TestComposeCancel(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
s := NewMetricsServer(c.MetricsSocket())
|
||||
s.Start()
|
||||
defer s.Stop()
|
||||
|
||||
started := false
|
||||
|
||||
for i := 0; i < 30; i++ {
|
||||
c.RunDockerCmd("help", "ps")
|
||||
if len(s.GetUsage()) > 0 {
|
||||
started = true
|
||||
fmt.Printf(" [%s] Server up in %d ms\n", t.Name(), i*100)
|
||||
break
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
assert.Assert(t, started, "Metrics mock server not available after 3 secs")
|
||||
|
||||
t.Run("metrics on cancel Compose build", func(t *testing.T) {
|
||||
s.ResetUsage()
|
||||
|
||||
c.RunDockerCmd("compose", "ls")
|
||||
buildProjectPath := "../compose/fixtures/build-infinite/docker-compose.yml"
|
||||
|
||||
// require a separate groupID from the process running tests, in order to simulate ctrl+C from a terminal.
|
||||
// sending kill signal
|
||||
cmd, stdout, stderr, err := StartWithNewGroupID(c.NewDockerCmd("compose", "-f", buildProjectPath, "build", "--progress", "plain"))
|
||||
assert.NilError(t, err)
|
||||
|
||||
c.WaitForCondition(func() (bool, string) {
|
||||
out := stdout.String()
|
||||
errors := stderr.String()
|
||||
return strings.Contains(out, "RUN sleep infinity"), fmt.Sprintf("'RUN sleep infinity' not found in : \n%s\nStderr: \n%s\n", out, errors)
|
||||
}, 30*time.Second, 1*time.Second)
|
||||
|
||||
err = syscall.Kill(-cmd.Process.Pid, syscall.SIGINT) // simulate Ctrl-C : send signal to processGroup, children will have same groupId by default
|
||||
|
||||
assert.NilError(t, err)
|
||||
c.WaitForCondition(func() (bool, string) {
|
||||
out := stdout.String()
|
||||
errors := stderr.String()
|
||||
return strings.Contains(out, "CANCELED"), fmt.Sprintf("'CANCELED' not found in : \n%s\nStderr: \n%s\n", out, errors)
|
||||
}, 10*time.Second, 1*time.Second)
|
||||
|
||||
usage := s.GetUsage()
|
||||
assert.DeepEqual(t, []string{
|
||||
`{"command":"compose ls","context":"moby","source":"cli","status":"success"}`,
|
||||
`{"command":"compose build","context":"moby","source":"cli","status":"canceled"}`,
|
||||
}, usage)
|
||||
})
|
||||
}
|
||||
|
||||
func StartWithNewGroupID(command icmd.Cmd) (*exec.Cmd, *bytes.Buffer, *bytes.Buffer, error) {
|
||||
cmd := exec.Command(command.Command[0], command.Command[1:]...)
|
||||
cmd.Env = command.Env
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Start()
|
||||
return cmd, &stdout, &stderr, err
|
||||
}
|
||||
|
66
main.go
Normal file
66
main.go
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
dockercli "github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli-plugins/plugin"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
api "github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/context/store"
|
||||
"github.com/docker/compose-cli/cli/cmd/compose"
|
||||
"github.com/docker/compose-cli/cli/metrics"
|
||||
"github.com/docker/compose-cli/internal"
|
||||
impl "github.com/docker/compose-cli/local/compose"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plugin.Run(func(dockerCli command.Cli) *cobra.Command {
|
||||
lazyInit := api.ServiceDelegator{
|
||||
Delegate: api.NoImpl{},
|
||||
}
|
||||
cmd := compose.RootCommand(store.DefaultContextType, &lazyInit)
|
||||
originalPreRun := cmd.PersistentPreRunE
|
||||
cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
|
||||
if err := plugin.PersistentPreRunE(cmd, args); err != nil {
|
||||
return err
|
||||
}
|
||||
lazyInit.Delegate = impl.NewComposeService(dockerCli.Client(), dockerCli.ConfigFile())
|
||||
if originalPreRun != nil {
|
||||
return originalPreRun(cmd, args)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
cmd.SetFlagErrorFunc(func(c *cobra.Command, err error) error {
|
||||
return dockercli.StatusError{
|
||||
StatusCode: metrics.CommandSyntaxFailure.ExitCode,
|
||||
Status: err.Error(),
|
||||
}
|
||||
})
|
||||
return cmd
|
||||
},
|
||||
manager.Metadata{
|
||||
SchemaVersion: "0.1.0",
|
||||
Vendor: "Docker Inc.",
|
||||
Version: strings.TrimPrefix(internal.Version, "v"),
|
||||
})
|
||||
}
|
@ -85,6 +85,17 @@ func newE2eCLI(t *testing.T, binDir string) *E2eCLI {
|
||||
_ = os.RemoveAll(d)
|
||||
})
|
||||
|
||||
_ = os.MkdirAll(filepath.Join(d, "cli-plugins"), 0755)
|
||||
composePluginFile := "docker-compose"
|
||||
if runtime.GOOS == "windows" {
|
||||
composePluginFile += ".exe"
|
||||
}
|
||||
composePlugin, _ := findExecutable(composePluginFile, []string{"../../bin", "../../../bin"})
|
||||
err = CopyFile(composePlugin, filepath.Join(d, "cli-plugins", composePluginFile))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &E2eCLI{binDir, d, t}
|
||||
}
|
||||
|
||||
@ -117,7 +128,7 @@ func SetupExistingCLI() (string, func(), error) {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
bin, err := findExecutable([]string{"../../bin", "../../../bin"})
|
||||
bin, err := findExecutable(DockerExecutableName, []string{"../../bin", "../../../bin"})
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -133,9 +144,9 @@ func SetupExistingCLI() (string, func(), error) {
|
||||
return d, cleanup, nil
|
||||
}
|
||||
|
||||
func findExecutable(paths []string) (string, error) {
|
||||
func findExecutable(executableName string, paths []string) (string, error) {
|
||||
for _, p := range paths {
|
||||
bin, err := filepath.Abs(path.Join(p, DockerExecutableName))
|
||||
bin, err := filepath.Abs(path.Join(p, executableName))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -241,6 +252,18 @@ func (c *E2eCLI) WaitForCmdResult(command icmd.Cmd, predicate func(*icmd.Result)
|
||||
poll.WaitOn(c.test, checkStopped, poll.WithDelay(delay), poll.WithTimeout(timeout))
|
||||
}
|
||||
|
||||
// WaitForCondition wait for predicate to execute to true
|
||||
func (c *E2eCLI) WaitForCondition(predicate func() (bool, string), timeout time.Duration, delay time.Duration) {
|
||||
checkStopped := func(logt poll.LogT) poll.Result {
|
||||
pass, description := predicate()
|
||||
if !pass {
|
||||
return poll.Continue("Condition not met: %q", description)
|
||||
}
|
||||
return poll.Success()
|
||||
}
|
||||
poll.WaitOn(c.test, checkStopped, poll.WithDelay(delay), poll.WithTimeout(timeout))
|
||||
}
|
||||
|
||||
// PathEnvVar returns path (os sensitive) for running test
|
||||
func (c *E2eCLI) PathEnvVar() string {
|
||||
path := c.BinDir + ":" + os.Getenv("PATH")
|
||||
|
Loading…
x
Reference in New Issue
Block a user