mirror of
https://github.com/docker/compose.git
synced 2026-02-15 04:59:24 +08:00
Compare commits
18 Commits
add-e2e-dd
...
v2.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d815ff587 | ||
|
|
c9fbb9ba9c | ||
|
|
f2d9acd3d4 | ||
|
|
fcff36fc8a | ||
|
|
804ef4af5b | ||
|
|
0309a735a9 | ||
|
|
56e48f8360 | ||
|
|
c7473c68ae | ||
|
|
5e63f12ae8 | ||
|
|
60363c36df | ||
|
|
e700f0a5d7 | ||
|
|
6dbd6ffe11 | ||
|
|
eee0e8bed9 | ||
|
|
934b596e00 | ||
|
|
ff73827a6f | ||
|
|
3c12b94519 | ||
|
|
9b02add4df | ||
|
|
5ace5bdeda |
@@ -23,6 +23,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/loader"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
buildx "github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
@@ -40,6 +41,28 @@ type buildOptions struct {
|
||||
args []string
|
||||
noCache bool
|
||||
memory string
|
||||
ssh string
|
||||
}
|
||||
|
||||
func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) {
|
||||
var SSHKeys []types.SSHKey
|
||||
var err error
|
||||
if opts.ssh != "" {
|
||||
SSHKeys, err = loader.ParseShortSSHSyntax(opts.ssh)
|
||||
if err != nil {
|
||||
return api.BuildOptions{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return api.BuildOptions{
|
||||
Pull: opts.pull,
|
||||
Progress: opts.progress,
|
||||
Args: types.NewMappingWithEquals(opts.args),
|
||||
NoCache: opts.noCache,
|
||||
Quiet: opts.quiet,
|
||||
Services: services,
|
||||
SSHs: SSHKeys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var printerModes = []string{
|
||||
@@ -73,7 +96,10 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
RunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
if cmd.Flags().Changed("ssh") && opts.ssh == "" {
|
||||
opts.ssh = "default"
|
||||
}
|
||||
return runBuild(ctx, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: serviceCompletion(p),
|
||||
@@ -82,6 +108,7 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
cmd.Flags().BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image.")
|
||||
cmd.Flags().StringVar(&opts.progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
|
||||
cmd.Flags().StringArrayVar(&opts.args, "build-arg", []string{}, "Set build-time variables for services.")
|
||||
cmd.Flags().StringVar(&opts.ssh, "ssh", "", "Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)")
|
||||
cmd.Flags().Bool("parallel", true, "Build images in parallel. DEPRECATED")
|
||||
cmd.Flags().MarkHidden("parallel") //nolint:errcheck
|
||||
cmd.Flags().Bool("compress", true, "Compress the build context using gzip. DEPRECATED")
|
||||
@@ -103,12 +130,9 @@ func runBuild(ctx context.Context, backend api.Service, opts buildOptions, servi
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Build(ctx, project, api.BuildOptions{
|
||||
Pull: opts.pull,
|
||||
Progress: opts.progress,
|
||||
Args: types.NewMappingWithEquals(opts.args),
|
||||
NoCache: opts.noCache,
|
||||
Quiet: opts.quiet,
|
||||
Services: services,
|
||||
})
|
||||
apiBuildOptions, err := opts.toAPIBuildOptions(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return backend.Build(ctx, project, apiBuildOptions)
|
||||
}
|
||||
|
||||
@@ -89,9 +89,6 @@ func Adapt(fn Command) func(cmd *cobra.Command, args []string) error {
|
||||
})
|
||||
}
|
||||
|
||||
// Warning is a global warning to be displayed to user on command failure
|
||||
var Warning string
|
||||
|
||||
type projectOptions struct {
|
||||
ProjectName string
|
||||
Profiles []string
|
||||
@@ -143,6 +140,11 @@ func (o *projectOptions) toProjectName() (string, error) {
|
||||
return o.ProjectName, nil
|
||||
}
|
||||
|
||||
envProjectName := os.Getenv("COMPOSE_PROJECT_NAME")
|
||||
if envProjectName != "" {
|
||||
return envProjectName, nil
|
||||
}
|
||||
|
||||
project, err := o.toProject(nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -32,11 +32,6 @@ import (
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
)
|
||||
|
||||
func init() {
|
||||
commands.Warning = "The new 'docker compose' command is currently experimental. " +
|
||||
"To provide feedback or request new features please open issues at https://github.com/docker/compose"
|
||||
}
|
||||
|
||||
func pluginMain() {
|
||||
plugin.Run(func(dockerCli command.Cli) *cobra.Command {
|
||||
lazyInit := api.NewServiceProxy()
|
||||
|
||||
@@ -12,6 +12,7 @@ Build or rebuild services
|
||||
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
|
||||
| `--pull` | | | Always attempt to pull a newer version of the image. |
|
||||
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
|
||||
| `--ssh` | `string` | | Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent) |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -117,6 +117,16 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: ssh
|
||||
value_type: string
|
||||
description: |
|
||||
Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
|
||||
4
go.mod
4
go.mod
@@ -6,9 +6,9 @@ require (
|
||||
github.com/AlecAivazis/survey/v2 v2.3.2
|
||||
github.com/buger/goterm v1.0.4
|
||||
github.com/cnabio/cnab-to-oci v0.3.1-beta1
|
||||
github.com/compose-spec/compose-go v1.2.1
|
||||
github.com/compose-spec/compose-go v1.2.2
|
||||
github.com/containerd/console v1.0.3
|
||||
github.com/containerd/containerd v1.6.1
|
||||
github.com/containerd/containerd v1.6.2
|
||||
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
|
||||
github.com/docker/buildx v0.8.1 // when updating, also update the replace rules accordingly
|
||||
github.com/docker/cli v20.10.12+incompatible
|
||||
|
||||
7
go.sum
7
go.sum
@@ -302,8 +302,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
|
||||
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/compose-spec/compose-go v1.0.8/go.mod h1:REnCbBugoIdHB7S1sfkN/aJ7AJpNApGNjNiVjA9L8x4=
|
||||
github.com/compose-spec/compose-go v1.2.1 h1:8+DAP7Mt/Ohl5y6YbZdilLMvIhMxvuSZcNZyywjQmJE=
|
||||
github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
|
||||
github.com/compose-spec/compose-go v1.2.2 h1:y1dwl3KUTBnWPVur6EZno9zUIum6Q87/F5keljnGQB4=
|
||||
github.com/compose-spec/compose-go v1.2.2/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
|
||||
github.com/compose-spec/godotenv v1.1.1/go.mod h1:zF/3BOa18Z24tts5qnO/E9YURQanJTBUf7nlcCTNsyc=
|
||||
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
||||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||
@@ -348,8 +348,9 @@ github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoT
|
||||
github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g=
|
||||
github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
|
||||
github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
|
||||
github.com/containerd/containerd v1.6.1 h1:oa2uY0/0G+JX4X7hpGCYvkp9FjUancz56kSNnb1sG3o=
|
||||
github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
|
||||
github.com/containerd/containerd v1.6.2 h1:pcaPUGbYW8kBw6OgIZwIVIeEhdWVrBzsoCfVJ5BjrLU=
|
||||
github.com/containerd/containerd v1.6.2/go.mod h1:sidY30/InSE1j2vdD1ihtKoJz+lWdaXMdiAeIupaf+s=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
|
||||
@@ -91,6 +91,8 @@ type BuildOptions struct {
|
||||
Quiet bool
|
||||
// Services passed in the command line to be built
|
||||
Services []string
|
||||
// Ssh authentications passed in the command line
|
||||
SSHs []types.SSHKey
|
||||
}
|
||||
|
||||
// CreateOptions group options of the Create API
|
||||
|
||||
@@ -48,7 +48,7 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, lis
|
||||
fmt.Printf("Attaching to %s\n", strings.Join(names, ", "))
|
||||
|
||||
for _, container := range containers {
|
||||
err := s.attachContainer(ctx, container, listener, project)
|
||||
err := s.attachContainer(ctx, container, listener)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,13 +56,9 @@ func (s *composeService) attach(ctx context.Context, project *types.Project, lis
|
||||
return containers, err
|
||||
}
|
||||
|
||||
func (s *composeService) attachContainer(ctx context.Context, container moby.Container, listener api.ContainerEventListener, project *types.Project) error {
|
||||
func (s *composeService) attachContainer(ctx context.Context, container moby.Container, listener api.ContainerEventListener) error {
|
||||
serviceName := container.Labels[api.ServiceLabel]
|
||||
containerName := getContainerNameWithoutProject(container)
|
||||
service, err := project.GetService(serviceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
listener(api.ContainerEvent{
|
||||
Type: api.ContainerEventAttach,
|
||||
@@ -78,7 +74,13 @@ func (s *composeService) attachContainer(ctx context.Context, container moby.Con
|
||||
Line: line,
|
||||
})
|
||||
})
|
||||
_, _, err = s.attachContainerStreams(ctx, container.ID, service.Tty, nil, w, w)
|
||||
|
||||
inspect, err := s.dockerCli.Client().ContainerInspect(ctx, container.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, err = s.attachContainerStreams(ctx, container.ID, inspect.Config.Tty, nil, w, w)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
bclient "github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/session/auth/authprovider"
|
||||
"github.com/moby/buildkit/session/sshforward/sshprovider"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
@@ -62,7 +63,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
||||
if service.Build != nil {
|
||||
imageName := getImageName(service, project.Name)
|
||||
imagesToBuild = append(imagesToBuild, imageName)
|
||||
buildOptions, err := s.toBuildOptions(project, service, imageName)
|
||||
buildOptions, err := s.toBuildOptions(project, service, imageName, options.SSHs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -80,7 +81,6 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
||||
Attrs: map[string]string{"ref": image},
|
||||
})
|
||||
}
|
||||
|
||||
opts[imageName] = buildOptions
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
|
||||
if localImagePresent && service.PullPolicy != types.PullPolicyBuild {
|
||||
continue
|
||||
}
|
||||
opt, err := s.toBuildOptions(project, service, imageName)
|
||||
opt, err := s.toBuildOptions(project, service, imageName, []types.SSHKey{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -209,7 +209,7 @@ func (s *composeService) doBuild(ctx context.Context, project *types.Project, op
|
||||
return s.doBuildBuildkit(ctx, project, opts, mode)
|
||||
}
|
||||
|
||||
func (s *composeService) toBuildOptions(project *types.Project, service types.ServiceConfig, imageTag string) (build.Options, error) {
|
||||
func (s *composeService) toBuildOptions(project *types.Project, service types.ServiceConfig, imageTag string, sshKeys []types.SSHKey) (build.Options, error) {
|
||||
var tags []string
|
||||
tags = append(tags, imageTag)
|
||||
|
||||
@@ -243,6 +243,17 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
|
||||
return build.Options{}, err
|
||||
}
|
||||
|
||||
sessionConfig := []session.Attachable{
|
||||
authprovider.NewDockerAuthProvider(s.stderr()),
|
||||
}
|
||||
if len(sshKeys) > 0 || len(service.Build.SSH) > 0 {
|
||||
sshAgentProvider, err := sshAgentProvider(append(service.Build.SSH, sshKeys...))
|
||||
if err != nil {
|
||||
return build.Options{}, err
|
||||
}
|
||||
sessionConfig = append(sessionConfig, sshAgentProvider)
|
||||
}
|
||||
|
||||
return build.Options{
|
||||
Inputs: build.Inputs{
|
||||
ContextPath: service.Build.Context,
|
||||
@@ -260,9 +271,7 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
|
||||
Labels: service.Build.Labels,
|
||||
NetworkMode: service.Build.Network,
|
||||
ExtraHosts: service.Build.ExtraHosts,
|
||||
Session: []session.Attachable{
|
||||
authprovider.NewDockerAuthProvider(s.stderr()),
|
||||
},
|
||||
Session: sessionConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -296,3 +305,14 @@ func dockerFilePath(context string, dockerfile string) string {
|
||||
}
|
||||
return filepath.Join(context, dockerfile)
|
||||
}
|
||||
|
||||
func sshAgentProvider(sshKeys types.SSHConfig) (session.Attachable, error) {
|
||||
sshConfig := make([]sshprovider.AgentConfig, 0, len(sshKeys))
|
||||
for _, sshKey := range sshKeys {
|
||||
sshConfig = append(sshConfig, sshprovider.AgentConfig{
|
||||
ID: sshKey.ID,
|
||||
Paths: []string{sshKey.Path},
|
||||
})
|
||||
}
|
||||
return sshprovider.NewSSHAgentProvider(sshConfig)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/registry/client"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -131,6 +132,11 @@ func (s *composeService) ensureNetworksDown(ctx context.Context, project *types.
|
||||
continue
|
||||
}
|
||||
networkName := n.Name
|
||||
_, err := s.apiClient().NetworkInspect(ctx, networkName, moby.NetworkInspectOptions{})
|
||||
if client.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ops = append(ops, func() error {
|
||||
return s.removeNetwork(ctx, networkName, w)
|
||||
})
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
|
||||
compose "github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/mocks"
|
||||
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/volume"
|
||||
@@ -60,6 +59,7 @@ func TestDown(t *testing.T) {
|
||||
api.EXPECT().ContainerRemove(gomock.Any(), "456", moby.ContainerRemoveOptions{Force: true}).Return(nil)
|
||||
api.EXPECT().ContainerRemove(gomock.Any(), "789", moby.ContainerRemoveOptions{Force: true}).Return(nil)
|
||||
|
||||
api.EXPECT().NetworkInspect(gomock.Any(), "myProject_default", moby.NetworkInspectOptions{}).Return(moby.NetworkResource{Name: "myProject_default"}, nil)
|
||||
api.EXPECT().NetworkRemove(gomock.Any(), "myProject_default").Return(nil)
|
||||
|
||||
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{})
|
||||
@@ -94,6 +94,7 @@ func TestDownRemoveOrphans(t *testing.T) {
|
||||
api.EXPECT().ContainerRemove(gomock.Any(), "789", moby.ContainerRemoveOptions{Force: true}).Return(nil)
|
||||
api.EXPECT().ContainerRemove(gomock.Any(), "321", moby.ContainerRemoveOptions{Force: true}).Return(nil)
|
||||
|
||||
api.EXPECT().NetworkInspect(gomock.Any(), "myProject_default", moby.NetworkInspectOptions{}).Return(moby.NetworkResource{Name: "myProject_default"}, nil)
|
||||
api.EXPECT().NetworkRemove(gomock.Any(), "myProject_default").Return(nil)
|
||||
|
||||
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{RemoveOrphans: true})
|
||||
|
||||
@@ -89,7 +89,7 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
|
||||
updateServices(&service, observedState)
|
||||
|
||||
created, err := s.createContainer(ctx, project, service, service.ContainerName, 1,
|
||||
opts.Detach && opts.AutoRemove, opts.UseNetworkAliases, opts.Interactive)
|
||||
opts.AutoRemove, opts.UseNetworkAliases, opts.Interactive)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options
|
||||
|
||||
eg.Go(func() error {
|
||||
return s.watchContainers(context.Background(), project.Name, options.AttachTo, listener, attached, func(container moby.Container) error {
|
||||
return s.attachContainer(ctx, container, listener, project)
|
||||
return s.attachContainer(ctx, container, listener)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package e2e
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -79,6 +80,57 @@ func TestLocalComposeBuild(t *testing.T) {
|
||||
res.Assert(t, icmd.Expected{Out: `"RESULT": "SUCCESS"`})
|
||||
})
|
||||
|
||||
t.Run("build failed with ssh default value", func(t *testing.T) {
|
||||
//unset SSH_AUTH_SOCK to be sure we don't have a default value for the SSH Agent
|
||||
defaultSSHAUTHSOCK := os.Getenv("SSH_AUTH_SOCK")
|
||||
os.Unsetenv("SSH_AUTH_SOCK") //nolint:errcheck
|
||||
defer os.Setenv("SSH_AUTH_SOCK", defaultSSHAUTHSOCK) //nolint:errcheck
|
||||
|
||||
res := c.RunDockerComposeCmdNoCheck("--project-directory", "fixtures/build-test", "build", "--ssh", "")
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "invalid empty ssh agent socket: make sure SSH_AUTH_SOCK is set",
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
t.Run("build succeed with ssh from Compose file", func(t *testing.T) {
|
||||
c.RunDockerOrExitError("rmi", "build-test-ssh")
|
||||
|
||||
c.RunDockerComposeCmd("--project-directory", "fixtures/build-test/ssh", "build")
|
||||
c.RunDockerCmd("image", "inspect", "build-test-ssh")
|
||||
})
|
||||
|
||||
t.Run("build succeed with ssh from CLI", func(t *testing.T) {
|
||||
c.RunDockerOrExitError("rmi", "build-test-ssh")
|
||||
|
||||
c.RunDockerComposeCmd("-f", "fixtures/build-test/ssh/compose-without-ssh.yaml", "--project-directory",
|
||||
"fixtures/build-test/ssh", "build", "--no-cache", "--ssh", "fake-ssh=./fixtures/build-test/ssh/fake_rsa")
|
||||
c.RunDockerCmd("image", "inspect", "build-test-ssh")
|
||||
})
|
||||
|
||||
t.Run("build failed with wrong ssh key id from CLI", func(t *testing.T) {
|
||||
c.RunDockerOrExitError("rmi", "build-test-ssh")
|
||||
|
||||
res := c.RunDockerComposeCmdNoCheck("-f", "fixtures/build-test/ssh/compose-without-ssh.yaml",
|
||||
"--project-directory", "fixtures/build-test/ssh", "build", "--no-cache", "--ssh",
|
||||
"wrong-ssh=./fixtures/build-test/ssh/fake_rsa")
|
||||
res.Assert(t, icmd.Expected{
|
||||
ExitCode: 17,
|
||||
Err: "failed to solve: rpc error: code = Unknown desc = unset ssh forward key fake-ssh",
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("build succeed as part of up with ssh from Compose file", func(t *testing.T) {
|
||||
c.RunDockerOrExitError("rmi", "build-test-ssh")
|
||||
|
||||
c.RunDockerComposeCmd("--project-directory", "fixtures/build-test/ssh", "up", "-d", "--build")
|
||||
t.Cleanup(func() {
|
||||
c.RunDockerComposeCmd("--project-directory", "fixtures/build-test/ssh", "down")
|
||||
})
|
||||
c.RunDockerCmd("image", "inspect", "build-test-ssh")
|
||||
})
|
||||
|
||||
t.Run("build as part of up", func(t *testing.T) {
|
||||
c.RunDockerOrExitError("rmi", "build-test_nginx")
|
||||
c.RunDockerOrExitError("rmi", "custom-nginx")
|
||||
|
||||
24
pkg/e2e/fixtures/build-test/ssh/Dockerfile
Normal file
24
pkg/e2e/fixtures/build-test/ssh/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
||||
# syntax=docker/dockerfile:1.2
|
||||
|
||||
|
||||
# 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.
|
||||
|
||||
FROM alpine
|
||||
RUN apk add --no-cache openssh-client
|
||||
|
||||
WORKDIR /compose
|
||||
COPY fake_rsa.pub /compose/
|
||||
|
||||
RUN --mount=type=ssh,id=fake-ssh,required=true diff <(ssh-add -L) <(cat /compose/fake_rsa.pub)
|
||||
5
pkg/e2e/fixtures/build-test/ssh/compose-without-ssh.yaml
Normal file
5
pkg/e2e/fixtures/build-test/ssh/compose-without-ssh.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
services:
|
||||
ssh:
|
||||
image: build-test-ssh
|
||||
build:
|
||||
context: .
|
||||
7
pkg/e2e/fixtures/build-test/ssh/compose.yaml
Normal file
7
pkg/e2e/fixtures/build-test/ssh/compose.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
services:
|
||||
ssh:
|
||||
image: build-test-ssh
|
||||
build:
|
||||
context: .
|
||||
ssh:
|
||||
- fake-ssh=./fixtures/build-test/ssh/fake_rsa
|
||||
49
pkg/e2e/fixtures/build-test/ssh/fake_rsa
Normal file
49
pkg/e2e/fixtures/build-test/ssh/fake_rsa
Normal file
@@ -0,0 +1,49 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
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
|
||||
Xsd/RqSc66MAAAAAAQID
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
1
pkg/e2e/fixtures/build-test/ssh/fake_rsa.pub
Normal file
1
pkg/e2e/fixtures/build-test/ssh/fake_rsa.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDucnjECEntXAjre25rLcMIdpNd4Rj3Yfpg1nym0AgFjSZSfoZz2az3ge9wAp6YImQ7R/LpTYk6hJP6rVg8Al/zo2shTjWFl3OvDZB2ob8DeNrhVMBo4lsf3Bp8oelYuzqTKKAa2LcpIFpubgcBFTyWC1EToC4ILX6bDzbUXNOwxYzFGn+spXGCyIxSx13ntZEo52fxNGbo0dwSzLtfvMAnv4KH+a4YYIKTdn35hTOhVW1j/AZiZZdeP81TPGcSrRcvI7wcL5BT/11aWHU4uagy7E3WVi0dEVZay0Jugo2w5wiImwsp9DW3jPiNerk/slMsTk+eB6auvjErbVEWNVoZCk6PJCBmfWjTAC/Lvwo5HCA3QSXBxv9cgol6nPN7MIjJeVJp95e4c/6gyMzazYxc0eUwq/onCHhBjBRDrX5sBw+RyYh2W2IAw0tzFiKoS53zkRBCX1yK6EwprRtmXU4QgvBVIhqwS70EQpWvPnZllUsYxyGo5X/h/U+o8RqCd+dFgS20noC5phRole9JA/pmPgAVvpas/AQEgU64Af2Lha0bnZAArq5zXCw9mUebwn5WdMQEoW4YRG7+4kFY+jjcuO7xWse5lTxB440REp8ltzUQj1empaL7dVxZPRAm3EQZbZiYPnTn5wo1zfXHA61yrCiC3BPTCe6PQEB/fcdjfw==
|
||||
@@ -204,17 +204,20 @@ func (c *E2eCLI) RunDockerCmd(args ...string) *icmd.Result {
|
||||
|
||||
// RunDockerComposeCmd runs a docker compose command, expects no error and returns a result
|
||||
func (c *E2eCLI) RunDockerComposeCmd(args ...string) *icmd.Result {
|
||||
res := c.RunDockerComposeCmdNoCheck(args...)
|
||||
res.Assert(c.test, icmd.Success)
|
||||
return res
|
||||
}
|
||||
|
||||
// RunDockerComposeCmdNoCheck runs a docker compose command, don't presume of any expectation and returns a result
|
||||
func (c *E2eCLI) RunDockerComposeCmdNoCheck(args ...string) *icmd.Result {
|
||||
if composeStandaloneMode {
|
||||
composeBinary, err := findExecutable(DockerComposeExecutableName, []string{"../../bin", "../../../bin"})
|
||||
assert.NilError(c.test, err)
|
||||
res := icmd.RunCmd(c.NewCmd(composeBinary, args...))
|
||||
res.Assert(c.test, icmd.Success)
|
||||
return res
|
||||
return icmd.RunCmd(c.NewCmd(composeBinary, args...))
|
||||
}
|
||||
args = append([]string{"compose"}, args...)
|
||||
res := icmd.RunCmd(c.NewCmd(DockerExecutableName, args...))
|
||||
res.Assert(c.test, icmd.Success)
|
||||
return res
|
||||
return icmd.RunCmd(c.NewCmd(DockerExecutableName, args...))
|
||||
}
|
||||
|
||||
// StdoutContains returns a predicate on command result expecting a string in stdout
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
|
||||
func TestStartStop(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
const projectName = "e2e-start-stop"
|
||||
const projectName = "e2e-start-stop-no-dependencies"
|
||||
|
||||
getProjectRegx := func(status string) string {
|
||||
// match output with random spaces like:
|
||||
@@ -43,7 +43,7 @@ func TestStartStop(t *testing.T) {
|
||||
|
||||
t.Run("Up a project", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd("-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-simple-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-no-dependencies-simple-1 Started"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("ls", "--all")
|
||||
testify.Regexp(t, getProjectRegx("running"), res.Stdout())
|
||||
@@ -57,13 +57,13 @@ func TestStartStop(t *testing.T) {
|
||||
c.RunDockerComposeCmd("-f", "./fixtures/start-stop/compose.yaml", "--project-name", projectName, "stop")
|
||||
|
||||
res := c.RunDockerComposeCmd("ls")
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-no-dependencies"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("ls", "--all")
|
||||
testify.Regexp(t, getProjectRegx("exited"), res.Stdout())
|
||||
|
||||
res = c.RunDockerComposeCmd("--project-name", projectName, "ps")
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-words-1"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-start-stop-no-dependencies-words-1"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("--project-name", projectName, "ps", "--all")
|
||||
testify.Regexp(t, getServiceRegx("simple", "exited"), res.Stdout())
|
||||
|
||||
Reference in New Issue
Block a user