|
@@ -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)
|
|
|
|
|
+}
|