Merge lp:~hatch/juju-gui/inspector-relation-status into lp:juju-gui/experimental

Proposed by Jeff Pihach
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
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+196770@code.launchpad.net

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.

https://codereview.appspot.com/33130043/

To post a comment you must log in.
Revision history for this message
Jeff Pihach (hatch) wrote :

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):
   A [revision details]
   M app/models/models.js
   M app/templates/service-relations-list.handlebars
   M app/templates/service-relations-viewlet.handlebars
   D app/templates/service-relations.handlebars
   M app/views/utils.js
   M app/views/viewlets/service-relations.js
   M lib/views/juju-inspector.less
   M test/test_model.js

Revision history for this message
Jeff Pihach (hatch) wrote :

reviewer notes

https://codereview.appspot.com/33130043/diff/1/app/templates/service-relations.handlebars
File app/templates/service-relations.handlebars (left):

https://codereview.appspot.com/33130043/diff/1/app/templates/service-relations.handlebars#oldcode1
app/templates/service-relations.handlebars:1: {{> service-header}}
Template from old inspector

https://codereview.appspot.com/33130043/

Revision history for this message
Jeff Pihach (hatch) wrote :
1214. By Jeff Pihach

fixed issue where the first error status delta would get ignored for relation errors

Revision history for this message
Jeff Pihach (hatch) wrote :

reviewer notes v2

https://codereview.appspot.com/33130043/diff/20001/app/models/models.js
File app/models/models.js (right):

https://codereview.appspot.com/33130043/diff/20001/app/models/models.js#newcode605
app/models/models.js:605: if (state === 'error') {
Fix for bug from first rev (see test_model)

https://codereview.appspot.com/33130043/diff/20001/test/test_model.js
File test/test_model.js (right):

https://codereview.appspot.com/33130043/diff/20001/test/test_model.js#newcode136
test/test_model.js:136: id: 'wordpress/2',
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)

https://codereview.appspot.com/33130043/

Revision history for this message
Gary Poster (gary) wrote :

LGTM with trivials and sandbox QA good. waiting on QA on ec2.

https://codereview.appspot.com/33130043/diff/20001/app/models/models.js
File app/models/models.js (right):

https://codereview.appspot.com/33130043/diff/20001/app/models/models.js#newcode591
app/models/models.js:591: @return {Array} An array of the aggregate map
and relation errors
Thank you for improving names and docs. Nice.

https://codereview.appspot.com/33130043/diff/20001/app/models/models.js#newcode614
app/models/models.js:614: if (farService) {
this code fixes peer relation issues?

https://codereview.appspot.com/33130043/diff/20001/test/test_model.js
File test/test_model.js (right):

https://codereview.appspot.com/33130043/diff/20001/test/test_model.js#newcode136
test/test_model.js:136: id: 'wordpress/2',
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.

https://codereview.appspot.com/33130043/

Revision history for this message
Gary Poster (gary) wrote :

QA OK on real environment also. Thanks! These are really cool changes
you are making.

https://codereview.appspot.com/33130043/

Revision history for this message
Jeff Pihach (hatch) wrote :

Thanks for the review! Changes landing

https://codereview.appspot.com/33130043/diff/20001/test/test_model.js
File test/test_model.js (right):

https://codereview.appspot.com/33130043/diff/20001/test/test_model.js#newcode136
test/test_model.js:136: id: 'wordpress/2',
good call, done

https://codereview.appspot.com/33130043/

Revision history for this message
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://codereview.appspot.com/33130043

https://codereview.appspot.com/33130043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 this._events.push(
6 this.get('relations').on(
7 ['*:change', '*:add', '*:remove'], function(e) {
8- this.set('aggregateRelations', e);
9+ this.set('relationChangeTrigger', e);
10 }, this));
11 },
12
13@@ -340,14 +340,16 @@
14 relations: {},
15
16 /**
17- An aggregate of the relations statuses that we use to trigger
18- databinding changes
19+ When there is a change to the relation or to any units in the relation
20+ this value is changed to trigger changes in the inspector.
21
22- @attribute aggregateRelations
23+ @attribute relationChangeTrigger
24 @default {}
25 @type {Object}
26 */
27- aggregateRelations: {},
28+ relationChangeTrigger: {
29+ value: {}
30+ },
31
32 /**
33 An aggregate of the relation errors that we use to trigger
34@@ -580,11 +582,14 @@
35 return result;
36 },
37
38- /*
39- * Return information about the state of the set of units for a
40- * given service in the form of a map of agent states:
41- * state => number of units in that state
42- */
43+ /**
44+ Returns information about the state of the set of units for a given
45+ service in the form of a map of agent states.
46+
47+ @method get_informative_states_for_service
48+ @param {Object} service The service model.
49+ @return {Array} An array of the aggregate map and relation errors
50+ */
51 get_informative_states_for_service: function(service) {
52 var aggregate_map = {},
53 relationError = {},
54@@ -596,22 +601,24 @@
55 aggregate_map[state] = 1;
56 } else {
57 aggregate_map[state] += 1;
58- if (state === 'error') {
59- // If in error status then we need to parse out why it's in error.
60- var info = unit.agent_state_info;
61- if (info !== undefined && info.indexOf('failed') > -1) {
62- // If we parse more than the relation info then split this out
63- if (info.indexOf('relation') > -1) {
64- var hook = info.split(':')[1].split('-'),
65- interfaceName = hook.slice(0, hook.length - 2)[0].trim();
66- relationError[unit.service] = interfaceName;
67+ }
68+ if (state === 'error') {
69+ // If in error status then we need to parse out why it's in error.
70+ var info = unit.agent_state_info;
71+ if (info !== undefined && info.indexOf('failed') > -1) {
72+ // If we parse more than the relation info then split this out
73+ if (info.indexOf('relation') > -1) {
74+ var stateData = unit.agent_state_data;
75+ if (stateData) {
76+ var farService = stateData['remote-unit'].split('/')[0];
77+ if (farService) {
78+ relationError[farService] = stateData.hook;
79+ }
80 }
81 }
82 }
83 }
84-
85 });
86-
87 return [aggregate_map, relationError];
88 },
89
90@@ -626,7 +633,9 @@
91 var previous_unit_count = service.get('unit_count');
92 service.set('unit_count', sum);
93 service.set('aggregated_status', aggregate[0]);
94- service.set('aggregateRelationError', aggregate[1]);
95+
96+ service.set('relationChangeTrigger', { error: aggregate[1] });
97+
98 // Set Google Analytics tracking event.
99 if (previous_unit_count !== sum && window._gaq) {
100 window._gaq.push(['_trackEvent', 'Service Stats', 'Update',
101
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 </div>
107 {{/unless}}
108 {{#relations}}
109- <h3>{{far.service}}</h3>
110+ <div class="relation-label {{relationStatus far.service ../errors}}"><h3>{{far.service}}</h3></div>
111 <h4>Interface: {{interface}}</h4>
112 <h4>Name: {{near.name}}</h4>
113 <h4>Role: {{near.role}}</h4>
114
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 <div class="view-container settings-config">
120 <h2>Relations</h2>
121- <div data-bind="aggregateRelations"></div>
122+ <div data-bind="relationChangeTrigger"></div>
123 </div>
124
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-{{> service-header}}
130-<div class="view-container">
131- <div>
132- <h5>Service Relations</h5>
133- <form id="service-relations">
134- <table class="table table-striped table-bordered">
135- <thead>
136- <tr>
137- <th>Id</th>
138- <th>Role</th>
139- <th>Remote</th>
140- <th>Scope</th>
141- </thead>
142-
143- <tbody>
144- {{#relations}}
145- <tr {{#if highlight}}class="highlighted"{{/if}}>
146- <td>
147- {{ident}}
148- <button type="submit" class="btn" id="{{elementId}}" value="{{relation_id}}">
149- Remove
150- </button>
151- </td>
152- <td>{{near.role}}</td>
153- <td>
154- {{#if far}}
155- <a href="{{../../serviceRemoteUri}}{{far.service}}/">{{far.service}}</a>
156- {{/if}}
157- </td>
158- <td>{{scope}}</td>
159- </tr>
160- {{/relations}}
161- </tbody>
162- </table>
163- </form>
164- </div>
165-</div>
166-<div id="remove-modal-panel"></div>
167-{{> service-footer}}
168-
169
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 /*jshint debug:false */
175 });
176
177+ Y.Handlebars.registerHelper('relationStatus', function(value, errors) {
178+ if (errors[value]) {
179+ return 'error';
180+ }
181+ });
182+
183 /*
184 * Extension for views to provide an apiFailure method.
185 *
186
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 template: templates['service-relations-viewlet'],
192
193 bindings: {
194- aggregateRelations: {
195+ relationChangeTrigger: {
196 'update': function(node, value) {
197 var db = this.viewlet.options.db;
198 var service = this.viewlet.model;
199 var relations = utils.getRelationDataForService(db, service);
200 node.setHTML(templates['service-relations-list']({
201- relations: relations
202+ relations: relations,
203+ errors: value && value.error
204 }));
205 }
206- },
207- aggregateRelationError: {
208- 'update': function(node, value) {
209- // Aggregate the unit statuses here to display the relation status
210- }
211 }
212 }
213 };
214
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 .transition(none);
220 }
221 }
222+
223+ .relation-label {
224+ padding-left: 10px;
225+ background-repeat: no-repeat;
226+ background-position: 10px 17px;
227+ background-image: url("/juju-ui/assets/images/inspector-charm-running.png");
228+
229+ &.error {
230+ background-image: url("/juju-ui/assets/images/inspector-charm-error.png");
231+ }
232+ }
233 }
234 .status {
235 display: inline-block;
236
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 id: 'wordpress/0',
242 agent_state: 'pending'});
243 var wp1 = new models.ServiceUnit({
244+ id: 'wordpress/2',
245+ agent_state: 'error',
246+ agent_state_info: 'hook failed: "db-relation-changed"',
247+ agent_state_data: {
248+ hook: 'db-relation-changed',
249+ 'relation-id': 1,
250+ 'remote-unit': 'mysql/0'
251+ }});
252+ var wp2 = new models.ServiceUnit({
253 id: 'wordpress/1',
254- agent_state: 'error'});
255- wordpress.get('units').add([wp0, wp1]);
256+ agent_state: 'error',
257+ agent_state_info: 'hook failed: "install"'});
258+ wordpress.get('units').add([wp0, wp1, wp2]);
259
260 assert.deepEqual(mysql.get('units')
261 .get_informative_states_for_service(mysql),
262 [{'pending': 2}, {}]);
263 assert.deepEqual(wordpress.get('units')
264 .get_informative_states_for_service(wordpress),
265- [{'pending': 1, 'error': 1}, {}]);
266+ [{'pending': 1, 'error': 2}, { mysql: 'db-relation-changed'}]);
267 });
268
269 it('service unit list should update analytics when units are added',
270@@ -178,20 +188,22 @@
271 models.RelationList, true);
272 });
273
274- it('relation changes on service update aggregateRelations', function(done) {
275- var service = new models.Service();
276- var relations = service.get('relations');
277- var handler = relations.on(
278- '*:add', function() {
279- // This means that it will update the aggregate
280- // relations for databinding
281- handler.detach();
282- var isObject = yui.Lang.isObject;
283- assert.equal(isObject(service.get('aggregateRelations')), true);
284- done();
285- });
286- relations.add(new models.Relation());
287- });
288+ it('relation changes on service update relationChangeTrigger',
289+ function(done) {
290+ var service = new models.Service();
291+ var relations = service.get('relations');
292+ var handler = relations.on(
293+ '*:add', function() {
294+ // This means that it will update the aggregate
295+ // relations for databinding
296+ handler.detach();
297+ var isObject = yui.Lang.isObject;
298+ assert.equal(
299+ isObject(service.get('relationChangeTrigger')), true);
300+ done();
301+ });
302+ relations.add(new models.Relation());
303+ });
304
305 it('service unit objects should parse the service name from unit id',
306 function() {

Subscribers

People subscribed via source and target branches