Repository: docker/compose
File: pkg/compose/plugins.go (Go)

Code before:
	carrier := propagation.MapCarrier{}
	otel.GetTextMapPropagator().Inject(ctx, &carrier)
	cmd.Env = append(cmd.Env, types.Mapping(carrier).Values()...)
	return cmd
}

func (s *composeService) getPluginMetadata(path string) map[string]CommandMetadata {
	cmd := exec.Command(path, "compose", "metadata")
	stdout := &bytes.Buffer{}
	cmd.Stdout = stdout

	if err := cmd.Start(); err != nil {
		logrus.Debugf("failed to start plugin metadata command: %v", err)
		return nil
	}
	if err := cmd.Wait(); err != nil {
		var exiterr *exec.ExitError
		if errors.As(err, &exiterr) {
			logrus.Debugf("plugin metadata command failed with exit code: %d\n", exiterr.ExitCode())
		}
		return nil
	}

	decoder := json.NewDecoder(stdout)
	var metadata map[string]CommandMetadata
	if err := decoder.Decode(&metadata); err != nil {
		output, _ := io.ReadAll(stdout)
		logrus.Debugf("failed to decode plugin metadata: %v - %s", err, output)
		return nil
	}
	return metadata
}

type CommandMetadata struct {
	Parameters []ParametersMetadata `json:"parameters"`
}

type ParametersMetadata struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Required    bool   `json:"required"`
	Type        string `json:"type"`
	Default     string `json:"default,omitempty"`
}

func (c CommandMetadata) GetParameter(paramName string) (ParametersMetadata, bool) {
	for _, p := range c.Parameters {
		if p.Name == paramName {
			return p, true
		}
	}

Review comment (suggestion):
```suggestion
	var metadata map[string]CommandMetadata
	if err := json.Unmarshal(stdout, &metadata); err != nil {
```

Code after:
		env[key] = val
	}
	cmd.Env = env.Values()

	// 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, nil
}

func (s *composeService) getPluginMetadata(path, command string) ProviderMetadata {
	cmd := exec.Command(path, "compose", "metadata")
	stdout := &bytes.Buffer{}
	cmd.Stdout = stdout

	if err := cmd.Run(); err != nil {
		logrus.Debugf("failed to start plugin metadata command: %v", err)
		return ProviderMetadata{}
	}

	var metadata ProviderMetadata
	if err := json.Unmarshal(stdout.Bytes(), &metadata); err != nil {
		output, _ := io.ReadAll(stdout)
		logrus.Debugf("failed to decode plugin metadata: %v - %s", err, output)
		return ProviderMetadata{}
	}
	// Save metadata into docker home directory to be used by Docker LSP tool
	// Just log the error as it's not a critical error for the main flow
	metadataDir := filepath.Join(config.Dir(), providerMetadataDirectory)
	if err := os.MkdirAll(metadataDir, 0o700); err == nil {
		metadataFilePath := filepath.Join(metadataDir, command+".json")
		if err := os.WriteFile(metadataFilePath, stdout.Bytes(), 0o600); err != nil {
			logrus.Debugf("failed to save plugin metadata: %v", err)
		}
	} else {
		logrus.Debugf("failed to create plugin metadata directory: %v", err)
	}
	return metadata
}