Merge lp:~hatch/juju-gui/parse-pending-types into lp:juju-gui/experimental

Proposed by Jeff Pihach
Status: Merged
Merged at revision: 1217
Proposed branch: lp:~hatch/juju-gui/parse-pending-types
Merge into: lp:juju-gui/experimental
Diff against target: 282 lines (+52/-71)
9 files modified
app/models/handlers.js (+4/-1)
app/models/models.js (+16/-17)
app/store/env/simulator.js (+2/-12)
app/views/environment.js (+2/-23)
app/views/inspector.js (+1/-1)
app/views/utils.js (+15/-7)
app/views/viewlets/service-overview.js (+6/-4)
test/test_model.js (+5/-5)
test/test_service_module.js (+1/-1)
To merge this branch: bzr merge lp:~hatch/juju-gui/parse-pending-types
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+197441@code.launchpad.net

Description of the change

Adds pending and dying statuses to the inspector

A service in various states of pending are now properly represented in the
inspector.

Dying services are now left on the canvas with their inspectors until the service
is entirely destroyed from Juju.

https://codereview.appspot.com/36240043/

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

Reviewers: mp+197441_code.launchpad.net,

Message:
Please take a look.

Description:
Adds pending and dying statuses to the inspector

A service in various states of pending are now properly represented in
the
inspector.

Dying services are now left on the canvas with their inspectors until
the service
is entirely destroyed from Juju.

To QA:
Sandbox:
Deploy some services and make sure you can destroy them in various ways.
Deploy a service with a lot of units and wait for the simulator to show
   pending and installing statuses

Real Env:
Deploy 4 instances of failtester
Set one to fail on install hook
Open one of the pending services inspectors and then delete it from the
console
It should enter a 'dying' state then remove from the canvas when
finished
Wait for the remaining failtester services to come green/red
Destroy one from the GUI, it should enter a 'dying' state and then
remove from the canvas
   closing the inspector when it's done.
Open the other green one, destroy it from the console, it should enter a
'dying' state and
   then remove from the canvas
Open the red one's inspector, destroy it from the console, nothing
should happen in the GUI
Resolve the unit in error in the GUI and the service should enter a
'dying' state then
   remove from the canvas when done.

https://code.launchpad.net/~hatch/juju-gui/parse-pending-types/+merge/197441

(do not edit description out of merge proposal)

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

Affected files (+54, -71 lines):
   A [revision details]
   M app/models/handlers.js
   M app/models/models.js
   M app/store/env/simulator.js
   M app/views/environment.js
   M app/views/inspector.js
   M app/views/utils.js
   M app/views/viewlets/service-overview.js
   M test/test_model.js
   M test/test_service_module.js

Revision history for this message
Madison Scott-Clary (makyo) wrote :

LGTM, QA okay, one question, feel free to say no! Thanks.

https://codereview.appspot.com/36240043/diff/1/app/models/models.js
File app/models/models.js (right):

https://codereview.appspot.com/36240043/diff/1/app/models/models.js#newcode205
app/models/models.js:205: if (life === ALIVE || life === 'dying') {
We have a constant ALIVE, might it make sense to do he samefor DYING?

https://codereview.appspot.com/36240043/

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

*** Submitted:

Adds pending and dying statuses to the inspector

A service in various states of pending are now properly represented in
the
inspector.

Dying services are now left on the canvas with their inspectors until
the service
is entirely destroyed from Juju.

R=matthew.scott
CC=
https://codereview.appspot.com/36240043

https://codereview.appspot.com/36240043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'app/models/handlers.js'
--- app/models/handlers.js 2013-11-19 22:30:18 +0000
+++ app/models/handlers.js 2013-12-02 21:33:17 +0000
@@ -172,7 +172,10 @@
172 public_address: change.PublicAddress172 public_address: change.PublicAddress
173 };173 };
174 var service = db.services.getById(change.Name.split('/')[0]);174 var service = db.services.getById(change.Name.split('/')[0]);
175 service.get('units').process_delta(action, unitData, db);175 if (service) {
176 // The service can be destroyed before the last unit delta comes in.
177 service.get('units').process_delta(action, unitData, db);
178 }
176 db.machines.process_delta(action, machineData, db);179 db.machines.process_delta(action, machineData, db);
177 },180 },
178181
179182
=== modified file 'app/models/models.js'
--- app/models/models.js 2013-11-26 20:38:05 +0000
+++ app/models/models.js 2013-12-02 21:33:17 +0000
@@ -191,18 +191,21 @@
191 },191 },
192192
193 /**193 /**
194 Return true if this service life is "alive", false otherwise.194 Return true if this service life is 'alive' or 'dying', false otherwise.
195195
196 A model instance is alive if its life cycle (i.e. the "life" attribute)196 A model instance is alive if its life cycle (i.e. the "life" attribute)
197 is set to "alive". Other possible values, as they arrive from the197 is set to 'alive' or 'dying'. The other possible value, as they arrive
198 juju-core delta stream, are "dying" and "dead", in which cases the198 from the juju-core delta stream is 'dead'.
199 service is not considered alive.
200199
201 @method isAlive200 @method isAlive
202 @return {Boolean} Whether this service is alive.201 @return {Boolean} Whether this service is alive.
203 */202 */
204 isAlive: function() {203 isAlive: function() {
205 return this.get('life') === ALIVE;204 var life = this.get('life');
205 if (life === ALIVE || life === 'dying') {
206 return true;
207 }
208 return false;
206 },209 },
207210
208 /**211 /**
@@ -413,14 +416,10 @@
413 model: Service,416 model: Service,
414417
415 /**418 /**
416 Return a list of visible model instances.419 Return a list of visible model instances. A model instance is visible
417420 when it is alive or dying.
418 A model instance is visible when it is alive or when, even if it is dying421
419 or dead, one or more of its units are in an error state.422 @method visible
420 In the latter case, we want to still display the service in order to
421 allow users to retry or resolve its units.
422
423 @method alive
424 @return {Y.ModelList} The resulting visible model instances.423 @return {Y.ModelList} The resulting visible model instances.
425 */424 */
426 visible: function() {425 visible: function() {
@@ -593,10 +592,12 @@
593 get_informative_states_for_service: function(service) {592 get_informative_states_for_service: function(service) {
594 var aggregate_map = {},593 var aggregate_map = {},
595 relationError = {},594 relationError = {},
596 units_for_service = service.get('units');595 units_for_service = service.get('units'),
596 serviceLife = service.get('life');
597597
598 units_for_service.each(function(unit) {598 units_for_service.each(function(unit) {
599 var state = utils.determineCategoryType(utils.simplifyState(unit));599 var state = utils.determineCategoryType(
600 utils.simplifyState(unit, serviceLife));
600 if (aggregate_map[state] === undefined) {601 if (aggregate_map[state] === undefined) {
601 aggregate_map[state] = 1;602 aggregate_map[state] = 1;
602 } else {603 } else {
@@ -633,9 +634,7 @@
633 var previous_unit_count = service.get('unit_count');634 var previous_unit_count = service.get('unit_count');
634 service.set('unit_count', sum);635 service.set('unit_count', sum);
635 service.set('aggregated_status', aggregate[0]);636 service.set('aggregated_status', aggregate[0]);
636
637 service.set('relationChangeTrigger', { error: aggregate[1] });637 service.set('relationChangeTrigger', { error: aggregate[1] });
638
639 // Set Google Analytics tracking event.638 // Set Google Analytics tracking event.
640 if (previous_unit_count !== sum && window._gaq) {639 if (previous_unit_count !== sum && window._gaq) {
641 window._gaq.push(['_trackEvent', 'Service Stats', 'Update',640 window._gaq.push(['_trackEvent', 'Service Stats', 'Update',
642641
=== modified file 'app/store/env/simulator.js'
--- app/store/env/simulator.js 2013-11-22 22:52:30 +0000
+++ app/store/env/simulator.js 2013-12-02 21:33:17 +0000
@@ -157,18 +157,8 @@
157 unit.agent_state_info = undefined;157 unit.agent_state_info = undefined;
158 unit.agent_state_data = {};158 unit.agent_state_data = {};
159 } else if (roll <= 0.7) {159 } else if (roll <= 0.7) {
160 if (window.flags && window.flags.simPend) {160 if (roll <= 0.5) {
161 // Because the GUI does not yet support parsing the 'life'161 unit.agent_state = 'installing';
162 // status attribute from core and including it in the
163 // aggregate status this is here to simply simulate the
164 // functionality in the inspector unit list, until it is.
165 if (roll <= 0.4) {
166 unit.agent_state = 'dying';
167 } else if (roll <= 0.5) {
168 unit.agent_state = 'installing';
169 } else {
170 unit.agent_state = 'pending';
171 }
172 } else {162 } else {
173 unit.agent_state = 'pending';163 unit.agent_state = 'pending';
174 }164 }
175165
=== modified file 'app/views/environment.js'
--- app/views/environment.js 2013-11-13 15:41:46 +0000
+++ app/views/environment.js 2013-12-02 21:33:17 +0000
@@ -151,32 +151,11 @@
151 this.topo.fire('hideServiceMenu');151 this.topo.fire('hideServiceMenu');
152 }, this);152 }, this);
153153
154 model.get('units').on('deltaChange', function(e) {
155 var service = e.service;
156 var units = service.get('units');
157
158 var started = !units.some(function(unit) {
159 if ((/-?error$/).test(unit.agent_state)) {
160 return true;
161 }
162 });
163
164 if (started && service.get('life') === 'dying') {
165 var inspector = this.getInspector(service.get('packageName'));
166 if (inspector) { inspector.viewletManager.destroy(); }
167 this.topo.fire('hideServiceMenu');
168 }
169 }, this);
170
171 // If the service is destroyed from the console then we need to154 // If the service is destroyed from the console then we need to
172 // destroy the inspector and hide the service menu.155 // destroy the inspector and hide the service menu.
173 model.after(['lifeChange', 'destroy'], function(e) {156 model.on('destroy', function(e) {
174 var service = e.currentTarget;157 var service = e.currentTarget;
175 // The user can put the service in a dying state from the console158 var inspector = this.getInspector(service.get('id'));
176 // but it will not be destroyed if any of its units has errors.
177 if (service.isAlive() || service.hasErrors()) { return; }
178
179 var inspector = this.getInspector(service.get('packageName'));
180 if (inspector) { inspector.viewletManager.destroy(); }159 if (inspector) { inspector.viewletManager.destroy(); }
181 this.topo.fire('hideServiceMenu');160 this.topo.fire('hideServiceMenu');
182 }, this);161 }, this);
183162
=== modified file 'app/views/inspector.js'
--- app/views/inspector.js 2013-10-11 19:33:07 +0000
+++ app/views/inspector.js 2013-12-02 21:33:17 +0000
@@ -507,8 +507,8 @@
507 */507 */
508 _onInitiateDestroy: function(evt) {508 _onInitiateDestroy: function(evt) {
509 evt.halt();509 evt.halt();
510 this.closeInspector();
511 this.initiateServiceDestroy();510 this.initiateServiceDestroy();
511 this._onCancelDestroy(evt);
512 this.options.environment.topo.fire('clearState');512 this.options.environment.topo.fire('clearState');
513 },513 },
514514
515515
=== modified file 'app/views/utils.js'
--- app/views/utils.js 2013-11-27 19:27:32 +0000
+++ app/views/utils.js 2013-12-02 21:33:17 +0000
@@ -1232,14 +1232,21 @@
12321232
1233 @method simplifyState1233 @method simplifyState
1234 @param {Object} unit A service unit.1234 @param {Object} unit A service unit.
1235 @param {String} life The life status of the units service.
1235 @return {String} the filtered agent state of the unit.1236 @return {String} the filtered agent state of the unit.
1236 */1237 */
1237 utils.simplifyState = function(unit) {1238 utils.simplifyState = function(unit, life) {
1238 var state = unit.agent_state;1239 var state = unit.agent_state,
1239 if (state === 'started') { return 'running'; }1240 inError = (/-?error$/).test(state);
1240 if ((/-?error$/).test(state)) { return 'error'; }1241 if (life === 'dying' && !inError) {
1241 // "pending", "installed", and "stopped", plus anything unforeseen1242 return 'dying';
1242 return state;1243 } else {
1244 if (state === 'started') { return 'running'; }
1245 if (inError) { return 'error'; }
1246 // "pending", "installed", and "stopped", plus anything unforeseen
1247 return state;
1248 }
1249
1243 };1250 };
12441251
1245 /**1252 /**
@@ -1267,7 +1274,8 @@
12671274
1268 @method determineCategoryType1275 @method determineCategoryType
1269 @param {String} category The category name to test.1276 @param {String} category The category name to test.
1270 @param {String} The category type 'error', 'landscape', 'pending', 'running'1277 @return {String} The category type
1278 'error', 'landscape', 'pending', 'running'
1271 */1279 */
1272 utils.determineCategoryType = function(category) {1280 utils.determineCategoryType = function(category) {
1273 if ((/fail|error/).test(category)) { return 'error'; }1281 if ((/fail|error/).test(category)) { return 'error'; }
12741282
=== modified file 'app/views/viewlets/service-overview.js'
--- app/views/viewlets/service-overview.js 2013-11-21 23:21:49 +0000
+++ app/views/viewlets/service-overview.js 2013-12-02 21:33:17 +0000
@@ -83,11 +83,14 @@
83 [{ type: 'service', upgradeAvailable: true, upgradeTo: ...}].83 [{ type: 'service', upgradeAvailable: true, upgradeTo: ...}].
84 */84 */
85 function updateStatusList(unitList) {85 function updateStatusList(unitList) {
86 // Disable: Possible strict violation for the entire function
87 /* jshint -W040 */
86 var statuses = [],88 var statuses = [],
87 unitByStatus = {};89 unitByStatus = {},
90 serviceLife = this.model.get('life');
8891
89 unitList.each(function(unit) {92 unitList.each(function(unit) {
90 var category = utils.simplifyState(unit);93 var category = utils.simplifyState(unit, serviceLife);
91 // If the unit is in error we want it's category to be it's real error.94 // If the unit is in error we want it's category to be it's real error.
92 if (category === 'error') { category = unit.agent_state_info; }95 if (category === 'error') { category = unit.agent_state_info; }
9396
@@ -112,8 +115,7 @@
112 units: unitByStatus[category]115 units: unitByStatus[category]
113 });116 });
114 });117 });
115 // Disable: Possible strict violation118
116 /* jshint -W040 */
117 return sortStatuses(addCharmUpgrade(statuses, this.model));119 return sortStatuses(addCharmUpgrade(statuses, this.model));
118 }120 }
119121
120122
=== modified file 'test/test_model.js'
--- test/test_model.js 2013-11-26 22:30:42 +0000
+++ test/test_model.js 2013-12-02 21:33:17 +0000
@@ -1034,9 +1034,9 @@
1034 assert.isTrue(django.isAlive());1034 assert.isTrue(django.isAlive());
1035 });1035 });
10361036
1037 it('instances identify if they are not alive (dying or dead)', function() {1037 it('instances identify if they are not alive (dead)', function() {
1038 assert.isFalse(rails.isAlive(), rails.get('id'));1038 assert.isTrue(rails.isAlive(), rails.get('id'));
1039 assert.isFalse(wordpress.isAlive(), wordpress.get('id'));1039 assert.isTrue(wordpress.isAlive(), wordpress.get('id'));
1040 assert.isFalse(mysql.isAlive(), mysql.get('id'));1040 assert.isFalse(mysql.isAlive(), mysql.get('id'));
1041 });1041 });
10421042
@@ -1052,8 +1052,8 @@
10521052
1053 it('can be filtered so that it returns only visible models', function() {1053 it('can be filtered so that it returns only visible models', function() {
1054 var filtered = list.visible();1054 var filtered = list.visible();
1055 assert.strictEqual(2, filtered.size());1055 assert.strictEqual(filtered.size(), 3);
1056 assert.deepEqual([django, wordpress], filtered.toArray());1056 assert.deepEqual(filtered.toArray(), [rails, django, wordpress]);
1057 });1057 });
1058 });1058 });
1059});1059});
10601060
=== modified file 'test/test_service_module.js'
--- test/test_service_module.js 2013-11-21 12:18:26 +0000
+++ test/test_service_module.js 2013-12-02 21:33:17 +0000
@@ -258,7 +258,7 @@
258 // There are five services in total.258 // There are five services in total.
259 assert.strictEqual(5, db.services.size(), 'total');259 assert.strictEqual(5, db.services.size(), 'total');
260 // But only three of those are actually displayed.260 // But only three of those are actually displayed.
261 assert.strictEqual(3, Y.Object.size(boxes), 'displayed');261 assert.strictEqual(4, Y.Object.size(boxes), 'displayed');
262 // And they are the visible ones.262 // And they are the visible ones.
263 assert.deepPropertyVal(boxes, 'haproxy.model', haproxy);263 assert.deepPropertyVal(boxes, 'haproxy.model', haproxy);
264 assert.deepPropertyVal(boxes, 'django.model', django);264 assert.deepPropertyVal(boxes, 'django.model', django);

Subscribers

People subscribed via source and target branches