Merge lp:~menno.smits/juju-core/1194481-relation_name_in_status.0 into lp:~go-bot/juju-core/trunk

Proposed by Menno Finlay-Smits on 2014-05-18
Status: Work in progress
Proposed branch: lp:~menno.smits/juju-core/1194481-relation_name_in_status.0
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 266 lines (+68/-18)
4 files modified
state/api/client.go (+8/-0)
state/apiserver/client/api_test.go (+26/-7)
state/apiserver/client/perm_test.go (+2/-2)
state/apiserver/client/status.go (+32/-9)
To merge this branch: bzr merge lp:~menno.smits/juju-core/1194481-relation_name_in_status.0
Reviewer Review Type Date Requested Status
Juju Engineering 2014-05-18 Pending
Review via email: mp+219973@code.launchpad.net

Description of the change

state/api{,server}: more info from FullStatus API

Machines and units now have a StatusData map in the FullStatus API
response which holds extra status information that a client may choose
to use when displaying status. This was already being created but
wasn't through the client API.

The FullStatus response now also includes a map of relation id to
relation data (currently just the relation key). This can be used to
present a user friendly relation name to users (e.g. the StatusData
dict contains the relation id when a relation hook fails)

These new bits of data will be used to display the relation name in
the "juju status" output when a relation hook fails.

The client API test scenario has been extended to include a case of a
unit with an error with extra status data included.

https://codereview.appspot.com/93480044/

To post a comment you must log in.
Menno Finlay-Smits (menno.smits) wrote :
Download full text (7.0 KiB)

Reviewers: mp+219973_code.launchpad.net,

Message:
Please take a look.

Description:
state/api{,server}: StatusData through client API

Machines and units have a StatusData map which hold extra status
information that a client may use when displaying status but this
wasn't being passed through the client API.

The change is generally useful but is specifically required to support
reporting of the affected relation when a hook fails (coming soon).

The client API test scenario has been extended to include a case of a
unit with an error with status data included.

https://code.launchpad.net/~menno.smits/juju-core/1194481-relation_name_in_status.0/+merge/219973

(do not edit description out of merge proposal)

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

Affected files (+33, -12 lines):
   A [revision details]
   M state/api/client.go
   M state/apiserver/client/api_test.go
   M state/apiserver/client/perm_test.go
   M state/apiserver/client/status.go

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

Index: state/api/client.go
=== modified file 'state/api/client.go'
--- state/api/client.go 2014-05-13 04:30:48 +0000
+++ state/api/client.go 2014-05-16 04:14:32 +0000
@@ -50,6 +50,7 @@
   Err error
   AgentState params.Status
   AgentStateInfo string
+ AgentStateData params.StatusData
   AgentVersion string
   DNSName string
   InstanceId instance.Id
@@ -82,6 +83,7 @@
   Err error
   AgentState params.Status
   AgentStateInfo string
+ AgentStateData params.StatusData
   AgentVersion string
   Life string
   Machine string

Index: state/apiserver/client/api_test.go
=== modified file 'state/apiserver/client/api_test.go'
--- state/apiserver/client/api_test.go 2014-05-13 04:30:48 +0000
+++ state/apiserver/client/api_test.go 2014-05-16 04:14:32 +0000
@@ -152,6 +152,7 @@
     InstanceId: instance.Id("i-machine-0"),
     AgentState: "down",
     AgentStateInfo: "(started)",
+ AgentStateData: params.StatusData{},
     Series: "quantal",
     Containers: map[string]api.MachineStatus{},
     Jobs: []params.MachineJob{params.JobManageEnviron},
@@ -163,6 +164,7 @@
     InstanceId: instance.Id("i-machine-1"),
     AgentState: "down",
     AgentStateInfo: "(started)",
+ AgentStateData: params.StatusData{},
     Series: "quantal",
     Containers: map[string]api.MachineStatus{},
     Jobs: []params.MachineJob{params.JobHostUnits},
@@ -174,6 +176,7 @@
     InstanceId: instance.Id("i-machine-2"),
     AgentState: "down",
     AgentStateInfo: "(started)",
+ AgentStateData: params.StatusData{},
     Series: "quantal",
     Containers: map[string]api.MachineStatus{},
     Jobs: []params.MachineJob{params.JobHostUnits},
@@ -203,20 +206,25 @@
     SubordinateTo: []string{},
     Units: map[string]api.UnitStatus{
      "wordpress/0": api.UnitSta...

Read more...

William Reade (fwereade) wrote :

I don't think this quite works. It's not about just dumping the internal
state in front of the user and letting them figure it out, it's about
helping them figure out what the problem is.

To be fair, I'm not sure how to show it cleanly (and machine-parseably);
I can come on tonight for a chat if you like.

https://codereview.appspot.com/93480044/diff/1/state/apiserver/client/api_test.go
File state/apiserver/client/api_test.go (right):

https://codereview.appspot.com/93480044/diff/1/state/apiserver/client/api_test.go#newcode211
state/apiserver/client/api_test.go:211: AgentStateData:
params.StatusData{"foo": "bar"},
How does this look in practice? The repetition of the failed hook is
going to be a bit stuttery. And... where in the rest of status do we
output relation ids? I'm not sure we ever even accept them on the
command line. I think we need relation names, and not to expose
status-data at all: if its contents go straight into the user's face we
have much less freedom about how we actually use it in future.

https://codereview.appspot.com/93480044/

William Reade (fwereade) wrote :

I know we need to keep the "(status: info)" bit for old clients, but I
thought we were going to do it properly as well? Otherwise looks good.

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go
File state/api/client.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go#newcode114
state/api/client.go:114: Relations map[string]RelationStatus
so we're turning int ids into strings to satisfy json? fair enough, I
guess, but I have a bit of the same old "eww" reaction.

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go
File state/apiserver/client/api_test.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go#newcode211
state/apiserver/client/api_test.go:211: AgentStateData:
params.StatusData{"foo": "bar"},
Were we going to add the components of the "(error: blam)" stuff into
StatusData (or something similar)?

The contents of StatusData are technically arbitrary, but they're
actually pretty well-defined. We could tighten them up to prevent key
collisions with whatever we pick; or we could put the arbitrary data
into its own dict?

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/status.go
File state/apiserver/client/status.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/status.go#newcode536
state/apiserver/client/status.go:536: subordSet.Add(ep.ServiceName)
I was thinking it might be simpler to keep all the relation processing
together, but then I realised that, no, we need to have all the
relations and all the services in memory together before we can do it
smartly.

https://codereview.appspot.com/93480044/

Menno Finlay-Smits (menno.smits) wrote :

Replies inline.

Given that there is another branch in the works which builds on this
one, adding the extra items to StatusData when required and actually
using them in the client, what's still needed to get this branch ready
for landing?

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go
File state/api/client.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go#newcode114
state/api/client.go:114: Relations map[string]RelationStatus
On 2014/05/26 06:45:34, fwereade wrote:
> so we're turning int ids into strings to satisfy json? fair enough, I
guess, but
> I have a bit of the same old "eww" reaction.

I discovered the hard way what happens if you try to serialise map[int]
over the API: seemingly hung tests (perhaps due to API retries?)

I didn't like converting the relation ids to strings much either. I was
considering making Relations a []RelationStatus instead and including Id
in RelationStatus. That way the client may end up generating a map
itself which is bit crappy but hey. Would that be preferable?

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go
File state/apiserver/client/api_test.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go#newcode211
state/apiserver/client/api_test.go:211: AgentStateData:
params.StatusData{"foo": "bar"},
On 2014/05/26 06:45:34, fwereade wrote:
> Were we going to add the components of the "(error: blam)" stuff into
StatusData
> (or something similar)?

Yes that's coming (in a separate branch). This branch is just about
getting the supporting infrastructure in place.

The test data here isn't realistic. This test is just checking that
StatusData is making it where it should the status response.

> The contents of StatusData are technically arbitrary, but they're
actually
> pretty well-defined. We could tighten them up to prevent key
collisions with
> whatever we pick; or we could put the arbitrary data into its own
dict?

Agreed that we should be careful about what we put in StatusData. How
about namespacing the keys along the lines of "category.item" to help
avoid collisions?

https://codereview.appspot.com/93480044/

William Reade (fwereade) wrote :

LGTM with relation ids in the array (assuming followups as discussed).

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go
File state/api/client.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go#newcode114
state/api/client.go:114: Relations map[string]RelationStatus
On 2014/05/26 21:47:43, menn0 wrote:
> On 2014/05/26 06:45:34, fwereade wrote:
> > so we're turning int ids into strings to satisfy json? fair enough,
I guess,
> but
> > I have a bit of the same old "eww" reaction.

> I discovered the hard way what happens if you try to serialise
map[int] over the
> API: seemingly hung tests (perhaps due to API retries?)

> I didn't like converting the relation ids to strings much either. I
was
> considering making Relations a []RelationStatus instead and including
Id in
> RelationStatus. That way the client may end up generating a map itself
which is
> bit crappy but hey. Would that be preferable?

Hmm... yeah, I think it probably would. I also find myself wondering
whether we should actually be representing the endpoint data as well,
lest clients have to mess around parsing keys? Don't let this block you,
it's addressable in a followup, but take a quick look at the AddRelation
API: what we chose there *may* have bearing on what we should expose
here.

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go
File state/apiserver/client/api_test.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go#newcode211
state/apiserver/client/api_test.go:211: AgentStateData:
params.StatusData{"foo": "bar"},
On 2014/05/26 21:47:43, menn0 wrote:
> On 2014/05/26 06:45:34, fwereade wrote:
> > Were we going to add the components of the "(error: blam)" stuff
into
> StatusData
> > (or something similar)?

> Yes that's coming (in a separate branch). This branch is just about
getting the
> supporting infrastructure in place.

Great, sorry for the confusion, I fear you will have to get used to me
asking stupid questions to which I should already know the answers :).

> The test data here isn't realistic. This test is just checking that
StatusData
> is making it where it should the status response.

> > The contents of StatusData are technically arbitrary, but they're
actually
> > pretty well-defined. We could tighten them up to prevent key
collisions with
> > whatever we pick; or we could put the arbitrary data into its own
dict?

> Agreed that we should be careful about what we put in StatusData. How
about
> namespacing the keys along the lines of "category.item" to help avoid
> collisions?

Depends what we mean by StatusData -- the stuff that gets set by the
agent, or the stuff we return over status? For the latter, I think it
may be better to separate the explicitly-set-by-agent bits from the
also-relevant-to-status bits.

https://codereview.appspot.com/93480044/

Menno Finlay-Smits (menno.smits) wrote :
Download full text (3.3 KiB)

Replies to latest review comments in-line.

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go
File state/api/client.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go#newcode114
state/api/client.go:114: Relations map[string]RelationStatus
> Hmm... yeah, I think it probably would. I also find myself wondering
whether we
> should actually be representing the endpoint data as well, lest
clients have to
> mess around parsing keys? Don't let this block you, it's addressable
in a
> followup, but take a quick look at the AddRelation API: what we chose
there
> *may* have bearing on what we should expose here.

Funnily enough, my initial implementation did include endpoint data in
RelationStatus but I removed it because the data was mostly repeating
what was already in the relation name. I'm happy to put this back in
though.

Looking at the AddRelation API, it returns a map[string]charm.Relation
where the key is the service name. I'm not sure that it makes sense for
RelationStatus to represent endpoints in a map - a slice probably makes
more sense.

How about each RelationStatus holds a slice of EndpointStatus structs
which have a subset of what AddRelation returns? The EndpointStatus
fields would be something like:

   ServiceName string
   Interface string
   Role charm.RelationRole (string)

How does that sound?

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go
File state/apiserver/client/api_test.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go#newcode211
state/apiserver/client/api_test.go:211: AgentStateData:
params.StatusData{"foo": "bar"},
On 2014/05/28 08:52:38, fwereade wrote:
> On 2014/05/26 21:47:43, menn0 wrote:
> > On 2014/05/26 06:45:34, fwereade wrote:
> > > Were we going to add the components of the "(error: blam)" stuff
into
> > StatusData
> > > (or something similar)?
> >
> > Yes that's coming (in a separate branch). This branch is just about
getting
> the
> > supporting infrastructure in place.

> Great, sorry for the confusion, I fear you will have to get used to me
asking
> stupid questions to which I should already know the answers :).

> > The test data here isn't realistic. This test is just checking that
StatusData
> > is making it where it should the status response.
> >
> > > The contents of StatusData are technically arbitrary, but they're
actually
> > > pretty well-defined. We could tighten them up to prevent key
collisions with
> > > whatever we pick; or we could put the arbitrary data into its own
dict?
> >
> > Agreed that we should be careful about what we put in StatusData.
How about
> > namespacing the keys along the lines of "category.item" to help
avoid
> > collisions?

> Depends what we mean by StatusData -- the stuff that gets set by the
agent, or
> the stuff we return over status? For the latter, I think it may be
better to
> separate the explicitly-set-by-agent bits from the
also-relevant-to-status bits.

I haven't been making a distinction - these changes currently let the
StatusData-as-set-by-the-agent straight out - but I guess we probably
should to ensur...

Read more...

William Reade (fwereade) wrote :
Download full text (4.3 KiB)

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go
File state/api/client.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/api/client.go#newcode114
state/api/client.go:114: Relations map[string]RelationStatus
On 2014/06/03 11:57:09, menn0 wrote:
> > Hmm... yeah, I think it probably would. I also find myself wondering
whether
> we
> > should actually be representing the endpoint data as well, lest
clients have
> to
> > mess around parsing keys? Don't let this block you, it's addressable
in a
> > followup, but take a quick look at the AddRelation API: what we
chose there
> > *may* have bearing on what we should expose here.

> Funnily enough, my initial implementation did include endpoint data in
> RelationStatus but I removed it because the data was mostly repeating
what was
> already in the relation name. I'm happy to put this back in though.

> Looking at the AddRelation API, it returns a map[string]charm.Relation
where the
> key is the service name. I'm not sure that it makes sense for
RelationStatus to
> represent endpoints in a map - a slice probably makes more sense.

> How about each RelationStatus holds a slice of EndpointStatus structs
which have
> a subset of what AddRelation returns? The EndpointStatus fields would
be
> something like:

> ServiceName string
> Interface string
> Role charm.RelationRole (string)

> How does that sound?

SGTM, but let's also record the relation scope (it should match across
the endpoints, so I think it's relation-level status).

Also, please see if you can think of a nice way to show which (if any)
is the subordinate in a given relation.(It's potentially subtle: if foo
is subordinate to bar via some locally-scoped relation, it's only
subordinate in the context of that relation: it can have a perfectly
good global relation with some other service.) This information is
encoded elsewhere in status output, though, so it's optional to some
degree; but it might be a cleaner way of doing some things, so bear it
in mind.

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go
File state/apiserver/client/api_test.go (right):

https://codereview.appspot.com/93480044/diff/20001/state/apiserver/client/api_test.go#newcode211
state/apiserver/client/api_test.go:211: AgentStateData:
params.StatusData{"foo": "bar"},
On 2014/06/03 11:57:09, menn0 wrote:
> On 2014/05/28 08:52:38, fwereade wrote:
> > On 2014/05/26 21:47:43, menn0 wrote:
> > > On 2014/05/26 06:45:34, fwereade wrote:
> > > > Were we going to add the components of the "(error: blam)" stuff
into
> > > StatusData
> > > > (or something similar)?
> > >
> > > Yes that's coming (in a separate branch). This branch is just
about getting
> > the
> > > supporting infrastructure in place.
> >
> > Great, sorry for the confusion, I fear you will have to get used to
me asking
> > stupid questions to which I should already know the answers :).
> >
> > > The test data here isn't realistic. This test is just checking
that
> StatusData
> > > is making it where it should the status response.
> > >
> > > > The contents of StatusData are technically arbitrary, but
they're actually
> ...

Read more...

Unmerged revisions

2735. By Menno Finlay-Smits on 2014-05-26

Return relation map in status API response

This can be helpful for clients wishing to display the relation name
when, for example, relation hooks fail (coming soon).

2734. By Menno Finlay-Smits on 2014-05-22

Merged from trunk

2733. By Menno Finlay-Smits on 2014-05-16

Pass Machine and Unit StatusData through the client API

This is generally useful but is also specifically required to support
reporting of the affected relation when a hook fails.

The client API test scenario has been extended to include a case of a
unit with an error with status data included.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'state/api/client.go'
2--- state/api/client.go 2014-05-13 04:30:48 +0000
3+++ state/api/client.go 2014-05-26 05:45:28 +0000
4@@ -50,6 +50,7 @@
5 Err error
6 AgentState params.Status
7 AgentStateInfo string
8+ AgentStateData params.StatusData
9 AgentVersion string
10 DNSName string
11 InstanceId instance.Id
12@@ -82,6 +83,7 @@
13 Err error
14 AgentState params.Status
15 AgentStateInfo string
16+ AgentStateData params.StatusData
17 AgentVersion string
18 Life string
19 Machine string
20@@ -91,6 +93,11 @@
21 Subordinates map[string]UnitStatus
22 }
23
24+// RelationStatus holds status info about a relation.
25+type RelationStatus struct {
26+ Key string
27+}
28+
29 // NetworkStatus holds status info about a network.
30 type NetworkStatus struct {
31 Err error
32@@ -104,6 +111,7 @@
33 EnvironmentName string
34 Machines map[string]MachineStatus
35 Services map[string]ServiceStatus
36+ Relations map[string]RelationStatus
37 Networks map[string]NetworkStatus
38 }
39
40
41=== modified file 'state/apiserver/client/api_test.go'
42--- state/apiserver/client/api_test.go 2014-05-13 04:30:48 +0000
43+++ state/apiserver/client/api_test.go 2014-05-26 05:45:28 +0000
44@@ -152,6 +152,7 @@
45 InstanceId: instance.Id("i-machine-0"),
46 AgentState: "down",
47 AgentStateInfo: "(started)",
48+ AgentStateData: params.StatusData{},
49 Series: "quantal",
50 Containers: map[string]api.MachineStatus{},
51 Jobs: []params.MachineJob{params.JobManageEnviron},
52@@ -163,6 +164,7 @@
53 InstanceId: instance.Id("i-machine-1"),
54 AgentState: "down",
55 AgentStateInfo: "(started)",
56+ AgentStateData: params.StatusData{},
57 Series: "quantal",
58 Containers: map[string]api.MachineStatus{},
59 Jobs: []params.MachineJob{params.JobHostUnits},
60@@ -174,6 +176,7 @@
61 InstanceId: instance.Id("i-machine-2"),
62 AgentState: "down",
63 AgentStateInfo: "(started)",
64+ AgentStateData: params.StatusData{},
65 Series: "quantal",
66 Containers: map[string]api.MachineStatus{},
67 Jobs: []params.MachineJob{params.JobHostUnits},
68@@ -203,26 +206,36 @@
69 SubordinateTo: []string{},
70 Units: map[string]api.UnitStatus{
71 "wordpress/0": api.UnitStatus{
72- AgentState: "pending",
73- Machine: "1",
74+ AgentState: "down",
75+ AgentStateInfo: "(error: blam)",
76+ AgentStateData: params.StatusData{"foo": "bar"},
77+ Machine: "1",
78 Subordinates: map[string]api.UnitStatus{
79 "logging/0": api.UnitStatus{
80- AgentState: "pending",
81+ AgentState: "pending",
82+ AgentStateData: params.StatusData{},
83 },
84 },
85 },
86 "wordpress/1": api.UnitStatus{
87- AgentState: "pending",
88- Machine: "2",
89+ AgentState: "pending",
90+ AgentStateData: params.StatusData{},
91+ Machine: "2",
92 Subordinates: map[string]api.UnitStatus{
93 "logging/1": api.UnitStatus{
94- AgentState: "pending",
95+ AgentState: "pending",
96+ AgentStateData: params.StatusData{},
97 },
98 },
99 },
100 },
101 },
102 },
103+ Relations: map[string]api.RelationStatus{
104+ "0": api.RelationStatus{
105+ Key: "logging:logging-directory wordpress:logging-dir",
106+ },
107+ },
108 Networks: map[string]api.NetworkStatus{},
109 }
110
111@@ -252,7 +265,8 @@
112 // service-wordpress
113 // service-logging
114 // unit-wordpress-0
115-// deployer-name=machine-1
116+// deployer-name=machine-1
117+// status=down with error and status data attached
118 // unit-logging-0
119 // deployer-name=unit-wordpress-0
120 // unit-wordpress-1
121@@ -328,6 +342,11 @@
122 wru, err := rel.Unit(wu)
123 c.Assert(err, gc.IsNil)
124
125+ if i == 0 {
126+ sd := params.StatusData{"foo": "bar"}
127+ wu.SetStatus(params.StatusError, "blam", sd)
128+ }
129+
130 // Create the subordinate unit as a side-effect of entering
131 // scope in the principal's relation-unit.
132 err = wru.EnterScope(nil)
133
134=== modified file 'state/apiserver/client/perm_test.go'
135--- state/apiserver/client/perm_test.go 2014-04-03 15:14:21 +0000
136+++ state/apiserver/client/perm_test.go 2014-05-26 05:45:28 +0000
137@@ -279,7 +279,7 @@
138 }
139
140 func opClientResolved(c *gc.C, st *api.State, _ *state.State) (func(), error) {
141- err := st.Client().Resolved("wordpress/0", false)
142+ err := st.Client().Resolved("wordpress/1", false)
143 // There are several scenarios in which this test is called, one is
144 // that the user is not authorized. In that case we want to exit now,
145 // letting the error percolate out so the caller knows that the
146@@ -292,7 +292,7 @@
147 // the error. Therefore, since it is complaining it means that the
148 // call to Resolved worked, so we're happy.
149 c.Assert(err, gc.NotNil)
150- c.Assert(err.Error(), gc.Equals, `unit "wordpress/0" is not in an error state`)
151+ c.Assert(err.Error(), gc.Equals, `unit "wordpress/1" is not in an error state`)
152 return func() {}, nil
153 }
154
155
156=== modified file 'state/apiserver/client/status.go'
157--- state/apiserver/client/status.go 2014-05-22 03:06:00 +0000
158+++ state/apiserver/client/status.go 2014-05-26 05:45:28 +0000
159@@ -7,6 +7,7 @@
160 "fmt"
161 "path"
162 "regexp"
163+ "strconv"
164 "strings"
165
166 "github.com/juju/errors"
167@@ -60,6 +61,7 @@
168 EnvironmentName: conn.Environ.Name(),
169 Machines: context.processMachines(),
170 Services: context.processServices(),
171+ Relations: context.processRelations(),
172 Networks: context.processNetworks(),
173 }, nil
174 }
175@@ -284,10 +286,10 @@
176
177 // fetchRelations returns a map of all relations keyed by service name.
178 //
179-// This structure is useful for processRelations() which needs to have
180-// the relations for each service. Reading them once here avoids the
181-// repeated DB hits to retrieve the relations for each service that
182-// used to happen in processRelations().
183+// This structure is useful for processServiceRelations() which needs
184+// to have the relations for each service. Reading them once here
185+// avoids the repeated DB hits to retrieve the relations for each
186+// service that used to happen in processServiceRelations().
187 func fetchRelations(st *state.State) (map[string][]*state.Relation, error) {
188 relations, err := st.AllRelations()
189 if err != nil {
190@@ -353,6 +355,7 @@
191 status.AgentVersion,
192 status.AgentState,
193 status.AgentStateInfo,
194+ status.AgentStateData,
195 status.Err = processAgent(machine)
196 status.Series = machine.Series()
197 status.Jobs = paramsJobsFromJobs(machine.Jobs())
198@@ -390,6 +393,23 @@
199 return
200 }
201
202+func (context *statusContext) processRelations() map[string]api.RelationStatus {
203+ out := make(map[string]api.RelationStatus)
204+ for _, relations := range context.relations {
205+ for _, relation := range relations {
206+ relationId := strconv.Itoa(relation.Id())
207+ // relations will appear multiple times in
208+ // context.relations so skip if we've already seen one
209+ if _, found := out[relationId]; !found {
210+ out[relationId] = api.RelationStatus{
211+ Key: relation.String(),
212+ }
213+ }
214+ }
215+ }
216+ return out
217+}
218+
219 func (context *statusContext) processNetworks() map[string]api.NetworkStatus {
220 networksMap := make(map[string]api.NetworkStatus)
221 for name, network := range context.networks {
222@@ -434,7 +454,7 @@
223 status.CanUpgradeTo = latestCharm
224 }
225 var err error
226- status.Relations, status.SubordinateTo, err = context.processRelations(service)
227+ status.Relations, status.SubordinateTo, err = context.processServiceRelations(service)
228 if err != nil {
229 status.Err = err
230 return
231@@ -476,6 +496,7 @@
232 status.AgentVersion,
233 status.AgentState,
234 status.AgentStateInfo,
235+ status.AgentStateData,
236 status.Err = processAgent(unit)
237 if subUnits := unit.SubordinateNames(); len(subUnits) > 0 {
238 status.Subordinates = make(map[string]api.UnitStatus)
239@@ -495,7 +516,8 @@
240 return context.units[serviceName][name]
241 }
242
243-func (context *statusContext) processRelations(service *state.Service) (related map[string][]string, subord []string, err error) {
244+func (context *statusContext) processServiceRelations(service *state.Service) (
245+ related map[string][]string, subord []string, err error) {
246 var subordSet set.Strings
247 related = make(map[string][]string)
248 relations := context.relations[service.Name()]
249@@ -536,13 +558,14 @@
250
251 // processAgent retrieves version and status information from the given entity
252 // and sets the destination version, status and info values accordingly.
253-func processAgent(entity stateAgent) (life string, version string, status params.Status, info string, err error) {
254+func processAgent(entity stateAgent) (
255+ life string, version string, status params.Status, info string, statusData params.StatusData, err error,
256+) {
257 life = processLife(entity)
258 if t, err := entity.AgentTools(); err == nil {
259 version = t.Version.Number.String()
260 }
261- // TODO(mue) StatusData may be useful here too.
262- status, info, _, err = entity.Status()
263+ status, info, statusData, err = entity.Status()
264 if err != nil {
265 return
266 }

Subscribers

People subscribed via source and target branches

to status/vote changes: