From 4c2d7b7f7036ae47bbfbb2210e99a7888ec2dd41 Mon Sep 17 00:00:00 2001 From: Nick Adcock Date: Tue, 7 Jan 2020 11:28:28 +0000 Subject: [PATCH] Detect single value advanced config/secret syntax Allow the use of the advanced source=x syntax for config and secret values when there is no comma Before this change the following would fail with config not found: docker service create --name hello1 --config source=myconfig nginx:alpine And the following would fail with secret not found: docker service create --name hello2 --secret source=mysecret nginx:alpine Signed-off-by: Nick Adcock --- opts/config.go | 2 +- opts/config_test.go | 92 +++++++++++++++++++++++++++++++++++++++++++++ opts/secret.go | 2 +- opts/secret_test.go | 12 ++++++ 4 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 opts/config_test.go diff --git a/opts/config.go b/opts/config.go index 82fd2bce4e..3e56d5de61 100644 --- a/opts/config.go +++ b/opts/config.go @@ -32,7 +32,7 @@ func (o *ConfigOpt) Set(value string) error { } // support a simple syntax of --config foo - if len(fields) == 1 { + if len(fields) == 1 && !strings.Contains(fields[0], "=") { options.File.Name = fields[0] options.ConfigName = fields[0] o.values = append(o.values, options) diff --git a/opts/config_test.go b/opts/config_test.go new file mode 100644 index 0000000000..4e9b707267 --- /dev/null +++ b/opts/config_test.go @@ -0,0 +1,92 @@ +package opts + +import ( + "os" + "testing" + + "gotest.tools/assert" + is "gotest.tools/assert/cmp" +) + +func TestConfigOptionsSimple(t *testing.T) { + var opt ConfigOpt + + testCase := "app-config" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("app-config", req.ConfigName)) + assert.Check(t, is.Equal("app-config", req.File.Name)) + assert.Check(t, is.Equal("0", req.File.UID)) + assert.Check(t, is.Equal("0", req.File.GID)) +} + +func TestConfigOptionsSource(t *testing.T) { + var opt ConfigOpt + + testCase := "source=foo" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("foo", req.ConfigName)) +} + +func TestConfigOptionsSourceTarget(t *testing.T) { + var opt ConfigOpt + + testCase := "source=foo,target=testing" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("foo", req.ConfigName)) + assert.Check(t, is.Equal("testing", req.File.Name)) +} + +func TestConfigOptionsShorthand(t *testing.T) { + var opt ConfigOpt + + testCase := "src=foo,target=testing" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("foo", req.ConfigName)) +} + +func TestConfigOptionsCustomUidGid(t *testing.T) { + var opt ConfigOpt + + testCase := "source=foo,target=testing,uid=1000,gid=1001" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("foo", req.ConfigName)) + assert.Check(t, is.Equal("testing", req.File.Name)) + assert.Check(t, is.Equal("1000", req.File.UID)) + assert.Check(t, is.Equal("1001", req.File.GID)) +} + +func TestConfigOptionsCustomMode(t *testing.T) { + var opt ConfigOpt + + testCase := "source=foo,target=testing,uid=1000,gid=1001,mode=0444" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("foo", req.ConfigName)) + assert.Check(t, is.Equal("testing", req.File.Name)) + assert.Check(t, is.Equal("1000", req.File.UID)) + assert.Check(t, is.Equal("1001", req.File.GID)) + assert.Check(t, is.Equal(os.FileMode(0444), req.File.Mode)) +} diff --git a/opts/secret.go b/opts/secret.go index a1fde54d91..6a66dbdfd5 100644 --- a/opts/secret.go +++ b/opts/secret.go @@ -32,7 +32,7 @@ func (o *SecretOpt) Set(value string) error { } // support a simple syntax of --secret foo - if len(fields) == 1 { + if len(fields) == 1 && !strings.Contains(fields[0], "=") { options.File.Name = fields[0] options.SecretName = fields[0] o.values = append(o.values, options) diff --git a/opts/secret_test.go b/opts/secret_test.go index 94dd80d19a..539f0167f2 100644 --- a/opts/secret_test.go +++ b/opts/secret_test.go @@ -23,6 +23,18 @@ func TestSecretOptionsSimple(t *testing.T) { assert.Check(t, is.Equal("0", req.File.GID)) } +func TestSecretOptionsSource(t *testing.T) { + var opt SecretOpt + + testCase := "source=foo" + assert.NilError(t, opt.Set(testCase)) + + reqs := opt.Value() + assert.Assert(t, is.Len(reqs, 1)) + req := reqs[0] + assert.Check(t, is.Equal("foo", req.SecretName)) +} + func TestSecretOptionsSourceTarget(t *testing.T) { var opt SecretOpt