mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
secrets: support simple syntax --secret foo
Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
This commit is contained in:
parent
b2e4c7f3b5
commit
a257f674ba
5 changed files with 125 additions and 51 deletions
|
@ -1,13 +1,11 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/testutil/assert"
|
||||
)
|
||||
|
||||
|
@ -106,47 +104,3 @@ func TestHealthCheckOptionsToHealthConfigConflict(t *testing.T) {
|
|||
_, err := opt.toHealthConfig()
|
||||
assert.Error(t, err, "--no-healthcheck conflicts with --health-* options")
|
||||
}
|
||||
|
||||
func TestSecretOptionsSimple(t *testing.T) {
|
||||
var opt opts.SecretOpt
|
||||
|
||||
testCase := "source=foo,target=testing"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "foo")
|
||||
assert.Equal(t, req.Target, "testing")
|
||||
}
|
||||
|
||||
func TestSecretOptionsCustomUidGid(t *testing.T) {
|
||||
var opt opts.SecretOpt
|
||||
|
||||
testCase := "source=foo,target=testing,uid=1000,gid=1001"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "foo")
|
||||
assert.Equal(t, req.Target, "testing")
|
||||
assert.Equal(t, req.UID, "1000")
|
||||
assert.Equal(t, req.GID, "1001")
|
||||
}
|
||||
|
||||
func TestSecretOptionsCustomMode(t *testing.T) {
|
||||
var opt opts.SecretOpt
|
||||
|
||||
testCase := "source=foo,target=testing,uid=1000,gid=1001,mode=0444"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "foo")
|
||||
assert.Equal(t, req.Target, "testing")
|
||||
assert.Equal(t, req.UID, "1000")
|
||||
assert.Equal(t, req.GID, "1001")
|
||||
assert.Equal(t, req.Mode, os.FileMode(0444))
|
||||
}
|
||||
|
|
|
@ -122,11 +122,22 @@ ID NAME MODE REPLICAS IMAGE
|
|||
|
||||
### Create a service with secrets
|
||||
Use the `--secret` flag to give a container access to a
|
||||
[secret](secret_create.md). The following command will create a service
|
||||
with two secrets named `ssh-key` and `app-key`:
|
||||
[secret](secret_create.md).
|
||||
|
||||
Create a service specifying a secret:
|
||||
|
||||
```bash
|
||||
$ docker service create --name redis --secret source=ssh-key,target=ssh --secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 redis:3.0.6
|
||||
$ docker service create --name redis --secret secret.json redis:3.0.6
|
||||
4cdgfyky7ozwh3htjfw0d12qv
|
||||
```
|
||||
|
||||
Create a service specifying the secret, target, user/group ID and mode:
|
||||
|
||||
```bash
|
||||
$ docker service create --name redis \
|
||||
--secret source=ssh-key,target=ssh \
|
||||
--secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \
|
||||
redis:3.0.6
|
||||
4cdgfyky7ozwh3htjfw0d12qv
|
||||
```
|
||||
|
||||
|
|
|
@ -45,7 +45,37 @@ func (s *DockerSwarmSuite) TestServiceCreateMountVolume(c *check.C) {
|
|||
c.Assert(mounts[0].RW, checker.Equals, true)
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceCreateWithSecret(c *check.C) {
|
||||
func (s *DockerSwarmSuite) TestServiceCreateWithSecretSimple(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
serviceName := "test-service-secret"
|
||||
testName := "test_secret"
|
||||
id := d.createSecret(c, swarm.SecretSpec{
|
||||
swarm.Annotations{
|
||||
Name: testName,
|
||||
},
|
||||
[]byte("TESTINGDATA"),
|
||||
})
|
||||
c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
||||
|
||||
out, err := d.Cmd("service", "create", "--name", serviceName, "--secret", testName, "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
out, err = d.Cmd("service", "inspect", "--format", "{{ json .Spec.TaskTemplate.ContainerSpec.Secrets }}", serviceName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var refs []swarm.SecretReference
|
||||
c.Assert(json.Unmarshal([]byte(out), &refs), checker.IsNil)
|
||||
c.Assert(refs, checker.HasLen, 1)
|
||||
|
||||
c.Assert(refs[0].SecretName, checker.Equals, testName)
|
||||
c.Assert(refs[0].Target, checker.Not(checker.IsNil))
|
||||
c.Assert(refs[0].Target.Name, checker.Equals, testName)
|
||||
c.Assert(refs[0].Target.UID, checker.Equals, "0")
|
||||
c.Assert(refs[0].Target.GID, checker.Equals, "0")
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceCreateWithSecretSourceTarget(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
serviceName := "test-service-secret"
|
||||
|
|
|
@ -32,6 +32,14 @@ func (o *SecretOpt) Set(value string) error {
|
|||
Mode: 0444,
|
||||
}
|
||||
|
||||
// support a simple syntax of --secret foo
|
||||
if len(fields) == 1 {
|
||||
options.Source = fields[0]
|
||||
options.Target = fields[0]
|
||||
o.values = append(o.values, options)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
parts := strings.SplitN(field, "=", 2)
|
||||
key := strings.ToLower(parts[0])
|
||||
|
@ -62,7 +70,11 @@ func (o *SecretOpt) Set(value string) error {
|
|||
|
||||
options.Mode = os.FileMode(m)
|
||||
default:
|
||||
return fmt.Errorf("invalid field in secret request: %s", key)
|
||||
if len(fields) == 1 && value == "" {
|
||||
|
||||
} else {
|
||||
return fmt.Errorf("invalid field in secret request: %s", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
67
opts/secret_test.go
Normal file
67
opts/secret_test.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package opts
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/testutil/assert"
|
||||
)
|
||||
|
||||
func TestSecretOptionsSimple(t *testing.T) {
|
||||
var opt SecretOpt
|
||||
|
||||
testCase := "app-secret"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "app-secret")
|
||||
assert.Equal(t, req.Target, "app-secret")
|
||||
assert.Equal(t, req.UID, "0")
|
||||
assert.Equal(t, req.GID, "0")
|
||||
}
|
||||
|
||||
func TestSecretOptionsSourceTarget(t *testing.T) {
|
||||
var opt SecretOpt
|
||||
|
||||
testCase := "source=foo,target=testing"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "foo")
|
||||
assert.Equal(t, req.Target, "testing")
|
||||
}
|
||||
|
||||
func TestSecretOptionsCustomUidGid(t *testing.T) {
|
||||
var opt SecretOpt
|
||||
|
||||
testCase := "source=foo,target=testing,uid=1000,gid=1001"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "foo")
|
||||
assert.Equal(t, req.Target, "testing")
|
||||
assert.Equal(t, req.UID, "1000")
|
||||
assert.Equal(t, req.GID, "1001")
|
||||
}
|
||||
|
||||
func TestSecretOptionsCustomMode(t *testing.T) {
|
||||
var opt SecretOpt
|
||||
|
||||
testCase := "source=foo,target=testing,uid=1000,gid=1001,mode=0444"
|
||||
assert.NilError(t, opt.Set(testCase))
|
||||
|
||||
reqs := opt.Value()
|
||||
assert.Equal(t, len(reqs), 1)
|
||||
req := reqs[0]
|
||||
assert.Equal(t, req.Source, "foo")
|
||||
assert.Equal(t, req.Target, "testing")
|
||||
assert.Equal(t, req.UID, "1000")
|
||||
assert.Equal(t, req.GID, "1001")
|
||||
assert.Equal(t, req.Mode, os.FileMode(0444))
|
||||
}
|
Loading…
Add table
Reference in a new issue