Merge lp:~frankban/juju-gui/bug-1169858-life into lp:juju-gui/experimental

Proposed by Francesco Banconi
Status: Merged
Merged at revision: 567
Proposed branch: lp:~frankban/juju-gui/bug-1169858-life
Merge into: lp:juju-gui/experimental
Diff against target: 209 lines (+99/-4)
7 files modified
app/models/handlers.js (+1/-0)
app/models/models.js (+35/-1)
app/views/topology/service.js (+1/-1)
test/test_fakebackend.js (+1/-0)
test/test_model.js (+36/-0)
test/test_model_handlers.js (+6/-2)
test/test_service_module.js (+19/-0)
To merge this branch: bzr merge lp:~frankban/juju-gui/bug-1169858-life
Reviewer Review Type Date Requested Status
Juju GUI Hackers Pending
Review via email: mp+159356@code.launchpad.net

Description of the change

Handle service life

The Life change included in the juju-core delta stream is
now stored in the service model, and used to avoid displaying
dying services in the topology view.

QA:

- bootstrap a juju-core env;
- deploy a service;
- connect the GUI to the env;
- use the GUI to destroy the service;
- suddenly refresh (or visit the GUI from another browser tab).

At this point, even if the service could be still
present in the db, it should not be alive and you should
not see it in the topology view.

https://codereview.appspot.com/8824044/

To post a comment you must log in.
Revision history for this message
Francesco Banconi (frankban) wrote :
Download full text (7.8 KiB)

Reviewers: mp+159356_code.launchpad.net,

Message:
Please take a look.

Description:
Handle service life

The Life change included in the juju-core delta stream is
now stored in the service model, and used to avoid displaying
dying services in the topology view.

QA:

- bootstrap a juju-core env;
- deploy a service;
- connect the GUI to the env;
- use the GUI to destroy the service;
- suddenly refresh (or visit the GUI from another browser tab).

At this point, even if the service could be still
present in the db, it should not be alive and you should
not see it in the topology view.

https://code.launchpad.net/~frankban/juju-gui/bug-1169858-life/+merge/159356

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M app/models/handlers.js
   M app/models/models.js
   M app/views/topology/service.js
   M test/test_fakebackend.js
   M test/test_model.js
   M test/test_model_handlers.js
   M test/test_service_module.js

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: <email address hidden>
+New revision:
<email address hidden>

Index: app/models/handlers.js
=== modified file 'app/models/handlers.js'
--- app/models/handlers.js 2013-04-16 12:24:34 +0000
+++ app/models/handlers.js 2013-04-17 10:50:07 +0000
@@ -166,6 +166,7 @@
          id: change.Name,
          charm: change.CharmURL,
          exposed: change.Exposed,
+ life: change.Life,
          constraints: change.Constraints || {}
        };
        db.services.process_delta(action, data);

Index: app/models/models.js
=== modified file 'app/models/models.js'
--- app/models/models.js 2013-04-12 16:04:02 +0000
+++ app/models/models.js 2013-04-17 11:23:44 +0000
@@ -91,7 +91,21 @@
    });
    models.Environment = Environment;

- var Service = Y.Base.create('service', Y.Model, [], {}, {
+ var ALIVE = 'alive';
+
+ var Service = Y.Base.create('service', Y.Model, [], {
+
+ /**
+ Return true if this service life is "alive", false otherwise.
+
+ @method isAlive
+ @return {Boolean} Whether this service is alive.
+ */
+ isAlive: function() {
+ return this.get('life') === ALIVE;
+ }
+
+ }, {
      ATTRS: {
        displayName: {
          /**
@@ -115,6 +129,9 @@
        pending: {
          value: false
        },
+ life: {
+ value: ALIVE
+ },
        unit_count: {},
        aggregated_status: {}
      }
@@ -124,6 +141,18 @@
    var ServiceList = Y.Base.create('serviceList', Y.ModelList, [], {
      model: Service,

+ /**
+ Return a list of alive model instances.
+
+ @method alive
+ @return {Y.ModelList} The model instances having life === 'alive'.
+ */
+ alive: function() {
+ return this.filter({asList: true}, function(model) {
+ return model.isAlive();
+ });
+ },
+
      process_delta: function(action, data) {
        _process_delta(this, action, data, {exposed: false});
      }

...

Read more...

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

Looks good. QAing.

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

https://codereview.appspot.com/8824044/diff/1/app/models/models.js#newcode99
app/models/models.js:99: Return true if this service life is "alive",
false otherwise.
On 2013/04/17 12:37:59, benji wrote:
> It might be nice to explain (ether here or in "alive" below) what it
means for a
> service to be "alive".
+1

https://codereview.appspot.com/8824044/diff/1/test/test_model.js
File test/test_model.js (right):

https://codereview.appspot.com/8824044/diff/1/test/test_model.js#newcode665
test/test_model.js:665: it('instances identify if they are alive',
function() {
(and also verifies that the default state is alive :-) )

https://codereview.appspot.com/8824044/

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

LGTM. QA went well. Thank you!

Gary

https://codereview.appspot.com/8824044/

570. By Francesco Banconi

Changes as per review.

571. By Francesco Banconi

Merged trunk.

Revision history for this message
Francesco Banconi (frankban) wrote :

*** Submitted:

Handle service life

The Life change included in the juju-core delta stream is
now stored in the service model, and used to avoid displaying
dying services in the topology view.

QA:

- bootstrap a juju-core env;
- deploy a service;
- connect the GUI to the env;
- use the GUI to destroy the service;
- suddenly refresh (or visit the GUI from another browser tab).

At this point, even if the service could be still
present in the db, it should not be alive and you should
not see it in the topology view.

R=benji, gary.poster
CC=
https://codereview.appspot.com/8824044

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

https://codereview.appspot.com/8824044/diff/1/app/models/models.js#newcode99
app/models/models.js:99: Return true if this service life is "alive",
false otherwise.
On 2013/04/17 12:37:59, benji wrote:
> It might be nice to explain (ether here or in "alive" below) what it
means for a
> service to be "alive".

Done.

https://codereview.appspot.com/8824044/diff/1/test/test_model.js
File test/test_model.js (right):

https://codereview.appspot.com/8824044/diff/1/test/test_model.js#newcode665
test/test_model.js:665: it('instances identify if they are alive',
function() {
On 2013/04/17 12:54:26, gary.poster wrote:
> (and also verifies that the default state is alive :-) )

Indeed! Added a comment.

https://codereview.appspot.com/8824044/

Revision history for this message
Francesco Banconi (frankban) wrote :

Thank you both for the reviews!

https://codereview.appspot.com/8824044/

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-04-16 12:24:34 +0000
+++ app/models/handlers.js 2013-04-17 13:37:24 +0000
@@ -166,6 +166,7 @@
166 id: change.Name,166 id: change.Name,
167 charm: change.CharmURL,167 charm: change.CharmURL,
168 exposed: change.Exposed,168 exposed: change.Exposed,
169 life: change.Life,
169 constraints: change.Constraints || {}170 constraints: change.Constraints || {}
170 };171 };
171 db.services.process_delta(action, data);172 db.services.process_delta(action, data);
172173
=== modified file 'app/models/models.js'
--- app/models/models.js 2013-04-12 16:04:02 +0000
+++ app/models/models.js 2013-04-17 13:37:24 +0000
@@ -91,7 +91,26 @@
91 });91 });
92 models.Environment = Environment;92 models.Environment = Environment;
9393
94 var Service = Y.Base.create('service', Y.Model, [], {}, {94 var ALIVE = 'alive';
95
96 var Service = Y.Base.create('service', Y.Model, [], {
97
98 /**
99 Return true if this service life is "alive", false otherwise.
100
101 A model instance is alive if its life cycle (i.e. the "life" attribute)
102 is set to "alive". Other possible values, as they arrive from the
103 juju-core delta stream, are "dying" and "dead", in which cases the
104 service is not considered alive.
105
106 @method isAlive
107 @return {Boolean} Whether this service is alive.
108 */
109 isAlive: function() {
110 return this.get('life') === ALIVE;
111 }
112
113 }, {
95 ATTRS: {114 ATTRS: {
96 displayName: {115 displayName: {
97 /**116 /**
@@ -115,6 +134,9 @@
115 pending: {134 pending: {
116 value: false135 value: false
117 },136 },
137 life: {
138 value: ALIVE
139 },
118 unit_count: {},140 unit_count: {},
119 aggregated_status: {}141 aggregated_status: {}
120 }142 }
@@ -124,6 +146,18 @@
124 var ServiceList = Y.Base.create('serviceList', Y.ModelList, [], {146 var ServiceList = Y.Base.create('serviceList', Y.ModelList, [], {
125 model: Service,147 model: Service,
126148
149 /**
150 Return a list of alive model instances.
151
152 @method alive
153 @return {Y.ModelList} The model instances having life === 'alive'.
154 */
155 alive: function() {
156 return this.filter({asList: true}, function(model) {
157 return model.isAlive();
158 });
159 },
160
127 process_delta: function(action, data) {161 process_delta: function(action, data) {
128 _process_delta(this, action, data, {exposed: false});162 _process_delta(this, action, data, {exposed: false});
129 }163 }
130164
=== modified file 'app/views/topology/service.js'
--- app/views/topology/service.js 2013-04-17 01:04:26 +0000
+++ app/views/topology/service.js 2013-04-17 13:37:24 +0000
@@ -353,7 +353,7 @@
353 var vis = topo.vis;353 var vis = topo.vis;
354 var db = topo.get('db');354 var db = topo.get('db');
355355
356 views.toBoundingBoxes(this, db.services, topo.service_boxes);356 views.toBoundingBoxes(this, db.services.alive(), topo.service_boxes);
357357
358 // Nodes are mapped by modelId tuples.358 // Nodes are mapped by modelId tuples.
359 this.node = vis.selectAll('.service')359 this.node = vis.selectAll('.service')
360360
=== modified file 'test/test_fakebackend.js'
--- test/test_fakebackend.js 2013-04-16 20:21:27 +0000
+++ test/test_fakebackend.js 2013-04-17 13:37:24 +0000
@@ -102,6 +102,7 @@
102 initialized: true,102 initialized: true,
103 name: 'wordpress',103 name: 'wordpress',
104 pending: false,104 pending: false,
105 life: 'alive',
105 subordinate: false,106 subordinate: false,
106 unit_count: undefined107 unit_count: undefined
107 });108 });
108109
=== modified file 'test/test_model.js'
--- test/test_model.js 2013-04-12 22:57:49 +0000
+++ test/test_model.js 2013-04-17 13:37:24 +0000
@@ -643,3 +643,39 @@
643 instance.get('recent_commit_count').should.equal(3);643 instance.get('recent_commit_count').should.equal(3);
644 });644 });
645});645});
646
647
648describe('service models', function() {
649 var models, list, django, rails, mysql;
650
651 before(function(done) {
652 YUI(GlobalConfig).use(['juju-models'], function(Y) {
653 models = Y.namespace('juju.models');
654 done();
655 });
656 });
657
658 beforeEach(function() {
659 django = new models.Service({id: 'django'});
660 rails = new models.Service({id: 'rails', life: 'dying'});
661 mysql = new models.Service({id: 'mysql', life: 'dead'});
662 list = new models.ServiceList({items: [rails, django, mysql]});
663 });
664
665 it('instances identify if they are alive', function() {
666 // This test also verifies that the default state is "alive".
667 assert.isTrue(django.isAlive());
668 });
669
670 it('instances identify if they are not alive (dying or dead)', function() {
671 assert.isFalse(rails.isAlive());
672 assert.isFalse(mysql.isAlive());
673 });
674
675 it('can be filtered so that it returns only alive models', function() {
676 var filtered = list.alive();
677 assert.strictEqual(1, filtered.size());
678 assert.deepEqual([django], filtered.toArray());
679 });
680
681});
646682
=== modified file 'test/test_model_handlers.js'
--- test/test_model_handlers.js 2013-04-15 19:00:44 +0000
+++ test/test_model_handlers.js 2013-04-17 13:37:24 +0000
@@ -193,7 +193,8 @@
193 Name: 'django',193 Name: 'django',
194 CharmURL: 'cs:precise/django-42',194 CharmURL: 'cs:precise/django-42',
195 Exposed: true,195 Exposed: true,
196 Constraints: constraints196 Constraints: constraints,
197 Life: 'alive'
197 };198 };
198 serviceInfo(db, 'add', change);199 serviceInfo(db, 'add', change);
199 assert.strictEqual(1, db.services.size());200 assert.strictEqual(1, db.services.size());
@@ -202,6 +203,7 @@
202 assert.strictEqual('cs:precise/django-42', service.get('charm'));203 assert.strictEqual('cs:precise/django-42', service.get('charm'));
203 assert.isTrue(service.get('exposed'));204 assert.isTrue(service.get('exposed'));
204 assert.deepEqual(constraints, service.get('constraints'));205 assert.deepEqual(constraints, service.get('constraints'));
206 assert.strictEqual('alive', service.get('life'));
205 });207 });
206208
207 it('updates a service in the database', function() {209 it('updates a service in the database', function() {
@@ -213,7 +215,8 @@
213 var change = {215 var change = {
214 Name: 'wordpress',216 Name: 'wordpress',
215 CharmURL: 'cs:quantal/wordpress-11',217 CharmURL: 'cs:quantal/wordpress-11',
216 Exposed: false218 Exposed: false,
219 Life: 'dying'
217 };220 };
218 serviceInfo(db, 'change', change);221 serviceInfo(db, 'change', change);
219 assert.strictEqual(1, db.services.size());222 assert.strictEqual(1, db.services.size());
@@ -221,6 +224,7 @@
221 var service = db.services.getById('wordpress');224 var service = db.services.getById('wordpress');
222 assert.strictEqual('cs:quantal/wordpress-11', service.get('charm'));225 assert.strictEqual('cs:quantal/wordpress-11', service.get('charm'));
223 assert.isFalse(service.get('exposed'));226 assert.isFalse(service.get('exposed'));
227 assert.strictEqual('dying', service.get('life'));
224 });228 });
225229
226 it('if constraints are not in the change stream they are {}',230 it('if constraints are not in the change stream they are {}',
227231
=== modified file 'test/test_service_module.js'
--- test/test_service_module.js 2013-04-08 21:40:05 +0000
+++ test/test_service_module.js 2013-04-17 13:37:24 +0000
@@ -311,4 +311,23 @@
311 // The flag is reset when encountered and ignored.311 // The flag is reset when encountered and ignored.
312 assert.isFalse(topo.ignoreServiceClick);312 assert.isFalse(topo.ignoreServiceClick);
313 });313 });
314
315 it('should hide dying or dead services', function() {
316 var haproxy = db.services.getById('haproxy'); // Added in beforeEach.
317 db.services.add([
318 {id: 'rails', life: 'dying'},
319 {id: 'mysql', life: 'dead'}
320 ]);
321 var django = db.services.add({id: 'django'});
322 serviceModule.update();
323 var boxes = topo.service_boxes;
324 // There are four services in total.
325 assert.strictEqual(4, db.services.size());
326 // But only two of those are actually displayed.
327 assert.strictEqual(2, Y.Object.size(boxes));
328 // And they are the alive ones.
329 assert.deepPropertyVal(boxes, 'haproxy.model', haproxy);
330 assert.deepPropertyVal(boxes, 'django.model', django);
331 });
332
314});333});

Subscribers

People subscribed via source and target branches