Merge lp:~fwereade/juju-core/config-6-state-service-sane-methods into lp:~juju/juju-core/trunk
- config-6-state-service-sane-methods
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 1276 |
Proposed branch: | lp:~fwereade/juju-core/config-6-state-service-sane-methods |
Merge into: | lp:~juju/juju-core/trunk |
Prerequisite: | lp:~fwereade/juju-core/config-5-state-service-config-yaml |
Diff against target: |
1196 lines (+259/-365) 21 files modified
cmd/juju/cmd_test.go (+2/-2) cmd/juju/config_test.go (+11/-12) cmd/juju/deploy.go (+3/-4) cmd/juju/deploy_test.go (+6/-0) cmd/juju/set.go (+40/-32) juju/conn.go (+15/-13) juju/conn_test.go (+4/-4) state/api/client.go (+0/-1) state/api/params/params_test.go (+1/-1) state/apiserver/client.go (+18/-2) state/apiserver/client_test.go (+4/-4) state/megawatcher_internal_test.go (+13/-20) state/service.go (+12/-39) state/service_test.go (+69/-151) state/statecmd/config_test.go (+3/-1) state/statecmd/deploy_test.go (+4/-4) state/statecmd/get.go (+26/-31) state/unit_test.go (+7/-7) worker/uniter/context_test.go (+3/-4) worker/uniter/filter_test.go (+17/-29) worker/uniter/uniter_test.go (+1/-4) |
To merge this branch: | bzr merge lp:~fwereade/juju-core/config-6-state-service-sane-methods |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+168580@code.launchpad.net |
Commit message
Description of the change
state: Service ConfigSettings methods
Config, SetConfig, and SetConfigYAML methods have been dropped in favour of
ConfigSettings and UpdateConfigSet
are expected to parse their own damn data and supply a sensible format.
William Reade (fwereade) wrote : | # |
Frank Mueller (themue) wrote : | # |
LGTM, cleaner interface now.
Roger Peppe (rogpeppe) wrote : | # |
https:/
File cmd/juju/deploy.go (right):
https:/
cmd/juju/
unit")
personally i don't see why we require >0 units.
Roger Peppe (rogpeppe) wrote : | # |
LGTM
https:/
File juju/conn.go (right):
https:/
juju/conn.go:219: if err := svc.UpdateConfi
nil {
much nicer to only have one operation here, thanks.
https:/
File state/apiserver
https:/
state/apiserver
ch.Config(
we should check with the GUI folks that they haven't put in a workaround
for the current behaviour before this branch lands.
https:/
File state/service.go (left):
https:/
state/service.
error {
it's gone!
https:/
File state/service.go (right):
https:/
state/service.
i'd be tempted to return settings.core to avoid yet another unnecessary
map copy (or implement Settings.sharedMap which just returns
settings.core,
amounting to the same thing).
perhaps the overhead amounts to nothing in the long run though. <hits
self>.
https:/
File state/statecmd/
https:/
state/statecmd/
this should really be a struct, i think.
https:/
File worker/
https:/
worker/
c.Assert(err, IsNil)
William Reade (fwereade) wrote : | # |
*** Submitted:
state: Service ConfigSettings methods
Config, SetConfig, and SetConfigYAML methods have been dropped in favour
of
ConfigSettings and UpdateConfigSet
Clients
are expected to parse their own damn data and supply a sensible format.
R=mue, rog
CC=
https:/
https:/
File cmd/juju/deploy.go (right):
https:/
cmd/juju/
unit")
On 2013/06/11 12:31:23, rog wrote:
> personally i don't see why we require >0 units.
I'm trying not to get sidetracked with such questions here ;).
https:/
File state/apiserver
https:/
state/apiserver
ch.Config(
On 2013/06/11 12:53:12, rog wrote:
> we should check with the GUI folks that they haven't put in a
workaround for the
> current behaviour before this branch lands.
Agreed before embarking on this course of action -- they just pass it
through directly when they actually use it, so they're not affected.
https:/
File state/service.go (right):
https:/
state/service.
On 2013/06/11 12:53:12, rog wrote:
> i'd be tempted to return settings.core to avoid yet another
unnecessary map copy
> (or implement Settings.sharedMap which just returns settings.core,
> amounting to the same thing).
> perhaps the overhead amounts to nothing in the long run though. <hits
self>.
I officially do not care about the overhead of in-memory copies of small
maps :).
https:/
File state/statecmd/
https:/
state/statecmd/
On 2013/06/11 12:53:12, rog wrote:
> this should really be a struct, i think.
I resisted the temptation to pull this whole lot into the charm
package... I think I'll leave it out for now.
https:/
File worker/
https:/
worker/
On 2013/06/11 12:53:12, rog wrote:
> c.Assert(err, IsNil)
Gaaah! Thank you.
Preview Diff
1 | === modified file 'cmd/juju/cmd_test.go' | |||
2 | --- cmd/juju/cmd_test.go 2013-05-02 15:55:42 +0000 | |||
3 | +++ cmd/juju/cmd_test.go 2013-06-12 01:17:26 +0000 | |||
4 | @@ -334,8 +334,8 @@ | |||
5 | 334 | file.Close() | 334 | file.Close() |
6 | 335 | com, err := initSetCommand("--config", "testconfig.yaml", "service") | 335 | com, err := initSetCommand("--config", "testconfig.yaml", "service") |
7 | 336 | c.Assert(err, IsNil) | 336 | c.Assert(err, IsNil) |
10 | 337 | c.Assert(com.Config.Path, Equals, "testconfig.yaml") | 337 | c.Assert(com.SettingsYAML.Path, Equals, "testconfig.yaml") |
11 | 338 | actual, err := com.Config.Read(ctx) | 338 | actual, err := com.SettingsYAML.Read(ctx) |
12 | 339 | c.Assert(err, IsNil) | 339 | c.Assert(err, IsNil) |
13 | 340 | c.Assert(actual, DeepEquals, expected) | 340 | c.Assert(actual, DeepEquals, expected) |
14 | 341 | 341 | ||
15 | 342 | 342 | ||
16 | === modified file 'cmd/juju/config_test.go' | |||
17 | --- cmd/juju/config_test.go 2013-06-12 00:58:52 +0000 | |||
18 | +++ cmd/juju/config_test.go 2013-06-12 01:17:26 +0000 | |||
19 | @@ -9,6 +9,7 @@ | |||
20 | 9 | 9 | ||
21 | 10 | . "launchpad.net/gocheck" | 10 | . "launchpad.net/gocheck" |
22 | 11 | "launchpad.net/goyaml" | 11 | "launchpad.net/goyaml" |
23 | 12 | "launchpad.net/juju-core/charm" | ||
24 | 12 | "launchpad.net/juju-core/cmd" | 13 | "launchpad.net/juju-core/cmd" |
25 | 13 | "launchpad.net/juju-core/juju/testing" | 14 | "launchpad.net/juju-core/juju/testing" |
26 | 14 | coretesting "launchpad.net/juju-core/testing" | 15 | coretesting "launchpad.net/juju-core/testing" |
27 | @@ -67,9 +68,7 @@ | |||
28 | 67 | sch := s.AddTestingCharm(c, "dummy") | 68 | sch := s.AddTestingCharm(c, "dummy") |
29 | 68 | svc, err := s.State.AddService("dummy-service", sch) | 69 | svc, err := s.State.AddService("dummy-service", sch) |
30 | 69 | c.Assert(err, IsNil) | 70 | c.Assert(err, IsNil) |
34 | 70 | err = svc.SetConfig(map[string]string{ | 71 | err = svc.UpdateConfigSettings(charm.Settings{"title": "Nearly There"}) |
32 | 71 | "title": "Nearly There", | ||
33 | 72 | }) | ||
35 | 73 | c.Assert(err, IsNil) | 72 | c.Assert(err, IsNil) |
36 | 74 | for _, t := range getTests { | 73 | for _, t := range getTests { |
37 | 75 | ctx := coretesting.Context(c) | 74 | ctx := coretesting.Context(c) |
38 | @@ -94,9 +93,9 @@ | |||
39 | 94 | 93 | ||
40 | 95 | var setTests = []struct { | 94 | var setTests = []struct { |
41 | 96 | about string | 95 | about string |
45 | 97 | args []string // command to be executed | 96 | args []string // command to be executed |
46 | 98 | expect map[string]interface{} // resulting configuration of the dummy service. | 97 | expect charm.Settings // resulting configuration of the dummy service. |
47 | 99 | err string // error regex | 98 | err string // error regex |
48 | 100 | }{{ | 99 | }{{ |
49 | 101 | about: "invalid option", | 100 | about: "invalid option", |
50 | 102 | args: []string{"foo", "bar"}, | 101 | args: []string{"foo", "bar"}, |
51 | @@ -112,21 +111,21 @@ | |||
52 | 112 | }, { | 111 | }, { |
53 | 113 | about: "set with options", | 112 | about: "set with options", |
54 | 114 | args: []string{"username=hello"}, | 113 | args: []string{"username=hello"}, |
56 | 115 | expect: map[string]interface{}{ | 114 | expect: charm.Settings{ |
57 | 116 | "username": "hello", | 115 | "username": "hello", |
58 | 117 | }, | 116 | }, |
59 | 118 | }, { | 117 | }, { |
60 | 119 | about: "set with option values containing =", | 118 | about: "set with option values containing =", |
61 | 120 | args: []string{"username=hello=foo"}, | 119 | args: []string{"username=hello=foo"}, |
63 | 121 | expect: map[string]interface{}{ | 120 | expect: charm.Settings{ |
64 | 122 | "username": "hello=foo", | 121 | "username": "hello=foo", |
65 | 123 | }, | 122 | }, |
66 | 124 | }, { | 123 | }, { |
67 | 125 | about: "--config $FILE test", | 124 | about: "--config $FILE test", |
68 | 126 | args: []string{"--config", "testconfig.yaml"}, | 125 | args: []string{"--config", "testconfig.yaml"}, |
70 | 127 | expect: map[string]interface{}{ | 126 | expect: charm.Settings{ |
71 | 128 | "username": "admin001", | 127 | "username": "admin001", |
73 | 129 | "skill-level": int64(9000), // yaml int types are int64 | 128 | "skill-level": int64(9000), // charm int types are int64 |
74 | 130 | }, | 129 | }, |
75 | 131 | }, | 130 | }, |
76 | 132 | } | 131 | } |
77 | @@ -147,9 +146,9 @@ | |||
78 | 147 | c.Assert(ctx.Stderr.(*bytes.Buffer).String(), Matches, t.err) | 146 | c.Assert(ctx.Stderr.(*bytes.Buffer).String(), Matches, t.err) |
79 | 148 | } else { | 147 | } else { |
80 | 149 | c.Check(code, Equals, 0) | 148 | c.Check(code, Equals, 0) |
82 | 150 | cfg, err := svc.Config() | 149 | settings, err := svc.ConfigSettings() |
83 | 151 | c.Assert(err, IsNil) | 150 | c.Assert(err, IsNil) |
85 | 152 | c.Assert(cfg.Map(), DeepEquals, t.expect) | 151 | c.Assert(settings, DeepEquals, t.expect) |
86 | 153 | } | 152 | } |
87 | 154 | } | 153 | } |
88 | 155 | } | 154 | } |
89 | 156 | 155 | ||
90 | === modified file 'cmd/juju/deploy.go' | |||
91 | --- cmd/juju/deploy.go 2013-05-22 19:34:42 +0000 | |||
92 | +++ cmd/juju/deploy.go 2013-06-12 01:17:26 +0000 | |||
93 | @@ -92,16 +92,15 @@ | |||
94 | 92 | return cmd.CheckEmpty(args[2:]) | 92 | return cmd.CheckEmpty(args[2:]) |
95 | 93 | } | 93 | } |
96 | 94 | if c.NumUnits < 1 { | 94 | if c.NumUnits < 1 { |
97 | 95 | // TODO improve/remove: this is misleading when deploying subordinates. | ||
98 | 96 | return errors.New("must deploy at least one unit") | 95 | return errors.New("must deploy at least one unit") |
99 | 97 | } | 96 | } |
100 | 98 | if c.ForceMachineId != "" { | 97 | if c.ForceMachineId != "" { |
101 | 98 | if c.NumUnits > 1 { | ||
102 | 99 | return errors.New("cannot use --num-units with --force-machine") | ||
103 | 100 | } | ||
104 | 99 | if !state.IsMachineId(c.ForceMachineId) { | 101 | if !state.IsMachineId(c.ForceMachineId) { |
105 | 100 | return fmt.Errorf("invalid machine id %q", c.ForceMachineId) | 102 | return fmt.Errorf("invalid machine id %q", c.ForceMachineId) |
106 | 101 | } | 103 | } |
107 | 102 | if c.NumUnits > 1 { | ||
108 | 103 | return fmt.Errorf("force-machine cannot be used for multiple units") | ||
109 | 104 | } | ||
110 | 105 | } | 104 | } |
111 | 106 | return nil | 105 | return nil |
112 | 107 | } | 106 | } |
113 | 108 | 107 | ||
114 | === modified file 'cmd/juju/deploy_test.go' | |||
115 | --- cmd/juju/deploy_test.go 2013-05-27 03:00:31 +0000 | |||
116 | +++ cmd/juju/deploy_test.go 2013-06-12 01:17:26 +0000 | |||
117 | @@ -37,6 +37,12 @@ | |||
118 | 37 | args: []string{"craziness", "burble1", "-n", "0"}, | 37 | args: []string{"craziness", "burble1", "-n", "0"}, |
119 | 38 | err: `must deploy at least one unit`, | 38 | err: `must deploy at least one unit`, |
120 | 39 | }, { | 39 | }, { |
121 | 40 | args: []string{"craziness", "burble1", "--force-machine", "bigglesplop"}, | ||
122 | 41 | err: `invalid machine id "bigglesplop"`, | ||
123 | 42 | }, { | ||
124 | 43 | args: []string{"craziness", "burble1", "-n", "2", "--force-machine", "123"}, | ||
125 | 44 | err: `cannot use --num-units with --force-machine`, | ||
126 | 45 | }, { | ||
127 | 40 | args: []string{"craziness", "burble1", "--constraints", "gibber=plop"}, | 46 | args: []string{"craziness", "burble1", "--constraints", "gibber=plop"}, |
128 | 41 | err: `invalid value "gibber=plop" for flag --constraints: unknown constraint "gibber"`, | 47 | err: `invalid value "gibber=plop" for flag --constraints: unknown constraint "gibber"`, |
129 | 42 | }, | 48 | }, |
130 | 43 | 49 | ||
131 | === modified file 'cmd/juju/set.go' | |||
132 | --- cmd/juju/set.go 2013-05-02 15:55:42 +0000 | |||
133 | +++ cmd/juju/set.go 2013-06-12 01:17:26 +0000 | |||
134 | @@ -9,6 +9,7 @@ | |||
135 | 9 | "strings" | 9 | "strings" |
136 | 10 | 10 | ||
137 | 11 | "launchpad.net/gnuflag" | 11 | "launchpad.net/gnuflag" |
138 | 12 | "launchpad.net/juju-core/charm" | ||
139 | 12 | "launchpad.net/juju-core/cmd" | 13 | "launchpad.net/juju-core/cmd" |
140 | 13 | "launchpad.net/juju-core/juju" | 14 | "launchpad.net/juju-core/juju" |
141 | 14 | ) | 15 | ) |
142 | @@ -16,10 +17,9 @@ | |||
143 | 16 | // SetCommand updates the configuration of a service | 17 | // SetCommand updates the configuration of a service |
144 | 17 | type SetCommand struct { | 18 | type SetCommand struct { |
145 | 18 | EnvCommandBase | 19 | EnvCommandBase |
150 | 19 | ServiceName string | 20 | ServiceName string |
151 | 20 | // either Options or Config will contain the configuration data | 21 | SettingsStrings map[string]string |
152 | 21 | Options []string | 22 | SettingsYAML cmd.FileVar |
149 | 22 | Config cmd.FileVar | ||
153 | 23 | } | 23 | } |
154 | 24 | 24 | ||
155 | 25 | func (c *SetCommand) Info() *cmd.Info { | 25 | func (c *SetCommand) Info() *cmd.Info { |
156 | @@ -33,51 +33,59 @@ | |||
157 | 33 | 33 | ||
158 | 34 | func (c *SetCommand) SetFlags(f *gnuflag.FlagSet) { | 34 | func (c *SetCommand) SetFlags(f *gnuflag.FlagSet) { |
159 | 35 | c.EnvCommandBase.SetFlags(f) | 35 | c.EnvCommandBase.SetFlags(f) |
161 | 36 | f.Var(&c.Config, "config", "path to yaml-formatted service config") | 36 | f.Var(&c.SettingsYAML, "config", "path to yaml-formatted service config") |
162 | 37 | } | 37 | } |
163 | 38 | 38 | ||
164 | 39 | func (c *SetCommand) Init(args []string) error { | 39 | func (c *SetCommand) Init(args []string) error { |
165 | 40 | if len(args) == 0 || len(strings.Split(args[0], "=")) > 1 { | 40 | if len(args) == 0 || len(strings.Split(args[0], "=")) > 1 { |
166 | 41 | return errors.New("no service name specified") | 41 | return errors.New("no service name specified") |
167 | 42 | } | 42 | } |
169 | 43 | if len(c.Config.Path) > 0 && len(args) > 1 { | 43 | if c.SettingsYAML.Path != "" && len(args) > 1 { |
170 | 44 | return errors.New("cannot specify --config when using key=value arguments") | 44 | return errors.New("cannot specify --config when using key=value arguments") |
171 | 45 | } | 45 | } |
173 | 46 | c.ServiceName, c.Options = args[0], args[1:] | 46 | c.ServiceName = args[0] |
174 | 47 | settings, err := parse(args[1:]) | ||
175 | 48 | if err != nil { | ||
176 | 49 | return err | ||
177 | 50 | } | ||
178 | 51 | c.SettingsStrings = settings | ||
179 | 47 | return nil | 52 | return nil |
180 | 48 | } | 53 | } |
181 | 49 | 54 | ||
183 | 50 | // Run updates the configuration of a service | 55 | // Run updates the configuration of a service. |
184 | 51 | func (c *SetCommand) Run(ctx *cmd.Context) error { | 56 | func (c *SetCommand) Run(ctx *cmd.Context) error { |
185 | 52 | contents, err := c.Config.Read(ctx) | ||
186 | 53 | if err != nil && err != cmd.ErrNoPath { | ||
187 | 54 | return err | ||
188 | 55 | } | ||
189 | 56 | var options map[string]string | ||
190 | 57 | if len(contents) == 0 { | ||
191 | 58 | if len(c.Options) == 0 { | ||
192 | 59 | // nothing to do. | ||
193 | 60 | return nil | ||
194 | 61 | } | ||
195 | 62 | options, err = parse(c.Options) | ||
196 | 63 | if err != nil { | ||
197 | 64 | return err | ||
198 | 65 | } | ||
199 | 66 | } | ||
200 | 67 | conn, err := juju.NewConnFromName(c.EnvName) | 57 | conn, err := juju.NewConnFromName(c.EnvName) |
201 | 68 | if err != nil { | 58 | if err != nil { |
202 | 69 | return err | 59 | return err |
203 | 70 | } | 60 | } |
204 | 71 | defer conn.Close() | 61 | defer conn.Close() |
214 | 72 | 62 | service, err := conn.State.Service(c.ServiceName) | |
215 | 73 | svc, err := conn.State.Service(c.ServiceName) | 63 | if err != nil { |
216 | 74 | if err != nil { | 64 | return err |
217 | 75 | return err | 65 | } |
218 | 76 | } | 66 | ch, _, err := service.Charm() |
219 | 77 | if len(contents) == 0 { | 67 | if err != nil { |
220 | 78 | return svc.SetConfig(options) | 68 | return err |
221 | 79 | } | 69 | } |
222 | 80 | return svc.SetConfigYAML(contents) | 70 | var settings charm.Settings |
223 | 71 | if c.SettingsYAML.Path != "" { | ||
224 | 72 | settingsYAML, err := c.SettingsYAML.Read(ctx) | ||
225 | 73 | if err != nil { | ||
226 | 74 | return err | ||
227 | 75 | } | ||
228 | 76 | settings, err = ch.Config().ParseSettingsYAML(settingsYAML, c.ServiceName) | ||
229 | 77 | if err != nil { | ||
230 | 78 | return err | ||
231 | 79 | } | ||
232 | 80 | } else if len(c.SettingsStrings) > 0 { | ||
233 | 81 | settings, err = ch.Config().ParseSettingsStrings(c.SettingsStrings) | ||
234 | 82 | if err != nil { | ||
235 | 83 | return err | ||
236 | 84 | } | ||
237 | 85 | } else { | ||
238 | 86 | return nil | ||
239 | 87 | } | ||
240 | 88 | return service.UpdateConfigSettings(settings) | ||
241 | 81 | } | 89 | } |
242 | 82 | 90 | ||
243 | 83 | // parse parses the option k=v strings into a map of options to be | 91 | // parse parses the option k=v strings into a map of options to be |
244 | 84 | 92 | ||
245 | === modified file 'juju/conn.go' | |||
246 | --- juju/conn.go 2013-06-10 10:30:13 +0000 | |||
247 | +++ juju/conn.go 2013-06-12 01:17:26 +0000 | |||
248 | @@ -200,21 +200,23 @@ | |||
249 | 200 | 200 | ||
250 | 201 | // DeployService takes a charm and various parameters and deploys it. | 201 | // DeployService takes a charm and various parameters and deploys it. |
251 | 202 | func (conn *Conn) DeployService(args DeployServiceParams) (*state.Service, error) { | 202 | func (conn *Conn) DeployService(args DeployServiceParams) (*state.Service, error) { |
260 | 203 | // TODO(rog) validate the configuration before adding the service. | 203 | var err error |
261 | 204 | svc, err := conn.State.AddService(args.ServiceName, args.Charm) | 204 | var settings charm.Settings |
262 | 205 | if err != nil { | 205 | config := args.Charm.Config() |
255 | 206 | return nil, err | ||
256 | 207 | } | ||
257 | 208 | // TODO(rog) should we destroy if we return an error in any of the | ||
258 | 209 | // subsequent operations? | ||
259 | 210 | // BUG(lp:1162122): Config/ConfigYAML have no tests. | ||
263 | 211 | if args.ConfigYAML != "" { | 206 | if args.ConfigYAML != "" { |
267 | 212 | if err := svc.SetConfigYAML([]byte(args.ConfigYAML)); err != nil { | 207 | settings, err = config.ParseSettingsYAML([]byte(args.ConfigYAML), args.ServiceName) |
265 | 213 | return nil, err | ||
266 | 214 | } | ||
268 | 215 | } else if args.Config != nil { | 208 | } else if args.Config != nil { |
271 | 216 | if err := svc.SetConfig(args.Config); err != nil { | 209 | settings, err = config.ParseSettingsStrings(args.Config) |
272 | 217 | // TODO(rog) should we destroy the service here? | 210 | } |
273 | 211 | if err != nil { | ||
274 | 212 | return nil, err | ||
275 | 213 | } | ||
276 | 214 | svc, err := conn.State.AddService(args.ServiceName, args.Charm) | ||
277 | 215 | if err != nil { | ||
278 | 216 | return nil, err | ||
279 | 217 | } | ||
280 | 218 | if len(settings) > 0 { | ||
281 | 219 | if err := svc.UpdateConfigSettings(settings); err != nil { | ||
282 | 218 | return nil, err | 220 | return nil, err |
283 | 219 | } | 221 | } |
284 | 220 | } | 222 | } |
285 | 221 | 223 | ||
286 | === modified file 'juju/conn_test.go' | |||
287 | --- juju/conn_test.go 2013-06-10 22:46:06 +0000 | |||
288 | +++ juju/conn_test.go 2013-06-12 01:17:26 +0000 | |||
289 | @@ -426,12 +426,12 @@ | |||
290 | 426 | } | 426 | } |
291 | 427 | 427 | ||
292 | 428 | func (s *DeployLocalSuite) TestDeploy(c *C) { | 428 | func (s *DeployLocalSuite) TestDeploy(c *C) { |
294 | 429 | charm, err := s.Conn.PutCharm(s.charmUrl, s.repo, false) | 429 | ch, err := s.Conn.PutCharm(s.charmUrl, s.repo, false) |
295 | 430 | c.Assert(err, IsNil) | 430 | c.Assert(err, IsNil) |
296 | 431 | cons := constraints.MustParse("mem=4G") | 431 | cons := constraints.MustParse("mem=4G") |
297 | 432 | args := juju.DeployServiceParams{ | 432 | args := juju.DeployServiceParams{ |
298 | 433 | ServiceName: "bob", | 433 | ServiceName: "bob", |
300 | 434 | Charm: charm, | 434 | Charm: ch, |
301 | 435 | NumUnits: 3, | 435 | NumUnits: 3, |
302 | 436 | Constraints: cons, | 436 | Constraints: cons, |
303 | 437 | ConfigYAML: "bob: {blog-title: aspidistra flagpole}", | 437 | ConfigYAML: "bob: {blog-title: aspidistra flagpole}", |
304 | @@ -441,9 +441,9 @@ | |||
305 | 441 | scons, err := svc.Constraints() | 441 | scons, err := svc.Constraints() |
306 | 442 | c.Assert(err, IsNil) | 442 | c.Assert(err, IsNil) |
307 | 443 | c.Assert(scons, DeepEquals, cons) | 443 | c.Assert(scons, DeepEquals, cons) |
309 | 444 | config, err := svc.Config() | 444 | settings, err := svc.ConfigSettings() |
310 | 445 | c.Assert(err, IsNil) | 445 | c.Assert(err, IsNil) |
312 | 446 | c.Assert(config.Map(), DeepEquals, map[string]interface{}{ | 446 | c.Assert(settings, DeepEquals, charm.Settings{ |
313 | 447 | "blog-title": "aspidistra flagpole", | 447 | "blog-title": "aspidistra flagpole", |
314 | 448 | }) | 448 | }) |
315 | 449 | 449 | ||
316 | 450 | 450 | ||
317 | === modified file 'state/api/client.go' | |||
318 | --- state/api/client.go 2013-06-05 09:36:10 +0000 | |||
319 | +++ state/api/client.go 2013-06-12 01:17:26 +0000 | |||
320 | @@ -105,7 +105,6 @@ | |||
321 | 105 | ServiceName: serviceName, | 105 | ServiceName: serviceName, |
322 | 106 | CharmUrl: charmUrl, | 106 | CharmUrl: charmUrl, |
323 | 107 | NumUnits: numUnits, | 107 | NumUnits: numUnits, |
324 | 108 | // BUG(lp:1162122): ConfigYAML has no tests. | ||
325 | 109 | ConfigYAML: configYAML, | 108 | ConfigYAML: configYAML, |
326 | 110 | Constraints: cons, | 109 | Constraints: cons, |
327 | 111 | } | 110 | } |
328 | 112 | 111 | ||
329 | === modified file 'state/api/params/params_test.go' | |||
330 | --- state/api/params/params_test.go 2013-05-21 16:40:29 +0000 | |||
331 | +++ state/api/params/params_test.go 2013-06-12 01:17:26 +0000 | |||
332 | @@ -48,7 +48,7 @@ | |||
333 | 48 | CharmURL: "cs:series/name", | 48 | CharmURL: "cs:series/name", |
334 | 49 | Life: params.Life(state.Dying.String()), | 49 | Life: params.Life(state.Dying.String()), |
335 | 50 | Constraints: constraints.MustParse("arch=arm mem=1024M"), | 50 | Constraints: constraints.MustParse("arch=arm mem=1024M"), |
337 | 51 | Config: map[string]interface{}{ | 51 | Config: charm.Settings{ |
338 | 52 | "hello": "goodbye", | 52 | "hello": "goodbye", |
339 | 53 | "foo": false, | 53 | "foo": false, |
340 | 54 | }, | 54 | }, |
341 | 55 | 55 | ||
342 | === modified file 'state/apiserver/client.go' | |||
343 | --- state/apiserver/client.go 2013-05-24 19:04:47 +0000 | |||
344 | +++ state/apiserver/client.go 2013-06-12 01:17:26 +0000 | |||
345 | @@ -46,7 +46,15 @@ | |||
346 | 46 | if err != nil { | 46 | if err != nil { |
347 | 47 | return err | 47 | return err |
348 | 48 | } | 48 | } |
350 | 49 | return svc.SetConfig(p.Options) | 49 | ch, _, err := svc.Charm() |
351 | 50 | if err != nil { | ||
352 | 51 | return err | ||
353 | 52 | } | ||
354 | 53 | changes, err := ch.Config().ParseSettingsStrings(p.Options) | ||
355 | 54 | if err != nil { | ||
356 | 55 | return err | ||
357 | 56 | } | ||
358 | 57 | return svc.UpdateConfigSettings(changes) | ||
359 | 50 | } | 58 | } |
360 | 51 | 59 | ||
361 | 52 | // ServiceSetYAML implements the server side of Client.ServerSetYAML. | 60 | // ServiceSetYAML implements the server side of Client.ServerSetYAML. |
362 | @@ -55,7 +63,15 @@ | |||
363 | 55 | if err != nil { | 63 | if err != nil { |
364 | 56 | return err | 64 | return err |
365 | 57 | } | 65 | } |
367 | 58 | return svc.SetConfigYAML([]byte(p.Config)) | 66 | ch, _, err := svc.Charm() |
368 | 67 | if err != nil { | ||
369 | 68 | return err | ||
370 | 69 | } | ||
371 | 70 | changes, err := ch.Config().ParseSettingsYAML([]byte(p.Config), p.ServiceName) | ||
372 | 71 | if err != nil { | ||
373 | 72 | return err | ||
374 | 73 | } | ||
375 | 74 | return svc.UpdateConfigSettings(changes) | ||
376 | 59 | } | 75 | } |
377 | 60 | 76 | ||
378 | 61 | // ServiceGet returns the configuration for a service. | 77 | // ServiceGet returns the configuration for a service. |
379 | 62 | 78 | ||
380 | === modified file 'state/apiserver/client_test.go' | |||
381 | --- state/apiserver/client_test.go 2013-06-10 22:46:06 +0000 | |||
382 | +++ state/apiserver/client_test.go 2013-06-12 01:17:26 +0000 | |||
383 | @@ -36,9 +36,9 @@ | |||
384 | 36 | "username": "yyy", | 36 | "username": "yyy", |
385 | 37 | }) | 37 | }) |
386 | 38 | c.Assert(err, IsNil) | 38 | c.Assert(err, IsNil) |
388 | 39 | conf, err := dummy.Config() | 39 | settings, err := dummy.ConfigSettings() |
389 | 40 | c.Assert(err, IsNil) | 40 | c.Assert(err, IsNil) |
391 | 41 | c.Assert(conf.Map(), DeepEquals, map[string]interface{}{ | 41 | c.Assert(settings, DeepEquals, charm.Settings{ |
392 | 42 | "title": "xxx", | 42 | "title": "xxx", |
393 | 43 | "username": "yyy", | 43 | "username": "yyy", |
394 | 44 | }) | 44 | }) |
395 | @@ -49,9 +49,9 @@ | |||
396 | 49 | c.Assert(err, IsNil) | 49 | c.Assert(err, IsNil) |
397 | 50 | err = s.APIState.Client().ServiceSetYAML("dummy", "dummy:\n title: aaa\n username: bbb") | 50 | err = s.APIState.Client().ServiceSetYAML("dummy", "dummy:\n title: aaa\n username: bbb") |
398 | 51 | c.Assert(err, IsNil) | 51 | c.Assert(err, IsNil) |
400 | 52 | conf, err := dummy.Config() | 52 | settings, err := dummy.ConfigSettings() |
401 | 53 | c.Assert(err, IsNil) | 53 | c.Assert(err, IsNil) |
403 | 54 | c.Assert(conf.Map(), DeepEquals, map[string]interface{}{ | 54 | c.Assert(settings, DeepEquals, charm.Settings{ |
404 | 55 | "title": "aaa", | 55 | "title": "aaa", |
405 | 56 | "username": "bbb", | 56 | "username": "bbb", |
406 | 57 | }) | 57 | }) |
407 | 58 | 58 | ||
408 | === modified file 'state/megawatcher_internal_test.go' | |||
409 | --- state/megawatcher_internal_test.go 2013-05-27 03:00:31 +0000 | |||
410 | +++ state/megawatcher_internal_test.go 2013-06-12 01:17:26 +0000 | |||
411 | @@ -85,7 +85,7 @@ | |||
412 | 85 | CharmURL: serviceCharmURL(wordpress).String(), | 85 | CharmURL: serviceCharmURL(wordpress).String(), |
413 | 86 | Life: params.Life(Alive.String()), | 86 | Life: params.Life(Alive.String()), |
414 | 87 | Constraints: constraints.MustParse("mem=100M"), | 87 | Constraints: constraints.MustParse("mem=100M"), |
416 | 88 | Config: map[string]interface{}{"blog-title": "boring"}, | 88 | Config: charm.Settings{"blog-title": "boring"}, |
417 | 89 | }) | 89 | }) |
418 | 90 | pairs := map[string]string{"x": "12", "y": "99"} | 90 | pairs := map[string]string{"x": "12", "y": "99"} |
419 | 91 | err = wordpress.SetAnnotations(pairs) | 91 | err = wordpress.SetAnnotations(pairs) |
420 | @@ -101,7 +101,7 @@ | |||
421 | 101 | Name: "logging", | 101 | Name: "logging", |
422 | 102 | CharmURL: serviceCharmURL(logging).String(), | 102 | CharmURL: serviceCharmURL(logging).String(), |
423 | 103 | Life: params.Life(Alive.String()), | 103 | Life: params.Life(Alive.String()), |
425 | 104 | Config: map[string]interface{}{}, | 104 | Config: charm.Settings{}, |
426 | 105 | }) | 105 | }) |
427 | 106 | 106 | ||
428 | 107 | eps, err := s.State.InferEndpoints([]string{"logging", "wordpress"}) | 107 | eps, err := s.State.InferEndpoints([]string{"logging", "wordpress"}) |
429 | @@ -411,7 +411,7 @@ | |||
430 | 411 | Exposed: true, | 411 | Exposed: true, |
431 | 412 | CharmURL: "local:series/series-wordpress-3", | 412 | CharmURL: "local:series/series-wordpress-3", |
432 | 413 | Life: params.Life(Alive.String()), | 413 | Life: params.Life(Alive.String()), |
434 | 414 | Config: map[string]interface{}{}, | 414 | Config: charm.Settings{}, |
435 | 415 | }, | 415 | }, |
436 | 416 | }, | 416 | }, |
437 | 417 | }, { | 417 | }, { |
438 | @@ -421,7 +421,7 @@ | |||
439 | 421 | Exposed: true, | 421 | Exposed: true, |
440 | 422 | CharmURL: "local:series/series-wordpress-3", | 422 | CharmURL: "local:series/series-wordpress-3", |
441 | 423 | Constraints: constraints.MustParse("mem=99M"), | 423 | Constraints: constraints.MustParse("mem=99M"), |
443 | 424 | Config: map[string]interface{}{"blog-title": "boring"}, | 424 | Config: charm.Settings{"blog-title": "boring"}, |
444 | 425 | }}, | 425 | }}, |
445 | 426 | setUp: func(c *C, st *State) { | 426 | setUp: func(c *C, st *State) { |
446 | 427 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) | 427 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) |
447 | @@ -438,7 +438,7 @@ | |||
448 | 438 | CharmURL: "local:series/series-wordpress-3", | 438 | CharmURL: "local:series/series-wordpress-3", |
449 | 439 | Life: params.Life(Alive.String()), | 439 | Life: params.Life(Alive.String()), |
450 | 440 | Constraints: constraints.MustParse("mem=99M"), | 440 | Constraints: constraints.MustParse("mem=99M"), |
452 | 441 | Config: map[string]interface{}{"blog-title": "boring"}, | 441 | Config: charm.Settings{"blog-title": "boring"}, |
453 | 442 | }, | 442 | }, |
454 | 443 | }, | 443 | }, |
455 | 444 | }, { | 444 | }, { |
456 | @@ -448,16 +448,12 @@ | |||
457 | 448 | // Note: CharmURL has a different revision number from | 448 | // Note: CharmURL has a different revision number from |
458 | 449 | // the wordpress revision in the testing repo. | 449 | // the wordpress revision in the testing repo. |
459 | 450 | CharmURL: "local:series/series-wordpress-2", | 450 | CharmURL: "local:series/series-wordpress-2", |
461 | 451 | Config: map[string]interface{}{"foo": "bar"}, | 451 | Config: charm.Settings{"foo": "bar"}, |
462 | 452 | }}, | 452 | }}, |
463 | 453 | setUp: func(c *C, st *State) { | 453 | setUp: func(c *C, st *State) { |
464 | 454 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) | 454 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) |
465 | 455 | c.Assert(err, IsNil) | 455 | c.Assert(err, IsNil) |
471 | 456 | cfg, err := svc.Config() | 456 | setServiceConfigAttr(c, svc, "blog-title", "boring") |
467 | 457 | c.Assert(err, IsNil) | ||
468 | 458 | cfg.Set("blog-title", "boring") | ||
469 | 459 | _, err = cfg.Write() | ||
470 | 460 | c.Assert(err, IsNil) | ||
472 | 461 | }, | 457 | }, |
473 | 462 | change: watcher.Change{ | 458 | change: watcher.Change{ |
474 | 463 | C: "services", | 459 | C: "services", |
475 | @@ -468,7 +464,7 @@ | |||
476 | 468 | Name: "wordpress", | 464 | Name: "wordpress", |
477 | 469 | CharmURL: "local:series/series-wordpress-3", | 465 | CharmURL: "local:series/series-wordpress-3", |
478 | 470 | Life: params.Life(Alive.String()), | 466 | Life: params.Life(Alive.String()), |
480 | 471 | Config: map[string]interface{}{"blog-title": "boring"}, | 467 | Config: charm.Settings{"blog-title": "boring"}, |
481 | 472 | }, | 468 | }, |
482 | 473 | }, | 469 | }, |
483 | 474 | }, | 470 | }, |
484 | @@ -758,7 +754,7 @@ | |||
485 | 758 | add: []params.EntityInfo{¶ms.ServiceInfo{ | 754 | add: []params.EntityInfo{¶ms.ServiceInfo{ |
486 | 759 | Name: "wordpress", | 755 | Name: "wordpress", |
487 | 760 | CharmURL: "local:series/series-wordpress-3", | 756 | CharmURL: "local:series/series-wordpress-3", |
489 | 761 | Config: map[string]interface{}{"foo": "bar"}, | 757 | Config: charm.Settings{"foo": "bar"}, |
490 | 762 | }}, | 758 | }}, |
491 | 763 | setUp: func(c *C, st *State) { | 759 | setUp: func(c *C, st *State) { |
492 | 764 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) | 760 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) |
493 | @@ -773,7 +769,7 @@ | |||
494 | 773 | ¶ms.ServiceInfo{ | 769 | ¶ms.ServiceInfo{ |
495 | 774 | Name: "wordpress", | 770 | Name: "wordpress", |
496 | 775 | CharmURL: "local:series/series-wordpress-3", | 771 | CharmURL: "local:series/series-wordpress-3", |
498 | 776 | Config: map[string]interface{}{"blog-title": "foo"}, | 772 | Config: charm.Settings{"blog-title": "foo"}, |
499 | 777 | }, | 773 | }, |
500 | 778 | }, | 774 | }, |
501 | 779 | }, { | 775 | }, { |
502 | @@ -781,7 +777,7 @@ | |||
503 | 781 | add: []params.EntityInfo{¶ms.ServiceInfo{ | 777 | add: []params.EntityInfo{¶ms.ServiceInfo{ |
504 | 782 | Name: "wordpress", | 778 | Name: "wordpress", |
505 | 783 | CharmURL: "local:series/series-wordpress-2", // Note different revno. | 779 | CharmURL: "local:series/series-wordpress-2", // Note different revno. |
507 | 784 | Config: map[string]interface{}{"foo": "bar"}, | 780 | Config: charm.Settings{"foo": "bar"}, |
508 | 785 | }}, | 781 | }}, |
509 | 786 | setUp: func(c *C, st *State) { | 782 | setUp: func(c *C, st *State) { |
510 | 787 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) | 783 | svc, err := st.AddService("wordpress", AddTestingCharm(c, st, "wordpress")) |
511 | @@ -796,7 +792,7 @@ | |||
512 | 796 | ¶ms.ServiceInfo{ | 792 | ¶ms.ServiceInfo{ |
513 | 797 | Name: "wordpress", | 793 | Name: "wordpress", |
514 | 798 | CharmURL: "local:series/series-wordpress-2", | 794 | CharmURL: "local:series/series-wordpress-2", |
516 | 799 | Config: map[string]interface{}{"foo": "bar"}, | 795 | Config: charm.Settings{"foo": "bar"}, |
517 | 800 | }, | 796 | }, |
518 | 801 | }, | 797 | }, |
519 | 802 | }, { | 798 | }, { |
520 | @@ -817,10 +813,7 @@ | |||
521 | 817 | } | 813 | } |
522 | 818 | 814 | ||
523 | 819 | func setServiceConfigAttr(c *C, svc *Service, attr string, val interface{}) { | 815 | func setServiceConfigAttr(c *C, svc *Service, attr string, val interface{}) { |
528 | 820 | cfg, err := svc.Config() | 816 | err := svc.UpdateConfigSettings(charm.Settings{attr: val}) |
525 | 821 | c.Assert(err, IsNil) | ||
526 | 822 | cfg.Set("blog-title", val) | ||
527 | 823 | _, err = cfg.Write() | ||
529 | 824 | c.Assert(err, IsNil) | 817 | c.Assert(err, IsNil) |
530 | 825 | } | 818 | } |
531 | 826 | 819 | ||
532 | 827 | 820 | ||
533 | === modified file 'state/service.go' | |||
534 | --- state/service.go 2013-06-10 22:46:06 +0000 | |||
535 | +++ state/service.go 2013-06-12 01:17:26 +0000 | |||
536 | @@ -719,9 +719,19 @@ | |||
537 | 719 | return relations, nil | 719 | return relations, nil |
538 | 720 | } | 720 | } |
539 | 721 | 721 | ||
541 | 722 | // updateConfigSettings changes a service's charm config settings. Values set | 722 | // ConfigSettings returns the raw user configuration for the service's charm. |
542 | 723 | // Unset values are omitted. | ||
543 | 724 | func (s *Service) ConfigSettings() (charm.Settings, error) { | ||
544 | 725 | settings, err := readSettings(s.st, s.settingsKey()) | ||
545 | 726 | if err != nil { | ||
546 | 727 | return nil, err | ||
547 | 728 | } | ||
548 | 729 | return settings.Map(), nil | ||
549 | 730 | } | ||
550 | 731 | |||
551 | 732 | // UpdateConfigSettings changes a service's charm config settings. Values set | ||
552 | 723 | // to nil will be deleted; unknown and invalid values will return an error. | 733 | // to nil will be deleted; unknown and invalid values will return an error. |
554 | 724 | func (s *Service) updateConfigSettings(changes charm.Settings) error { | 734 | func (s *Service) UpdateConfigSettings(changes charm.Settings) error { |
555 | 725 | charm, _, err := s.Charm() | 735 | charm, _, err := s.Charm() |
556 | 726 | if err != nil { | 736 | if err != nil { |
557 | 727 | return err | 737 | return err |
558 | @@ -749,43 +759,6 @@ | |||
559 | 749 | return err | 759 | return err |
560 | 750 | } | 760 | } |
561 | 751 | 761 | ||
562 | 752 | // Config returns the configuration node for the service. | ||
563 | 753 | func (s *Service) Config() (config *Settings, err error) { | ||
564 | 754 | config, err = readSettings(s.st, s.settingsKey()) | ||
565 | 755 | if err != nil { | ||
566 | 756 | return nil, fmt.Errorf("cannot get configuration of service %q: %v", s, err) | ||
567 | 757 | } | ||
568 | 758 | return config, nil | ||
569 | 759 | } | ||
570 | 760 | |||
571 | 761 | // SetConfig changes a service's configuration values. | ||
572 | 762 | // Values set to the empty string will be deleted. | ||
573 | 763 | func (s *Service) SetConfig(options map[string]string) error { | ||
574 | 764 | charm, _, err := s.Charm() | ||
575 | 765 | if err != nil { | ||
576 | 766 | return err | ||
577 | 767 | } | ||
578 | 768 | changes, err := charm.Config().ParseSettingsStrings(options) | ||
579 | 769 | if err != nil { | ||
580 | 770 | return err | ||
581 | 771 | } | ||
582 | 772 | return s.updateConfigSettings(changes) | ||
583 | 773 | } | ||
584 | 774 | |||
585 | 775 | // SetConfigYAML is like Set except that the | ||
586 | 776 | // configuration data is specified in YAML format. | ||
587 | 777 | func (s *Service) SetConfigYAML(yamlData []byte) error { | ||
588 | 778 | charm, _, err := s.Charm() | ||
589 | 779 | if err != nil { | ||
590 | 780 | return err | ||
591 | 781 | } | ||
592 | 782 | changes, err := charm.Config().ParseSettingsYAML(yamlData, s.doc.Name) | ||
593 | 783 | if err != nil { | ||
594 | 784 | return err | ||
595 | 785 | } | ||
596 | 786 | return s.updateConfigSettings(changes) | ||
597 | 787 | } | ||
598 | 788 | |||
599 | 789 | var ErrSubordinateConstraints = stderrors.New("constraints do not apply to subordinate services") | 762 | var ErrSubordinateConstraints = stderrors.New("constraints do not apply to subordinate services") |
600 | 790 | 763 | ||
601 | 791 | // Constraints returns the current service constraints. | 764 | // Constraints returns the current service constraints. |
602 | 792 | 765 | ||
603 | === modified file 'state/service_test.go' | |||
604 | --- state/service_test.go 2013-06-10 22:46:06 +0000 | |||
605 | +++ state/service_test.go 2013-06-12 01:17:26 +0000 | |||
606 | @@ -226,9 +226,9 @@ | |||
607 | 226 | var setCharmConfigTests = []struct { | 226 | var setCharmConfigTests = []struct { |
608 | 227 | summary string | 227 | summary string |
609 | 228 | startconfig string | 228 | startconfig string |
611 | 229 | startvalues map[string]interface{} | 229 | startvalues charm.Settings |
612 | 230 | endconfig string | 230 | endconfig string |
614 | 231 | endvalues map[string]interface{} | 231 | endvalues charm.Settings |
615 | 232 | err string | 232 | err string |
616 | 233 | }{ | 233 | }{ |
617 | 234 | { | 234 | { |
618 | @@ -242,18 +242,18 @@ | |||
619 | 242 | }, { | 242 | }, { |
620 | 243 | summary: "add string key and preserve existing values", | 243 | summary: "add string key and preserve existing values", |
621 | 244 | startconfig: stringConfig, | 244 | startconfig: stringConfig, |
623 | 245 | startvalues: map[string]interface{}{"key": "foo", "other": "bar"}, | 245 | startvalues: charm.Settings{"key": "foo"}, |
624 | 246 | endconfig: newStringConfig, | 246 | endconfig: newStringConfig, |
626 | 247 | endvalues: map[string]interface{}{"key": "foo", "other": "bar"}, | 247 | endvalues: charm.Settings{"key": "foo"}, |
627 | 248 | }, { | 248 | }, { |
628 | 249 | summary: "remove string key", | 249 | summary: "remove string key", |
629 | 250 | startconfig: stringConfig, | 250 | startconfig: stringConfig, |
631 | 251 | startvalues: map[string]interface{}{"key": "value"}, | 251 | startvalues: charm.Settings{"key": "value"}, |
632 | 252 | endconfig: emptyConfig, | 252 | endconfig: emptyConfig, |
633 | 253 | }, { | 253 | }, { |
634 | 254 | summary: "remove float key", | 254 | summary: "remove float key", |
635 | 255 | startconfig: floatConfig, | 255 | startconfig: floatConfig, |
637 | 256 | startvalues: map[string]interface{}{"key": 123.45}, | 256 | startvalues: charm.Settings{"key": 123.45}, |
638 | 257 | endconfig: emptyConfig, | 257 | endconfig: emptyConfig, |
639 | 258 | }, { | 258 | }, { |
640 | 259 | summary: "change key type without values", | 259 | summary: "change key type without values", |
641 | @@ -262,7 +262,7 @@ | |||
642 | 262 | }, { | 262 | }, { |
643 | 263 | summary: "change key type with values", | 263 | summary: "change key type with values", |
644 | 264 | startconfig: stringConfig, | 264 | startconfig: stringConfig, |
646 | 265 | startvalues: map[string]interface{}{"key": "value"}, | 265 | startvalues: charm.Settings{"key": "value"}, |
647 | 266 | endconfig: floatConfig, | 266 | endconfig: floatConfig, |
648 | 267 | }, | 267 | }, |
649 | 268 | } | 268 | } |
650 | @@ -281,15 +281,12 @@ | |||
651 | 281 | origCh := charms[t.startconfig] | 281 | origCh := charms[t.startconfig] |
652 | 282 | svc, err := s.State.AddService("wordpress", origCh) | 282 | svc, err := s.State.AddService("wordpress", origCh) |
653 | 283 | c.Assert(err, IsNil) | 283 | c.Assert(err, IsNil) |
658 | 284 | cfg, err := svc.Config() | 284 | err = svc.UpdateConfigSettings(t.startvalues) |
655 | 285 | c.Assert(err, IsNil) | ||
656 | 286 | cfg.Update(t.startvalues) | ||
657 | 287 | _, err = cfg.Write() | ||
659 | 288 | c.Assert(err, IsNil) | 285 | c.Assert(err, IsNil) |
660 | 289 | 286 | ||
661 | 290 | newCh := charms[t.endconfig] | 287 | newCh := charms[t.endconfig] |
662 | 291 | err = svc.SetCharm(newCh, false) | 288 | err = svc.SetCharm(newCh, false) |
664 | 292 | var expectVals map[string]interface{} | 289 | var expectVals charm.Settings |
665 | 293 | var expectCh *state.Charm | 290 | var expectCh *state.Charm |
666 | 294 | if t.err != "" { | 291 | if t.err != "" { |
667 | 295 | c.Assert(err, ErrorMatches, t.err) | 292 | c.Assert(err, ErrorMatches, t.err) |
668 | @@ -304,12 +301,12 @@ | |||
669 | 304 | sch, _, err := svc.Charm() | 301 | sch, _, err := svc.Charm() |
670 | 305 | c.Assert(err, IsNil) | 302 | c.Assert(err, IsNil) |
671 | 306 | c.Assert(sch.URL(), DeepEquals, expectCh.URL()) | 303 | c.Assert(sch.URL(), DeepEquals, expectCh.URL()) |
673 | 307 | cfg, err = svc.Config() | 304 | settings, err := svc.ConfigSettings() |
674 | 308 | c.Assert(err, IsNil) | 305 | c.Assert(err, IsNil) |
675 | 309 | if len(expectVals) == 0 { | 306 | if len(expectVals) == 0 { |
677 | 310 | c.Assert(cfg.Map(), HasLen, 0) | 307 | c.Assert(settings, HasLen, 0) |
678 | 311 | } else { | 308 | } else { |
680 | 312 | c.Assert(cfg.Map(), DeepEquals, expectVals) | 309 | c.Assert(settings, DeepEquals, expectVals) |
681 | 313 | } | 310 | } |
682 | 314 | 311 | ||
683 | 315 | err = svc.Destroy() | 312 | err = svc.Destroy() |
684 | @@ -317,138 +314,78 @@ | |||
685 | 317 | } | 314 | } |
686 | 318 | } | 315 | } |
687 | 319 | 316 | ||
701 | 320 | func serviceSet(options map[string]string) func(svc *state.Service) error { | 317 | var serviceUpdateConfigSettingsTests = []struct { |
689 | 321 | return func(svc *state.Service) error { | ||
690 | 322 | return svc.SetConfig(options) | ||
691 | 323 | } | ||
692 | 324 | } | ||
693 | 325 | |||
694 | 326 | func serviceSetYAML(yaml string) func(svc *state.Service) error { | ||
695 | 327 | return func(svc *state.Service) error { | ||
696 | 328 | return svc.SetConfigYAML([]byte(yaml)) | ||
697 | 329 | } | ||
698 | 330 | } | ||
699 | 331 | |||
700 | 332 | var serviceSetTests = []struct { | ||
702 | 333 | about string | 318 | about string |
707 | 334 | initial map[string]interface{} | 319 | initial charm.Settings |
708 | 335 | set func(st *state.Service) error | 320 | update charm.Settings |
709 | 336 | expect map[string]interface{} // resulting configuration of the dummy service. | 321 | expect charm.Settings |
710 | 337 | err string // error regex | 322 | err string |
711 | 338 | }{{ | 323 | }{{ |
803 | 339 | about: "unknown option", | 324 | about: "unknown option", |
804 | 340 | set: serviceSet(map[string]string{"foo": "bar"}), | 325 | update: charm.Settings{"foo": "bar"}, |
805 | 341 | err: `unknown option "foo"`, | 326 | err: `unknown option "foo"`, |
806 | 342 | }, { | 327 | }, { |
807 | 343 | about: "set outlook", | 328 | about: "bad type", |
808 | 344 | set: serviceSet(map[string]string{"outlook": "positive"}), | 329 | update: charm.Settings{"skill-level": "profound"}, |
809 | 345 | expect: map[string]interface{}{ | 330 | err: `option "skill-level" expected int, got "profound"`, |
810 | 346 | "outlook": "positive", | 331 | }, { |
811 | 347 | }, | 332 | about: "set string", |
812 | 348 | }, { | 333 | update: charm.Settings{"outlook": "positive"}, |
813 | 349 | about: "unset outlook and set title", | 334 | expect: charm.Settings{"outlook": "positive"}, |
814 | 350 | initial: map[string]interface{}{ | 335 | }, { |
815 | 351 | "outlook": "positive", | 336 | about: "unset string and set another", |
816 | 352 | }, | 337 | initial: charm.Settings{"outlook": "positive"}, |
817 | 353 | set: serviceSet(map[string]string{ | 338 | update: charm.Settings{"outlook": nil, "title": "sir"}, |
818 | 354 | "outlook": "", | 339 | expect: charm.Settings{"title": "sir"}, |
819 | 355 | "title": "sir", | 340 | }, { |
820 | 356 | }, | 341 | about: "unset missing string", |
821 | 357 | ), | 342 | update: charm.Settings{"outlook": nil}, |
822 | 358 | expect: map[string]interface{}{ | 343 | }, { |
823 | 359 | "title": "sir", | 344 | about: `empty strings unset string values`, |
824 | 360 | }, | 345 | initial: charm.Settings{"outlook": "positive"}, |
825 | 361 | }, { | 346 | update: charm.Settings{"outlook": "", "title": ""}, |
826 | 362 | about: "set a default value", | 347 | }, { |
827 | 363 | initial: map[string]interface{}{ | 348 | about: "preserve existing value", |
828 | 364 | "title": "sir", | 349 | initial: charm.Settings{"title": "sir"}, |
829 | 365 | }, | 350 | update: charm.Settings{"username": "admin001"}, |
830 | 366 | set: serviceSet(map[string]string{"username": "admin001"}), | 351 | expect: charm.Settings{"username": "admin001", "title": "sir"}, |
831 | 367 | expect: map[string]interface{}{ | 352 | }, { |
832 | 368 | "username": "admin001", | 353 | about: "unset a default value, set a different default", |
833 | 369 | "title": "sir", | 354 | initial: charm.Settings{"username": "admin001", "title": "sir"}, |
834 | 370 | }, | 355 | update: charm.Settings{"username": nil, "title": "My Title"}, |
835 | 371 | }, { | 356 | expect: charm.Settings{"title": "My Title"}, |
836 | 372 | about: "unset a default value, set a different default", | 357 | }, { |
837 | 373 | initial: map[string]interface{}{ | 358 | about: "non-string type", |
838 | 374 | "username": "admin001", | 359 | update: charm.Settings{"skill-level": 303}, |
839 | 375 | "title": "sir", | 360 | expect: charm.Settings{"skill-level": int64(303)}, |
840 | 376 | }, | 361 | }, { |
841 | 377 | set: serviceSet(map[string]string{ | 362 | about: "unset non-string type", |
842 | 378 | "username": "", | 363 | initial: charm.Settings{"skill-level": 303}, |
843 | 379 | "title": "My Title", | 364 | update: charm.Settings{"skill-level": nil}, |
844 | 380 | }, | 365 | }} |
754 | 381 | ), | ||
755 | 382 | expect: map[string]interface{}{ | ||
756 | 383 | "title": "My Title", | ||
757 | 384 | }, | ||
758 | 385 | }, { | ||
759 | 386 | about: "gibberish", | ||
760 | 387 | set: serviceSetYAML("`"), | ||
761 | 388 | err: `cannot parse settings data: .*`, | ||
762 | 389 | }, { | ||
763 | 390 | about: "bad configuration", | ||
764 | 391 | set: serviceSetYAML("{}"), | ||
765 | 392 | err: `no settings found for "dummy-service"`, | ||
766 | 393 | }, { | ||
767 | 394 | about: "config with no options", | ||
768 | 395 | set: serviceSetYAML("dummy-service: {}"), | ||
769 | 396 | expect: map[string]interface{}{}, | ||
770 | 397 | }, { | ||
771 | 398 | about: "set some attributes", | ||
772 | 399 | initial: map[string]interface{}{ | ||
773 | 400 | "title": "sir", | ||
774 | 401 | }, | ||
775 | 402 | set: serviceSetYAML("dummy-service:\n skill-level: 9000\n username: admin001\n\n"), | ||
776 | 403 | expect: map[string]interface{}{ | ||
777 | 404 | "title": "sir", | ||
778 | 405 | "username": "admin001", | ||
779 | 406 | "skill-level": int64(9000), // yaml int types are int64 | ||
780 | 407 | }, | ||
781 | 408 | }, { | ||
782 | 409 | about: "remove an attribute by setting to nil", | ||
783 | 410 | initial: map[string]interface{}{ | ||
784 | 411 | "title": "sir", | ||
785 | 412 | "username": "foo", | ||
786 | 413 | }, | ||
787 | 414 | set: serviceSetYAML("dummy-service: {title: null}"), | ||
788 | 415 | expect: map[string]interface{}{ | ||
789 | 416 | "username": "foo", | ||
790 | 417 | }, | ||
791 | 418 | }, { | ||
792 | 419 | about: "remove an attribute by setting to empty string", | ||
793 | 420 | initial: map[string]interface{}{ | ||
794 | 421 | "title": "sir", | ||
795 | 422 | "username": "foo", | ||
796 | 423 | }, | ||
797 | 424 | set: serviceSetYAML("dummy-service: {title: ''}"), | ||
798 | 425 | expect: map[string]interface{}{ | ||
799 | 426 | "username": "foo", | ||
800 | 427 | }, | ||
801 | 428 | }, | ||
802 | 429 | } | ||
845 | 430 | 366 | ||
847 | 431 | func (s *ServiceSuite) TestSet(c *C) { | 367 | func (s *ServiceSuite) TestUpdateConfigSettings(c *C) { |
848 | 432 | sch := s.AddTestingCharm(c, "dummy") | 368 | sch := s.AddTestingCharm(c, "dummy") |
850 | 433 | for i, t := range serviceSetTests { | 369 | for i, t := range serviceUpdateConfigSettingsTests { |
851 | 434 | c.Logf("test %d. %s", i, t.about) | 370 | c.Logf("test %d. %s", i, t.about) |
852 | 435 | svc, err := s.State.AddService("dummy-service", sch) | 371 | svc, err := s.State.AddService("dummy-service", sch) |
853 | 436 | c.Assert(err, IsNil) | 372 | c.Assert(err, IsNil) |
854 | 437 | if t.initial != nil { | 373 | if t.initial != nil { |
859 | 438 | cfg, err := svc.Config() | 374 | err := svc.UpdateConfigSettings(t.initial) |
856 | 439 | c.Assert(err, IsNil) | ||
857 | 440 | cfg.Update(t.initial) | ||
858 | 441 | _, err = cfg.Write() | ||
860 | 442 | c.Assert(err, IsNil) | 375 | c.Assert(err, IsNil) |
861 | 443 | } | 376 | } |
863 | 444 | err = t.set(svc) | 377 | err = svc.UpdateConfigSettings(t.update) |
864 | 445 | if t.err != "" { | 378 | if t.err != "" { |
865 | 446 | c.Assert(err, ErrorMatches, t.err) | 379 | c.Assert(err, ErrorMatches, t.err) |
866 | 447 | } else { | 380 | } else { |
867 | 448 | c.Assert(err, IsNil) | 381 | c.Assert(err, IsNil) |
869 | 449 | cfg, err := svc.Config() | 382 | settings, err := svc.ConfigSettings() |
870 | 450 | c.Assert(err, IsNil) | 383 | c.Assert(err, IsNil) |
872 | 451 | c.Assert(cfg.Map(), DeepEquals, t.expect) | 384 | expect := t.expect |
873 | 385 | if expect == nil { | ||
874 | 386 | expect = charm.Settings{} | ||
875 | 387 | } | ||
876 | 388 | c.Assert(settings, DeepEquals, expect) | ||
877 | 452 | } | 389 | } |
878 | 453 | err = svc.Destroy() | 390 | err = svc.Destroy() |
879 | 454 | c.Assert(err, IsNil) | 391 | c.Assert(err, IsNil) |
880 | @@ -1127,25 +1064,6 @@ | |||
881 | 1127 | c.Assert(err, ErrorMatches, `unit "mysql/0" not found`) | 1064 | c.Assert(err, ErrorMatches, `unit "mysql/0" not found`) |
882 | 1128 | } | 1065 | } |
883 | 1129 | 1066 | ||
884 | 1130 | func (s *ServiceSuite) TestServiceConfig(c *C) { | ||
885 | 1131 | env, err := s.mysql.Config() | ||
886 | 1132 | c.Assert(err, IsNil) | ||
887 | 1133 | err = env.Read() | ||
888 | 1134 | c.Assert(err, IsNil) | ||
889 | 1135 | c.Assert(env.Map(), DeepEquals, map[string]interface{}{}) | ||
890 | 1136 | |||
891 | 1137 | env.Update(map[string]interface{}{"spam": "eggs", "eggs": "spam"}) | ||
892 | 1138 | env.Update(map[string]interface{}{"spam": "spam", "chaos": "emeralds"}) | ||
893 | 1139 | _, err = env.Write() | ||
894 | 1140 | c.Assert(err, IsNil) | ||
895 | 1141 | |||
896 | 1142 | env, err = s.mysql.Config() | ||
897 | 1143 | c.Assert(err, IsNil) | ||
898 | 1144 | err = env.Read() | ||
899 | 1145 | c.Assert(err, IsNil) | ||
900 | 1146 | c.Assert(env.Map(), DeepEquals, map[string]interface{}{"spam": "spam", "eggs": "spam", "chaos": "emeralds"}) | ||
901 | 1147 | } | ||
902 | 1148 | |||
903 | 1149 | func uint64p(val uint64) *uint64 { | 1067 | func uint64p(val uint64) *uint64 { |
904 | 1150 | return &val | 1068 | return &val |
905 | 1151 | } | 1069 | } |
906 | 1152 | 1070 | ||
907 | === modified file 'state/statecmd/config_test.go' | |||
908 | --- state/statecmd/config_test.go 2013-05-02 15:55:42 +0000 | |||
909 | +++ state/statecmd/config_test.go 2013-06-12 01:17:26 +0000 | |||
910 | @@ -134,7 +134,9 @@ | |||
911 | 134 | c.Assert(err, IsNil) | 134 | c.Assert(err, IsNil) |
912 | 135 | } | 135 | } |
913 | 136 | if t.config != nil { | 136 | if t.config != nil { |
915 | 137 | err = svc.SetConfig(t.config) | 137 | settings, err := ch.Config().ParseSettingsStrings(t.config) |
916 | 138 | c.Assert(err, IsNil) | ||
917 | 139 | err = svc.UpdateConfigSettings(settings) | ||
918 | 138 | c.Assert(err, IsNil) | 140 | c.Assert(err, IsNil) |
919 | 139 | } | 141 | } |
920 | 140 | expect := t.expect | 142 | expect := t.expect |
921 | 141 | 143 | ||
922 | === modified file 'state/statecmd/deploy_test.go' | |||
923 | --- state/statecmd/deploy_test.go 2013-06-10 22:46:06 +0000 | |||
924 | +++ state/statecmd/deploy_test.go 2013-06-12 01:17:26 +0000 | |||
925 | @@ -219,9 +219,9 @@ | |||
926 | 219 | s.AssertService(c, "dummy", curl, 1, 0) | 219 | s.AssertService(c, "dummy", curl, 1, 0) |
927 | 220 | svc, err := s.State.Service("dummy") | 220 | svc, err := s.State.Service("dummy") |
928 | 221 | c.Assert(err, IsNil) | 221 | c.Assert(err, IsNil) |
930 | 222 | cfg, err := svc.Config() | 222 | settings, err := svc.ConfigSettings() |
931 | 223 | c.Assert(err, IsNil) | 223 | c.Assert(err, IsNil) |
933 | 224 | c.Assert(cfg.Map(), DeepEquals, map[string]interface{}{ | 224 | c.Assert(settings, DeepEquals, charm.Settings{ |
934 | 225 | "skill-level": int64(1), | 225 | "skill-level": int64(1), |
935 | 226 | }) | 226 | }) |
936 | 227 | } | 227 | } |
937 | @@ -239,9 +239,9 @@ | |||
938 | 239 | s.AssertService(c, "dummy", curl, 1, 0) | 239 | s.AssertService(c, "dummy", curl, 1, 0) |
939 | 240 | svc, err := s.State.Service("dummy") | 240 | svc, err := s.State.Service("dummy") |
940 | 241 | c.Assert(err, IsNil) | 241 | c.Assert(err, IsNil) |
942 | 242 | cfg, err := svc.Config() | 242 | settings, err := svc.ConfigSettings() |
943 | 243 | c.Assert(err, IsNil) | 243 | c.Assert(err, IsNil) |
945 | 244 | c.Assert(cfg.Map(), DeepEquals, map[string]interface{}{ | 244 | c.Assert(settings, DeepEquals, charm.Settings{ |
946 | 245 | "skill-level": int64(9001), | 245 | "skill-level": int64(9001), |
947 | 246 | }) | 246 | }) |
948 | 247 | } | 247 | } |
949 | 248 | 248 | ||
950 | === modified file 'state/statecmd/get.go' | |||
951 | --- state/statecmd/get.go 2013-05-02 15:55:42 +0000 | |||
952 | +++ state/statecmd/get.go 2013-06-12 01:17:26 +0000 | |||
953 | @@ -18,53 +18,48 @@ | |||
954 | 18 | 18 | ||
955 | 19 | // ServiceGet returns the configuration for the named service. | 19 | // ServiceGet returns the configuration for the named service. |
956 | 20 | func ServiceGet(st *state.State, p params.ServiceGet) (params.ServiceGetResults, error) { | 20 | func ServiceGet(st *state.State, p params.ServiceGet) (params.ServiceGetResults, error) { |
971 | 21 | svc, err := st.Service(p.ServiceName) | 21 | service, err := st.Service(p.ServiceName) |
972 | 22 | if err != nil { | 22 | if err != nil { |
973 | 23 | return params.ServiceGetResults{}, err | 23 | return params.ServiceGetResults{}, err |
974 | 24 | } | 24 | } |
975 | 25 | svcCfg, err := svc.Config() | 25 | settings, err := service.ConfigSettings() |
976 | 26 | if err != nil { | 26 | if err != nil { |
977 | 27 | return params.ServiceGetResults{}, err | 27 | return params.ServiceGetResults{}, err |
978 | 28 | } | 28 | } |
979 | 29 | charm, _, err := svc.Charm() | 29 | charm, _, err := service.Charm() |
980 | 30 | if err != nil { | 30 | if err != nil { |
981 | 31 | return params.ServiceGetResults{}, err | 31 | return params.ServiceGetResults{}, err |
982 | 32 | } | 32 | } |
983 | 33 | charmCfg := charm.Config().Options | 33 | configInfo := describe(settings, charm.Config()) |
970 | 34 | |||
984 | 35 | var constraints constraints.Value | 34 | var constraints constraints.Value |
987 | 36 | if svc.IsPrincipal() { | 35 | if service.IsPrincipal() { |
988 | 37 | constraints, err = svc.Constraints() | 36 | constraints, err = service.Constraints() |
989 | 38 | if err != nil { | 37 | if err != nil { |
990 | 39 | return params.ServiceGetResults{}, err | 38 | return params.ServiceGetResults{}, err |
991 | 40 | } | 39 | } |
992 | 41 | } | 40 | } |
993 | 42 | |||
994 | 43 | return params.ServiceGetResults{ | 41 | return params.ServiceGetResults{ |
995 | 44 | Service: p.ServiceName, | 42 | Service: p.ServiceName, |
996 | 45 | Charm: charm.Meta().Name, | 43 | Charm: charm.Meta().Name, |
998 | 46 | Config: merge(svcCfg.Map(), charmCfg), | 44 | Config: configInfo, |
999 | 47 | Constraints: constraints, | 45 | Constraints: constraints, |
1000 | 48 | }, nil | 46 | }, nil |
1001 | 49 | } | 47 | } |
1002 | 50 | 48 | ||
1007 | 51 | // merge returns the service settings merged with the charm | 49 | func describe(settings charm.Settings, config *charm.Config) map[string]interface{} { |
1004 | 52 | // schema, taking default values from the configuration | ||
1005 | 53 | // in the charm metadata. | ||
1006 | 54 | func merge(serviceCfg map[string]interface{}, charmCfg map[string]charm.Option) map[string]interface{} { | ||
1008 | 55 | results := make(map[string]interface{}) | 50 | results := make(map[string]interface{}) |
1013 | 56 | for k, v := range charmCfg { | 51 | for name, option := range config.Options { |
1014 | 57 | m := map[string]interface{}{ | 52 | info := map[string]interface{}{ |
1015 | 58 | "description": v.Description, | 53 | "description": option.Description, |
1016 | 59 | "type": v.Type, | 54 | "type": option.Type, |
1017 | 60 | } | 55 | } |
1020 | 61 | if s, ok := serviceCfg[k]; ok { | 56 | if value := settings[name]; value != nil { |
1021 | 62 | m["value"] = s | 57 | info["value"] = value |
1022 | 63 | } else { | 58 | } else { |
1025 | 64 | m["value"] = v.Default | 59 | info["value"] = option.Default |
1026 | 65 | m["default"] = true | 60 | info["default"] = true |
1027 | 66 | } | 61 | } |
1029 | 67 | results[k] = m | 62 | results[name] = info |
1030 | 68 | } | 63 | } |
1031 | 69 | return results | 64 | return results |
1032 | 70 | } | 65 | } |
1033 | 71 | 66 | ||
1034 | === modified file 'state/unit_test.go' | |||
1035 | --- state/unit_test.go 2013-06-10 21:30:13 +0000 | |||
1036 | +++ state/unit_test.go 2013-06-12 01:17:26 +0000 | |||
1037 | @@ -59,7 +59,7 @@ | |||
1038 | 59 | } | 59 | } |
1039 | 60 | 60 | ||
1040 | 61 | func (s *UnitSuite) TestConfigSettingsReflectService(c *C) { | 61 | func (s *UnitSuite) TestConfigSettingsReflectService(c *C) { |
1042 | 62 | err := s.service.SetConfig(map[string]string{"blog-title": "no title"}) | 62 | err := s.service.UpdateConfigSettings(charm.Settings{"blog-title": "no title"}) |
1043 | 63 | c.Assert(err, IsNil) | 63 | c.Assert(err, IsNil) |
1044 | 64 | err = s.unit.SetCharmURL(s.charm.URL()) | 64 | err = s.unit.SetCharmURL(s.charm.URL()) |
1045 | 65 | c.Assert(err, IsNil) | 65 | c.Assert(err, IsNil) |
1046 | @@ -67,7 +67,7 @@ | |||
1047 | 67 | c.Assert(err, IsNil) | 67 | c.Assert(err, IsNil) |
1048 | 68 | c.Assert(settings, DeepEquals, charm.Settings{"blog-title": "no title"}) | 68 | c.Assert(settings, DeepEquals, charm.Settings{"blog-title": "no title"}) |
1049 | 69 | 69 | ||
1051 | 70 | err = s.service.SetConfig(map[string]string{"blog-title": "ironic title"}) | 70 | err = s.service.UpdateConfigSettings(charm.Settings{"blog-title": "ironic title"}) |
1052 | 71 | c.Assert(err, IsNil) | 71 | c.Assert(err, IsNil) |
1053 | 72 | settings, err = s.unit.ConfigSettings() | 72 | settings, err = s.unit.ConfigSettings() |
1054 | 73 | c.Assert(err, IsNil) | 73 | c.Assert(err, IsNil) |
1055 | @@ -127,18 +127,18 @@ | |||
1056 | 127 | assertChange() | 127 | assertChange() |
1057 | 128 | 128 | ||
1058 | 129 | // Update config a couple of times, check a single event. | 129 | // Update config a couple of times, check a single event. |
1060 | 130 | err = s.service.SetConfig(map[string]string{ | 130 | err = s.service.UpdateConfigSettings(charm.Settings{ |
1061 | 131 | "blog-title": "superhero paparazzi", | 131 | "blog-title": "superhero paparazzi", |
1062 | 132 | }) | 132 | }) |
1063 | 133 | c.Assert(err, IsNil) | 133 | c.Assert(err, IsNil) |
1065 | 134 | err = s.service.SetConfig(map[string]string{ | 134 | err = s.service.UpdateConfigSettings(charm.Settings{ |
1066 | 135 | "blog-title": "sauceror central", | 135 | "blog-title": "sauceror central", |
1067 | 136 | }) | 136 | }) |
1068 | 137 | c.Assert(err, IsNil) | 137 | c.Assert(err, IsNil) |
1069 | 138 | assertChange() | 138 | assertChange() |
1070 | 139 | 139 | ||
1071 | 140 | // Non-change is not reported. | 140 | // Non-change is not reported. |
1073 | 141 | err = s.service.SetConfig(map[string]string{ | 141 | err = s.service.UpdateConfigSettings(charm.Settings{ |
1074 | 142 | "blog-title": "sauceror central", | 142 | "blog-title": "sauceror central", |
1075 | 143 | }) | 143 | }) |
1076 | 144 | c.Assert(err, IsNil) | 144 | c.Assert(err, IsNil) |
1077 | @@ -151,8 +151,8 @@ | |||
1078 | 151 | assertNoChange() | 151 | assertNoChange() |
1079 | 152 | 152 | ||
1080 | 153 | // Change service config for new charm; nothing detected. | 153 | // Change service config for new charm; nothing detected. |
1083 | 154 | err = s.service.SetConfig(map[string]string{ | 154 | err = s.service.UpdateConfigSettings(charm.Settings{ |
1084 | 155 | "key": "42.0", | 155 | "key": 42.0, |
1085 | 156 | }) | 156 | }) |
1086 | 157 | c.Assert(err, IsNil) | 157 | c.Assert(err, IsNil) |
1087 | 158 | assertNoChange() | 158 | assertNoChange() |
1088 | 159 | 159 | ||
1089 | === modified file 'worker/uniter/context_test.go' | |||
1090 | --- worker/uniter/context_test.go 2013-06-10 21:04:37 +0000 | |||
1091 | +++ worker/uniter/context_test.go 2013-06-12 01:17:26 +0000 | |||
1092 | @@ -577,10 +577,9 @@ | |||
1093 | 577 | c.Assert(settings, DeepEquals, charm.Settings{"blog-title": "My Title"}) | 577 | c.Assert(settings, DeepEquals, charm.Settings{"blog-title": "My Title"}) |
1094 | 578 | 578 | ||
1095 | 579 | // Change remote config. | 579 | // Change remote config. |
1100 | 580 | node, err := s.service.Config() | 580 | err = s.service.UpdateConfigSettings(charm.Settings{ |
1101 | 581 | c.Assert(err, IsNil) | 581 | "blog-title": "Something Else", |
1102 | 582 | node.Set("blog-title", "Something Else") | 582 | }) |
1099 | 583 | _, err = node.Write() | ||
1103 | 584 | c.Assert(err, IsNil) | 583 | c.Assert(err, IsNil) |
1104 | 585 | 584 | ||
1105 | 586 | // Local view is not changed. | 585 | // Local view is not changed. |
1106 | 587 | 586 | ||
1107 | === modified file 'worker/uniter/filter_test.go' | |||
1108 | --- worker/uniter/filter_test.go 2013-05-02 15:55:42 +0000 | |||
1109 | +++ worker/uniter/filter_test.go 2013-06-12 01:17:26 +0000 | |||
1110 | @@ -266,6 +266,9 @@ | |||
1111 | 266 | } | 266 | } |
1112 | 267 | assertNoChange() | 267 | assertNoChange() |
1113 | 268 | 268 | ||
1114 | 269 | // Set the charm URL to trigger config events. | ||
1115 | 270 | err = f.SetCharm(s.wpcharm.URL()) | ||
1116 | 271 | c.Assert(err, IsNil) | ||
1117 | 269 | assertChange := func() { | 272 | assertChange := func() { |
1118 | 270 | s.State.Sync() | 273 | s.State.Sync() |
1119 | 271 | select { | 274 | select { |
1120 | @@ -276,34 +279,23 @@ | |||
1121 | 276 | } | 279 | } |
1122 | 277 | assertNoChange() | 280 | assertNoChange() |
1123 | 278 | } | 281 | } |
1124 | 279 | |||
1125 | 280 | // Set the charm URL to trigger config events. | ||
1126 | 281 | err = f.SetCharm(s.wpcharm.URL()) | ||
1127 | 282 | c.Assert(err, IsNil) | ||
1128 | 283 | assertChange() | 282 | assertChange() |
1129 | 284 | 283 | ||
1130 | 285 | // Make sure the charm URL is set now. | ||
1131 | 286 | s.unit.Refresh() | ||
1132 | 287 | curl, ok := s.unit.CharmURL() | ||
1133 | 288 | c.Assert(ok, Equals, true) | ||
1134 | 289 | c.Assert(curl, DeepEquals, s.wpcharm.URL()) | ||
1135 | 290 | |||
1136 | 291 | // Change the config; new event received. | 284 | // Change the config; new event received. |
1142 | 292 | node, err := s.wordpress.Config() | 285 | changeConfig := func(title interface{}) { |
1143 | 293 | c.Assert(err, IsNil) | 286 | err := s.wordpress.UpdateConfigSettings(charm.Settings{ |
1144 | 294 | node.Set("skill-level", 9001) | 287 | "blog-title": title, |
1145 | 295 | _, err = node.Write() | 288 | }) |
1146 | 296 | c.Assert(err, IsNil) | 289 | c.Assert(err, IsNil) |
1147 | 290 | } | ||
1148 | 291 | changeConfig("20,000 leagues in the cloud") | ||
1149 | 297 | assertChange() | 292 | assertChange() |
1150 | 298 | 293 | ||
1159 | 299 | // Change the config a couple of times, then reset the events. | 294 | // Change the config a few more times, then reset the events. We sync to |
1160 | 300 | node.Set("title", "20,000 leagues in the cloud") | 295 | // make sure the event has come into the filter before we tell it to discard |
1161 | 301 | _, err = node.Write() | 296 | // all received events. |
1162 | 302 | c.Assert(err, IsNil) | 297 | changeConfig(nil) |
1163 | 303 | node.Set("outlook", "precipitous") | 298 | changeConfig("the curious incident of the dog in the cloud") |
1156 | 304 | _, err = node.Write() | ||
1157 | 305 | c.Assert(err, IsNil) | ||
1158 | 306 | // We make sure the event has come into the filter before we tell it to discard any received. | ||
1164 | 307 | s.State.Sync() | 299 | s.State.Sync() |
1165 | 308 | f.DiscardConfigEvent() | 300 | f.DiscardConfigEvent() |
1166 | 309 | assertNoChange() | 301 | assertNoChange() |
1167 | @@ -318,12 +310,8 @@ | |||
1168 | 318 | assertNoChange() | 310 | assertNoChange() |
1169 | 319 | 311 | ||
1170 | 320 | // Further changes are still collapsed as appropriate. | 312 | // Further changes are still collapsed as appropriate. |
1177 | 321 | node.Set("skill-level", 123) | 313 | changeConfig("forsooth") |
1178 | 322 | _, err = node.Write() | 314 | changeConfig("imagination failure") |
1173 | 323 | c.Assert(err, IsNil) | ||
1174 | 324 | node.Set("outlook", "expressive") | ||
1175 | 325 | _, err = node.Write() | ||
1176 | 326 | c.Assert(err, IsNil) | ||
1179 | 327 | assertChange() | 315 | assertChange() |
1180 | 328 | } | 316 | } |
1181 | 329 | 317 | ||
1182 | 330 | 318 | ||
1183 | === modified file 'worker/uniter/uniter_test.go' | |||
1184 | --- worker/uniter/uniter_test.go 2013-06-05 02:44:14 +0000 | |||
1185 | +++ worker/uniter/uniter_test.go 2013-06-12 01:17:26 +0000 | |||
1186 | @@ -1320,10 +1320,7 @@ | |||
1187 | 1320 | type changeConfig map[string]interface{} | 1320 | type changeConfig map[string]interface{} |
1188 | 1321 | 1321 | ||
1189 | 1322 | func (s changeConfig) step(c *C, ctx *context) { | 1322 | func (s changeConfig) step(c *C, ctx *context) { |
1194 | 1323 | node, err := ctx.svc.Config() | 1323 | err := ctx.svc.UpdateConfigSettings(charm.Settings(s)) |
1191 | 1324 | c.Assert(err, IsNil) | ||
1192 | 1325 | node.Update(s) | ||
1193 | 1326 | _, err = node.Write() | ||
1195 | 1327 | c.Assert(err, IsNil) | 1324 | c.Assert(err, IsNil) |
1196 | 1328 | } | 1325 | } |
1197 | 1329 | 1326 |
Reviewers: mp+168580_ code.launchpad. net,
Message:
Please take a look.
Description:
state: Service ConfigSettings methods
Config, SetConfig, and SetConfigYAML methods have been dropped in favour tings, which use sensible types.
of
ConfigSettings and UpdateConfigSet
Clients
are expected to parse their own damn data and supply a sensible format.
https:/ /code.launchpad .net/~fwereade/ juju-core/ config- 6-state- service- sane-methods/ +merge/ 168580
Requires: /code.launchpad .net/~fwereade/ juju-core/ config- 5-state- service- config- yaml/+merge/ 168579
https:/
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/10083047/
Affected files: cmd_test. go config_ test.go deploy_ test.go params/ params_ test.go /client. go /client_ test.go er_internal_ test.go test.go config_ test.go deploy_ test.go get.go uniter/ context_ test.go uniter/ filter_ test.go uniter/ uniter_ test.go
A [revision details]
M cmd/juju/
M cmd/juju/
M cmd/juju/deploy.go
M cmd/juju/
M cmd/juju/set.go
M juju/conn.go
M juju/conn_test.go
M state/api/client.go
M state/api/
M state/apiserver
M state/apiserver
M state/megawatch
M state/service.go
M state/service_
M state/statecmd/
M state/statecmd/
M state/statecmd/
M state/unit_test.go
M worker/
M worker/
M worker/