Skip to content

Commit 60ee6ad

Browse files
ndeloofglours
authored andcommitted
a single place for shell-out command setup
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 8faf1eb commit 60ee6ad

File tree

4 files changed

+92
-94
lines changed

4 files changed

+92
-94
lines changed

pkg/compose/build_bake.go

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import (
3434

3535
"github.com/compose-spec/compose-go/v2/types"
3636
"github.com/docker/cli/cli-plugins/manager"
37-
"github.com/docker/cli/cli-plugins/socket"
3837
"github.com/docker/cli/cli/command"
3938
"github.com/docker/compose/v2/pkg/api"
4039
"github.com/docker/compose/v2/pkg/progress"
@@ -45,8 +44,6 @@ import (
4544
"github.com/moby/buildkit/util/progress/progressui"
4645
"github.com/sirupsen/logrus"
4746
"github.com/spf13/cobra"
48-
"go.opentelemetry.io/otel"
49-
"go.opentelemetry.io/otel/propagation"
5047
"golang.org/x/sync/errgroup"
5148
)
5249

@@ -294,26 +291,12 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
294291
logrus.Debugf("Executing bake with args: %v", args)
295292

296293
cmd := exec.CommandContext(ctx, buildx.Path, args...)
297-
// Remove DOCKER_CLI_PLUGIN... variable so buildx can detect it run standalone
298-
cmd.Env = filter(project.Environment.Values(), manager.ReexecEnvvar)
299294

300-
// Use docker/cli mechanism to propagate termination signal to child process
301-
server, err := socket.NewPluginServer(nil)
302-
if err == nil {
303-
defer server.Close() //nolint:errcheck
304-
cmd.Env = replace(cmd.Env, socket.EnvKey, server.Addr().String())
295+
err = s.prepareShellOut(ctx, project, cmd)
296+
if err != nil {
297+
return nil, err
305298
}
306299

307-
cmd.Env = append(cmd.Env,
308-
fmt.Sprintf("DOCKER_CONTEXT=%s", s.dockerCli.CurrentContext()),
309-
fmt.Sprintf("DOCKER_HOST=%s", s.dockerCli.DockerEndpoint().Host),
310-
)
311-
312-
// propagate opentelemetry context to child process, see https://github.com/open-telemetry/oteps/blob/main/text/0258-env-context-baggage-carriers.md
313-
carrier := propagation.MapCarrier{}
314-
otel.GetTextMapPropagator().Inject(ctx, &carrier)
315-
cmd.Env = append(cmd.Env, types.Mapping(carrier).Values()...)
316-
317300
cmd.Stdout = s.stdout()
318301
cmd.Stdin = bytes.NewBuffer(b)
319302
pipe, err := cmd.StderrPipe()
@@ -443,22 +426,6 @@ func toBakeSecrets(project *types.Project, secrets []types.ServiceSecretConfig)
443426
return s
444427
}
445428

446-
func filter(environ []string, variable string) []string {
447-
prefix := variable + "="
448-
filtered := make([]string, 0, len(environ))
449-
for _, val := range environ {
450-
if !strings.HasPrefix(val, prefix) {
451-
filtered = append(filtered, val)
452-
}
453-
}
454-
return filtered
455-
}
456-
457-
func replace(environ []string, variable, value string) []string {
458-
filtered := filter(environ, variable)
459-
return append(filtered, fmt.Sprintf("%s=%s", variable, value))
460-
}
461-
462429
func dockerFilePath(ctxName string, dockerfile string) string {
463430
if dockerfile == "" {
464431
return ""

pkg/compose/model.go

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"context"
2222
"encoding/json"
2323
"fmt"
24-
"os"
2524
"os/exec"
2625
"slices"
2726
"strconv"
@@ -32,8 +31,6 @@ import (
3231
"github.com/docker/cli/cli-plugins/manager"
3332
"github.com/docker/compose/v2/pkg/progress"
3433
"github.com/spf13/cobra"
35-
"go.opentelemetry.io/otel"
36-
"go.opentelemetry.io/otel/propagation"
3734
"golang.org/x/sync/errgroup"
3835
)
3936

@@ -51,7 +48,11 @@ func (s *composeService) ensureModels(ctx context.Context, project *types.Projec
5148
}
5249

5350
cmd := exec.CommandContext(ctx, dockerModel.Path, "ls", "--json")
54-
s.setupChildProcess(ctx, cmd)
51+
err = s.prepareShellOut(ctx, project, cmd)
52+
if err != nil {
53+
return err
54+
}
55+
5556
output, err := cmd.CombinedOutput()
5657
if err != nil {
5758
return fmt.Errorf("error checking available models: %w", err)
@@ -85,32 +86,29 @@ func (s *composeService) ensureModels(ctx context.Context, project *types.Projec
8586
eg.Go(func() error {
8687
w := progress.ContextWriter(gctx)
8788
if !slices.Contains(availableModels, config.Model) {
88-
err = s.pullModel(gctx, dockerModel, config, quietPull, w)
89+
err = s.pullModel(gctx, dockerModel, project, config, quietPull, w)
8990
if err != nil {
9091
return err
9192
}
9293
}
93-
err = s.configureModel(gctx, dockerModel, config, w)
94-
if err != nil {
95-
return err
96-
}
97-
w.Event(progress.CreatedEvent(config.Name))
98-
return nil
94+
return s.configureModel(gctx, dockerModel, project, config, w)
9995
})
10096
}
10197
return eg.Wait()
10298
}
10399

104-
func (s *composeService) pullModel(ctx context.Context, dockerModel *manager.Plugin, model types.ModelConfig, quietPull bool, w progress.Writer) error {
100+
func (s *composeService) pullModel(ctx context.Context, dockerModel *manager.Plugin, project *types.Project, model types.ModelConfig, quietPull bool, w progress.Writer) error {
105101
w.Event(progress.Event{
106102
ID: model.Name,
107103
Status: progress.Working,
108104
Text: "Pulling",
109105
})
110106

111107
cmd := exec.CommandContext(ctx, dockerModel.Path, "pull", model.Model)
112-
s.setupChildProcess(ctx, cmd)
113-
108+
err := s.prepareShellOut(ctx, project, cmd)
109+
if err != nil {
110+
return err
111+
}
114112
stream, err := cmd.StdoutPipe()
115113
if err != nil {
116114
return err
@@ -150,7 +148,7 @@ func (s *composeService) pullModel(ctx context.Context, dockerModel *manager.Plu
150148
return err
151149
}
152150

153-
func (s *composeService) configureModel(ctx context.Context, dockerModel *manager.Plugin, config types.ModelConfig, w progress.Writer) error {
151+
func (s *composeService) configureModel(ctx context.Context, dockerModel *manager.Plugin, project *types.Project, config types.ModelConfig, w progress.Writer) error {
154152
w.Event(progress.Event{
155153
ID: config.Name,
156154
Status: progress.Working,
@@ -167,13 +165,20 @@ func (s *composeService) configureModel(ctx context.Context, dockerModel *manage
167165
args = append(args, config.RuntimeFlags...)
168166
}
169167
cmd := exec.CommandContext(ctx, dockerModel.Path, args...)
170-
s.setupChildProcess(ctx, cmd)
168+
err := s.prepareShellOut(ctx, project, cmd)
169+
if err != nil {
170+
return err
171+
}
171172
return cmd.Run()
172173
}
173174

174175
func (s *composeService) setModelVariables(ctx context.Context, dockerModel *manager.Plugin, project *types.Project) error {
175176
cmd := exec.CommandContext(ctx, dockerModel.Path, "status", "--json")
176-
s.setupChildProcess(ctx, cmd)
177+
err := s.prepareShellOut(ctx, project, cmd)
178+
if err != nil {
179+
return err
180+
}
181+
177182
statusOut, err := cmd.CombinedOutput()
178183
if err != nil {
179184
return fmt.Errorf("error checking docker-model status: %w", err)
@@ -211,19 +216,6 @@ func (s *composeService) setModelVariables(ctx context.Context, dockerModel *man
211216
return nil
212217
}
213218

214-
func (s *composeService) setupChildProcess(gctx context.Context, cmd *exec.Cmd) {
215-
// exec provider command with same environment Compose is running
216-
env := types.NewMapping(os.Environ())
217-
// but remove DOCKER_CLI_PLUGIN... variable so plugin can detect it run standalone
218-
delete(env, manager.ReexecEnvvar)
219-
// propagate opentelemetry context to child process, see https://github.com/open-telemetry/oteps/blob/main/text/0258-env-context-baggage-carriers.md
220-
carrier := propagation.MapCarrier{}
221-
otel.GetTextMapPropagator().Inject(gctx, &carrier)
222-
env.Merge(types.Mapping(carrier))
223-
env["DOCKER_CONTEXT"] = s.dockerCli.CurrentContext()
224-
cmd.Env = env.Values()
225-
}
226-
227219
type Model struct {
228220
Id string `json:"id"`
229221
Tags []string `json:"tags"`

pkg/compose/plugins.go

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,12 @@ import (
2929
"strings"
3030
"sync"
3131

32-
"github.com/docker/compose/v2/pkg/progress"
33-
"github.com/sirupsen/logrus"
34-
"github.com/spf13/cobra"
35-
"go.opentelemetry.io/otel"
36-
"go.opentelemetry.io/otel/propagation"
37-
3832
"github.com/compose-spec/compose-go/v2/types"
3933
"github.com/docker/cli/cli-plugins/manager"
40-
"github.com/docker/cli/cli-plugins/socket"
4134
"github.com/docker/cli/cli/config"
35+
"github.com/docker/compose/v2/pkg/progress"
36+
"github.com/sirupsen/logrus"
37+
"github.com/spf13/cobra"
4238
)
4339

4440
type JsonMessage struct {
@@ -199,29 +195,11 @@ func (s *composeService) setupPluginCommand(ctx context.Context, project *types.
199195
args = append(args, service.Name)
200196

201197
cmd := exec.CommandContext(ctx, path, args...)
202-
// exec provider command with same environment Compose is running
203-
env := types.NewMapping(os.Environ())
204-
// but remove DOCKER_CLI_PLUGIN... variable so plugin can detect it run standalone
205-
delete(env, manager.ReexecEnvvar)
206-
// and add the explicit environment variables set for service
207-
for key, val := range service.Environment.RemoveEmpty().ToMapping() {
208-
env[key] = val
209-
}
210-
cmd.Env = env.Values()
211198

212-
// Use docker/cli mechanism to propagate termination signal to child process
213-
server, err := socket.NewPluginServer(nil)
214-
if err == nil {
215-
defer server.Close() //nolint:errcheck
216-
cmd.Env = replace(cmd.Env, socket.EnvKey, server.Addr().String())
199+
err := s.prepareShellOut(ctx, project, cmd)
200+
if err != nil {
201+
return nil, err
217202
}
218-
219-
cmd.Env = append(cmd.Env, fmt.Sprintf("DOCKER_CONTEXT=%s", s.dockerCli.CurrentContext()))
220-
221-
// propagate opentelemetry context to child process, see https://github.com/open-telemetry/oteps/blob/main/text/0258-env-context-baggage-carriers.md
222-
carrier := propagation.MapCarrier{}
223-
otel.GetTextMapPropagator().Inject(ctx, &carrier)
224-
cmd.Env = append(cmd.Env, types.Mapping(carrier).Values()...)
225203
return cmd, nil
226204
}
227205

pkg/compose/shellout.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package compose
18+
19+
import (
20+
"context"
21+
"os/exec"
22+
23+
"github.com/compose-spec/compose-go/v2/types"
24+
"github.com/docker/cli/cli-plugins/manager"
25+
"github.com/docker/cli/cli/context/docker"
26+
"go.opentelemetry.io/otel"
27+
"go.opentelemetry.io/otel/propagation"
28+
)
29+
30+
// prepareShellOut prepare a shell-out command to be ran by Compose
31+
func (s *composeService) prepareShellOut(gctx context.Context, project *types.Project, cmd *exec.Cmd) error {
32+
// exec command with same environment Compose is running
33+
env := types.NewMapping(project.Environment.Values())
34+
35+
// remove DOCKER_CLI_PLUGIN... variable so a docker-cli plugin will detect it run standalone
36+
delete(env, manager.ReexecEnvvar)
37+
38+
// propagate opentelemetry context to child process, see https://github.com/open-telemetry/oteps/blob/main/text/0258-env-context-baggage-carriers.md
39+
carrier := propagation.MapCarrier{}
40+
otel.GetTextMapPropagator().Inject(gctx, &carrier)
41+
env.Merge(types.Mapping(carrier))
42+
43+
env["DOCKER_CONTEXT"] = s.dockerCli.CurrentContext()
44+
45+
metadata, err := s.dockerCli.ContextStore().GetMetadata(s.dockerCli.CurrentContext())
46+
if err != nil {
47+
return err
48+
}
49+
endpoint, err := docker.EndpointFromContext(metadata)
50+
if err != nil {
51+
return err
52+
}
53+
actualHost := s.dockerCli.DockerEndpoint().Host
54+
if endpoint.Host != actualHost {
55+
// We are running with `--host` or `DOCKER_HOST` which overrides selected context
56+
env["DOCKER_HOST"] = actualHost
57+
}
58+
59+
cmd.Env = env.Values()
60+
return nil
61+
}

0 commit comments

Comments
 (0)