Merge lp:~axwalk/juju-core/api-push-env-secrets-take2 into lp:~go-bot/juju-core/trunk

Proposed by Andrew Wilkins
Status: Merged
Approved by: Andrew Wilkins
Approved revision: no longer in the source branch.
Merged at revision: 2038
Proposed branch: lp:~axwalk/juju-core/api-push-env-secrets-take2
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 165 lines (+61/-5)
5 files modified
juju/api.go (+30/-2)
juju/apiconn_test.go (+19/-1)
juju/export_test.go (+1/-0)
state/apiserver/client/client.go (+5/-2)
state/apiserver/client/client_test.go (+6/-0)
To merge this branch: bzr merge lp:~axwalk/juju-core/api-push-env-secrets-take2
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+194288@code.launchpad.net

Commit message

Push environment secrets after connecting API

This is a much simpler alternative to
https://codereview.appspot.com/22080044/,
implementing the same logic as is present
for the straight-to-state juju.NewConn.

As secrets-pushing will be obsoleted by
synchronous bootstrapping, which is slated
for introduction soon, I have a strong
preference for this option.

There's a drive-by-fix to the EnvironmentSet
API which simplifies testing: allow agent-version
in the parameters as long as it matches the
existing value.

https://codereview.appspot.com/22720043/

Description of the change

Push environment secrets after connecting API

This is a much simpler alternative to
https://codereview.appspot.com/22080044/,
implementing the same logic as is present
for the straight-to-state juju.NewConn.

As secrets-pushing will be obsoleted by
synchronous bootstrapping, which is slated
for introduction soon, I have a strong
preference for this option.

There's a drive-by-fix to the EnvironmentSet
API which simplifies testing: allow agent-version
in the parameters as long as it matches the
existing value.

https://codereview.appspot.com/22720043/

To post a comment you must log in.
Revision history for this message
Andrew Wilkins (axwalk) wrote :
Download full text (6.5 KiB)

Reviewers: mp+194288_code.launchpad.net,

Message:
Please take a look.

Description:
Push environment secrets after connecting API

This is a much simpler alternative to
https://codereview.appspot.com/22080044/,
implementing the same logic as is present
for the straight-to-state juju.NewConn.

As secrets-pushing will be obsoleted by
synchronous bootstrapping, which is slated
for introduction soon, I have a strong
preference for this option.

There's a drive-by-fix to the EnvironmentSet
API which simplifies testing: allow agent-version
in the parameters as long as it matches the
existing value.

https://code.launchpad.net/~axwalk/juju-core/api-push-env-secrets-take2/+merge/194288

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/22720043/

Affected files (+61, -4 lines):
   A [revision details]
   M juju/api.go
   M juju/apiconn_test.go
   M juju/export_test.go
   M state/apiserver/client/client.go
   M state/apiserver/client/client_test.go

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-20131106165607-vwv921qmnm416g10
+New revision: <email address hidden>

Index: juju/api.go
=== modified file 'juju/api.go'
--- juju/api.go 2013-10-24 18:44:46 +0000
+++ juju/api.go 2013-11-07 06:48:00 +0000
@@ -55,13 +55,40 @@
   if err != nil {
    return nil, err
   }
- // TODO(rog): implement updateSecrets (see Conn.updateSecrets)
+ // TODO(axw) remove this once we have synchronous bootstrap.
+ if err := updateSecrets(environ, st); err != nil {
+ return nil, err
+ }
   return &APIConn{
    Environ: environ,
    State: st,
   }, nil
  }

+// updateSecrets pushes environment secrets to the API server.
+// NOTE: this is a temporary hack, and will disappear when we
+// have synchronous bootstrap.
+var updateSecrets = func(environ environs.Environ, st *api.State) error {
+ secrets, err := environ.Provider().SecretAttrs(environ.Config())
+ if err != nil {
+ return err
+ }
+ client := st.Client()
+ cfg, err := client.EnvironmentGet()
+ if err != nil {
+ return err
+ }
+ for k, v := range secrets {
+ if _, exists := cfg[k]; exists {
+ // Environment already has secrets. Won't send again.
+ return nil
+ } else {
+ cfg[k] = v
+ }
+ }
+ return client.EnvironmentSet(cfg)
+}
+
  // Close terminates the connection to the environment and releases
  // any associated resources.
  func (c *APIConn) Close() error {

Index: juju/apiconn_test.go
=== modified file 'juju/apiconn_test.go'
--- juju/apiconn_test.go 2013-10-24 19:01:23 +0000
+++ juju/apiconn_test.go 2013-11-07 06:48:00 +0000
@@ -52,12 +52,22 @@
   err = bootstrap.Bootstrap(env, constraints.Value{})
   c.Assert(err, gc.IsNil)

+ cfg = env.Config()
+ cfg, err = cfg.Apply(map[string]interface{}{
+ "secret": "fnord",
+ })
+ c.Assert(err, gc.IsNil)
+ err = env.SetConfig(cfg)
+ c.Assert(err, gc.IsNil)
+
   conn, err := juju.NewAPIConn(env, api.DefaultDialOpts())
   c.Assert(err, gc.IsNil)
-
   c.Assert(conn.Environ, gc.Equals, env)
   c.Assert(conn.State, gc.NotNil)

...

Read more...

Revision history for this message
Andrew Wilkins (axwalk) wrote :
Revision history for this message
John A Meinel (jameinel) wrote :

LGTM

I like this quite a bit better than the ones that poked at api.Open.

https://codereview.appspot.com/22720043/

Revision history for this message
William Reade (fwereade) wrote :

LGTM, very nice.

https://codereview.appspot.com/22720043/diff/20001/juju/api.go
File juju/api.go (right):

https://codereview.appspot.com/22720043/diff/20001/juju/api.go#newcode90
juju/api.go:90: return client.EnvironmentSet(cfg)
Ehh, EnvironmentSet requires a whole config, does it? I guess this is a
one-time thing so it's probably not a big problem.

https://codereview.appspot.com/22720043/diff/20001/juju/apiconn_test.go
File juju/apiconn_test.go (right):

https://codereview.appspot.com/22720043/diff/20001/juju/apiconn_test.go#newcode57
juju/apiconn_test.go:57: "secret": "fnord",
Why did you leave out the value there?

;p

https://codereview.appspot.com/22720043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

https://codereview.appspot.com/22720043/diff/20001/juju/api.go
File juju/api.go (right):

https://codereview.appspot.com/22720043/diff/20001/juju/api.go#newcode90
juju/api.go:90: return client.EnvironmentSet(cfg)
On 2013/11/07 09:23:26, fwereade wrote:
> Ehh, EnvironmentSet requires a whole config, does it? I guess this is
a one-time
> thing so it's probably not a big problem.

True, it's sending more than necessary. This is going to be deleted soon
so I'm just going to land as is (otherwise secrets needs to be converted
to map[string]interface{}... not worth the extra lines).

https://codereview.appspot.com/22720043/

Revision history for this message
Roger Peppe (rogpeppe) wrote :

LGTM, thanks.

https://codereview.appspot.com/22720043/diff/20001/juju/api.go
File juju/api.go (right):

https://codereview.appspot.com/22720043/diff/20001/juju/api.go#newcode54
juju/api.go:54: // TODO(rog): handle errUnauthorized when the API
handles passwords.
d
(this should have gone ages ago!)

https://codereview.appspot.com/22720043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'juju/api.go'
2--- juju/api.go 2013-10-24 18:44:46 +0000
3+++ juju/api.go 2013-11-07 07:18:28 +0000
4@@ -55,17 +55,45 @@
5 if err != nil {
6 return nil, err
7 }
8- // TODO(rog): implement updateSecrets (see Conn.updateSecrets)
9+ // TODO(axw) remove this once we have synchronous bootstrap.
10+ if err := updateSecrets(environ, st); err != nil {
11+ apiClose(st)
12+ return nil, err
13+ }
14 return &APIConn{
15 Environ: environ,
16 State: st,
17 }, nil
18 }
19
20+// updateSecrets pushes environment secrets to the API server.
21+// NOTE: this is a temporary hack, and will disappear when we
22+// have synchronous bootstrap.
23+var updateSecrets = func(environ environs.Environ, st *api.State) error {
24+ secrets, err := environ.Provider().SecretAttrs(environ.Config())
25+ if err != nil {
26+ return err
27+ }
28+ client := st.Client()
29+ cfg, err := client.EnvironmentGet()
30+ if err != nil {
31+ return err
32+ }
33+ for k, v := range secrets {
34+ if _, exists := cfg[k]; exists {
35+ // Environment already has secrets. Won't send again.
36+ return nil
37+ } else {
38+ cfg[k] = v
39+ }
40+ }
41+ return client.EnvironmentSet(cfg)
42+}
43+
44 // Close terminates the connection to the environment and releases
45 // any associated resources.
46 func (c *APIConn) Close() error {
47- return c.State.Close()
48+ return apiClose(c.State)
49 }
50
51 // NewAPIClientFromName returns an api.Client connected to the API Server for
52
53=== modified file 'juju/apiconn_test.go'
54--- juju/apiconn_test.go 2013-10-24 19:01:23 +0000
55+++ juju/apiconn_test.go 2013-11-07 07:18:28 +0000
56@@ -52,12 +52,22 @@
57 err = bootstrap.Bootstrap(env, constraints.Value{})
58 c.Assert(err, gc.IsNil)
59
60+ cfg = env.Config()
61+ cfg, err = cfg.Apply(map[string]interface{}{
62+ "secret": "fnord",
63+ })
64+ c.Assert(err, gc.IsNil)
65+ err = env.SetConfig(cfg)
66+ c.Assert(err, gc.IsNil)
67+
68 conn, err := juju.NewAPIConn(env, api.DefaultDialOpts())
69 c.Assert(err, gc.IsNil)
70-
71 c.Assert(conn.Environ, gc.Equals, env)
72 c.Assert(conn.State, gc.NotNil)
73
74+ attrs, err := conn.State.Client().EnvironmentGet()
75+ c.Assert(attrs["secret"], gc.Equals, "fnord")
76+
77 c.Assert(conn.Close(), gc.IsNil)
78 }
79
80@@ -127,6 +137,7 @@
81 return expectState, nil
82 }
83 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore()
84+ defer testbase.PatchValue(juju.UpdateSecrets, updateSecretsNoop).Restore()
85 st, err := juju.NewAPIFromName("noconfig", store)
86 c.Assert(err, gc.IsNil)
87 c.Assert(st, gc.Equals, expectState)
88@@ -175,6 +186,7 @@
89 return nil, expectErr
90 }
91 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore()
92+ defer testbase.PatchValue(juju.UpdateSecrets, updateSecretsNoop).Restore()
93 st, err := juju.NewAPIFromName("noconfig", store)
94 c.Assert(err, gc.Equals, expectErr)
95 c.Assert(st, gc.IsNil)
96@@ -201,6 +213,7 @@
97 return cfgOpenedState, nil
98 }
99 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore()
100+ defer testbase.PatchValue(juju.UpdateSecrets, updateSecretsNoop).Restore()
101
102 stateClosed, restoreAPIClose := setAPIClosed()
103 defer restoreAPIClose.Restore()
104@@ -265,6 +278,7 @@
105 return cfgOpenedState, nil
106 }
107 defer testbase.PatchValue(juju.APIOpen, apiOpen).Restore()
108+ defer testbase.PatchValue(juju.UpdateSecrets, updateSecretsNoop).Restore()
109
110 stateClosed, restoreAPIClose := setAPIClosed()
111 defer restoreAPIClose.Restore()
112@@ -415,6 +429,10 @@
113 return stateClosed, testbase.PatchValue(juju.APIClose, apiClose)
114 }
115
116+func updateSecretsNoop(_ environs.Environ, _ *api.State) error {
117+ return nil
118+}
119+
120 // newConfigStoreWithError that will return the given
121 // error from ReadInfo.
122 func newConfigStoreWithError(err error) configstore.Storage {
123
124=== modified file 'juju/export_test.go'
125--- juju/export_test.go 2013-09-19 16:59:12 +0000
126+++ juju/export_test.go 2013-11-07 07:18:28 +0000
127@@ -5,4 +5,5 @@
128 APIClose = &apiClose
129 ProviderConnectDelay = &providerConnectDelay
130 NewAPIFromName = newAPIFromName
131+ UpdateSecrets = &updateSecrets
132 )
133
134=== modified file 'state/apiserver/client/client.go'
135--- state/apiserver/client/client.go 2013-11-06 14:13:01 +0000
136+++ state/apiserver/client/client.go 2013-11-07 07:18:28 +0000
137@@ -578,8 +578,11 @@
138 return err
139 }
140 // Make sure we don't allow changing agent-version.
141- if _, found := args.Config["agent-version"]; found {
142- return fmt.Errorf("agent-version cannot be changed")
143+ if v, found := args.Config["agent-version"]; found {
144+ oldVersion, _ := oldConfig.AgentVersion()
145+ if v != oldVersion.String() {
146+ return fmt.Errorf("agent-version cannot be changed")
147+ }
148 }
149 // Apply the attributes specified for the command to the state config.
150 newConfig, err := oldConfig.Apply(args.Config)
151
152=== modified file 'state/apiserver/client/client_test.go'
153--- state/apiserver/client/client_test.go 2013-11-06 14:13:01 +0000
154+++ state/apiserver/client/client_test.go 2013-11-07 07:18:28 +0000
155@@ -1261,4 +1261,10 @@
156 args := map[string]interface{}{"agent-version": "9.9.9"}
157 err := s.APIState.Client().EnvironmentSet(args)
158 c.Assert(err, gc.ErrorMatches, "agent-version cannot be changed")
159+ // It's okay to pass env back with the same agent-version.
160+ cfg, err := s.APIState.Client().EnvironmentGet()
161+ c.Assert(err, gc.IsNil)
162+ c.Assert(cfg["agent-version"], gc.NotNil)
163+ err = s.APIState.Client().EnvironmentSet(cfg)
164+ c.Assert(err, gc.IsNil)
165 }

Subscribers

People subscribed via source and target branches

to status/vote changes: