Browse code

make secret update support name and id prefix

Signed-off-by: allencloud <allen.sun@daocloud.io>

allencloud authored on 2017/02/09 16:06:44
Showing 4 changed files
... ...
@@ -8069,7 +8069,7 @@ paths:
8069 8069
       parameters:
8070 8070
         - name: "id"
8071 8071
           in: "path"
8072
-          description: "The ID of the secret"
8072
+          description: "The ID or name of the secret"
8073 8073
           type: "string"
8074 8074
           required: true
8075 8075
         - name: "body"
... ...
@@ -95,13 +95,18 @@ func (c *Cluster) RemoveSecret(input string) error {
95 95
 
96 96
 // UpdateSecret updates a secret in a managed swarm cluster.
97 97
 // Note: this is not exposed to the CLI but is available from the API only
98
-func (c *Cluster) UpdateSecret(id string, version uint64, spec types.SecretSpec) error {
98
+func (c *Cluster) UpdateSecret(input string, version uint64, spec types.SecretSpec) error {
99 99
 	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
100
+		secret, err := getSecret(ctx, state.controlClient, input)
101
+		if err != nil {
102
+			return err
103
+		}
104
+
100 105
 		secretSpec := convert.SecretSpecToGRPC(spec)
101 106
 
102
-		_, err := state.controlClient.UpdateSecret(ctx,
107
+		_, err = state.controlClient.UpdateSecret(ctx,
103 108
 			&swarmapi.UpdateSecretRequest{
104
-				SecretID: id,
109
+				SecretID: secret.ID,
105 110
 				SecretVersion: &swarmapi.Version{
106 111
 					Index: version,
107 112
 				},
... ...
@@ -115,6 +115,9 @@ type ServiceConstructor func(*swarm.Service)
115 115
 // NodeConstructor defines a swarm node constructor
116 116
 type NodeConstructor func(*swarm.Node)
117 117
 
118
+// SecretConstructor defines a swarm secret constructor
119
+type SecretConstructor func(*swarm.Secret)
120
+
118 121
 // SpecConstructor defines a swarm spec constructor
119 122
 type SpecConstructor func(*swarm.Spec)
120 123
 
... ...
@@ -319,7 +322,7 @@ func (d *Swarm) ListNodes(c *check.C) []swarm.Node {
319 319
 	return nodes
320 320
 }
321 321
 
322
-// ListServices return the list of the current swarm services
322
+// ListServices returns the list of the current swarm services
323 323
 func (d *Swarm) ListServices(c *check.C) []swarm.Service {
324 324
 	status, out, err := d.SockRequest("GET", "/services", nil)
325 325
 	c.Assert(err, checker.IsNil, check.Commentf(string(out)))
... ...
@@ -370,7 +373,20 @@ func (d *Swarm) DeleteSecret(c *check.C, id string) {
370 370
 	c.Assert(status, checker.Equals, http.StatusNoContent, check.Commentf("output: %q", string(out)))
371 371
 }
372 372
 
373
-// GetSwarm return the current swarm object
373
+// UpdateSecret updates the swarm secret identified by the specified id
374
+// Currently, only label update is supported.
375
+func (d *Swarm) UpdateSecret(c *check.C, id string, f ...SecretConstructor) {
376
+	secret := d.GetSecret(c, id)
377
+	for _, fn := range f {
378
+		fn(secret)
379
+	}
380
+	url := fmt.Sprintf("/secrets/%s/update?version=%d", secret.ID, secret.Version.Index)
381
+	status, out, err := d.SockRequest("POST", url, secret.Spec)
382
+	c.Assert(err, checker.IsNil, check.Commentf(string(out)))
383
+	c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
384
+}
385
+
386
+// GetSwarm returns the current swarm object
374 387
 func (d *Swarm) GetSwarm(c *check.C) swarm.Swarm {
375 388
 	var sw swarm.Swarm
376 389
 	status, out, err := d.SockRequest("GET", "/swarm", nil)
... ...
@@ -3,6 +3,7 @@
3 3
 package main
4 4
 
5 5
 import (
6
+	"fmt"
6 7
 	"net/http"
7 8
 
8 9
 	"github.com/docker/docker/api/types/swarm"
... ...
@@ -56,3 +57,63 @@ func (s *DockerSwarmSuite) TestAPISwarmSecretsDelete(c *check.C) {
56 56
 	c.Assert(err, checker.IsNil)
57 57
 	c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf("secret delete: %s", string(out)))
58 58
 }
59
+
60
+func (s *DockerSwarmSuite) TestAPISwarmSecretsUpdate(c *check.C) {
61
+	d := s.AddDaemon(c, true, true)
62
+
63
+	testName := "test_secret"
64
+	id := d.CreateSecret(c, swarm.SecretSpec{
65
+		swarm.Annotations{
66
+			Name: testName,
67
+			Labels: map[string]string{
68
+				"test": "test1",
69
+			},
70
+		},
71
+		[]byte("TESTINGDATA"),
72
+	})
73
+	c.Assert(id, checker.Not(checker.Equals), "", check.Commentf("secrets: %s", id))
74
+
75
+	secret := d.GetSecret(c, id)
76
+	c.Assert(secret.ID, checker.Equals, id, check.Commentf("secret: %v", secret))
77
+
78
+	// test UpdateSecret with full ID
79
+	d.UpdateSecret(c, id, func(s *swarm.Secret) {
80
+		s.Spec.Labels = map[string]string{
81
+			"test": "test1",
82
+		}
83
+	})
84
+
85
+	secret = d.GetSecret(c, id)
86
+	c.Assert(secret.Spec.Labels["test"], checker.Equals, "test1", check.Commentf("secret: %v", secret))
87
+
88
+	// test UpdateSecret with full name
89
+	d.UpdateSecret(c, secret.Spec.Name, func(s *swarm.Secret) {
90
+		s.Spec.Labels = map[string]string{
91
+			"test": "test2",
92
+		}
93
+	})
94
+
95
+	secret = d.GetSecret(c, id)
96
+	c.Assert(secret.Spec.Labels["test"], checker.Equals, "test2", check.Commentf("secret: %v", secret))
97
+
98
+	// test UpdateSecret with prefix ID
99
+	d.UpdateSecret(c, id[:1], func(s *swarm.Secret) {
100
+		s.Spec.Labels = map[string]string{
101
+			"test": "test3",
102
+		}
103
+	})
104
+
105
+	secret = d.GetSecret(c, id)
106
+	c.Assert(secret.Spec.Labels["test"], checker.Equals, "test3", check.Commentf("secret: %v", secret))
107
+
108
+	// test UpdateSecret in updating Data which is not supported in daemon
109
+	// this test will produce an error in func UpdateSecret
110
+	secret = d.GetSecret(c, id)
111
+	secret.Spec.Data = []byte("TESTINGDATA2")
112
+
113
+	url := fmt.Sprintf("/secrets/%s/update?version=%d", secret.ID, secret.Version.Index)
114
+	status, out, err := d.SockRequest("POST", url, secret.Spec)
115
+
116
+	c.Assert(err, checker.IsNil, check.Commentf(string(out)))
117
+	c.Assert(status, checker.Equals, http.StatusInternalServerError, check.Commentf("output: %q", string(out)))
118
+}