~makyo/juju-gui/rel-prep

« back to all changes in this revision

Viewing changes to app/store/env/sandbox.js

  • Committer: Benjamin Saller
  • Author(s): Benjamin Saller
  • Date: 2013-10-10 17:06:41 UTC
  • mfrom: (1108.2.4 restore-bundle-annotations)
  • Revision ID: bcsaller@gmail.com-20131010170641-igy2gv5i6qsinl4s
Fix annotations on go backend

Fix annotation roundtrips with go backend
      Splits how we prepare deltas for py/go juju fakebackends
      Change test expectations to merge updateAnnotation calls
  
  Fix import of constraints
  Fix export of undefined/default values
  
  Adjust simulator unit count rate of change.

R=benjamin.saller, gary.poster, jeff.pihach
CC=
https://codereview.appspot.com/14485046

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
/**
22
22
Sandbox APIs mimicking communications with the Go and Python backends.
23
 
 
24
23
@module env
25
24
@submodule env.sandbox
26
25
*/
28
27
YUI.add('juju-env-sandbox', function(Y) {
29
28
 
30
29
  var sandboxModule = Y.namespace('juju.environments.sandbox');
 
30
  var models = Y.namespace('juju.models');
31
31
  var CLOSEDERROR = 'INVALID_STATE_ERR : Connection is closed.';
32
32
 
33
33
  /**
237
237
  };
238
238
 
239
239
  /**
240
 
  Prepare a delta of events to send to the client since the last time they
241
 
  asked.  The deltas list is prepared nearly the same way depending on Py or Go
242
 
  implentation, but the data within the individual deltas must be structured
243
 
  dependent on the backend.  This method is called using `apply` from within
244
 
  the appropriate sandbox so that `this._deltaWhitelist` and
245
 
  `self._getDeltaAttrs` can structure the delta according to the juju type.
246
 
 
247
 
  @method _prepareDelta
248
 
  @return {Array} An array of deltas events.
249
 
  */
250
 
  var _prepareDelta = function() {
251
 
    var self = this;
252
 
    var state = this.get('state');
253
 
    var deltas = [];
254
 
    var changes = state.nextChanges();
255
 
    if (changes && changes.error) {
256
 
      changes = null;
257
 
    }
258
 
    var annotations = state.nextAnnotations();
259
 
    if (annotations && annotations.error) {
260
 
      annotations = null;
261
 
    }
262
 
    if (changes || annotations) {
263
 
      Y.each(this._deltaWhitelist, function(whitelist, changeType) {
264
 
        var collectionName = changeType + 's';
265
 
        if (changes) {
266
 
          Y.each(changes[collectionName], function(change) {
267
 
            var attrs = self._getDeltaAttrs(change[0], whitelist);
268
 
            var action = change[1] ? 'change' : 'remove';
269
 
            // The unit changeType is actually "serviceUnit" in the Python
270
 
            // stream.  Our model code handles either, so we're not modifying
271
 
            // it for now.
272
 
            var delta = [changeType, action, attrs];
273
 
            deltas.push(delta);
274
 
          });
275
 
        }
276
 
        if (annotations) {
277
 
          Y.each(annotations[changeType + 's'], function(attrs, key) {
278
 
            if (!changes || !changes[key]) {
279
 
              attrs = self._getDeltaAttrs(attrs, whitelist);
280
 
              // Special case environment handling.
281
 
              if (changeType === 'annotation') {
282
 
                changeType = 'annotations';
283
 
                attrs = attrs.annotations;
284
 
              }
285
 
              deltas.push([changeType, 'change', attrs]);
286
 
            }
287
 
          });
288
 
        }
289
 
      });
290
 
    }
291
 
    return deltas;
292
 
  };
293
 
 
294
 
  /**
295
240
  A sandbox Juju environment using the Python API.
296
241
 
297
242
  @class PyJujuAPI
388
333
    },
389
334
 
390
335
    /**
 
336
      Prepare a delta of events to send to the client since the last time they
 
337
      asked.  The deltas list is prepared nearly the same way depending on Py
 
338
      or Go implentation, but the data within the individual deltas must be
 
339
      structured dependent on the backend.  This method is called using `apply`
 
340
      from within the appropriate sandbox so that `this._deltaWhitelist` and
 
341
      `self._getDeltaAttrs` can structure the delta according to the juju type.
 
342
 
 
343
      @method _prepareDelta
 
344
      @return {Array} An array of deltas events.
 
345
      */
 
346
    _prepareDelta: function() {
 
347
      var self = this;
 
348
      var state = this.get('state');
 
349
      var deltas = [];
 
350
      var changes = state.nextChanges();
 
351
      if (changes && changes.error) {
 
352
        changes = null;
 
353
      }
 
354
      var annotations = state.nextAnnotations();
 
355
      if (annotations && annotations.error) {
 
356
        annotations = null;
 
357
      }
 
358
      if (changes || annotations) {
 
359
        Y.each(this._deltaWhitelist, function(whitelist, changeType) {
 
360
          var collectionName = changeType + 's';
 
361
          if (changes) {
 
362
            Y.each(changes[collectionName], function(change) {
 
363
              var attrs = self._getDeltaAttrs(change[0], whitelist);
 
364
              var action = change[1] ? 'change' : 'remove';
 
365
              // The unit changeType is actually "serviceUnit" in the Python
 
366
              // stream.  Our model code handles either, so we're not modifying
 
367
              // it for now.
 
368
              var delta = [changeType, action, attrs];
 
369
              deltas.push(delta);
 
370
            });
 
371
          }
 
372
          if (annotations) {
 
373
            Y.each(annotations[changeType + 's'], function(attrs, key) {
 
374
              if (!changes || !changes[key]) {
 
375
                attrs = self._getDeltaAttrs(attrs, whitelist);
 
376
                // Special case environment handling.
 
377
                if (changeType === 'annotation') {
 
378
                  changeType = 'annotations';
 
379
                  attrs = attrs.annotations;
 
380
                }
 
381
                deltas.push([changeType, 'change', attrs]);
 
382
              }
 
383
            });
 
384
          }
 
385
        });
 
386
      }
 
387
      return deltas;
 
388
    },
 
389
 
 
390
    /**
391
391
    Send a delta of events to the client from since the last time they asked.
392
392
 
393
393
    @method sendDelta
394
394
    @return {undefined} Nothing.
395
395
    */
396
396
    sendDelta: function() {
397
 
      var deltas = _prepareDelta.apply(this);
 
397
      var deltas = this._prepareDelta();
398
398
      if (deltas.length) {
399
399
        this.get('client').receiveNow({op: 'delta', result: deltas});
400
400
      }
804
804
      }
805
805
    },
806
806
 
 
807
 
807
808
    /**
808
809
    Handle Login messages to the state object.
809
810
 
908
909
        }
909
910
      },
910
911
      annotation: {
911
 
        'Tag': function() {
 
912
        'Tag': function(entity) {
 
913
          return entity.id;
912
914
        },
913
 
        'Annotations': function() {}
 
915
        'Annotations': function(entity) {
 
916
          return entity.annotations;
 
917
        }
914
918
      }
915
919
    },
916
920
 
942
946
    },
943
947
 
944
948
    /**
 
949
      Prepare a delta of events to send to the client since the last time they
 
950
      asked.  The deltas list is prepared nearly the same way depending on Py
 
951
      or Go implentation, but the data within the individual deltas must be
 
952
      structured dependent on the backend.  This method is called using `apply`
 
953
      from within the appropriate sandbox so that `this._deltaWhitelist` and
 
954
      `self._getDeltaAttrs` can structure the delta according to the juju type.
 
955
 
 
956
      @method _prepareDelta
 
957
      @return {Array} An array of deltas events.
 
958
      */
 
959
    _prepareDelta: function() {
 
960
      var self = this;
 
961
      var state = this.get('state');
 
962
      var deltas = [];
 
963
      var changes = state.nextChanges();
 
964
      if (changes && changes.error) {
 
965
        changes = null;
 
966
      }
 
967
      if (changes) {
 
968
        Y.each(this._deltaWhitelist, function(whitelist, changeType) {
 
969
          var collectionName = changeType + 's';
 
970
          if (changes) {
 
971
            Y.each(changes[collectionName], function(change) {
 
972
              var attrs = self._getDeltaAttrs(change[0], whitelist);
 
973
              var action = change[1] ? 'change' : 'remove';
 
974
              // The unit changeType is actually "serviceUnit" in the Python
 
975
              // stream.  Our model code handles either, so we're not modifying
 
976
              // it for now.
 
977
              var delta = [changeType, action, attrs];
 
978
              deltas.push(delta);
 
979
            });
 
980
          }
 
981
        });
 
982
      }
 
983
      return deltas;
 
984
    },
 
985
 
 
986
    /**
 
987
 
 
988
      Prepare the juju-core specific version of annotation information.
 
989
      This has its own (core styled) formatting. This is different from
 
990
      the Python version which includes annotations in the normal object
 
991
      change stream.
 
992
 
 
993
      @method _prepareAnnotations
 
994
      @return [ {Object} ] Array of annotation deltas.
 
995
    */
 
996
    _prepareAnnotations: function() {
 
997
      var state = this.get('state');
 
998
      var deltas = [];
 
999
      var annotations = state.nextAnnotations();
 
1000
      if (annotations && annotations.error) {
 
1001
        annotations = null;
 
1002
      }
 
1003
      if (annotations) {
 
1004
        Y.each(this._deltaWhitelist, function(whitelist, changeType) {
 
1005
          Y.each(annotations[changeType + 's'], function(model, key) {
 
1006
            var attrs = models.getAnnotations(model);
 
1007
            var tag = this.modelToTag(model);
 
1008
            // This form will trigger the annotationInfo handler.
 
1009
            deltas.push(['annotation', 'change', {
 
1010
              Tag: tag, Annotations: attrs}]);
 
1011
          }, this);
 
1012
        }, this);
 
1013
      }
 
1014
      return deltas;
 
1015
    },
 
1016
 
 
1017
    /**
 
1018
     Map from a model to a Tag name as used in juju-core
 
1019
 
 
1020
     @method modelToTag
 
1021
     @param {Object} model
 
1022
     @return {String} tag.
 
1023
    */
 
1024
    modelToTag: function(model) {
 
1025
      var name = model.name;
 
1026
      if (name === 'serviceUnit') {
 
1027
        name = 'unit';
 
1028
      } else if (name === 'environment') {
 
1029
        return 'env';
 
1030
      }
 
1031
      return name + '-' + (model.id || model.get('id'));
 
1032
    },
 
1033
 
 
1034
 
 
1035
 
 
1036
    /**
945
1037
    Send a delta of events to the client from since the last time they asked.
946
1038
 
947
1039
    @method sendDelta
950
1042
    sendDelta: function() {
951
1043
      var nextRequestId = this.get('nextRequestId');
952
1044
      if (nextRequestId) {
953
 
        var deltas = _prepareDelta.apply(this);
954
 
        if (deltas.length) {
 
1045
        var deltas = this._prepareDelta();
 
1046
        var annotations = this._prepareAnnotations();
 
1047
        if (deltas.length || annotations.length) {
955
1048
          this.get('client').receive({
956
1049
            RequestId: this.get('nextRequestId'),
957
 
            Response: {Deltas: deltas}
 
1050
            Response: {Deltas: deltas.concat(annotations)}
958
1051
          });
959
1052
          // Prevent sending additional deltas until the Go environment is
960
1053
          // ready for them (when the next `Next` message is sent).
1264
1357
    @return {undefined} Side effects only.
1265
1358
    */
1266
1359
    handleClientSetAnnotations: function(data, client, state) {
1267
 
      var serviceId = /service-([^ ]*)$/.exec(data.Params.Tag)[1];
1268
 
      var result = state.updateAnnotations(serviceId, data.Params.Pairs);
 
1360
      var entityId = /^(service|unit|machine|environment)-([^ ]*)$/.
 
1361
          exec(data.Params.Tag)[2];
 
1362
      var result = state.updateAnnotations(entityId, data.Params.Pairs);
1269
1363
      this._basicReceive(data, client, result);
1270
1364
    },
1271
1365