github.com/kjdelisle/consul@v1.4.5/ui/javascripts/app/routes.js (about)

     1  //
     2  // Superclass to be used by all of the main routes below.
     3  //
     4  App.BaseRoute = Ember.Route.extend({
     5    rootKey: '',
     6    condensedView: false,
     7  
     8    // Don't record characters in browser history
     9    // for the "search" query item (filter)
    10    queryParams: {
    11      filter: {
    12        replace: true
    13      }
    14    },
    15  
    16    getParentAndGrandparent: function(key) {
    17      var parentKey = this.rootKey,
    18          grandParentKey = this.rootKey,
    19          parts = key.split('/');
    20  
    21      if (parts.length > 0) {
    22        parts.pop();
    23        parentKey = parts.join("/") + "/";
    24      }
    25  
    26      if (parts.length > 1) {
    27        parts.pop();
    28        grandParentKey = parts.join("/") + "/";
    29      }
    30  
    31      return {
    32        parent: parentKey,
    33        grandParent: grandParentKey,
    34        isRoot: parentKey === '/'
    35      };
    36    },
    37  
    38    removeDuplicateKeys: function(keys, matcher) {
    39      // Loop over the keys
    40      keys.forEach(function(item, index) {
    41        if (item.get('Key') == matcher) {
    42        // If we are in a nested folder and the folder
    43        // name matches our position, remove it
    44          keys.splice(index, 1);
    45        }
    46      });
    47      return keys;
    48    },
    49  
    50    actions: {
    51      // Used to link to keys that are not objects,
    52      // like parents and grandParents
    53      linkToKey: function(key) {
    54        if (key == "/") {
    55          this.transitionTo('kv.show', "");
    56        }
    57        else if (key.slice(-1) === '/' || key === this.rootKey) {
    58          this.transitionTo('kv.show', key);
    59        } else {
    60          this.transitionTo('kv.edit', key);
    61        }
    62      }
    63    }
    64  });
    65  
    66  //
    67  // The route for choosing datacenters, typically the first route loaded.
    68  //
    69  App.IndexRoute = App.BaseRoute.extend({
    70    // Retrieve the list of datacenters
    71    model: function(params) {
    72      return Ember.$.getJSON(consulHost + '/v1/catalog/datacenters').then(function(data) {
    73        return data;
    74      });
    75    },
    76  
    77    afterModel: function(model, transition) {
    78      // If we only have one datacenter, jump
    79      // straight to it and bypass the global
    80      // view
    81      if (model.get('length') === 1) {
    82        this.transitionTo('services', model[0]);
    83      }
    84    }
    85  });
    86  
    87  // The parent route for all resources. This keeps the top bar
    88  // functioning, as well as the per-dc requests.
    89  App.DcRoute = App.BaseRoute.extend({
    90    model: function(params) {
    91      var token = App.get('settings.token');
    92  
    93      // Return a promise hash to retrieve the
    94      // dcs and nodes used in the header
    95      return Ember.RSVP.hash({
    96        dc: params.dc,
    97        dcs: Ember.$.getJSON(consulHost + '/v1/catalog/datacenters'),
    98        nodes: Ember.$.getJSON(formatUrl(consulHost + '/v1/internal/ui/nodes', params.dc, token)).then(function(data) {
    99          var objs = [];
   100  
   101          // Merge the nodes into a list and create objects out of them
   102          data.map(function(obj){
   103            objs.push(App.Node.create(obj));
   104          });
   105  
   106          return objs;
   107        }),
   108        coordinates: Ember.$.getJSON(formatUrl(consulHost + '/v1/coordinate/nodes', params.dc, token)).then(function(data) {
   109          return data;
   110        })
   111      });
   112    },
   113  
   114    setupController: function(controller, models) {
   115      controller.set('content', models.dc);
   116      controller.set('nodes', models.nodes);
   117      controller.set('dcs', models.dcs);
   118      controller.set('coordinates', models.coordinates);
   119      controller.set('isDropdownVisible', false);
   120    },
   121  });
   122  
   123  App.KvIndexRoute = App.BaseRoute.extend({
   124    beforeModel: function() {
   125      this.transitionTo('kv.show', this.rootKey);
   126    }
   127  });
   128  
   129  App.KvShowRoute = App.BaseRoute.extend({
   130    model: function(params) {
   131      var key = params.key;
   132      var dc = this.modelFor('dc').dc;
   133      var token = App.get('settings.token');
   134  
   135      // Return a promise has with the ?keys for that namespace
   136      // and the original key requested in params
   137      return Ember.RSVP.hash({
   138        key: key,
   139        keys: Ember.$.getJSON(formatUrl(consulHost + '/v1/kv/' + key + '?keys&seperator=/', dc, token)).then(function(data) {
   140          var objs = [];
   141          data.map(function(obj){
   142            objs.push(App.Key.create({Key: obj}));
   143          });
   144          return objs;
   145        })
   146      });
   147    },
   148  
   149    setupController: function(controller, models) {
   150      var key = models.key;
   151      var parentKeys = this.getParentAndGrandparent(key);
   152      models.keys = this.removeDuplicateKeys(models.keys, models.key);
   153  
   154      controller.set('content', models.keys);
   155      controller.set('parentKey', parentKeys.parent);
   156      controller.set('grandParentKey', parentKeys.grandParent);
   157      controller.set('isRoot', parentKeys.isRoot);
   158      controller.set('newKey', App.Key.create());
   159      controller.set('rootKey', this.rootKey);
   160    }
   161  });
   162  
   163  App.KvEditRoute = App.BaseRoute.extend({
   164    model: function(params) {
   165      var key = params.key;
   166      var dc = this.modelFor('dc').dc;
   167      var parentKeys = this.getParentAndGrandparent(key);
   168      var token = App.get('settings.token');
   169  
   170      // Return a promise hash to get the data for both columns
   171      return Ember.RSVP.hash({
   172        dc: dc,
   173        token: token,
   174        key: Ember.$.getJSON(formatUrl(consulHost + '/v1/kv/' + key, dc, token)).then(function(data) {
   175          // Convert the returned data to a Key
   176          return App.Key.create().setProperties(data[0]);
   177        }),
   178        keys: keysPromise = Ember.$.getJSON(formatUrl(consulHost + '/v1/kv/' + parentKeys.parent + '?keys&seperator=/', dc, token)).then(function(data) {
   179          var objs = [];
   180          data.map(function(obj){
   181           objs.push(App.Key.create({Key: obj}));
   182          });
   183          return objs;
   184        }),
   185      });
   186    },
   187  
   188    // Load the session on the key, if there is one
   189    afterModel: function(models) {
   190      if (models.key.get('isLocked')) {
   191        return Ember.$.getJSON(formatUrl(consulHost + '/v1/session/info/' + models.key.Session, models.dc, models.token)).then(function(data) {
   192          models.session = data[0];
   193          return models;
   194        });
   195      } else {
   196        return models;
   197      }
   198    },
   199  
   200    setupController: function(controller, models) {
   201      var key = models.key;
   202      var parentKeys = this.getParentAndGrandparent(key.get('Key'));
   203      models.keys = this.removeDuplicateKeys(models.keys, parentKeys.parent);
   204  
   205      controller.set('content', models.key);
   206      controller.set('parentKey', parentKeys.parent);
   207      controller.set('grandParentKey', parentKeys.grandParent);
   208      controller.set('isRoot', parentKeys.isRoot);
   209      controller.set('siblings', models.keys);
   210      controller.set('rootKey', this.rootKey);
   211      controller.set('session', models.session);
   212    }
   213  });
   214  
   215  App.ServicesRoute = App.BaseRoute.extend({
   216    model: function(params) {
   217      var dc = this.modelFor('dc').dc;
   218      var token = App.get('settings.token');
   219  
   220      // Return a promise to retrieve all of the services
   221      return Ember.$.getJSON(formatUrl(consulHost + '/v1/internal/ui/services', dc, token)).then(function(data) {
   222        var objs = [];
   223        data.map(function(obj){
   224         objs.push(App.Service.create(obj));
   225        });
   226        return objs;
   227      });
   228    },
   229    setupController: function(controller, model) {
   230      controller.set('services', model);
   231    }
   232  });
   233  
   234  
   235  App.ServicesShowRoute = App.BaseRoute.extend({
   236    model: function(params) {
   237      var dc = this.modelFor('dc').dc;
   238      var token = App.get('settings.token');
   239  
   240      // Here we just use the built-in health endpoint, as it gives us everything
   241      // we need.
   242      return Ember.$.getJSON(formatUrl(consulHost + '/v1/health/service/' + params.name, dc, token)).then(function(data) {
   243        var objs = [];
   244        data.map(function(obj){
   245         objs.push(App.Node.create(obj));
   246        });
   247        return objs;
   248      });
   249    },
   250    setupController: function(controller, model) {
   251      var tags = [];
   252      model.map(function(obj){
   253        if (obj.Service.Tags !== null) {
   254          tags = tags.concat(obj.Service.Tags);
   255        }
   256      });
   257  
   258      tags = tags.filter(function(n){ return n !== undefined; });
   259      tags = tags.uniq().join(', ');
   260  
   261      controller.set('content', model);
   262      controller.set('tags', tags);
   263    }
   264  });
   265  
   266  function distance(a, b) {
   267      a = a.Coord;
   268      b = b.Coord;
   269      var sum = 0;
   270      for (var i = 0; i < a.Vec.length; i++) {
   271          var diff = a.Vec[i] - b.Vec[i];
   272          sum += diff * diff;
   273      }
   274      var rtt = Math.sqrt(sum) + a.Height + b.Height;
   275  
   276      var adjusted = rtt + a.Adjustment + b.Adjustment;
   277      if (adjusted > 0.0) {
   278          rtt = adjusted;
   279      }
   280  
   281      return Math.round(rtt * 100000.0) / 100.0;
   282  }
   283  
   284  App.NodesShowRoute = App.BaseRoute.extend({
   285    model: function(params) {
   286      var dc = this.modelFor('dc');
   287      var token = App.get('settings.token');
   288  
   289      var min = 999999999;
   290      var max = -999999999;
   291      var sum = 0;
   292      var distances = [];
   293      dc.coordinates.forEach(function (node) {
   294        if (params.name == node.Node) {
   295          var segment = node.Segment;
   296          dc.coordinates.forEach(function (other) {
   297            if (node.Node != other.Node && other.Segment == segment) {
   298              var dist = distance(node, other);
   299              distances.push({ node: other.Node, distance: dist, segment: segment });
   300              sum += dist;
   301              if (dist < min) {
   302                min = dist;
   303              }
   304              if (dist > max) {
   305                max = dist;
   306              }
   307            }
   308          });
   309          distances.sort(function (a, b) {
   310            return a.distance - b.distance;
   311          });
   312        }
   313      });
   314      var n = distances.length;
   315      var halfN = Math.floor(n / 2);
   316      var median;
   317  
   318      if (n > 0) {
   319        if (n % 2) {
   320          // odd
   321          median = distances[halfN].distance;
   322        } else {
   323          median = (distances[halfN - 1].distance + distances[halfN].distance) / 2;
   324        }
   325      } else {
   326        median = 0;
   327        min = 0;
   328        max = 0;
   329      }
   330  
   331      // Return a promise hash of the node
   332      return Ember.RSVP.hash({
   333        dc: dc.dc,
   334        token: token,
   335        tomography: {
   336          distances: distances,
   337          n: distances.length,
   338          min: parseInt(min * 100) / 100,
   339          median: parseInt(median * 100) / 100,
   340          max: parseInt(max * 100) / 100
   341        },
   342        node: Ember.$.getJSON(formatUrl(consulHost + '/v1/internal/ui/node/' + params.name, dc.dc, token)).then(function(data) {
   343          return App.Node.create(data);
   344        })
   345      });
   346    },
   347  
   348    // Load the sessions for the node
   349    afterModel: function(models) {
   350      return Ember.$.getJSON(formatUrl(consulHost + '/v1/session/node/' + models.node.Node, models.dc, models.token)).then(function(data) {
   351        models.sessions = data;
   352        return models;
   353      });
   354    },
   355  
   356    setupController: function(controller, models) {
   357        controller.set('content', models.node);
   358        controller.set('sessions', models.sessions);
   359        controller.set('tomography', models.tomography);
   360    }
   361  });
   362  
   363  App.NodesRoute = App.BaseRoute.extend({
   364    model: function(params) {
   365      var dc = this.modelFor('dc').dc;
   366      var token = App.get('settings.token');
   367  
   368      // Return a promise containing the nodes
   369      return Ember.$.getJSON(formatUrl(consulHost + '/v1/internal/ui/nodes', dc, token)).then(function(data) {
   370        var objs = [];
   371        data.map(function(obj){
   372         objs.push(App.Node.create(obj));
   373        });
   374        return objs;
   375      });
   376    },
   377    setupController: function(controller, model) {
   378      controller.set('nodes', model);
   379    }
   380  });
   381  
   382  
   383  App.AclsRoute = App.BaseRoute.extend({
   384    model: function(params) {
   385      var dc = this.modelFor('dc').dc;
   386      var token = App.get('settings.token');
   387      // Return a promise containing the ACLS
   388      return Ember.$.getJSON(formatUrl(consulHost + '/v1/acl/list', dc, token)).then(function(data) {
   389        var objs = [];
   390        data.map(function(obj){
   391          if (obj.ID === "anonymous") {
   392            objs.unshift(App.Acl.create(obj));
   393          } else {
   394            objs.push(App.Acl.create(obj));
   395          }
   396        });
   397        return objs;
   398      });
   399    },
   400  
   401    actions: {
   402      error: function(error, transition) {
   403        // If consul returns 401, ACLs are disabled
   404        if (error && error.status === 401) {
   405          this.transitionTo('dc.aclsdisabled');
   406        // If consul returns 403, they key isn't authorized for that
   407        // action.
   408        } else if (error && error.status === 403) {
   409          this.transitionTo('dc.unauthorized');
   410        }
   411        return true;
   412      }
   413    },
   414  
   415    setupController: function(controller, model) {
   416        controller.set('acls', model);
   417        controller.set('newAcl', App.Acl.create());
   418    }
   419  });
   420  
   421  App.AclsShowRoute = App.BaseRoute.extend({
   422    model: function(params) {
   423      var dc = this.modelFor('dc').dc;
   424      var token = App.get('settings.token');
   425  
   426      // Return a promise hash of the ACLs
   427      return Ember.RSVP.hash({
   428        dc: dc,
   429        acl: Ember.$.getJSON(formatUrl(consulHost + '/v1/acl/info/'+ params.id, dc, token)).then(function(data) {
   430          return App.Acl.create(data[0]);
   431        })
   432      });
   433    },
   434  
   435    setupController: function(controller, models) {
   436        controller.set('content', models.acl);
   437    }
   438  });
   439  
   440  App.SettingsRoute = App.BaseRoute.extend({
   441    model: function(params) {
   442      return App.get('settings');
   443    }
   444  });
   445  
   446  
   447  // Adds any global parameters we need to set to a url/path
   448  function formatUrl(url, dc, token) {
   449    if (token == null) {
   450      token = "";
   451    }
   452    if (url.indexOf("?") > 0) {
   453      // If our url has existing params
   454      url = url + "&dc=" + dc;
   455      url = url + "&token=" + token;
   456    } else {
   457      // Our url doesn't have params
   458      url = url + "?dc=" + dc;
   459      url = url + "&token=" + token;
   460    }
   461    return url;
   462  }