Skip to content

Commit 0ee20b8

Browse files
authored
Merge pull request #5995 from vvoland/swarm-init-cacert
swarm/init: Fix `--external-ca` ignoring `cacert` option
2 parents c07cd8a + 6c2d023 commit 0ee20b8

5 files changed

Lines changed: 48 additions & 16 deletions

File tree

cli/command/swarm/ca.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func runCA(ctx context.Context, dockerCli command.Cli, flags *pflag.FlagSet, opt
9696
func updateSwarmSpec(spec *swarm.Spec, flags *pflag.FlagSet, opts caOptions) {
9797
caCert := opts.rootCACert.Contents()
9898
caKey := opts.rootCAKey.Contents()
99-
opts.mergeSwarmSpecCAFlags(spec, flags, caCert)
99+
opts.mergeSwarmSpecCAFlags(spec, flags, &caCert)
100100

101101
spec.CAConfig.SigningCACert = caCert
102102
spec.CAConfig.SigningCAKey = caKey

cli/command/swarm/client_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
type fakeClient struct {
1212
client.Client
1313
infoFunc func() (system.Info, error)
14-
swarmInitFunc func() (string, error)
14+
swarmInitFunc func(req swarm.InitRequest) (string, error)
1515
swarmInspectFunc func() (swarm.Swarm, error)
1616
nodeInspectFunc func() (swarm.Node, []byte, error)
1717
swarmGetUnlockKeyFunc func() (swarm.UnlockKeyResponse, error)
@@ -35,9 +35,9 @@ func (cli *fakeClient) NodeInspectWithRaw(context.Context, string) (swarm.Node,
3535
return swarm.Node{}, []byte{}, nil
3636
}
3737

38-
func (cli *fakeClient) SwarmInit(context.Context, swarm.InitRequest) (string, error) {
38+
func (cli *fakeClient) SwarmInit(_ context.Context, req swarm.InitRequest) (string, error) {
3939
if cli.swarmInitFunc != nil {
40-
return cli.swarmInitFunc()
40+
return cli.swarmInitFunc(req)
4141
}
4242
return "", nil
4343
}

cli/command/swarm/init_test.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,37 @@ import (
44
"errors"
55
"fmt"
66
"io"
7+
"os"
8+
"path/filepath"
79
"testing"
810

911
"github.com/docker/cli/internal/test"
1012
"github.com/docker/docker/api/types/swarm"
1113
"gotest.tools/v3/assert"
14+
is "gotest.tools/v3/assert/cmp"
1215
"gotest.tools/v3/golden"
1316
)
1417

1518
func TestSwarmInitErrorOnAPIFailure(t *testing.T) {
1619
testCases := []struct {
1720
name string
1821
flags map[string]string
19-
swarmInitFunc func() (string, error)
22+
swarmInitFunc func(swarm.InitRequest) (string, error)
2023
swarmInspectFunc func() (swarm.Swarm, error)
2124
swarmGetUnlockKeyFunc func() (swarm.UnlockKeyResponse, error)
2225
nodeInspectFunc func() (swarm.Node, []byte, error)
2326
expectedError string
2427
}{
2528
{
2629
name: "init-failed",
27-
swarmInitFunc: func() (string, error) {
30+
swarmInitFunc: func(swarm.InitRequest) (string, error) {
2831
return "", errors.New("error initializing the swarm")
2932
},
3033
expectedError: "error initializing the swarm",
3134
},
3235
{
3336
name: "init-failed-with-ip-choice",
34-
swarmInitFunc: func() (string, error) {
37+
swarmInitFunc: func(swarm.InitRequest) (string, error) {
3538
return "", errors.New("could not choose an IP address to advertise")
3639
},
3740
expectedError: "could not choose an IP address to advertise - specify one with --advertise-addr",
@@ -85,14 +88,14 @@ func TestSwarmInit(t *testing.T) {
8588
testCases := []struct {
8689
name string
8790
flags map[string]string
88-
swarmInitFunc func() (string, error)
91+
swarmInitFunc func(req swarm.InitRequest) (string, error)
8992
swarmInspectFunc func() (swarm.Swarm, error)
9093
swarmGetUnlockKeyFunc func() (swarm.UnlockKeyResponse, error)
9194
nodeInspectFunc func() (swarm.Node, []byte, error)
9295
}{
9396
{
9497
name: "init",
95-
swarmInitFunc: func() (string, error) {
98+
swarmInitFunc: func(swarm.InitRequest) (string, error) {
9699
return "nodeID", nil
97100
},
98101
},
@@ -101,7 +104,7 @@ func TestSwarmInit(t *testing.T) {
101104
flags: map[string]string{
102105
flagAutolock: "true",
103106
},
104-
swarmInitFunc: func() (string, error) {
107+
swarmInitFunc: func(swarm.InitRequest) (string, error) {
105108
return "nodeID", nil
106109
},
107110
swarmGetUnlockKeyFunc: func() (swarm.UnlockKeyResponse, error) {
@@ -131,3 +134,28 @@ func TestSwarmInit(t *testing.T) {
131134
})
132135
}
133136
}
137+
138+
func TestSwarmInitWithExternalCA(t *testing.T) {
139+
cli := test.NewFakeCli(&fakeClient{
140+
swarmInitFunc: func(req swarm.InitRequest) (string, error) {
141+
if assert.Check(t, is.Len(req.Spec.CAConfig.ExternalCAs, 1)) {
142+
assert.Equal(t, req.Spec.CAConfig.ExternalCAs[0].CACert, cert)
143+
assert.Equal(t, req.Spec.CAConfig.ExternalCAs[0].Protocol, swarm.ExternalCAProtocolCFSSL)
144+
assert.Equal(t, req.Spec.CAConfig.ExternalCAs[0].URL, "https://example.com")
145+
}
146+
return "nodeID", nil
147+
},
148+
})
149+
150+
tempDir := t.TempDir()
151+
certFile := filepath.Join(tempDir, "cert.pem")
152+
err := os.WriteFile(certFile, []byte(cert), 0o644)
153+
assert.NilError(t, err)
154+
155+
cmd := newInitCommand(cli)
156+
cmd.SetArgs([]string{})
157+
cmd.SetOut(io.Discard)
158+
cmd.SetErr(io.Discard)
159+
assert.NilError(t, cmd.Flags().Set(flagExternalCA, "protocol=cfssl,url=https://example.com,cacert="+certFile))
160+
assert.NilError(t, cmd.Execute())
161+
}

cli/command/swarm/opts.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func addSwarmFlags(flags *pflag.FlagSet, options *swarmOptions) {
231231
addSwarmCAFlags(flags, &options.swarmCAOptions)
232232
}
233233

234-
func (o *swarmOptions) mergeSwarmSpec(spec *swarm.Spec, flags *pflag.FlagSet, caCert string) {
234+
func (o *swarmOptions) mergeSwarmSpec(spec *swarm.Spec, flags *pflag.FlagSet, caCert *string) {
235235
if flags.Changed(flagTaskHistoryLimit) {
236236
spec.Orchestration.TaskHistoryRetentionLimit = &o.taskHistoryLimit
237237
}
@@ -255,20 +255,24 @@ type swarmCAOptions struct {
255255
externalCA ExternalCAOption
256256
}
257257

258-
func (o *swarmCAOptions) mergeSwarmSpecCAFlags(spec *swarm.Spec, flags *pflag.FlagSet, caCert string) {
258+
func (o *swarmCAOptions) mergeSwarmSpecCAFlags(spec *swarm.Spec, flags *pflag.FlagSet, caCert *string) {
259259
if flags.Changed(flagCertExpiry) {
260260
spec.CAConfig.NodeCertExpiry = o.nodeCertExpiry
261261
}
262262
if flags.Changed(flagExternalCA) {
263263
spec.CAConfig.ExternalCAs = o.externalCA.Value()
264-
for _, ca := range spec.CAConfig.ExternalCAs {
265-
ca.CACert = caCert
264+
if caCert != nil {
265+
for _, ca := range spec.CAConfig.ExternalCAs {
266+
if ca.CACert == "" {
267+
ca.CACert = *caCert
268+
}
269+
}
266270
}
267271
}
268272
}
269273

270274
func (o *swarmOptions) ToSpec(flags *pflag.FlagSet) swarm.Spec {
271275
var spec swarm.Spec
272-
o.mergeSwarmSpec(&spec, flags, "")
276+
o.mergeSwarmSpec(&spec, flags, nil)
273277
return spec
274278
}

cli/command/swarm/update.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func runUpdate(ctx context.Context, dockerCli command.Cli, flags *pflag.FlagSet,
5353

5454
prevAutoLock := swarmInspect.Spec.EncryptionConfig.AutoLockManagers
5555

56-
opts.mergeSwarmSpec(&swarmInspect.Spec, flags, swarmInspect.ClusterInfo.TLSInfo.TrustRoot)
56+
opts.mergeSwarmSpec(&swarmInspect.Spec, flags, &swarmInspect.ClusterInfo.TLSInfo.TrustRoot)
5757

5858
curAutoLock := swarmInspect.Spec.EncryptionConfig.AutoLockManagers
5959

0 commit comments

Comments
 (0)