Merge lp:~dimitern/juju-core/148-apiuniter-fix-configsettings into lp:~go-bot/juju-core/trunk

Proposed by Dimiter Naydenov
Status: Merged
Approved by: Dimiter Naydenov
Approved revision: no longer in the source branch.
Merged at revision: 1893
Proposed branch: lp:~dimitern/juju-core/148-apiuniter-fix-configsettings
Merge into: lp:~go-bot/juju-core/trunk
Prerequisite: lp:~dimitern/juju-core/147-apiprovisioner-blank-env-secrets
Diff against target: 747 lines (+177/-113)
16 files modified
state/api/params/internal.go (+37/-22)
state/api/provisioner/provisioner.go (+1/-1)
state/api/uniter/relationunit.go (+3/-3)
state/api/uniter/relationunit_test.go (+2/-2)
state/api/uniter/settings.go (+6/-6)
state/api/uniter/settings_test.go (+11/-11)
state/api/uniter/unit.go (+2/-10)
state/apiserver/provisioner/provisioner.go (+2/-2)
state/apiserver/provisioner/provisioner_test.go (+1/-1)
state/apiserver/uniter/uniter.go (+24/-19)
state/apiserver/uniter/uniter_test.go (+64/-12)
worker/uniter/context.go (+2/-2)
worker/uniter/context_test.go (+15/-15)
worker/uniter/jujuc/context.go (+2/-2)
worker/uniter/jujuc/relation-get.go (+1/-1)
worker/uniter/jujuc/util_test.go (+4/-4)
To merge this branch: bzr merge lp:~dimitern/juju-core/148-apiuniter-fix-configsettings
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+187824@code.launchpad.net

Commit message

apiuniter: Fix lp:1231457

This changes several params types, while keeping
the field names for backward compatibility.
And changes the result of ConfigSettings() call
to return map[string]interface{}, because charm
settings are different from relation settings
(which are always strings), and coercing charm
settings to stings discards non-string config
settings, so this is fixed here.

https://codereview.appspot.com/13908044/

R=fwereade

Description of the change

apiuniter: Fix lp:1231457

This changes several params types, while keeping
the field names for backward compatibility.
And changes the result of ConfigSettings() call
to return map[string]interface{}, because charm
settings are different from relation settings
(which are always strings), and coercing charm
settings to stings discards non-string config
settings, so this is fixed here.

https://codereview.appspot.com/13908044/

To post a comment you must log in.
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Reviewers: mp+187824_code.launchpad.net,

Message:
Please take a look.

Description:
apiuniter: Fix lp:1231457

This changes several params types, while keeping
the field names for backward compatibility.
And changes the result of ConfigSettings() call
to return map[string]interface{}, because charm
settings are different from relation settings
(which are always strings), and coercing charm
settings to stings discards non-string config
settings, so this is fixed here.

https://code.launchpad.net/~dimitern/juju-core/148-apiuniter-fix-configsettings/+merge/187824

Requires:
https://code.launchpad.net/~dimitern/juju-core/147-apiprovisioner-blank-env-secrets/+merge/187738

(do not edit description out of merge proposal)

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

Affected files (+121, -111 lines):
   A [revision details]
   M state/api/params/internal.go
   M state/api/provisioner/provisioner.go
   M state/api/uniter/relationunit.go
   M state/api/uniter/relationunit_test.go
   M state/api/uniter/settings.go
   M state/api/uniter/settings_test.go
   M state/api/uniter/unit.go
   M state/apiserver/provisioner/provisioner.go
   M state/apiserver/provisioner/provisioner_test.go
   M state/apiserver/uniter/uniter.go
   M state/apiserver/uniter/uniter_test.go
   M worker/uniter/context.go
   M worker/uniter/context_test.go
   M worker/uniter/jujuc/context.go
   M worker/uniter/jujuc/relation-get.go
   M worker/uniter/jujuc/util_test.go

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

LGTM with an error return on unexpected relation settings.

https://codereview.appspot.com/13908044/diff/1/state/api/params/internal.go
File state/api/params/internal.go (right):

https://codereview.appspot.com/13908044/diff/1/state/api/params/internal.go#newcode138
state/api/params/internal.go:138: // EnvironConfig holds an environment
configuration.
Man, our vocabulary is still kinda screwed up here... "Config" means too
many things. Not much we can do about it right now though.

https://codereview.appspot.com/13908044/diff/1/state/api/uniter/unit.go
File state/api/uniter/unit.go (right):

https://codereview.appspot.com/13908044/diff/1/state/api/uniter/unit.go#newcode143
state/api/uniter/unit.go:143: return
map[string]interface{}(result.Settings), nil
can you not do charm.Settings(result.Settings)?

https://codereview.appspot.com/13908044/diff/1/state/apiserver/uniter/uniter.go
File state/apiserver/uniter/uniter.go (left):

https://codereview.appspot.com/13908044/diff/1/state/apiserver/uniter/uniter.go#oldcode797
state/apiserver/uniter/uniter.go:797: // All relation settings should be
strings.
Hmm. This is almost legitimate-panic territory. Best not, since we're
running in the API server and will cause a lot of collateral damage, but
I think we should at least error out -- if it happens, we're clearly not
in Kansas any more.

https://codereview.appspot.com/13908044/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Please take a look.

https://codereview.appspot.com/13908044/diff/1/state/api/uniter/unit.go
File state/api/uniter/unit.go (right):

https://codereview.appspot.com/13908044/diff/1/state/api/uniter/unit.go#newcode143
state/api/uniter/unit.go:143: return
map[string]interface{}(result.Settings), nil
On 2013/09/26 16:11:52, fwereade wrote:
> can you not do charm.Settings(result.Settings)?

Done.

https://codereview.appspot.com/13908044/diff/1/state/apiserver/uniter/uniter.go
File state/apiserver/uniter/uniter.go (left):

https://codereview.appspot.com/13908044/diff/1/state/apiserver/uniter/uniter.go#oldcode797
state/apiserver/uniter/uniter.go:797: // All relation settings should be
strings.
On 2013/09/26 16:11:52, fwereade wrote:
> Hmm. This is almost legitimate-panic territory. Best not, since we're
running in
> the API server and will cause a lot of collateral damage, but I think
we should
> at least error out -- if it happens, we're clearly not in Kansas any
more.

Done. Also added a couple of tests for the error.

https://codereview.appspot.com/13908044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'state/api/params/internal.go'
--- state/api/params/internal.go 2013-09-24 08:55:01 +0000
+++ state/api/params/internal.go 2013-09-26 17:24:28 +0000
@@ -105,28 +105,43 @@
105 Results []BoolResult105 Results []BoolResult
106}106}
107107
108// Settings holds charm config options names and values.108// RelationSettings holds relation settings names and values.
109type Settings map[string]string109type RelationSettings map[string]string
110110
111// SettingsResult holds a charm settings map or an error.111// RelationSettingsResult holds a relation settings map or an error.
112type SettingsResult struct {112type RelationSettingsResult struct {
113 Error *Error113 Error *Error
114 Settings Settings114 Settings RelationSettings
115}115}
116116
117// SettingsResults holds the result of an API calls that returns117// RelationSettingsResults holds the result of an API calls that
118// settings for multiple entities.118// returns settings for multiple relations.
119type SettingsResults struct {119type RelationSettingsResults struct {
120 Results []SettingsResult120 Results []RelationSettingsResult
121}121}
122122
123// Config holds configuration with string keys and arbitrary values.123// ConfigSettings holds unit, service or cham configuration settings
124type Config map[string]interface{}124// with string keys and arbitrary values.
125125type ConfigSettings map[string]interface{}
126// ConfigResult holds a configuration map or an error.126
127type ConfigResult struct {127// ConfigSettingsResult holds a configuration map or an error.
128type ConfigSettingsResult struct {
129 Error *Error
130 Settings ConfigSettings
131}
132
133// ConfigSettingsResults holds multiple configuration maps or errors.
134type ConfigSettingsResults struct {
135 Results []ConfigSettingsResult
136}
137
138// EnvironConfig holds an environment configuration.
139type EnvironConfig map[string]interface{}
140
141// EnvironConfigResult holds environment configuration or an error.
142type EnvironConfigResult struct {
128 Error *Error143 Error *Error
129 Config Config144 Config EnvironConfig
130}145}
131146
132// RelationUnit holds a relation and a unit tag.147// RelationUnit holds a relation and a unit tag.
@@ -164,7 +179,7 @@
164type RelationUnitSettings struct {179type RelationUnitSettings struct {
165 Relation string180 Relation string
166 Unit string181 Unit string
167 Settings Settings182 Settings RelationSettings
168}183}
169184
170// RelationUnitsSettings holds the arguments for making a EnterScope185// RelationUnitsSettings holds the arguments for making a EnterScope
171186
=== modified file 'state/api/provisioner/provisioner.go'
--- state/api/provisioner/provisioner.go 2013-09-26 10:38:59 +0000
+++ state/api/provisioner/provisioner.go 2013-09-26 17:24:28 +0000
@@ -71,7 +71,7 @@
7171
72// EnvironConfig returns the current environment configuration.72// EnvironConfig returns the current environment configuration.
73func (st *State) EnvironConfig() (*config.Config, error) {73func (st *State) EnvironConfig() (*config.Config, error) {
74 var result params.ConfigResult74 var result params.EnvironConfigResult
75 err := st.caller.Call("Provisioner", "", "EnvironConfig", nil, &result)75 err := st.caller.Call("Provisioner", "", "EnvironConfig", nil, &result)
76 if err != nil {76 if err != nil {
77 return nil, err77 return nil, err
7878
=== modified file 'state/api/uniter/relationunit.go'
--- state/api/uniter/relationunit.go 2013-09-10 17:00:19 +0000
+++ state/api/uniter/relationunit.go 2013-09-26 17:24:28 +0000
@@ -105,7 +105,7 @@
105// Settings returns a Settings which allows access to the unit's settings105// Settings returns a Settings which allows access to the unit's settings
106// within the relation.106// within the relation.
107func (ru *RelationUnit) Settings() (*Settings, error) {107func (ru *RelationUnit) Settings() (*Settings, error) {
108 var results params.SettingsResults108 var results params.RelationSettingsResults
109 args := params.RelationUnits{109 args := params.RelationUnits{
110 RelationUnits: []params.RelationUnit{{110 RelationUnits: []params.RelationUnit{{
111 Relation: ru.relation.tag,111 Relation: ru.relation.tag,
@@ -133,9 +133,9 @@
133// unit is not grounds for an error, because the unit settings are133// unit is not grounds for an error, because the unit settings are
134// guaranteed to persist for the lifetime of the relation, regardless134// guaranteed to persist for the lifetime of the relation, regardless
135// of the lifetime of the unit.135// of the lifetime of the unit.
136func (ru *RelationUnit) ReadSettings(uname string) (params.Settings, error) {136func (ru *RelationUnit) ReadSettings(uname string) (params.RelationSettings, error) {
137 tag := names.UnitTag(uname)137 tag := names.UnitTag(uname)
138 var results params.SettingsResults138 var results params.RelationSettingsResults
139 args := params.RelationUnitPairs{139 args := params.RelationUnitPairs{
140 RelationUnitPairs: []params.RelationUnitPair{{140 RelationUnitPairs: []params.RelationUnitPair{{
141 Relation: ru.relation.tag,141 Relation: ru.relation.tag,
142142
=== modified file 'state/api/uniter/relationunit_test.go'
--- state/api/uniter/relationunit_test.go 2013-09-13 11:35:33 +0000
+++ state/api/uniter/relationunit_test.go 2013-09-26 17:24:28 +0000
@@ -196,7 +196,7 @@
196196
197 gotSettings, err := apiRelUnit.Settings()197 gotSettings, err := apiRelUnit.Settings()
198 c.Assert(err, gc.IsNil)198 c.Assert(err, gc.IsNil)
199 c.Assert(gotSettings.Map(), gc.DeepEquals, params.Settings{199 c.Assert(gotSettings.Map(), gc.DeepEquals, params.RelationSettings{
200 "some": "settings",200 "some": "settings",
201 "other": "things",201 "other": "things",
202 })202 })
@@ -230,7 +230,7 @@
230 s.assertInScope(c, myRelUnit, true)230 s.assertInScope(c, myRelUnit, true)
231 gotSettings, err = apiRelUnit.ReadSettings("mysql/0")231 gotSettings, err = apiRelUnit.ReadSettings("mysql/0")
232 c.Assert(err, gc.IsNil)232 c.Assert(err, gc.IsNil)
233 c.Assert(gotSettings, gc.DeepEquals, params.Settings{233 c.Assert(gotSettings, gc.DeepEquals, params.RelationSettings{
234 "some": "settings",234 "some": "settings",
235 "other": "things",235 "other": "things",
236 })236 })
237237
=== modified file 'state/api/uniter/settings.go'
--- state/api/uniter/settings.go 2013-09-06 16:22:34 +0000
+++ state/api/uniter/settings.go 2013-09-26 17:24:28 +0000
@@ -15,12 +15,12 @@
15 st *State15 st *State
16 relationTag string16 relationTag string
17 unitTag string17 unitTag string
18 settings params.Settings18 settings params.RelationSettings
19}19}
2020
21func newSettings(st *State, relationTag, unitTag string, settings params.Settings) *Settings {21func newSettings(st *State, relationTag, unitTag string, settings params.RelationSettings) *Settings {
22 if settings == nil {22 if settings == nil {
23 settings = make(params.Settings)23 settings = make(params.RelationSettings)
24 }24 }
25 return &Settings{25 return &Settings{
26 st: st,26 st: st,
@@ -36,8 +36,8 @@
36// not return map[string]interface{}, but since all values are36// not return map[string]interface{}, but since all values are
37// expected to be strings anyway, we need to fix the uniter code37// expected to be strings anyway, we need to fix the uniter code
38// accordingly when migrating to the API.38// accordingly when migrating to the API.
39func (s *Settings) Map() params.Settings {39func (s *Settings) Map() params.RelationSettings {
40 settingsCopy := make(params.Settings)40 settingsCopy := make(params.RelationSettings)
41 for k, v := range s.settings {41 for k, v := range s.settings {
42 if v != "" {42 if v != "" {
43 // Skip deleted keys.43 // Skip deleted keys.
@@ -75,7 +75,7 @@
75// without overwritting.75// without overwritting.
76func (s *Settings) Write() error {76func (s *Settings) Write() error {
77 // First make a copy of the map, including deleted keys.77 // First make a copy of the map, including deleted keys.
78 settingsCopy := make(params.Settings)78 settingsCopy := make(params.RelationSettings)
79 for k, v := range s.settings {79 for k, v := range s.settings {
80 settingsCopy[k] = v80 settingsCopy[k] = v
81 }81 }
8282
=== modified file 'state/api/uniter/settings_test.go'
--- state/api/uniter/settings_test.go 2013-09-06 15:39:38 +0000
+++ state/api/uniter/settings_test.go 2013-09-26 17:24:28 +0000
@@ -34,7 +34,7 @@
34 c.Assert(theMap, gc.HasLen, 0)34 c.Assert(theMap, gc.HasLen, 0)
3535
36 // And also accepts a populated map, and returns a converted map.36 // And also accepts a populated map, and returns a converted map.
37 rawSettings := params.Settings{37 rawSettings := params.RelationSettings{
38 "some": "settings",38 "some": "settings",
39 "other": "stuff",39 "other": "stuff",
40 }40 }
@@ -47,15 +47,15 @@
47 settings := uniter.NewSettings(s.uniter, "blah", "foo", nil)47 settings := uniter.NewSettings(s.uniter, "blah", "foo", nil)
4848
49 settings.Set("foo", "bar")49 settings.Set("foo", "bar")
50 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{50 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
51 "foo": "bar",51 "foo": "bar",
52 })52 })
53 settings.Set("foo", "qaz")53 settings.Set("foo", "qaz")
54 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{54 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
55 "foo": "qaz",55 "foo": "qaz",
56 })56 })
57 settings.Set("bar", "Cheers")57 settings.Set("bar", "Cheers")
58 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{58 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
59 "foo": "qaz",59 "foo": "qaz",
60 "bar": "Cheers",60 "bar": "Cheers",
61 })61 })
@@ -67,27 +67,27 @@
67 settings.Set("foo", "qaz")67 settings.Set("foo", "qaz")
68 settings.Set("abc", "tink")68 settings.Set("abc", "tink")
69 settings.Set("bar", "tonk")69 settings.Set("bar", "tonk")
70 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{70 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
71 "foo": "qaz",71 "foo": "qaz",
72 "abc": "tink",72 "abc": "tink",
73 "bar": "tonk",73 "bar": "tonk",
74 })74 })
75 settings.Delete("abc")75 settings.Delete("abc")
76 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{76 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
77 "foo": "qaz",77 "foo": "qaz",
78 "bar": "tonk",78 "bar": "tonk",
79 })79 })
80 settings.Delete("bar")80 settings.Delete("bar")
81 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{81 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
82 "foo": "qaz",82 "foo": "qaz",
83 })83 })
84 settings.Set("abc", "123")84 settings.Set("abc", "123")
85 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{85 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
86 "foo": "qaz",86 "foo": "qaz",
87 "abc": "123",87 "abc": "123",
88 })88 })
89 settings.Delete("missing")89 settings.Delete("missing")
90 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{90 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
91 "foo": "qaz",91 "foo": "qaz",
92 "abc": "123",92 "abc": "123",
93 })93 })
@@ -112,7 +112,7 @@
112 c.Assert(err, gc.IsNil)112 c.Assert(err, gc.IsNil)
113 settings, err := apiRelUnit.Settings()113 settings, err := apiRelUnit.Settings()
114 c.Assert(err, gc.IsNil)114 c.Assert(err, gc.IsNil)
115 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{115 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
116 "some": "stuff",116 "some": "stuff",
117 "other": "things",117 "other": "things",
118 })118 })
@@ -126,7 +126,7 @@
126 c.Assert(err, gc.IsNil)126 c.Assert(err, gc.IsNil)
127 settings, err = apiRelUnit.Settings()127 settings, err = apiRelUnit.Settings()
128 c.Assert(err, gc.IsNil)128 c.Assert(err, gc.IsNil)
129 c.Assert(settings.Map(), gc.DeepEquals, params.Settings{129 c.Assert(settings.Map(), gc.DeepEquals, params.RelationSettings{
130 "foo": "qaz",130 "foo": "qaz",
131 "other": "days",131 "other": "days",
132 })132 })
133133
=== modified file 'state/api/uniter/unit.go'
--- state/api/uniter/unit.go 2013-09-17 18:18:44 +0000
+++ state/api/uniter/unit.go 2013-09-26 17:24:28 +0000
@@ -120,20 +120,12 @@
120 return service, nil120 return service, nil
121}121}
122122
123func convertSettings(input params.Settings) charm.Settings {
124 result := make(charm.Settings)
125 for k, v := range input {
126 result[k] = v
127 }
128 return result
129}
130
131// ConfigSettings returns the complete set of service charm config settings123// ConfigSettings returns the complete set of service charm config settings
132// available to the unit. Unset values will be replaced with the default124// available to the unit. Unset values will be replaced with the default
133// value for the associated option, and may thus be nil when no default is125// value for the associated option, and may thus be nil when no default is
134// specified.126// specified.
135func (u *Unit) ConfigSettings() (charm.Settings, error) {127func (u *Unit) ConfigSettings() (charm.Settings, error) {
136 var results params.SettingsResults128 var results params.ConfigSettingsResults
137 args := params.Entities{129 args := params.Entities{
138 Entities: []params.Entity{{Tag: u.tag}},130 Entities: []params.Entity{{Tag: u.tag}},
139 }131 }
@@ -148,7 +140,7 @@
148 if result.Error != nil {140 if result.Error != nil {
149 return nil, result.Error141 return nil, result.Error
150 }142 }
151 return convertSettings(result.Settings), nil143 return charm.Settings(result.Settings), nil
152}144}
153145
154// ServiceName returns the service name.146// ServiceName returns the service name.
155147
=== modified file 'state/apiserver/provisioner/provisioner.go'
--- state/apiserver/provisioner/provisioner.go 2013-09-26 16:01:47 +0000
+++ state/apiserver/provisioner/provisioner.go 2013-09-26 17:24:28 +0000
@@ -152,8 +152,8 @@
152}152}
153153
154// EnvironConfig returns the current environment's configuration.154// EnvironConfig returns the current environment's configuration.
155func (p *ProvisionerAPI) EnvironConfig() (params.ConfigResult, error) {155func (p *ProvisionerAPI) EnvironConfig() (params.EnvironConfigResult, error) {
156 result := params.ConfigResult{}156 result := params.EnvironConfigResult{}
157 config, err := p.st.EnvironConfig()157 config, err := p.st.EnvironConfig()
158 if err != nil {158 if err != nil {
159 return result, err159 return result, err
160160
=== modified file 'state/apiserver/provisioner/provisioner_test.go'
--- state/apiserver/provisioner/provisioner_test.go 2013-09-26 11:15:31 +0000
+++ state/apiserver/provisioner/provisioner_test.go 2013-09-26 17:24:28 +0000
@@ -421,7 +421,7 @@
421 result, err := s.provisioner.EnvironConfig()421 result, err := s.provisioner.EnvironConfig()
422 c.Assert(err, gc.IsNil)422 c.Assert(err, gc.IsNil)
423 c.Assert(result.Error, gc.IsNil)423 c.Assert(result.Error, gc.IsNil)
424 c.Assert(result.Config, gc.DeepEquals, params.Config(envConfig.AllAttrs()))424 c.Assert(result.Config, gc.DeepEquals, params.EnvironConfig(envConfig.AllAttrs()))
425425
426 // Now test it with a non-environment manager and make sure426 // Now test it with a non-environment manager and make sure
427 // the secret attributes are masked.427 // the secret attributes are masked.
428428
=== modified file 'state/apiserver/uniter/uniter.go'
--- state/apiserver/uniter/uniter.go 2013-09-12 14:58:40 +0000
+++ state/apiserver/uniter/uniter.go 2013-09-26 17:24:28 +0000
@@ -6,6 +6,8 @@
6package uniter6package uniter
77
8import (8import (
9 "fmt"
10
9 "launchpad.net/juju-core/charm"11 "launchpad.net/juju-core/charm"
10 "launchpad.net/juju-core/environs"12 "launchpad.net/juju-core/environs"
11 "launchpad.net/juju-core/errors"13 "launchpad.net/juju-core/errors"
@@ -489,13 +491,13 @@
489491
490// ConfigSettings returns the complete set of service charm config492// ConfigSettings returns the complete set of service charm config
491// settings available to each given unit.493// settings available to each given unit.
492func (u *UniterAPI) ConfigSettings(args params.Entities) (params.SettingsResults, error) {494func (u *UniterAPI) ConfigSettings(args params.Entities) (params.ConfigSettingsResults, error) {
493 result := params.SettingsResults{495 result := params.ConfigSettingsResults{
494 Results: make([]params.SettingsResult, len(args.Entities)),496 Results: make([]params.ConfigSettingsResult, len(args.Entities)),
495 }497 }
496 canAccess, err := u.accessUnit()498 canAccess, err := u.accessUnit()
497 if err != nil {499 if err != nil {
498 return params.SettingsResults{}, err500 return params.ConfigSettingsResults{}, err
499 }501 }
500 for i, entity := range args.Entities {502 for i, entity := range args.Entities {
501 err := common.ErrPerm503 err := common.ErrPerm
@@ -506,7 +508,7 @@
506 var settings charm.Settings508 var settings charm.Settings
507 settings, err = unit.ConfigSettings()509 settings, err = unit.ConfigSettings()
508 if err == nil {510 if err == nil {
509 result.Results[i].Settings = convertSettings(settings)511 result.Results[i].Settings = params.ConfigSettings(settings)
510 }512 }
511 }513 }
512 }514 }
@@ -791,25 +793,28 @@
791 return result, nil793 return result, nil
792}794}
793795
794func convertSettings(settings map[string]interface{}) params.Settings {796func convertRelationSettings(settings map[string]interface{}) (params.RelationSettings, error) {
795 result := make(params.Settings)797 result := make(params.RelationSettings)
796 for k, v := range settings {798 for k, v := range settings {
797 // All relation settings should be strings.799 // All relation settings should be strings.
798 sval, _ := v.(string)800 sval, ok := v.(string)
801 if !ok {
802 return nil, fmt.Errorf("unexpected relation setting %q: expected string, got %T", k, v)
803 }
799 result[k] = sval804 result[k] = sval
800 }805 }
801 return result806 return result, nil
802}807}
803808
804// ReadSettings returns the local settings of each given set of809// ReadSettings returns the local settings of each given set of
805// relation/unit.810// relation/unit.
806func (u *UniterAPI) ReadSettings(args params.RelationUnits) (params.SettingsResults, error) {811func (u *UniterAPI) ReadSettings(args params.RelationUnits) (params.RelationSettingsResults, error) {
807 result := params.SettingsResults{812 result := params.RelationSettingsResults{
808 Results: make([]params.SettingsResult, len(args.RelationUnits)),813 Results: make([]params.RelationSettingsResult, len(args.RelationUnits)),
809 }814 }
810 canAccess, err := u.accessUnit()815 canAccess, err := u.accessUnit()
811 if err != nil {816 if err != nil {
812 return params.SettingsResults{}, err817 return params.RelationSettingsResults{}, err
813 }818 }
814 for i, arg := range args.RelationUnits {819 for i, arg := range args.RelationUnits {
815 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, arg.Unit)820 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, arg.Unit)
@@ -817,7 +822,7 @@
817 var settings *state.Settings822 var settings *state.Settings
818 settings, err = relUnit.Settings()823 settings, err = relUnit.Settings()
819 if err == nil {824 if err == nil {
820 result.Results[i].Settings = convertSettings(settings.Map())825 result.Results[i].Settings, err = convertRelationSettings(settings.Map())
821 }826 }
822 }827 }
823 result.Results[i].Error = common.ServerError(err)828 result.Results[i].Error = common.ServerError(err)
@@ -845,13 +850,13 @@
845850
846// ReadRemoteSettings returns the remote settings of each given set of851// ReadRemoteSettings returns the remote settings of each given set of
847// relation/local unit/remote unit.852// relation/local unit/remote unit.
848func (u *UniterAPI) ReadRemoteSettings(args params.RelationUnitPairs) (params.SettingsResults, error) {853func (u *UniterAPI) ReadRemoteSettings(args params.RelationUnitPairs) (params.RelationSettingsResults, error) {
849 result := params.SettingsResults{854 result := params.RelationSettingsResults{
850 Results: make([]params.SettingsResult, len(args.RelationUnitPairs)),855 Results: make([]params.RelationSettingsResult, len(args.RelationUnitPairs)),
851 }856 }
852 canAccess, err := u.accessUnit()857 canAccess, err := u.accessUnit()
853 if err != nil {858 if err != nil {
854 return params.SettingsResults{}, err859 return params.RelationSettingsResults{}, err
855 }860 }
856 for i, arg := range args.RelationUnitPairs {861 for i, arg := range args.RelationUnitPairs {
857 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, arg.LocalUnit)862 relUnit, err := u.getRelationUnit(canAccess, arg.Relation, arg.LocalUnit)
@@ -862,7 +867,7 @@
862 var settings map[string]interface{}867 var settings map[string]interface{}
863 settings, err = relUnit.ReadSettings(remoteUnit)868 settings, err = relUnit.ReadSettings(remoteUnit)
864 if err == nil {869 if err == nil {
865 result.Results[i].Settings = convertSettings(settings)870 result.Results[i].Settings, err = convertRelationSettings(settings)
866 }871 }
867 }872 }
868 }873 }
869874
=== modified file 'state/apiserver/uniter/uniter_test.go'
--- state/apiserver/uniter/uniter_test.go 2013-09-18 15:57:30 +0000
+++ state/apiserver/uniter/uniter_test.go 2013-09-26 17:24:28 +0000
@@ -808,10 +808,10 @@
808 }}808 }}
809 result, err := s.uniter.ConfigSettings(args)809 result, err := s.uniter.ConfigSettings(args)
810 c.Assert(err, gc.IsNil)810 c.Assert(err, gc.IsNil)
811 c.Assert(result, gc.DeepEquals, params.SettingsResults{811 c.Assert(result, gc.DeepEquals, params.ConfigSettingsResults{
812 Results: []params.SettingsResult{812 Results: []params.ConfigSettingsResult{
813 {Error: apiservertesting.ErrUnauthorized},813 {Error: apiservertesting.ErrUnauthorized},
814 {Settings: params.Settings{"blog-title": "My Title"}},814 {Settings: params.ConfigSettings{"blog-title": "My Title"}},
815 {Error: apiservertesting.ErrUnauthorized},815 {Error: apiservertesting.ErrUnauthorized},
816 },816 },
817 })817 })
@@ -1097,10 +1097,10 @@
1097 }}1097 }}
1098 result, err := s.uniter.ReadSettings(args)1098 result, err := s.uniter.ReadSettings(args)
1099 c.Assert(err, gc.IsNil)1099 c.Assert(err, gc.IsNil)
1100 c.Assert(result, gc.DeepEquals, params.SettingsResults{1100 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{
1101 Results: []params.SettingsResult{1101 Results: []params.RelationSettingsResult{
1102 {Error: apiservertesting.ErrUnauthorized},1102 {Error: apiservertesting.ErrUnauthorized},
1103 {Settings: params.Settings{1103 {Settings: params.RelationSettings{
1104 "some": "settings",1104 "some": "settings",
1105 }},1105 }},
1106 {Error: apiservertesting.ErrUnauthorized},1106 {Error: apiservertesting.ErrUnauthorized},
@@ -1116,6 +1116,31 @@
1116 })1116 })
1117}1117}
11181118
1119func (s *uniterSuite) TestReadSettingsWithNonStringValuesFails(c *gc.C) {
1120 rel := s.addRelation(c, "wordpress", "mysql")
1121 relUnit, err := rel.Unit(s.wordpressUnit)
1122 c.Assert(err, gc.IsNil)
1123 settings := map[string]interface{}{
1124 "other": "things",
1125 "invalid-bool": false,
1126 }
1127 err = relUnit.EnterScope(settings)
1128 c.Assert(err, gc.IsNil)
1129 s.assertInScope(c, relUnit, true)
1130
1131 args := params.RelationUnits{RelationUnits: []params.RelationUnit{
1132 {Relation: rel.Tag(), Unit: "unit-wordpress-0"},
1133 }}
1134 expectErr := `unexpected relation setting "invalid-bool": expected string, got bool`
1135 result, err := s.uniter.ReadSettings(args)
1136 c.Assert(err, gc.IsNil)
1137 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{
1138 Results: []params.RelationSettingsResult{
1139 {Error: &params.Error{Message: expectErr}},
1140 },
1141 })
1142}
1143
1119func (s *uniterSuite) TestReadRemoteSettings(c *gc.C) {1144func (s *uniterSuite) TestReadRemoteSettings(c *gc.C) {
1120 rel := s.addRelation(c, "wordpress", "mysql")1145 rel := s.addRelation(c, "wordpress", "mysql")
1121 relUnit, err := rel.Unit(s.wordpressUnit)1146 relUnit, err := rel.Unit(s.wordpressUnit)
@@ -1146,8 +1171,8 @@
1146 // We don't set the remote unit settings on purpose to test the error.1171 // We don't set the remote unit settings on purpose to test the error.
1147 expectErr := `cannot read settings for unit "mysql/0" in relation "wordpress:db mysql:server": settings not found`1172 expectErr := `cannot read settings for unit "mysql/0" in relation "wordpress:db mysql:server": settings not found`
1148 c.Assert(err, gc.IsNil)1173 c.Assert(err, gc.IsNil)
1149 c.Assert(result, gc.DeepEquals, params.SettingsResults{1174 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{
1150 Results: []params.SettingsResult{1175 Results: []params.RelationSettingsResult{
1151 {Error: apiservertesting.ErrUnauthorized},1176 {Error: apiservertesting.ErrUnauthorized},
1152 {Error: apiservertesting.ErrUnauthorized},1177 {Error: apiservertesting.ErrUnauthorized},
1153 {Error: &params.Error{Message: expectErr}},1178 {Error: &params.Error{Message: expectErr}},
@@ -1182,15 +1207,42 @@
1182 }}}1207 }}}
1183 result, err = s.uniter.ReadRemoteSettings(args)1208 result, err = s.uniter.ReadRemoteSettings(args)
1184 c.Assert(err, gc.IsNil)1209 c.Assert(err, gc.IsNil)
1185 c.Assert(result, gc.DeepEquals, params.SettingsResults{1210 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{
1186 Results: []params.SettingsResult{1211 Results: []params.RelationSettingsResult{
1187 {Settings: params.Settings{1212 {Settings: params.RelationSettings{
1188 "other": "things",1213 "other": "things",
1189 }},1214 }},
1190 },1215 },
1191 })1216 })
1192}1217}
11931218
1219func (s *uniterSuite) TestReadRemoteSettingsWithNonStringValuesFails(c *gc.C) {
1220 rel := s.addRelation(c, "wordpress", "mysql")
1221 relUnit, err := rel.Unit(s.mysqlUnit)
1222 c.Assert(err, gc.IsNil)
1223 settings := map[string]interface{}{
1224 "other": "things",
1225 "invalid-bool": false,
1226 }
1227 err = relUnit.EnterScope(settings)
1228 c.Assert(err, gc.IsNil)
1229 s.assertInScope(c, relUnit, true)
1230
1231 args := params.RelationUnitPairs{RelationUnitPairs: []params.RelationUnitPair{{
1232 Relation: rel.Tag(),
1233 LocalUnit: "unit-wordpress-0",
1234 RemoteUnit: "unit-mysql-0",
1235 }}}
1236 expectErr := `unexpected relation setting "invalid-bool": expected string, got bool`
1237 result, err := s.uniter.ReadRemoteSettings(args)
1238 c.Assert(err, gc.IsNil)
1239 c.Assert(result, gc.DeepEquals, params.RelationSettingsResults{
1240 Results: []params.RelationSettingsResult{
1241 {Error: &params.Error{Message: expectErr}},
1242 },
1243 })
1244}
1245
1194func (s *uniterSuite) TestUpdateSettings(c *gc.C) {1246func (s *uniterSuite) TestUpdateSettings(c *gc.C) {
1195 rel := s.addRelation(c, "wordpress", "mysql")1247 rel := s.addRelation(c, "wordpress", "mysql")
1196 relUnit, err := rel.Unit(s.wordpressUnit)1248 relUnit, err := rel.Unit(s.wordpressUnit)
@@ -1202,7 +1254,7 @@
1202 err = relUnit.EnterScope(settings)1254 err = relUnit.EnterScope(settings)
1203 s.assertInScope(c, relUnit, true)1255 s.assertInScope(c, relUnit, true)
12041256
1205 newSettings := params.Settings{1257 newSettings := params.RelationSettings{
1206 "some": "different",1258 "some": "different",
1207 "other": "",1259 "other": "",
1208 }1260 }
12091261
=== modified file 'worker/uniter/context.go'
--- worker/uniter/context.go 2013-09-13 10:38:02 +0000
+++ worker/uniter/context.go 2013-09-26 17:24:28 +0000
@@ -275,7 +275,7 @@
275}275}
276276
277// SettingsMap is a map from unit name to relation settings.277// SettingsMap is a map from unit name to relation settings.
278type SettingsMap map[string]params.Settings278type SettingsMap map[string]params.RelationSettings
279279
280// ContextRelation is the implementation of jujuc.ContextRelation.280// ContextRelation is the implementation of jujuc.ContextRelation.
281type ContextRelation struct {281type ContextRelation struct {
@@ -367,7 +367,7 @@
367 return ctx.settings, nil367 return ctx.settings, nil
368}368}
369369
370func (ctx *ContextRelation) ReadSettings(unit string) (settings params.Settings, err error) {370func (ctx *ContextRelation) ReadSettings(unit string) (settings params.RelationSettings, err error) {
371 settings, member := ctx.members[unit]371 settings, member := ctx.members[unit]
372 if settings == nil {372 if settings == nil {
373 if settings = ctx.cache[unit]; settings == nil {373 if settings = ctx.cache[unit]; settings == nil {
374374
=== modified file 'worker/uniter/context_test.go'
--- worker/uniter/context_test.go 2013-09-17 03:12:12 +0000
+++ worker/uniter/context_test.go 2013-09-26 17:24:28 +0000
@@ -275,10 +275,10 @@
275 // Check that the changes to the local settings nodes have been discarded.275 // Check that the changes to the local settings nodes have been discarded.
276 node0, err = s.relctxs[0].Settings()276 node0, err = s.relctxs[0].Settings()
277 c.Assert(err, gc.IsNil)277 c.Assert(err, gc.IsNil)
278 c.Assert(node0.Map(), gc.DeepEquals, params.Settings{"relation-name": "db0"})278 c.Assert(node0.Map(), gc.DeepEquals, params.RelationSettings{"relation-name": "db0"})
279 node1, err = s.relctxs[1].Settings()279 node1, err = s.relctxs[1].Settings()
280 c.Assert(err, gc.IsNil)280 c.Assert(err, gc.IsNil)
281 c.Assert(node1.Map(), gc.DeepEquals, params.Settings{"relation-name": "db1"})281 c.Assert(node1.Map(), gc.DeepEquals, params.RelationSettings{"relation-name": "db1"})
282282
283 // Check that the changes have been written to state.283 // Check that the changes have been written to state.
284 settings0, err := s.relunits[0].ReadSettings("u/0")284 settings0, err := s.relunits[0].ReadSettings("u/0")
@@ -303,13 +303,13 @@
303 // Check that the changes to the local settings nodes are still there.303 // Check that the changes to the local settings nodes are still there.
304 node0, err = s.relctxs[0].Settings()304 node0, err = s.relctxs[0].Settings()
305 c.Assert(err, gc.IsNil)305 c.Assert(err, gc.IsNil)
306 c.Assert(node0.Map(), gc.DeepEquals, params.Settings{306 c.Assert(node0.Map(), gc.DeepEquals, params.RelationSettings{
307 "relation-name": "db0",307 "relation-name": "db0",
308 "baz": "3",308 "baz": "3",
309 })309 })
310 node1, err = s.relctxs[1].Settings()310 node1, err = s.relctxs[1].Settings()
311 c.Assert(err, gc.IsNil)311 c.Assert(err, gc.IsNil)
312 c.Assert(node1.Map(), gc.DeepEquals, params.Settings{312 c.Assert(node1.Map(), gc.DeepEquals, params.RelationSettings{
313 "relation-name": "db1",313 "relation-name": "db1",
314 "qux": "4",314 "qux": "4",
315 })315 })
@@ -383,13 +383,13 @@
383 "u/4": {"qux": "4"},383 "u/4": {"qux": "4"},
384 })384 })
385 c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/2", "u/4"})385 c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/2", "u/4"})
386 assertSettings := func(unit string, expect params.Settings) {386 assertSettings := func(unit string, expect params.RelationSettings) {
387 actual, err := ctx.ReadSettings(unit)387 actual, err := ctx.ReadSettings(unit)
388 c.Assert(err, gc.IsNil)388 c.Assert(err, gc.IsNil)
389 c.Assert(actual, gc.DeepEquals, expect)389 c.Assert(actual, gc.DeepEquals, expect)
390 }390 }
391 assertSettings("u/2", params.Settings{"baz": "2"})391 assertSettings("u/2", params.RelationSettings{"baz": "2"})
392 assertSettings("u/4", params.Settings{"qux": "4"})392 assertSettings("u/4", params.RelationSettings{"qux": "4"})
393393
394 // Send a second update; check that members are only added, not removed.394 // Send a second update; check that members are only added, not removed.
395 ctx.UpdateMembers(uniter.SettingsMap{395 ctx.UpdateMembers(uniter.SettingsMap{
@@ -400,10 +400,10 @@
400 c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1", "u/2", "u/3", "u/4"})400 c.Assert(ctx.UnitNames(), gc.DeepEquals, []string{"u/1", "u/2", "u/3", "u/4"})
401401
402 // Check that all settings remain cached.402 // Check that all settings remain cached.
403 assertSettings("u/1", params.Settings{"foo": "1"})403 assertSettings("u/1", params.RelationSettings{"foo": "1"})
404 assertSettings("u/2", params.Settings{"abc": "2"})404 assertSettings("u/2", params.RelationSettings{"abc": "2"})
405 assertSettings("u/3", params.Settings{"bar": "3"})405 assertSettings("u/3", params.RelationSettings{"bar": "3"})
406 assertSettings("u/4", params.Settings{"qux": "4"})406 assertSettings("u/4", params.RelationSettings{"qux": "4"})
407407
408 // Delete a member, and check that it is no longer a member...408 // Delete a member, and check that it is no longer a member...
409 ctx.DeleteMember("u/2")409 ctx.DeleteMember("u/2")
@@ -454,7 +454,7 @@
454 ctx.UpdateMembers(uniter.SettingsMap{"u/1": {"entirely": "different"}})454 ctx.UpdateMembers(uniter.SettingsMap{"u/1": {"entirely": "different"}})
455 m, err = ctx.ReadSettings("u/1")455 m, err = ctx.ReadSettings("u/1")
456 c.Assert(err, gc.IsNil)456 c.Assert(err, gc.IsNil)
457 c.Assert(m, gc.DeepEquals, params.Settings{"entirely": "different"})457 c.Assert(m, gc.DeepEquals, params.RelationSettings{"entirely": "different"})
458}458}
459459
460func (s *ContextRelationSuite) TestNonMemberCaching(c *gc.C) {460func (s *ContextRelationSuite) TestNonMemberCaching(c *gc.C) {
@@ -700,7 +700,7 @@
700 return context700 return context
701}701}
702702
703func convertSettings(settings params.Settings) map[string]interface{} {703func convertSettings(settings params.RelationSettings) map[string]interface{} {
704 result := make(map[string]interface{})704 result := make(map[string]interface{})
705 for k, v := range settings {705 for k, v := range settings {
706 result[k] = v706 result[k] = v
@@ -708,8 +708,8 @@
708 return result708 return result
709}709}
710710
711func convertMap(settingsMap map[string]interface{}) params.Settings {711func convertMap(settingsMap map[string]interface{}) params.RelationSettings {
712 result := make(params.Settings)712 result := make(params.RelationSettings)
713 for k, v := range settingsMap {713 for k, v := range settingsMap {
714 result[k] = v.(string)714 result[k] = v.(string)
715 }715 }
716716
=== modified file 'worker/uniter/jujuc/context.go'
--- worker/uniter/jujuc/context.go 2013-09-12 16:29:52 +0000
+++ worker/uniter/jujuc/context.go 2013-09-26 17:24:28 +0000
@@ -77,12 +77,12 @@
77 UnitNames() []string77 UnitNames() []string
7878
79 // ReadSettings returns the settings of any remote unit in the relation.79 // ReadSettings returns the settings of any remote unit in the relation.
80 ReadSettings(unit string) (params.Settings, error)80 ReadSettings(unit string) (params.RelationSettings, error)
81}81}
8282
83// Settings is implemented by types that manipulate unit settings.83// Settings is implemented by types that manipulate unit settings.
84type Settings interface {84type Settings interface {
85 Map() params.Settings85 Map() params.RelationSettings
86 Set(string, string)86 Set(string, string)
87 Delete(string)87 Delete(string)
88}88}
8989
=== modified file 'worker/uniter/jujuc/relation-get.go'
--- worker/uniter/jujuc/relation-get.go 2013-09-12 16:29:52 +0000
+++ worker/uniter/jujuc/relation-get.go 2013-09-26 17:24:28 +0000
@@ -78,7 +78,7 @@
78 if !found {78 if !found {
79 return fmt.Errorf("unknown relation id")79 return fmt.Errorf("unknown relation id")
80 }80 }
81 var settings params.Settings81 var settings params.RelationSettings
82 if c.UnitName == c.ctx.UnitName() {82 if c.UnitName == c.ctx.UnitName() {
83 node, err := r.Settings()83 node, err := r.Settings()
84 if err != nil {84 if err != nil {
8585
=== modified file 'worker/uniter/jujuc/util_test.go'
--- worker/uniter/jujuc/util_test.go 2013-09-12 16:29:52 +0000
+++ worker/uniter/jujuc/util_test.go 2013-09-26 17:24:28 +0000
@@ -166,7 +166,7 @@
166 return s166 return s
167}167}
168168
169func (r *ContextRelation) ReadSettings(name string) (params.Settings, error) {169func (r *ContextRelation) ReadSettings(name string) (params.RelationSettings, error) {
170 s, found := r.units[name]170 s, found := r.units[name]
171 if !found {171 if !found {
172 return nil, fmt.Errorf("unknown unit %s", name)172 return nil, fmt.Errorf("unknown unit %s", name)
@@ -174,7 +174,7 @@
174 return s.Map(), nil174 return s.Map(), nil
175}175}
176176
177type Settings params.Settings177type Settings params.RelationSettings
178178
179func (s Settings) Get(k string) (interface{}, bool) {179func (s Settings) Get(k string) (interface{}, bool) {
180 v, f := s[k]180 v, f := s[k]
@@ -189,8 +189,8 @@
189 delete(s, k)189 delete(s, k)
190}190}
191191
192func (s Settings) Map() params.Settings {192func (s Settings) Map() params.RelationSettings {
193 r := params.Settings{}193 r := params.RelationSettings{}
194 for k, v := range s {194 for k, v := range s {
195 r[k] = v195 r[k] = v
196 }196 }

Subscribers

People subscribed via source and target branches

to status/vote changes: