Merge lp:~hatch/juju-gui/inspector-relation-status into lp:juju-gui/experimental
- inspector-relation-status
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 1212 |
Proposed branch: | lp:~hatch/juju-gui/inspector-relation-status |
Merge into: | lp:juju-gui/experimental |
Diff against target: |
306 lines (+82/-88) 8 files modified
app/models/models.js (+31/-22) app/templates/service-relations-list.handlebars (+1/-1) app/templates/service-relations-viewlet.handlebars (+1/-1) app/templates/service-relations.handlebars (+0/-40) app/views/utils.js (+6/-0) app/views/viewlets/service-relations.js (+3/-7) lib/views/juju-inspector.less (+11/-0) test/test_model.js (+29/-17) |
To merge this branch: | bzr merge lp:~hatch/juju-gui/inspector-relation-status |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju GUI Hackers | Pending | ||
Review via email: mp+196770@code.launchpad.net |
Commit message
Description of the change
Adds relation status to inspector relation panel
The overall relation status is now indicated on the inspector relation
panel using the same icons as the unit status. If any unit has a relation
error the entire relation is shown as in error.
Jeff Pihach (hatch) wrote : | # |
Jeff Pihach (hatch) wrote : | # |
reviewer notes
https:/
File app/templates/
https:/
app/templates/
Template from old inspector
Jeff Pihach (hatch) wrote : | # |
Please take a look.
- 1214. By Jeff Pihach
-
fixed issue where the first error status delta would get ignored for relation errors
Jeff Pihach (hatch) wrote : | # |
reviewer notes v2
https:/
File app/models/
https:/
app/models/
Fix for bug from first rev (see test_model)
https:/
File test/test_model.js (right):
https:/
test/test_
The order of these is important to make sure that the first unit error,
if it's a relation error gets caught properly (bug from first rev)
Gary Poster (gary) wrote : | # |
LGTM with trivials and sandbox QA good. waiting on QA on ec2.
https:/
File app/models/
https:/
app/models/
and relation errors
Thank you for improving names and docs. Nice.
https:/
app/models/
this code fixes peer relation issues?
https:/
File test/test_model.js (right):
https:/
test/test_
On 2013/11/26 20:42:45, jeff.pihach wrote:
> The order of these is important to make sure that the first unit
error, if it's
> a relation error gets caught properly (bug from first rev)
In that case could you elaborate in a code comment what's going on? All
I see in the code is "one of these has a relation error and one has an
install error," not something subtle about ordering.
Gary Poster (gary) wrote : | # |
QA OK on real environment also. Thanks! These are really cool changes
you are making.
Jeff Pihach (hatch) wrote : | # |
Thanks for the review! Changes landing
https:/
File test/test_model.js (right):
https:/
test/test_
good call, done
Jeff Pihach (hatch) wrote : | # |
*** Submitted:
Adds relation status to inspector relation panel
The overall relation status is now indicated on the inspector relation
panel using the same icons as the unit status. If any unit has a
relation
error the entire relation is shown as in error.
R=gary.poster
CC=
https:/
Preview Diff
1 | === modified file 'app/models/models.js' | |||
2 | --- app/models/models.js 2013-11-21 23:21:49 +0000 | |||
3 | +++ app/models/models.js 2013-11-26 20:42:30 +0000 | |||
4 | @@ -186,7 +186,7 @@ | |||
5 | 186 | this._events.push( | 186 | this._events.push( |
6 | 187 | this.get('relations').on( | 187 | this.get('relations').on( |
7 | 188 | ['*:change', '*:add', '*:remove'], function(e) { | 188 | ['*:change', '*:add', '*:remove'], function(e) { |
9 | 189 | this.set('aggregateRelations', e); | 189 | this.set('relationChangeTrigger', e); |
10 | 190 | }, this)); | 190 | }, this)); |
11 | 191 | }, | 191 | }, |
12 | 192 | 192 | ||
13 | @@ -340,14 +340,16 @@ | |||
14 | 340 | relations: {}, | 340 | relations: {}, |
15 | 341 | 341 | ||
16 | 342 | /** | 342 | /** |
19 | 343 | An aggregate of the relations statuses that we use to trigger | 343 | When there is a change to the relation or to any units in the relation |
20 | 344 | databinding changes | 344 | this value is changed to trigger changes in the inspector. |
21 | 345 | 345 | ||
23 | 346 | @attribute aggregateRelations | 346 | @attribute relationChangeTrigger |
24 | 347 | @default {} | 347 | @default {} |
25 | 348 | @type {Object} | 348 | @type {Object} |
26 | 349 | */ | 349 | */ |
28 | 350 | aggregateRelations: {}, | 350 | relationChangeTrigger: { |
29 | 351 | value: {} | ||
30 | 352 | }, | ||
31 | 351 | 353 | ||
32 | 352 | /** | 354 | /** |
33 | 353 | An aggregate of the relation errors that we use to trigger | 355 | An aggregate of the relation errors that we use to trigger |
34 | @@ -580,11 +582,14 @@ | |||
35 | 580 | return result; | 582 | return result; |
36 | 581 | }, | 583 | }, |
37 | 582 | 584 | ||
43 | 583 | /* | 585 | /** |
44 | 584 | * Return information about the state of the set of units for a | 586 | Returns information about the state of the set of units for a given |
45 | 585 | * given service in the form of a map of agent states: | 587 | service in the form of a map of agent states. |
46 | 586 | * state => number of units in that state | 588 | |
47 | 587 | */ | 589 | @method get_informative_states_for_service |
48 | 590 | @param {Object} service The service model. | ||
49 | 591 | @return {Array} An array of the aggregate map and relation errors | ||
50 | 592 | */ | ||
51 | 588 | get_informative_states_for_service: function(service) { | 593 | get_informative_states_for_service: function(service) { |
52 | 589 | var aggregate_map = {}, | 594 | var aggregate_map = {}, |
53 | 590 | relationError = {}, | 595 | relationError = {}, |
54 | @@ -596,22 +601,24 @@ | |||
55 | 596 | aggregate_map[state] = 1; | 601 | aggregate_map[state] = 1; |
56 | 597 | } else { | 602 | } else { |
57 | 598 | aggregate_map[state] += 1; | 603 | aggregate_map[state] += 1; |
67 | 599 | if (state === 'error') { | 604 | } |
68 | 600 | // If in error status then we need to parse out why it's in error. | 605 | if (state === 'error') { |
69 | 601 | var info = unit.agent_state_info; | 606 | // If in error status then we need to parse out why it's in error. |
70 | 602 | if (info !== undefined && info.indexOf('failed') > -1) { | 607 | var info = unit.agent_state_info; |
71 | 603 | // If we parse more than the relation info then split this out | 608 | if (info !== undefined && info.indexOf('failed') > -1) { |
72 | 604 | if (info.indexOf('relation') > -1) { | 609 | // If we parse more than the relation info then split this out |
73 | 605 | var hook = info.split(':')[1].split('-'), | 610 | if (info.indexOf('relation') > -1) { |
74 | 606 | interfaceName = hook.slice(0, hook.length - 2)[0].trim(); | 611 | var stateData = unit.agent_state_data; |
75 | 607 | relationError[unit.service] = interfaceName; | 612 | if (stateData) { |
76 | 613 | var farService = stateData['remote-unit'].split('/')[0]; | ||
77 | 614 | if (farService) { | ||
78 | 615 | relationError[farService] = stateData.hook; | ||
79 | 616 | } | ||
80 | 608 | } | 617 | } |
81 | 609 | } | 618 | } |
82 | 610 | } | 619 | } |
83 | 611 | } | 620 | } |
84 | 612 | |||
85 | 613 | }); | 621 | }); |
86 | 614 | |||
87 | 615 | return [aggregate_map, relationError]; | 622 | return [aggregate_map, relationError]; |
88 | 616 | }, | 623 | }, |
89 | 617 | 624 | ||
90 | @@ -626,7 +633,9 @@ | |||
91 | 626 | var previous_unit_count = service.get('unit_count'); | 633 | var previous_unit_count = service.get('unit_count'); |
92 | 627 | service.set('unit_count', sum); | 634 | service.set('unit_count', sum); |
93 | 628 | service.set('aggregated_status', aggregate[0]); | 635 | service.set('aggregated_status', aggregate[0]); |
95 | 629 | service.set('aggregateRelationError', aggregate[1]); | 636 | |
96 | 637 | service.set('relationChangeTrigger', { error: aggregate[1] }); | ||
97 | 638 | |||
98 | 630 | // Set Google Analytics tracking event. | 639 | // Set Google Analytics tracking event. |
99 | 631 | if (previous_unit_count !== sum && window._gaq) { | 640 | if (previous_unit_count !== sum && window._gaq) { |
100 | 632 | window._gaq.push(['_trackEvent', 'Service Stats', 'Update', | 641 | window._gaq.push(['_trackEvent', 'Service Stats', 'Update', |
101 | 633 | 642 | ||
102 | === modified file 'app/templates/service-relations-list.handlebars' | |||
103 | --- app/templates/service-relations-list.handlebars 2013-09-19 20:11:53 +0000 | |||
104 | +++ app/templates/service-relations-list.handlebars 2013-11-26 20:42:30 +0000 | |||
105 | @@ -4,7 +4,7 @@ | |||
106 | 4 | </div> | 4 | </div> |
107 | 5 | {{/unless}} | 5 | {{/unless}} |
108 | 6 | {{#relations}} | 6 | {{#relations}} |
110 | 7 | <h3>{{far.service}}</h3> | 7 | <div class="relation-label {{relationStatus far.service ../errors}}"><h3>{{far.service}}</h3></div> |
111 | 8 | <h4>Interface: {{interface}}</h4> | 8 | <h4>Interface: {{interface}}</h4> |
112 | 9 | <h4>Name: {{near.name}}</h4> | 9 | <h4>Name: {{near.name}}</h4> |
113 | 10 | <h4>Role: {{near.role}}</h4> | 10 | <h4>Role: {{near.role}}</h4> |
114 | 11 | 11 | ||
115 | === modified file 'app/templates/service-relations-viewlet.handlebars' | |||
116 | --- app/templates/service-relations-viewlet.handlebars 2013-09-16 20:09:02 +0000 | |||
117 | +++ app/templates/service-relations-viewlet.handlebars 2013-11-26 20:42:30 +0000 | |||
118 | @@ -1,4 +1,4 @@ | |||
119 | 1 | <div class="view-container settings-config"> | 1 | <div class="view-container settings-config"> |
120 | 2 | <h2>Relations</h2> | 2 | <h2>Relations</h2> |
122 | 3 | <div data-bind="aggregateRelations"></div> | 3 | <div data-bind="relationChangeTrigger"></div> |
123 | 4 | </div> | 4 | </div> |
124 | 5 | 5 | ||
125 | === removed file 'app/templates/service-relations.handlebars' | |||
126 | --- app/templates/service-relations.handlebars 2013-04-11 16:16:12 +0000 | |||
127 | +++ app/templates/service-relations.handlebars 1970-01-01 00:00:00 +0000 | |||
128 | @@ -1,40 +0,0 @@ | |||
129 | 1 | {{> service-header}} | ||
130 | 2 | <div class="view-container"> | ||
131 | 3 | <div> | ||
132 | 4 | <h5>Service Relations</h5> | ||
133 | 5 | <form id="service-relations"> | ||
134 | 6 | <table class="table table-striped table-bordered"> | ||
135 | 7 | <thead> | ||
136 | 8 | <tr> | ||
137 | 9 | <th>Id</th> | ||
138 | 10 | <th>Role</th> | ||
139 | 11 | <th>Remote</th> | ||
140 | 12 | <th>Scope</th> | ||
141 | 13 | </thead> | ||
142 | 14 | |||
143 | 15 | <tbody> | ||
144 | 16 | {{#relations}} | ||
145 | 17 | <tr {{#if highlight}}class="highlighted"{{/if}}> | ||
146 | 18 | <td> | ||
147 | 19 | {{ident}} | ||
148 | 20 | <button type="submit" class="btn" id="{{elementId}}" value="{{relation_id}}"> | ||
149 | 21 | Remove | ||
150 | 22 | </button> | ||
151 | 23 | </td> | ||
152 | 24 | <td>{{near.role}}</td> | ||
153 | 25 | <td> | ||
154 | 26 | {{#if far}} | ||
155 | 27 | <a href="{{../../serviceRemoteUri}}{{far.service}}/">{{far.service}}</a> | ||
156 | 28 | {{/if}} | ||
157 | 29 | </td> | ||
158 | 30 | <td>{{scope}}</td> | ||
159 | 31 | </tr> | ||
160 | 32 | {{/relations}} | ||
161 | 33 | </tbody> | ||
162 | 34 | </table> | ||
163 | 35 | </form> | ||
164 | 36 | </div> | ||
165 | 37 | </div> | ||
166 | 38 | <div id="remove-modal-panel"></div> | ||
167 | 39 | {{> service-footer}} | ||
168 | 40 | |||
169 | 41 | 0 | ||
170 | === modified file 'app/views/utils.js' | |||
171 | --- app/views/utils.js 2013-11-21 22:42:48 +0000 | |||
172 | +++ app/views/utils.js 2013-11-26 20:42:30 +0000 | |||
173 | @@ -1686,6 +1686,12 @@ | |||
174 | 1686 | /*jshint debug:false */ | 1686 | /*jshint debug:false */ |
175 | 1687 | }); | 1687 | }); |
176 | 1688 | 1688 | ||
177 | 1689 | Y.Handlebars.registerHelper('relationStatus', function(value, errors) { | ||
178 | 1690 | if (errors[value]) { | ||
179 | 1691 | return 'error'; | ||
180 | 1692 | } | ||
181 | 1693 | }); | ||
182 | 1694 | |||
183 | 1689 | /* | 1695 | /* |
184 | 1690 | * Extension for views to provide an apiFailure method. | 1696 | * Extension for views to provide an apiFailure method. |
185 | 1691 | * | 1697 | * |
186 | 1692 | 1698 | ||
187 | === modified file 'app/views/viewlets/service-relations.js' | |||
188 | --- app/views/viewlets/service-relations.js 2013-09-10 14:53:01 +0000 | |||
189 | +++ app/views/viewlets/service-relations.js 2013-11-26 20:42:30 +0000 | |||
190 | @@ -33,20 +33,16 @@ | |||
191 | 33 | template: templates['service-relations-viewlet'], | 33 | template: templates['service-relations-viewlet'], |
192 | 34 | 34 | ||
193 | 35 | bindings: { | 35 | bindings: { |
195 | 36 | aggregateRelations: { | 36 | relationChangeTrigger: { |
196 | 37 | 'update': function(node, value) { | 37 | 'update': function(node, value) { |
197 | 38 | var db = this.viewlet.options.db; | 38 | var db = this.viewlet.options.db; |
198 | 39 | var service = this.viewlet.model; | 39 | var service = this.viewlet.model; |
199 | 40 | var relations = utils.getRelationDataForService(db, service); | 40 | var relations = utils.getRelationDataForService(db, service); |
200 | 41 | node.setHTML(templates['service-relations-list']({ | 41 | node.setHTML(templates['service-relations-list']({ |
202 | 42 | relations: relations | 42 | relations: relations, |
203 | 43 | errors: value && value.error | ||
204 | 43 | })); | 44 | })); |
205 | 44 | } | 45 | } |
206 | 45 | }, | ||
207 | 46 | aggregateRelationError: { | ||
208 | 47 | 'update': function(node, value) { | ||
209 | 48 | // Aggregate the unit statuses here to display the relation status | ||
210 | 49 | } | ||
211 | 50 | } | 46 | } |
212 | 51 | } | 47 | } |
213 | 52 | }; | 48 | }; |
214 | 53 | 49 | ||
215 | === modified file 'lib/views/juju-inspector.less' | |||
216 | --- lib/views/juju-inspector.less 2013-11-25 21:18:53 +0000 | |||
217 | +++ lib/views/juju-inspector.less 2013-11-26 20:42:30 +0000 | |||
218 | @@ -776,6 +776,17 @@ | |||
219 | 776 | .transition(none); | 776 | .transition(none); |
220 | 777 | } | 777 | } |
221 | 778 | } | 778 | } |
222 | 779 | |||
223 | 780 | .relation-label { | ||
224 | 781 | padding-left: 10px; | ||
225 | 782 | background-repeat: no-repeat; | ||
226 | 783 | background-position: 10px 17px; | ||
227 | 784 | background-image: url("/juju-ui/assets/images/inspector-charm-running.png"); | ||
228 | 785 | |||
229 | 786 | &.error { | ||
230 | 787 | background-image: url("/juju-ui/assets/images/inspector-charm-error.png"); | ||
231 | 788 | } | ||
232 | 789 | } | ||
233 | 779 | } | 790 | } |
234 | 780 | .status { | 791 | .status { |
235 | 781 | display: inline-block; | 792 | display: inline-block; |
236 | 782 | 793 | ||
237 | === modified file 'test/test_model.js' | |||
238 | --- test/test_model.js 2013-11-05 18:10:05 +0000 | |||
239 | +++ test/test_model.js 2013-11-26 20:42:30 +0000 | |||
240 | @@ -133,16 +133,26 @@ | |||
241 | 133 | id: 'wordpress/0', | 133 | id: 'wordpress/0', |
242 | 134 | agent_state: 'pending'}); | 134 | agent_state: 'pending'}); |
243 | 135 | var wp1 = new models.ServiceUnit({ | 135 | var wp1 = new models.ServiceUnit({ |
244 | 136 | id: 'wordpress/2', | ||
245 | 137 | agent_state: 'error', | ||
246 | 138 | agent_state_info: 'hook failed: "db-relation-changed"', | ||
247 | 139 | agent_state_data: { | ||
248 | 140 | hook: 'db-relation-changed', | ||
249 | 141 | 'relation-id': 1, | ||
250 | 142 | 'remote-unit': 'mysql/0' | ||
251 | 143 | }}); | ||
252 | 144 | var wp2 = new models.ServiceUnit({ | ||
253 | 136 | id: 'wordpress/1', | 145 | id: 'wordpress/1', |
256 | 137 | agent_state: 'error'}); | 146 | agent_state: 'error', |
257 | 138 | wordpress.get('units').add([wp0, wp1]); | 147 | agent_state_info: 'hook failed: "install"'}); |
258 | 148 | wordpress.get('units').add([wp0, wp1, wp2]); | ||
259 | 139 | 149 | ||
260 | 140 | assert.deepEqual(mysql.get('units') | 150 | assert.deepEqual(mysql.get('units') |
261 | 141 | .get_informative_states_for_service(mysql), | 151 | .get_informative_states_for_service(mysql), |
262 | 142 | [{'pending': 2}, {}]); | 152 | [{'pending': 2}, {}]); |
263 | 143 | assert.deepEqual(wordpress.get('units') | 153 | assert.deepEqual(wordpress.get('units') |
264 | 144 | .get_informative_states_for_service(wordpress), | 154 | .get_informative_states_for_service(wordpress), |
266 | 145 | [{'pending': 1, 'error': 1}, {}]); | 155 | [{'pending': 1, 'error': 2}, { mysql: 'db-relation-changed'}]); |
267 | 146 | }); | 156 | }); |
268 | 147 | 157 | ||
269 | 148 | it('service unit list should update analytics when units are added', | 158 | it('service unit list should update analytics when units are added', |
270 | @@ -178,20 +188,22 @@ | |||
271 | 178 | models.RelationList, true); | 188 | models.RelationList, true); |
272 | 179 | }); | 189 | }); |
273 | 180 | 190 | ||
288 | 181 | it('relation changes on service update aggregateRelations', function(done) { | 191 | it('relation changes on service update relationChangeTrigger', |
289 | 182 | var service = new models.Service(); | 192 | function(done) { |
290 | 183 | var relations = service.get('relations'); | 193 | var service = new models.Service(); |
291 | 184 | var handler = relations.on( | 194 | var relations = service.get('relations'); |
292 | 185 | '*:add', function() { | 195 | var handler = relations.on( |
293 | 186 | // This means that it will update the aggregate | 196 | '*:add', function() { |
294 | 187 | // relations for databinding | 197 | // This means that it will update the aggregate |
295 | 188 | handler.detach(); | 198 | // relations for databinding |
296 | 189 | var isObject = yui.Lang.isObject; | 199 | handler.detach(); |
297 | 190 | assert.equal(isObject(service.get('aggregateRelations')), true); | 200 | var isObject = yui.Lang.isObject; |
298 | 191 | done(); | 201 | assert.equal( |
299 | 192 | }); | 202 | isObject(service.get('relationChangeTrigger')), true); |
300 | 193 | relations.add(new models.Relation()); | 203 | done(); |
301 | 194 | }); | 204 | }); |
302 | 205 | relations.add(new models.Relation()); | ||
303 | 206 | }); | ||
304 | 195 | 207 | ||
305 | 196 | it('service unit objects should parse the service name from unit id', | 208 | it('service unit objects should parse the service name from unit id', |
306 | 197 | function() { | 209 | function() { |
Reviewers: mp+196770_ code.launchpad. net,
Message:
Please take a look.
Description:
Adds relation status to inspector relation panel
The overall relation status is now indicated on the inspector relation
panel using the same icons as the unit status. If any unit has a
relation
error the entire relation is shown as in error.
To QA:
Sandbox:
Deploy Mysql & Wordpress with 50 units each
Relate them
See the inspector relations panel, there should be a green icon
Wait for a relation error
See the inspector relations panel, there should be a red icon
Reduce the units on your inspector to 1
See the inspector relations panel, there should be a green icon
because it's very likely the unit in error is gone
LXC
Deploy two instances of failtester
set ones relation fail setting to true
relate them
the inspector relations panel should show an error
resolve the error
the inspector relations panel should show green
https:/ /code.launchpad .net/~hatch/ juju-gui/ inspector- relation- status/ +merge/ 196770
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/33130043/
Affected files (+77, -82 lines): models. js service- relations- list.handlebars service- relations- viewlet. handlebars service- relations. handlebars viewlets/ service- relations. js juju-inspector. less
A [revision details]
M app/models/
M app/templates/
M app/templates/
D app/templates/
M app/views/utils.js
M app/views/
M lib/views/
M test/test_model.js