Merge pull request #1688 from docker/interceptor

This commit is contained in:
Nicolas De loof 2021-05-20 18:33:41 +02:00 committed by GitHub
commit e91e163c84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 362 additions and 310 deletions

View File

@ -1,148 +0,0 @@
/*
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) (int, error) {
return s.Delegate.Exec(ctx, project, options)
}
//Copy implements Service interface
func (s *ServiceDelegator) Copy(ctx context.Context, project *types.Project, options CopyOptions) error {
return s.Delegate.Copy(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)
}

View File

@ -1,148 +0,0 @@
/*
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, opts RunOptions) (int, error) {
return 0, errdefs.ErrNotImplemented
}
//Copy implements Service interface
func (s NoImpl) Copy(ctx context.Context, project *types.Project, opts CopyOptions) 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
}

333
api/compose/proxy.go Normal file
View File

@ -0,0 +1,333 @@
/*
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/docker/compose-cli/api/errdefs"
"github.com/compose-spec/compose-go/types"
)
// ServiceProxy implements Service by delegating to implementation functions. This allows lazy init and per-method overrides
type ServiceProxy struct {
BuildFn func(ctx context.Context, project *types.Project, options BuildOptions) error
PushFn func(ctx context.Context, project *types.Project, options PushOptions) error
PullFn func(ctx context.Context, project *types.Project, opts PullOptions) error
CreateFn func(ctx context.Context, project *types.Project, opts CreateOptions) error
StartFn func(ctx context.Context, project *types.Project, options StartOptions) error
RestartFn func(ctx context.Context, project *types.Project, options RestartOptions) error
StopFn func(ctx context.Context, project *types.Project, options StopOptions) error
UpFn func(ctx context.Context, project *types.Project, options UpOptions) error
DownFn func(ctx context.Context, projectName string, options DownOptions) error
LogsFn func(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error
PsFn func(ctx context.Context, projectName string, options PsOptions) ([]ContainerSummary, error)
ListFn func(ctx context.Context, options ListOptions) ([]Stack, error)
ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
KillFn func(ctx context.Context, project *types.Project, options KillOptions) error
RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
RemoveFn func(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error)
ExecFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
CopyFn func(ctx context.Context, project *types.Project, opts CopyOptions) error
PauseFn func(ctx context.Context, project string, options PauseOptions) error
UnPauseFn func(ctx context.Context, project string, options PauseOptions) error
TopFn func(ctx context.Context, projectName string, services []string) ([]ContainerProcSummary, error)
EventsFn func(ctx context.Context, project string, options EventsOptions) error
PortFn func(ctx context.Context, project string, service string, port int, options PortOptions) (string, int, error)
ImagesFn func(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
interceptors []Interceptor
}
// NewServiceProxy produces a ServiceProxy
func NewServiceProxy() *ServiceProxy {
return &ServiceProxy{}
}
// Interceptor allow to customize the compose types.Project before the actual Service method is executed
type Interceptor func(ctx context.Context, project *types.Project)
var _ Service = &ServiceProxy{}
// WithService configure proxy to use specified Service as delegate
func (s *ServiceProxy) WithService(service Service) *ServiceProxy {
s.BuildFn = service.Build
s.PushFn = service.Push
s.PullFn = service.Pull
s.CreateFn = service.Create
s.StartFn = service.Start
s.RestartFn = service.Restart
s.StopFn = service.Stop
s.UpFn = service.Up
s.DownFn = service.Down
s.LogsFn = service.Logs
s.PsFn = service.Ps
s.ListFn = service.List
s.ConvertFn = service.Convert
s.KillFn = service.Kill
s.RunOneOffContainerFn = service.RunOneOffContainer
s.RemoveFn = service.Remove
s.ExecFn = service.Exec
s.CopyFn = service.Copy
s.PauseFn = service.Pause
s.UnPauseFn = service.UnPause
s.TopFn = service.Top
s.EventsFn = service.Events
s.PortFn = service.Port
s.ImagesFn = service.Images
return s
}
// WithInterceptor configures Interceptor to be applied to Service method execution
func (s *ServiceProxy) WithInterceptor(interceptors ...Interceptor) *ServiceProxy {
s.interceptors = append(s.interceptors, interceptors...)
return s
}
//Build implements Service interface
func (s *ServiceProxy) Build(ctx context.Context, project *types.Project, options BuildOptions) error {
if s.BuildFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.BuildFn(ctx, project, options)
}
//Push implements Service interface
func (s *ServiceProxy) Push(ctx context.Context, project *types.Project, options PushOptions) error {
if s.PushFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.PushFn(ctx, project, options)
}
//Pull implements Service interface
func (s *ServiceProxy) Pull(ctx context.Context, project *types.Project, options PullOptions) error {
if s.PullFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.PullFn(ctx, project, options)
}
//Create implements Service interface
func (s *ServiceProxy) Create(ctx context.Context, project *types.Project, options CreateOptions) error {
if s.CreateFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.CreateFn(ctx, project, options)
}
//Start implements Service interface
func (s *ServiceProxy) Start(ctx context.Context, project *types.Project, options StartOptions) error {
if s.StartFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.StartFn(ctx, project, options)
}
//Restart implements Service interface
func (s *ServiceProxy) Restart(ctx context.Context, project *types.Project, options RestartOptions) error {
if s.RestartFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.RestartFn(ctx, project, options)
}
//Stop implements Service interface
func (s *ServiceProxy) Stop(ctx context.Context, project *types.Project, options StopOptions) error {
if s.StopFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.StopFn(ctx, project, options)
}
//Up implements Service interface
func (s *ServiceProxy) Up(ctx context.Context, project *types.Project, options UpOptions) error {
if s.UpFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.UpFn(ctx, project, options)
}
//Down implements Service interface
func (s *ServiceProxy) Down(ctx context.Context, project string, options DownOptions) error {
if s.DownFn == nil {
return errdefs.ErrNotImplemented
}
return s.DownFn(ctx, project, options)
}
//Logs implements Service interface
func (s *ServiceProxy) Logs(ctx context.Context, project string, consumer LogConsumer, options LogOptions) error {
if s.LogsFn == nil {
return errdefs.ErrNotImplemented
}
return s.LogsFn(ctx, project, consumer, options)
}
//Ps implements Service interface
func (s *ServiceProxy) Ps(ctx context.Context, project string, options PsOptions) ([]ContainerSummary, error) {
if s.PsFn == nil {
return nil, errdefs.ErrNotImplemented
}
return s.PsFn(ctx, project, options)
}
//List implements Service interface
func (s *ServiceProxy) List(ctx context.Context, options ListOptions) ([]Stack, error) {
if s.ListFn == nil {
return nil, errdefs.ErrNotImplemented
}
return s.ListFn(ctx, options)
}
//Convert implements Service interface
func (s *ServiceProxy) Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error) {
if s.ConvertFn == nil {
return nil, errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.ConvertFn(ctx, project, options)
}
//Kill implements Service interface
func (s *ServiceProxy) Kill(ctx context.Context, project *types.Project, options KillOptions) error {
if s.KillFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.KillFn(ctx, project, options)
}
//RunOneOffContainer implements Service interface
func (s *ServiceProxy) RunOneOffContainer(ctx context.Context, project *types.Project, options RunOptions) (int, error) {
if s.RunOneOffContainerFn == nil {
return 0, errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.RunOneOffContainerFn(ctx, project, options)
}
//Remove implements Service interface
func (s *ServiceProxy) Remove(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error) {
if s.RemoveFn == nil {
return nil, errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.RemoveFn(ctx, project, options)
}
//Exec implements Service interface
func (s *ServiceProxy) Exec(ctx context.Context, project *types.Project, options RunOptions) (int, error) {
if s.ExecFn == nil {
return 0, errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.ExecFn(ctx, project, options)
}
//Copy implements Service interface
func (s *ServiceProxy) Copy(ctx context.Context, project *types.Project, options CopyOptions) error {
if s.CopyFn == nil {
return errdefs.ErrNotImplemented
}
for _, i := range s.interceptors {
i(ctx, project)
}
return s.CopyFn(ctx, project, options)
}
//Pause implements Service interface
func (s *ServiceProxy) Pause(ctx context.Context, project string, options PauseOptions) error {
if s.PauseFn == nil {
return errdefs.ErrNotImplemented
}
return s.PauseFn(ctx, project, options)
}
//UnPause implements Service interface
func (s *ServiceProxy) UnPause(ctx context.Context, project string, options PauseOptions) error {
if s.UnPauseFn == nil {
return errdefs.ErrNotImplemented
}
return s.UnPauseFn(ctx, project, options)
}
//Top implements Service interface
func (s *ServiceProxy) Top(ctx context.Context, project string, services []string) ([]ContainerProcSummary, error) {
if s.TopFn == nil {
return nil, errdefs.ErrNotImplemented
}
return s.TopFn(ctx, project, services)
}
//Events implements Service interface
func (s *ServiceProxy) Events(ctx context.Context, project string, options EventsOptions) error {
if s.EventsFn == nil {
return errdefs.ErrNotImplemented
}
return s.EventsFn(ctx, project, options)
}
//Port implements Service interface
func (s *ServiceProxy) Port(ctx context.Context, project string, service string, port int, options PortOptions) (string, int, error) {
if s.PortFn == nil {
return "", 0, errdefs.ErrNotImplemented
}
return s.PortFn(ctx, project, service, port, options)
}
//Images implements Service interface
func (s *ServiceProxy) Images(ctx context.Context, project string, options ImagesOptions) ([]ImageSummary, error) {
if s.ImagesFn == nil {
return nil, errdefs.ErrNotImplemented
}
return s.ImagesFn(ctx, project, options)
}

View File

@ -45,8 +45,6 @@ type composeOptions struct {
*projectOptions
Build bool
noBuild bool
// ACI only
DomainName string
}
type upOptions struct {
@ -186,8 +184,6 @@ func upCommand(p *projectOptions, contextType string, backend compose.Service) *
flags.BoolVar(&opts.noPrefix, "no-log-prefix", false, "Don't print prefix in logs.")
switch contextType {
case store.AciContextType:
flags.StringVar(&opts.DomainName, "domainname", "", "Container NIS domain name")
case store.LocalContextType, store.DefaultContextType, store.EcsLocalSimulationContextType:
flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
@ -360,10 +356,6 @@ func setup(opts composeOptions, services []string) (*types.Project, error) {
return nil, err
}
if opts.DomainName != "" {
// arbitrarily set the domain name on the first service ; ACI backend will expose the entire project
project.Services[0].DomainName = opts.DomainName
}
if opts.Build {
for i, service := range project.Services {
service.PullPolicy = types.PullPolicyBuild

View File

@ -28,12 +28,14 @@ import (
"syscall"
"time"
"github.com/compose-spec/compose-go/types"
"github.com/docker/cli/cli"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/docker/compose-cli/api/backend"
api "github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/config"
apicontext "github.com/docker/compose-cli/api/context"
"github.com/docker/compose-cli/api/context/store"
@ -223,7 +225,14 @@ func main() {
if ctype != store.DefaultContextType {
// On default context, "compose" is implemented by CLI Plugin
root.AddCommand(compose.RootCommand(ctype, service.ComposeService()))
proxy := api.NewServiceProxy().WithService(service.ComposeService())
command := compose.RootCommand(ctype, proxy)
if ctype == store.AciContextType {
customizeCliForACI(command, proxy)
}
root.AddCommand(command)
}
if err = root.ExecuteContext(ctx); err != nil {
@ -232,6 +241,22 @@ func main() {
metrics.Track(ctype, os.Args[1:], metrics.SuccessStatus)
}
func customizeCliForACI(command *cobra.Command, proxy *api.ServiceProxy) {
var domainName string
for _, c := range command.Commands() {
if c.Name() == "up" {
c.Flags().StringVar(&domainName, "domainname", "", "Container NIS domain name")
proxy.WithInterceptor(func(ctx context.Context, project *types.Project) {
if domainName != "" {
// arbitrarily set the domain name on the first service ; ACI backend will expose the entire project
project.Services[0].DomainName = domainName
}
})
}
}
}
func getBackend(ctype string, configDir string, opts cliopts.GlobalOpts) (backend.Service, error) {
switch ctype {
case store.DefaultContextType, store.LocalContextType:

View File

@ -35,16 +35,14 @@ import (
func main() {
plugin.Run(func(dockerCli command.Cli) *cobra.Command {
lazyInit := api.ServiceDelegator{
Delegate: api.NoImpl{},
}
cmd := compose.RootCommand(store.DefaultContextType, &lazyInit)
lazyInit := api.NewServiceProxy()
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())
lazyInit.WithService(impl.NewComposeService(dockerCli.Client(), dockerCli.ConfigFile()))
if originalPreRun != nil {
return originalPreRun(cmd, args)
}