Signed-off-by: allencloud <allen.sun@daocloud.io>
allencloud authored on 2017/02/09 16:06:44... | ... |
@@ -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 |
+} |