mirror of
https://github.com/docker/compose.git
synced 2025-07-25 14:44:29 +02:00
Add support of ssh authentications defined in compose file or via cli flags
Signed-off-by: Guillaume Lours <guillaume.lours@docker.com>
This commit is contained in:
parent
3c12b94519
commit
ff73827a6f
@ -23,6 +23,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/cli"
|
"github.com/compose-spec/compose-go/cli"
|
||||||
|
"github.com/compose-spec/compose-go/loader"
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
buildx "github.com/docker/buildx/util/progress"
|
buildx "github.com/docker/buildx/util/progress"
|
||||||
"github.com/docker/compose/v2/pkg/utils"
|
"github.com/docker/compose/v2/pkg/utils"
|
||||||
@ -40,6 +41,28 @@ type buildOptions struct {
|
|||||||
args []string
|
args []string
|
||||||
noCache bool
|
noCache bool
|
||||||
memory string
|
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{
|
var printerModes = []string{
|
||||||
@ -73,7 +96,10 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
|||||||
}
|
}
|
||||||
return nil
|
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)
|
return runBuild(ctx, backend, opts, args)
|
||||||
}),
|
}),
|
||||||
ValidArgsFunction: serviceCompletion(p),
|
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().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().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().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 you default SSH Agent)")
|
||||||
cmd.Flags().Bool("parallel", true, "Build images in parallel. DEPRECATED")
|
cmd.Flags().Bool("parallel", true, "Build images in parallel. DEPRECATED")
|
||||||
cmd.Flags().MarkHidden("parallel") //nolint:errcheck
|
cmd.Flags().MarkHidden("parallel") //nolint:errcheck
|
||||||
cmd.Flags().Bool("compress", true, "Compress the build context using gzip. DEPRECATED")
|
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 err
|
||||||
}
|
}
|
||||||
|
|
||||||
return backend.Build(ctx, project, api.BuildOptions{
|
apiBuildOptions, err := opts.toAPIBuildOptions(services)
|
||||||
Pull: opts.pull,
|
if err != nil {
|
||||||
Progress: opts.progress,
|
return err
|
||||||
Args: types.NewMappingWithEquals(opts.args),
|
}
|
||||||
NoCache: opts.noCache,
|
return backend.Build(ctx, project, apiBuildOptions)
|
||||||
Quiet: opts.quiet,
|
|
||||||
Services: services,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ Build or rebuild services
|
|||||||
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
|
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
|
||||||
| `--pull` | | | Always attempt to pull a newer version of the image. |
|
| `--pull` | | | Always attempt to pull a newer version of the image. |
|
||||||
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
|
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
|
||||||
|
| `--ssh` | `string` | | Set SSH authentications used when building service images. (use 'default' for using you default SSH Agent) |
|
||||||
|
|
||||||
|
|
||||||
<!---MARKER_GEN_END-->
|
<!---MARKER_GEN_END-->
|
||||||
|
@ -117,6 +117,16 @@ options:
|
|||||||
experimentalcli: false
|
experimentalcli: false
|
||||||
kubernetes: false
|
kubernetes: false
|
||||||
swarm: false
|
swarm: false
|
||||||
|
- option: ssh
|
||||||
|
value_type: string
|
||||||
|
description: |
|
||||||
|
Set SSH authentications used when building service images. (use 'default' for using you default SSH Agent)
|
||||||
|
deprecated: false
|
||||||
|
hidden: false
|
||||||
|
experimental: false
|
||||||
|
experimentalcli: false
|
||||||
|
kubernetes: false
|
||||||
|
swarm: false
|
||||||
deprecated: false
|
deprecated: false
|
||||||
experimental: false
|
experimental: false
|
||||||
experimentalcli: false
|
experimentalcli: false
|
||||||
|
2
go.mod
2
go.mod
@ -6,7 +6,7 @@ require (
|
|||||||
github.com/AlecAivazis/survey/v2 v2.3.2
|
github.com/AlecAivazis/survey/v2 v2.3.2
|
||||||
github.com/buger/goterm v1.0.4
|
github.com/buger/goterm v1.0.4
|
||||||
github.com/cnabio/cnab-to-oci v0.3.1-beta1
|
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/console v1.0.3
|
||||||
github.com/containerd/containerd v1.6.1
|
github.com/containerd/containerd v1.6.1
|
||||||
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
|
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
|
||||||
|
4
go.sum
4
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/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/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.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.2 h1:y1dwl3KUTBnWPVur6EZno9zUIum6Q87/F5keljnGQB4=
|
||||||
github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
|
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/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-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
||||||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||||
|
@ -91,6 +91,8 @@ type BuildOptions struct {
|
|||||||
Quiet bool
|
Quiet bool
|
||||||
// Services passed in the command line to be built
|
// Services passed in the command line to be built
|
||||||
Services []string
|
Services []string
|
||||||
|
// Ssh authentications passed in the command line
|
||||||
|
SSHs []types.SSHKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateOptions group options of the Create API
|
// CreateOptions group options of the Create API
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
bclient "github.com/moby/buildkit/client"
|
bclient "github.com/moby/buildkit/client"
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/session/auth/authprovider"
|
"github.com/moby/buildkit/session/auth/authprovider"
|
||||||
|
"github.com/moby/buildkit/session/sshforward/sshprovider"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
"github.com/docker/compose/v2/pkg/api"
|
"github.com/docker/compose/v2/pkg/api"
|
||||||
@ -81,6 +82,14 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(options.SSHs) > 0 || len(service.Build.SSH) > 0 {
|
||||||
|
sshAgentProvider, err := sshAgentProvider(append(service.Build.SSH, options.SSHs...))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buildOptions.Session = append(buildOptions.Session, sshAgentProvider)
|
||||||
|
}
|
||||||
|
|
||||||
opts[imageName] = buildOptions
|
opts[imageName] = buildOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -296,3 +305,14 @@ func dockerFilePath(context string, dockerfile string) string {
|
|||||||
}
|
}
|
||||||
return filepath.Join(context, dockerfile)
|
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)
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ package e2e
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -79,6 +80,20 @@ func TestLocalComposeBuild(t *testing.T) {
|
|||||||
res.Assert(t, icmd.Expected{Out: `"RESULT": "SUCCESS"`})
|
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 as part of up", func(t *testing.T) {
|
t.Run("build as part of up", func(t *testing.T) {
|
||||||
c.RunDockerOrExitError("rmi", "build-test_nginx")
|
c.RunDockerOrExitError("rmi", "build-test_nginx")
|
||||||
c.RunDockerOrExitError("rmi", "custom-nginx")
|
c.RunDockerOrExitError("rmi", "custom-nginx")
|
||||||
|
@ -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
|
// RunDockerComposeCmd runs a docker compose command, expects no error and returns a result
|
||||||
func (c *E2eCLI) RunDockerComposeCmd(args ...string) *icmd.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 {
|
if composeStandaloneMode {
|
||||||
composeBinary, err := findExecutable(DockerComposeExecutableName, []string{"../../bin", "../../../bin"})
|
composeBinary, err := findExecutable(DockerComposeExecutableName, []string{"../../bin", "../../../bin"})
|
||||||
assert.NilError(c.test, err)
|
assert.NilError(c.test, err)
|
||||||
res := icmd.RunCmd(c.NewCmd(composeBinary, args...))
|
return icmd.RunCmd(c.NewCmd(composeBinary, args...))
|
||||||
res.Assert(c.test, icmd.Success)
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
args = append([]string{"compose"}, args...)
|
args = append([]string{"compose"}, args...)
|
||||||
res := icmd.RunCmd(c.NewCmd(DockerExecutableName, args...))
|
return icmd.RunCmd(c.NewCmd(DockerExecutableName, args...))
|
||||||
res.Assert(c.test, icmd.Success)
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdoutContains returns a predicate on command result expecting a string in stdout
|
// StdoutContains returns a predicate on command result expecting a string in stdout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user