This updates secret inspect to support inspect by ID in addition to name
as well as inspecting multiple secrets. This also cleans up the
help text for consistency.
Signed-off-by: Evan Hazlett <ejhazlett@gmail.com>
| ... | ... |
@@ -9,18 +9,18 @@ import ( |
| 9 | 9 |
) |
| 10 | 10 |
|
| 11 | 11 |
type inspectOptions struct {
|
| 12 |
- name string |
|
| 12 |
+ names []string |
|
| 13 | 13 |
format string |
| 14 | 14 |
} |
| 15 | 15 |
|
| 16 | 16 |
func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
|
| 17 | 17 |
opts := inspectOptions{}
|
| 18 | 18 |
cmd := &cobra.Command{
|
| 19 |
- Use: "inspect [name]", |
|
| 19 |
+ Use: "inspect SECRET [SECRET]", |
|
| 20 | 20 |
Short: "Inspect a secret", |
| 21 |
- Args: cli.ExactArgs(1), |
|
| 21 |
+ Args: cli.RequiresMinArgs(1), |
|
| 22 | 22 |
RunE: func(cmd *cobra.Command, args []string) error {
|
| 23 |
- opts.name = args[0] |
|
| 23 |
+ opts.names = args |
|
| 24 | 24 |
return runSecretInspect(dockerCli, opts) |
| 25 | 25 |
}, |
| 26 | 26 |
} |
| ... | ... |
@@ -33,23 +33,13 @@ func runSecretInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
|
| 33 | 33 |
client := dockerCli.Client() |
| 34 | 34 |
ctx := context.Background() |
| 35 | 35 |
|
| 36 |
- // attempt to lookup secret by name |
|
| 37 |
- secrets, err := getSecretsByName(ctx, client, []string{opts.name})
|
|
| 36 |
+ ids, err := getCliRequestedSecretIDs(ctx, client, opts.names) |
|
| 38 | 37 |
if err != nil {
|
| 39 | 38 |
return err |
| 40 | 39 |
} |
| 41 |
- |
|
| 42 |
- id := opts.name |
|
| 43 |
- for _, s := range secrets {
|
|
| 44 |
- if s.Spec.Annotations.Name == opts.name {
|
|
| 45 |
- id = s.ID |
|
| 46 |
- break |
|
| 47 |
- } |
|
| 48 |
- } |
|
| 49 |
- |
|
| 50 |
- getRef := func(name string) (interface{}, []byte, error) {
|
|
| 40 |
+ getRef := func(id string) (interface{}, []byte, error) {
|
|
| 51 | 41 |
return client.SecretInspectWithRaw(ctx, id) |
| 52 | 42 |
} |
| 53 | 43 |
|
| 54 |
- return inspect.Inspect(dockerCli.Out(), []string{id}, opts.format, getRef)
|
|
| 44 |
+ return inspect.Inspect(dockerCli.Out(), ids, opts.format, getRef) |
|
| 55 | 45 |
} |
| ... | ... |
@@ -10,17 +10,17 @@ import ( |
| 10 | 10 |
) |
| 11 | 11 |
|
| 12 | 12 |
type removeOptions struct {
|
| 13 |
- ids []string |
|
| 13 |
+ names []string |
|
| 14 | 14 |
} |
| 15 | 15 |
|
| 16 | 16 |
func newSecretRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
|
| 17 | 17 |
return &cobra.Command{
|
| 18 |
- Use: "rm [id]", |
|
| 18 |
+ Use: "rm SECRET [SECRET]", |
|
| 19 | 19 |
Short: "Remove a secret", |
| 20 | 20 |
Args: cli.RequiresMinArgs(1), |
| 21 | 21 |
RunE: func(cmd *cobra.Command, args []string) error {
|
| 22 | 22 |
opts := removeOptions{
|
| 23 |
- ids: args, |
|
| 23 |
+ names: args, |
|
| 24 | 24 |
} |
| 25 | 25 |
return runSecretRemove(dockerCli, opts) |
| 26 | 26 |
}, |
| ... | ... |
@@ -31,32 +31,14 @@ func runSecretRemove(dockerCli *command.DockerCli, opts removeOptions) error {
|
| 31 | 31 |
client := dockerCli.Client() |
| 32 | 32 |
ctx := context.Background() |
| 33 | 33 |
|
| 34 |
- // attempt to lookup secret by name |
|
| 35 |
- secrets, err := getSecretsByName(ctx, client, opts.ids) |
|
| 34 |
+ ids, err := getCliRequestedSecretIDs(ctx, client, opts.names) |
|
| 36 | 35 |
if err != nil {
|
| 37 | 36 |
return err |
| 38 | 37 |
} |
| 39 | 38 |
|
| 40 |
- ids := opts.ids |
|
| 41 |
- |
|
| 42 |
- names := make(map[string]int) |
|
| 43 |
- for _, id := range ids {
|
|
| 44 |
- names[id] = 1 |
|
| 45 |
- } |
|
| 46 |
- |
|
| 47 |
- if len(secrets) > 0 {
|
|
| 48 |
- ids = []string{}
|
|
| 49 |
- |
|
| 50 |
- for _, s := range secrets {
|
|
| 51 |
- if _, ok := names[s.Spec.Annotations.Name]; ok {
|
|
| 52 |
- ids = append(ids, s.ID) |
|
| 53 |
- } |
|
| 54 |
- } |
|
| 55 |
- } |
|
| 56 |
- |
|
| 57 | 39 |
for _, id := range ids {
|
| 58 | 40 |
if err := client.SecretRemove(ctx, id); err != nil {
|
| 59 |
- return err |
|
| 41 |
+ fmt.Fprintf(dockerCli.Out(), "WARN: %s\n", err) |
|
| 60 | 42 |
} |
| 61 | 43 |
|
| 62 | 44 |
fmt.Fprintln(dockerCli.Out(), id) |
| ... | ... |
@@ -18,3 +18,30 @@ func getSecretsByName(ctx context.Context, client client.APIClient, names []stri |
| 18 | 18 |
Filters: args, |
| 19 | 19 |
}) |
| 20 | 20 |
} |
| 21 |
+ |
|
| 22 |
+func getCliRequestedSecretIDs(ctx context.Context, client client.APIClient, names []string) ([]string, error) {
|
|
| 23 |
+ ids := names |
|
| 24 |
+ |
|
| 25 |
+ // attempt to lookup secret by name |
|
| 26 |
+ secrets, err := getSecretsByName(ctx, client, ids) |
|
| 27 |
+ if err != nil {
|
|
| 28 |
+ return nil, err |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
+ lookup := make(map[string]struct{})
|
|
| 32 |
+ for _, id := range ids {
|
|
| 33 |
+ lookup[id] = struct{}{}
|
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ if len(secrets) > 0 {
|
|
| 37 |
+ ids = []string{}
|
|
| 38 |
+ |
|
| 39 |
+ for _, s := range secrets {
|
|
| 40 |
+ if _, ok := lookup[s.Spec.Annotations.Name]; ok {
|
|
| 41 |
+ ids = append(ids, s.ID) |
|
| 42 |
+ } |
|
| 43 |
+ } |
|
| 44 |
+ } |
|
| 45 |
+ |
|
| 46 |
+ return ids, nil |
|
| 47 |
+} |
| 21 | 48 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,68 @@ |
| 0 |
+// +build !windows |
|
| 1 |
+ |
|
| 2 |
+package main |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "encoding/json" |
|
| 6 |
+ |
|
| 7 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 8 |
+ "github.com/docker/docker/pkg/integration/checker" |
|
| 9 |
+ "github.com/go-check/check" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+func (s *DockerSwarmSuite) TestSecretInspect(c *check.C) {
|
|
| 13 |
+ d := s.AddDaemon(c, true, true) |
|
| 14 |
+ |
|
| 15 |
+ testName := "test_secret" |
|
| 16 |
+ id := d.createSecret(c, swarm.SecretSpec{
|
|
| 17 |
+ swarm.Annotations{
|
|
| 18 |
+ Name: testName, |
|
| 19 |
+ }, |
|
| 20 |
+ []byte("TESTINGDATA"),
|
|
| 21 |
+ }) |
|
| 22 |
+ c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
|
| 23 |
+ |
|
| 24 |
+ secret := d.getSecret(c, id) |
|
| 25 |
+ c.Assert(secret.Spec.Name, checker.Equals, testName) |
|
| 26 |
+ |
|
| 27 |
+ out, err := d.Cmd("secret", "inspect", testName)
|
|
| 28 |
+ c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 29 |
+ |
|
| 30 |
+ var secrets []swarm.Secret |
|
| 31 |
+ c.Assert(json.Unmarshal([]byte(out), &secrets), checker.IsNil) |
|
| 32 |
+ c.Assert(secrets, checker.HasLen, 1) |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+func (s *DockerSwarmSuite) TestSecretInspectMultiple(c *check.C) {
|
|
| 36 |
+ d := s.AddDaemon(c, true, true) |
|
| 37 |
+ |
|
| 38 |
+ testNames := []string{
|
|
| 39 |
+ "test0", |
|
| 40 |
+ "test1", |
|
| 41 |
+ } |
|
| 42 |
+ for _, n := range testNames {
|
|
| 43 |
+ id := d.createSecret(c, swarm.SecretSpec{
|
|
| 44 |
+ swarm.Annotations{
|
|
| 45 |
+ Name: n, |
|
| 46 |
+ }, |
|
| 47 |
+ []byte("TESTINGDATA"),
|
|
| 48 |
+ }) |
|
| 49 |
+ c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
|
|
| 50 |
+ |
|
| 51 |
+ secret := d.getSecret(c, id) |
|
| 52 |
+ c.Assert(secret.Spec.Name, checker.Equals, n) |
|
| 53 |
+ |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ args := []string{
|
|
| 57 |
+ "secret", |
|
| 58 |
+ "inspect", |
|
| 59 |
+ } |
|
| 60 |
+ args = append(args, testNames...) |
|
| 61 |
+ out, err := d.Cmd(args...) |
|
| 62 |
+ c.Assert(err, checker.IsNil, check.Commentf(out)) |
|
| 63 |
+ |
|
| 64 |
+ var secrets []swarm.Secret |
|
| 65 |
+ c.Assert(json.Unmarshal([]byte(out), &secrets), checker.IsNil) |
|
| 66 |
+ c.Assert(secrets, checker.HasLen, 2) |
|
| 67 |
+} |