Merge lp:~dave-cheney/juju-core/go-cmd-juju-status-plus-plus into lp:~juju/juju-core/trunk

Proposed by Dave Cheney
Status: Rejected
Rejected by: Dave Cheney
Proposed branch: lp:~dave-cheney/juju-core/go-cmd-juju-status-plus-plus
Merge into: lp:~juju/juju-core/trunk
Prerequisite: lp:~dave-cheney/juju-core/go-cmd-status-machine-versions
Diff against target: 291 lines (+180/-34)
2 files modified
cmd/juju/status.go (+84/-34)
cmd/juju/status_test.go (+96/-0)
To merge this branch: bzr merge lp:~dave-cheney/juju-core/go-cmd-juju-status-plus-plus
Reviewer Review Type Date Requested Status
The Go Language Gophers Pending
Review via email: mp+117100@code.launchpad.net

Description of the change

cmd/juju: status: gather unit information

Add basic support for units, and some cleanups.

https://codereview.appspot.com/6452056/

To post a comment you must log in.
Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

LGTM

https://codereview.appspot.com/6452056/diff/2001/cmd/juju/status.go
File cmd/juju/status.go (right):

https://codereview.appspot.com/6452056/diff/2001/cmd/juju/status.go#newcode216
cmd/juju/status.go:216: // TODO(dfc) we could make this nicer, ie
machine/0
I'd do "m-0", but unfortunately it's a bit late. :-(

https://codereview.appspot.com/6452056/diff/2001/cmd/juju/status.go#newcode225
cmd/juju/status.go:225: AgentVersion() (version.Version, error)
Same comment regarding winning the race.

https://codereview.appspot.com/6452056/diff/2001/cmd/juju/status.go#newcode264
cmd/juju/status.go:264: func chkError(m map[string]interface{}, err
error) map[string]interface{} {
s/chkError/checkError/

https://codereview.appspot.com/6452056/

351. By Dave Cheney

merge from trunk

Unmerged revisions

351. By Dave Cheney

merge from trunk

350. By Dave Cheney

cleanup

349. By Dave Cheney

added units

348. By Dave Cheney

added error checking

347. By Roger Peppe

container: add ToolsDir method

This allows the machine agent to copy tools into the correct directory
for a unit.

R=niemeyer
CC=
https://codereview.appspot.com/6441059

346. By William Reade

add new methods to RelationUnit

Endpoint is required to construct JUJU_RELATION for the unit agent
Relation is also required to construct JUJU_RELATION_ID for the unit agent
ReadSettings will be used by the unit agent to read settings for departed
units, and occasionally to populate cold settings caches.

R=niemeyer
CC=
https://codereview.appspot.com/6440050

345. By Roger Peppe

state: embed agentVersion into Unit

R=niemeyer
CC=
https://codereview.appspot.com/6449050

344. By Roger Peppe

state: add an agentVersion type and embed it into Machine.

R=niemeyer
CC=
https://codereview.appspot.com/6441053

343. By Roger Peppe

state: factor out getConfigString and setConfigString

This code was repeated in quite a few places with minor (and
IMHO mostly unjustified) variations. We're about to add more
calls (version and proposed-version), which hopefully should
justify this even more.

R=niemeyer
CC=
https://codereview.appspot.com/6442051

342. By Roger Peppe

state: move RelationScope type to charm.

Also make the schema error for OneOf a little
more useful.

R=niemeyer
CC=
https://codereview.appspot.com/6449043

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmd/juju/status.go'
2--- cmd/juju/status.go 2012-08-02 22:54:18 +0000
3+++ cmd/juju/status.go 2012-08-02 22:54:18 +0000
4@@ -9,6 +9,7 @@
5 "launchpad.net/juju-core/environs"
6 "launchpad.net/juju-core/juju"
7 "launchpad.net/juju-core/state"
8+ "launchpad.net/juju-core/version"
9 )
10
11 type StatusCommand struct {
12@@ -63,7 +64,7 @@
13 return err
14 }
15
16- result := make(map[string]interface{})
17+ result := m()
18
19 result["machines"], err = processMachines(machines, instances)
20 if err != nil {
21@@ -141,38 +142,22 @@
22 // yet the environ cannot find that id.
23 return nil, fmt.Errorf("instance %s for machine %d not found", instid, m.Id())
24 }
25- machine, err := processMachine(m, instance)
26- if err != nil {
27- machine = map[string]interface{}{
28- "status-error": err.Error(),
29- }
30- }
31- r[m.Id()] = machine
32+ r[m.Id()] = chkError(processMachine(m, instance))
33 }
34 }
35 return r, nil
36 }
37
38 func processMachine(machine *state.Machine, instance environs.Instance) (map[string]interface{}, error) {
39- r := make(map[string]interface{})
40+ r := m()
41 r["instance-id"] = instance.Id()
42
43 if dnsname, err := instance.DNSName(); err == nil {
44 r["dns-name"] = dnsname
45 }
46
47- if v, err := machine.AgentVersion(); err == nil {
48- r["agent-version"] = v.String()
49- }
50-
51- if v, err := machine.ProposedAgentVersion(); err == nil {
52- r["proposed-agent-version"] = v.String()
53- }
54-
55- if alive, err := machine.AgentAlive(); err == nil && alive {
56- // TODO(dfc) revisit this once unit-status is done
57- r["agent-state"] = "running"
58- }
59+ processVersion(r, machine)
60+ processAgentStatus(r, machine)
61
62 // TODO(dfc) unit-status
63 return r, nil
64@@ -180,32 +165,88 @@
65
66 // processServices gathers information about services.
67 func processServices(services map[string]*state.Service) (map[string]interface{}, error) {
68- r := make(map[string]interface{})
69+ r := m()
70 for _, s := range services {
71- service, err := processService(s)
72- if err != nil {
73- service = map[string]interface{}{
74- "status-error": err.Error(),
75- }
76- }
77- r[s.Name()] = service
78+ r[s.Name()] = chkError(processService(s))
79 }
80 return r, nil
81 }
82
83 func processService(service *state.Service) (map[string]interface{}, error) {
84- r := make(map[string]interface{})
85+ r := m()
86 ch, err := service.Charm()
87 if err != nil {
88 return nil, err
89 }
90 r["charm"] = ch.Meta().Name
91- r["exposed"], err = service.IsExposed()
92+
93+ if exposed, err := service.IsExposed(); err == nil {
94+ r["exposed"] = exposed
95+ }
96+
97+ // TODO(dfc) service.IsSubordinate() ?
98+
99+ units, err := service.AllUnits()
100 if err != nil {
101 return nil, err
102 }
103- // TODO(dfc) process units and relations
104- return r, nil
105+
106+ u := chkError(processUnits(units))
107+ if len(u) > 0 {
108+ r["units"] = u
109+ }
110+
111+ // TODO(dfc) process relations
112+ return r, nil
113+}
114+
115+func processUnits(units []*state.Unit) (map[string]interface{}, error) {
116+ r := m()
117+ for _, unit := range units {
118+ r[unit.Name()] = chkError(processUnit(unit))
119+ }
120+ return r, nil
121+}
122+
123+func processUnit(unit *state.Unit) (map[string]interface{}, error) {
124+ r := m()
125+
126+ if addr, err := unit.PublicAddress(); err == nil {
127+ r["public-address"] = addr
128+ }
129+
130+ if id, err := unit.AssignedMachineId(); err == nil {
131+ // TODO(dfc) we could make this nicer, ie machine/0
132+ r["machine"] = id
133+ }
134+
135+ processVersion(r, unit)
136+ return r, nil
137+}
138+
139+type versioned interface {
140+ AgentVersion() (version.Number, error)
141+ ProposedAgentVersion() (version.Number, error)
142+}
143+
144+func processVersion(r map[string]interface{}, v versioned) {
145+ if v, err := v.AgentVersion(); err == nil {
146+ r["agent-version"] = v.String()
147+ }
148+
149+ if v, err := v.ProposedAgentVersion(); err == nil {
150+ r["proposed-agent-version"] = v.String()
151+ }
152+}
153+
154+type agent interface {
155+ AgentAlive() (bool, error)
156+}
157+
158+func processAgentStatus(r map[string]interface{}, a agent) {
159+ if alive, err := a.AgentAlive(); err == nil && alive {
160+ r["agent-state"] = "running"
161+ }
162 }
163
164 // jsonify converts the keys of the machines map into their string
165@@ -213,10 +254,19 @@
166 func jsonify(r map[string]interface{}) map[string]map[string]interface{} {
167 m := map[string]map[string]interface{}{
168 "services": r["services"].(map[string]interface{}),
169- "machines": make(map[string]interface{}),
170+ "machines": m(),
171 }
172 for k, v := range r["machines"].(map[int]interface{}) {
173 m["machines"][strconv.Itoa(k)] = v
174 }
175 return m
176 }
177+
178+func m() map[string]interface{} { return make(map[string]interface{}) }
179+
180+func chkError(m map[string]interface{}, err error) map[string]interface{} {
181+ if err != nil {
182+ return map[string]interface{}{"status-error": err.Error()}
183+ }
184+ return m
185+}
186
187=== modified file 'cmd/juju/status_test.go'
188--- cmd/juju/status_test.go 2012-08-02 22:54:18 +0000
189+++ cmd/juju/status_test.go 2012-08-02 22:54:18 +0000
190@@ -181,6 +181,102 @@
191 },
192 },
193 },
194+ {
195+ "add two more machines for units",
196+ func(st *state.State, conn *juju.Conn, c *C) {
197+ for i := 1; i < 3; i++ {
198+ m, err := st.AddMachine()
199+ c.Assert(err, IsNil)
200+ c.Assert(m.Id(), Equals, i)
201+ inst, err := conn.Environ.StartInstance(m.Id(), nil)
202+ c.Assert(err, IsNil)
203+ err = m.SetInstanceId(inst.Id())
204+ c.Assert(err, IsNil)
205+ }
206+ },
207+ map[string]interface{}{
208+ "machines": map[int]interface{}{
209+ 0: map[string]interface{}{
210+ "dns-name": "palermo-0.dns",
211+ "instance-id": "palermo-0",
212+ "agent-version": "1.2.3",
213+ "proposed-agent-version": "2.0.3",
214+ },
215+ 1: map[string]interface{}{
216+ "dns-name": "palermo-1.dns",
217+ "instance-id": "palermo-1",
218+ },
219+ 2: map[string]interface{}{
220+ "dns-name": "palermo-2.dns",
221+ "instance-id": "palermo-2",
222+ },
223+ },
224+ "services": map[string]interface{}{
225+ "dummy-service": map[string]interface{}{
226+ "charm": "dummy",
227+ "exposed": false,
228+ },
229+ "exposed-service": map[string]interface{}{
230+ "charm": "dummy",
231+ "exposed": true,
232+ },
233+ },
234+ },
235+ },
236+ {
237+ "add units for services",
238+ func(st *state.State, conn *juju.Conn, c *C) {
239+ for i, n := range []string{"dummy-service", "exposed-service"} {
240+ s, err := st.Service(n)
241+ c.Assert(err, IsNil)
242+ u, err := s.AddUnit()
243+ c.Assert(err, IsNil)
244+ m, err := st.Machine(i + 1)
245+ c.Assert(err, IsNil)
246+ err = u.AssignToMachine(m)
247+ c.Assert(err, IsNil)
248+ }
249+ },
250+ map[string]interface{}{
251+ "machines": map[int]interface{}{
252+ 0: map[string]interface{}{
253+ "dns-name": "palermo-0.dns",
254+ "instance-id": "palermo-0",
255+ "agent-version": "1.2.3",
256+ "proposed-agent-version": "2.0.3",
257+ },
258+ 1: map[string]interface{}{
259+ "dns-name": "palermo-1.dns",
260+ "instance-id": "palermo-1",
261+ },
262+ 2: map[string]interface{}{
263+ "dns-name": "palermo-2.dns",
264+ "instance-id": "palermo-2",
265+ },
266+ },
267+ "services": map[string]interface{}{
268+ "exposed-service": map[string]interface{}{
269+ "exposed": true,
270+ "units": map[string]interface{}{
271+ "exposed-service/0": map[string]interface{}{
272+ "machine": 2,
273+ },
274+ },
275+ "charm": "dummy",
276+ },
277+ "dummy-service": map[string]interface{}{
278+ "charm": "dummy",
279+ "exposed": false,
280+ "units": map[string]interface{}{
281+ "dummy-service/0": map[string]interface{}{
282+ "machine": 1,
283+ },
284+ },
285+ },
286+ },
287+ },
288+ },
289+
290 // TODO(dfc) test failing components by destructively mutating zk under the hood
291 }
292

Subscribers

People subscribed via source and target branches