diff --git a/pkg/compose/plugins.go b/pkg/compose/plugins.go index c4fdbd2e6..ed489d4a6 100644 --- a/pkg/compose/plugins.go +++ b/pkg/compose/plugins.go @@ -30,7 +30,6 @@ import ( "github.com/docker/cli/cli-plugins/manager" "github.com/docker/cli/cli-plugins/socket" "github.com/docker/compose/v2/pkg/progress" - "github.com/docker/docker/errdefs" "github.com/spf13/cobra" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/propagation" @@ -48,41 +47,15 @@ const ( SetEnvType = "setenv" ) -func (s *composeService) runPlugin(ctx context.Context, project *types.Project, service types.ServiceConfig, command string) error { //nolint:gocyclo - x := *service.Provider +func (s *composeService) runPlugin(ctx context.Context, project *types.Project, service types.ServiceConfig, command string) error { + provider := *service.Provider - // Only support Docker CLI plugins for first iteration. Could support any binary from PATH - plugin, err := manager.GetPlugin(x.Type, s.dockerCli, &cobra.Command{}) + path, err := s.getPluginBinaryPath(provider.Type) if err != nil { - if errdefs.IsNotFound(err) { - return fmt.Errorf("unsupported external service type %s", x.Type) - } return err } - args := []string{"compose", "--project-name", project.Name, command} - for k, v := range x.Options { - args = append(args, fmt.Sprintf("--%s=%s", k, v)) - } - - cmd := exec.CommandContext(ctx, plugin.Path, args...) - // Remove DOCKER_CLI_PLUGIN... variable so plugin can detect it run standalone - cmd.Env = filter(os.Environ(), manager.ReexecEnvvar) - - // Use docker/cli mechanism to propagate termination signal to child process - server, err := socket.NewPluginServer(nil) - if err != nil { - defer server.Close() //nolint:errcheck - cmd.Cancel = server.Close - cmd.Env = replace(cmd.Env, socket.EnvKey, server.Addr().String()) - } - - cmd.Env = append(cmd.Env, fmt.Sprintf("DOCKER_CONTEXT=%s", s.dockerCli.CurrentContext())) - - // propagate opentelemetry context to child process, see https://github.com/open-telemetry/oteps/blob/main/text/0258-env-context-baggage-carriers.md - carrier := propagation.MapCarrier{} - otel.GetTextMapPropagator().Inject(ctx, &carrier) - cmd.Env = append(cmd.Env, types.Mapping(carrier).Values()...) + cmd := s.setupPluginCommand(ctx, project, provider, path, command) eg := errgroup.Group{} stdout, err := cmd.StdoutPipe() @@ -147,3 +120,39 @@ func (s *composeService) runPlugin(ctx context.Context, project *types.Project, } return nil } + +func (s *composeService) getPluginBinaryPath(providerType string) (string, error) { + // Only support Docker CLI plugins for first iteration. Could support any binary from PATH + plugin, err := manager.GetPlugin(providerType, s.dockerCli, &cobra.Command{}) + if err != nil { + return "", err + } + return plugin.Path, nil +} + +func (s *composeService) setupPluginCommand(ctx context.Context, project *types.Project, provider types.ServiceProviderConfig, path, command string) *exec.Cmd { + args := []string{"compose", "--project-name", project.Name, command} + for k, v := range provider.Options { + args = append(args, fmt.Sprintf("--%s=%s", k, v)) + } + + cmd := exec.CommandContext(ctx, path, args...) + // Remove DOCKER_CLI_PLUGIN... variable so plugin can detect it run standalone + cmd.Env = filter(os.Environ(), manager.ReexecEnvvar) + + // Use docker/cli mechanism to propagate termination signal to child process + server, err := socket.NewPluginServer(nil) + if err != nil { + defer server.Close() //nolint:errcheck + cmd.Cancel = server.Close + cmd.Env = replace(cmd.Env, socket.EnvKey, server.Addr().String()) + } + + cmd.Env = append(cmd.Env, fmt.Sprintf("DOCKER_CONTEXT=%s", s.dockerCli.CurrentContext())) + + // propagate opentelemetry context to child process, see https://github.com/open-telemetry/oteps/blob/main/text/0258-env-context-baggage-carriers.md + carrier := propagation.MapCarrier{} + otel.GetTextMapPropagator().Inject(ctx, &carrier) + cmd.Env = append(cmd.Env, types.Mapping(carrier).Values()...) + return cmd +}