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
1=== modified file 'app/models/handlers.js'
2--- app/models/handlers.js 2013-04-16 12:24:34 +0000
3+++ app/models/handlers.js 2013-04-17 13:37:24 +0000
4@@ -166,6 +166,7 @@
5 id: change.Name,
6 charm: change.CharmURL,
7 exposed: change.Exposed,
8+ life: change.Life,
9 constraints: change.Constraints || {}
10 };
11 db.services.process_delta(action, data);
12
13=== modified file 'app/models/models.js'
14--- app/models/models.js 2013-04-12 16:04:02 +0000
15+++ app/models/models.js 2013-04-17 13:37:24 +0000
16@@ -91,7 +91,26 @@
17 });
18 models.Environment = Environment;
19
20- var Service = Y.Base.create('service', Y.Model, [], {}, {
21+ var ALIVE = 'alive';
22+
23+ var Service = Y.Base.create('service', Y.Model, [], {
24+
25+ /**
26+ Return true if this service life is "alive", false otherwise.
27+
28+ A model instance is alive if its life cycle (i.e. the "life" attribute)
29+ is set to "alive". Other possible values, as they arrive from the
30+ juju-core delta stream, are "dying" and "dead", in which cases the
31+ service is not considered alive.
32+
33+ @method isAlive
34+ @return {Boolean} Whether this service is alive.
35+ */
36+ isAlive: function() {
37+ return this.get('life') === ALIVE;
38+ }
39+
40+ }, {
41 ATTRS: {
42 displayName: {
43 /**
44@@ -115,6 +134,9 @@
45 pending: {
46 value: false
47 },
48+ life: {
49+ value: ALIVE
50+ },
51 unit_count: {},
52 aggregated_status: {}
53 }
54@@ -124,6 +146,18 @@
55 var ServiceList = Y.Base.create('serviceList', Y.ModelList, [], {
56 model: Service,
57
58+ /**
59+ Return a list of alive model instances.
60+
61+ @method alive
62+ @return {Y.ModelList} The model instances having life === 'alive'.
63+ */
64+ alive: function() {
65+ return this.filter({asList: true}, function(model) {
66+ return model.isAlive();
67+ });
68+ },
69+
70 process_delta: function(action, data) {
71 _process_delta(this, action, data, {exposed: false});
72 }
73
74=== modified file 'app/views/topology/service.js'
75--- app/views/topology/service.js 2013-04-17 01:04:26 +0000
76+++ app/views/topology/service.js 2013-04-17 13:37:24 +0000
77@@ -353,7 +353,7 @@
78 var vis = topo.vis;
79 var db = topo.get('db');
80
81- views.toBoundingBoxes(this, db.services, topo.service_boxes);
82+ views.toBoundingBoxes(this, db.services.alive(), topo.service_boxes);
83
84 // Nodes are mapped by modelId tuples.
85 this.node = vis.selectAll('.service')
86
87=== modified file 'test/test_fakebackend.js'
88--- test/test_fakebackend.js 2013-04-16 20:21:27 +0000
89+++ test/test_fakebackend.js 2013-04-17 13:37:24 +0000
90@@ -102,6 +102,7 @@
91 initialized: true,
92 name: 'wordpress',
93 pending: false,
94+ life: 'alive',
95 subordinate: false,
96 unit_count: undefined
97 });
98
99=== modified file 'test/test_model.js'
100--- test/test_model.js 2013-04-12 22:57:49 +0000
101+++ test/test_model.js 2013-04-17 13:37:24 +0000
102@@ -643,3 +643,39 @@
103 instance.get('recent_commit_count').should.equal(3);
104 });
105 });
106+
107+
108+describe('service models', function() {
109+ var models, list, django, rails, mysql;
110+
111+ before(function(done) {
112+ YUI(GlobalConfig).use(['juju-models'], function(Y) {
113+ models = Y.namespace('juju.models');
114+ done();
115+ });
116+ });
117+
118+ beforeEach(function() {
119+ django = new models.Service({id: 'django'});
120+ rails = new models.Service({id: 'rails', life: 'dying'});
121+ mysql = new models.Service({id: 'mysql', life: 'dead'});
122+ list = new models.ServiceList({items: [rails, django, mysql]});
123+ });
124+
125+ it('instances identify if they are alive', function() {
126+ // This test also verifies that the default state is "alive".
127+ assert.isTrue(django.isAlive());
128+ });
129+
130+ it('instances identify if they are not alive (dying or dead)', function() {
131+ assert.isFalse(rails.isAlive());
132+ assert.isFalse(mysql.isAlive());
133+ });
134+
135+ it('can be filtered so that it returns only alive models', function() {
136+ var filtered = list.alive();
137+ assert.strictEqual(1, filtered.size());
138+ assert.deepEqual([django], filtered.toArray());
139+ });
140+
141+});
142
143=== modified file 'test/test_model_handlers.js'
144--- test/test_model_handlers.js 2013-04-15 19:00:44 +0000
145+++ test/test_model_handlers.js 2013-04-17 13:37:24 +0000
146@@ -193,7 +193,8 @@
147 Name: 'django',
148 CharmURL: 'cs:precise/django-42',
149 Exposed: true,
150- Constraints: constraints
151+ Constraints: constraints,
152+ Life: 'alive'
153 };
154 serviceInfo(db, 'add', change);
155 assert.strictEqual(1, db.services.size());
156@@ -202,6 +203,7 @@
157 assert.strictEqual('cs:precise/django-42', service.get('charm'));
158 assert.isTrue(service.get('exposed'));
159 assert.deepEqual(constraints, service.get('constraints'));
160+ assert.strictEqual('alive', service.get('life'));
161 });
162
163 it('updates a service in the database', function() {
164@@ -213,7 +215,8 @@
165 var change = {
166 Name: 'wordpress',
167 CharmURL: 'cs:quantal/wordpress-11',
168- Exposed: false
169+ Exposed: false,
170+ Life: 'dying'
171 };
172 serviceInfo(db, 'change', change);
173 assert.strictEqual(1, db.services.size());
174@@ -221,6 +224,7 @@
175 var service = db.services.getById('wordpress');
176 assert.strictEqual('cs:quantal/wordpress-11', service.get('charm'));
177 assert.isFalse(service.get('exposed'));
178+ assert.strictEqual('dying', service.get('life'));
179 });
180
181 it('if constraints are not in the change stream they are {}',
182
183=== modified file 'test/test_service_module.js'
184--- test/test_service_module.js 2013-04-08 21:40:05 +0000
185+++ test/test_service_module.js 2013-04-17 13:37:24 +0000
186@@ -311,4 +311,23 @@
187 // The flag is reset when encountered and ignored.
188 assert.isFalse(topo.ignoreServiceClick);
189 });
190+
191+ it('should hide dying or dead services', function() {
192+ var haproxy = db.services.getById('haproxy'); // Added in beforeEach.
193+ db.services.add([
194+ {id: 'rails', life: 'dying'},
195+ {id: 'mysql', life: 'dead'}
196+ ]);
197+ var django = db.services.add({id: 'django'});
198+ serviceModule.update();
199+ var boxes = topo.service_boxes;
200+ // There are four services in total.
201+ assert.strictEqual(4, db.services.size());
202+ // But only two of those are actually displayed.
203+ assert.strictEqual(2, Y.Object.size(boxes));
204+ // And they are the alive ones.
205+ assert.deepPropertyVal(boxes, 'haproxy.model', haproxy);
206+ assert.deepPropertyVal(boxes, 'django.model', django);
207+ });
208+
209 });

Subscribers

People subscribed via source and target branches