http://git-wip-us.apache.org/repos/asf/mesos/blob/c7685917/src/webui/master/static/js/controllers.js
----------------------------------------------------------------------
diff --git a/src/webui/master/static/js/controllers.js 
b/src/webui/master/static/js/controllers.js
deleted file mode 100644
index 66a4f29..0000000
--- a/src/webui/master/static/js/controllers.js
+++ /dev/null
@@ -1,1179 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-(function() {
-  'use strict';
-
-  var mesosApp = angular.module('mesos');
-
-  function hasSelectedText() {
-    if (window.getSelection) {  // All browsers except IE before version 9.
-      var range = window.getSelection();
-      return range.toString().length > 0;
-    }
-    return false;
-  }
-
-  // Returns the URL prefix for an agent, there are two cases
-  // to consider:
-  //
-  //   (1) Some endpoints for the agent process itself require
-  //       the agent PID.name (processId) in the path, this is
-  //       to ensure that the webui works correctly when running
-  //       against mesos-local or other instances of multiple agents
-  //       running within the same "host:port":
-  //
-  //         //hostname:port/slave(1)
-  //         //hostname:port/slave(2)
-  //         ...
-  //
-  //   (2) Some endpoints for other components in the agent
-  //       do not require the agent PID.name in the path, since
-  //       a single endpoint serves multiple agents within the
-  //       same process. In this case we just return:
-  //
-  //         //hostname:port
-  //
-  // Note that there are some clashing issues in mesos-local
-  // (e.g., hosting '/slave/log' for each agent log, we don't
-  // namespace metrics within '/metrics/snapshot', etc).
-  function agentURLPrefix(agent, includeProcessId) {
-    var port = agent.pid.substring(agent.pid.lastIndexOf(':') + 1);
-    var processId = agent.pid.substring(0, agent.pid.indexOf('@'));
-
-    var url = '//' + agent.hostname + ':' + port;
-
-    if (includeProcessId) {
-      url += '/' + processId;
-    }
-
-    return url;
-  }
-
-  // Invokes the pailer, building the endpoint URL with the specified urlPrefix
-  // and path.
-  function pailer(urlPrefix, path, window_title) {
-    var url = urlPrefix + '/files/read?path=' + path;
-
-    // The randomized `storageKey` is removed from `localStorage` once the
-    // pailer window loads the URL into its `sessionStorage`, therefore
-    // the probability of collisions is low and we do not use a uuid.
-    var storageKey = Math.random().toString(36).substr(2, 8);
-
-    // Store the target URL in `localStorage` which is
-    // accessed by the pailer window when opened.
-    localStorage.setItem(storageKey, url);
-
-    var pailer =
-      window.open('static/pailer.html', storageKey, 'width=580px, 
height=700px');
-
-    // Need to use window.onload instead of document.ready to make
-    // sure the title doesn't get overwritten.
-    pailer.onload = function() {
-      pailer.document.title = window_title;
-    };
-  }
-
-
-  function updateInterval(num_agents) {
-    // TODO(bmahler): Increasing the update interval for large clusters
-    // is done purely to mitigate webui performance issues. Ideally we can
-    // keep a consistently fast rate for updating statistical information.
-    // For the full system state updates, it may make sense to break
-    // it up using pagination and/or splitting the endpoint.
-    if (num_agents < 500) {
-      return 10000;
-    } else if (num_agents < 1000) {
-      return 20000;
-    } else if (num_agents < 5000) {
-      return 60000;
-    } else if (num_agents < 10000) {
-      return 120000;
-    } else if (num_agents < 15000) {
-      return 240000;
-    } else if (num_agents < 20000) {
-      return 480000;
-    } else {
-      return 960000;
-    }
-  }
-
-  // Set the task sandbox directory for use by the WebUI.
-  function setTaskSandbox(executor) {
-    _.each(
-        [executor.tasks, executor.queued_tasks, executor.completed_tasks],
-        function(tasks) {
-      _.each(tasks, function(task) {
-        if (executor.type === 'DEFAULT') {
-          task.directory = executor.directory + '/tasks/' + task.id;
-        } else {
-          task.directory = executor.directory;
-        }
-      });
-    });
-  }
-
-
-  // Update the outermost scope with the new state.
-  function updateState($scope, $timeout, state) {
-    // Don't do anything if the state hasn't changed.
-    if ($scope.state == state) {
-      return true; // Continue polling.
-    }
-
-    $scope.state = state;
-
-    // A cluster is named if the state returns a non-empty string name.
-    // Track whether this cluster is named in a Boolean for display purposes.
-    $scope.clusterNamed = !!$scope.state.cluster;
-
-    // Check for selected text, and allow up to 20 seconds to pass before
-    // potentially wiping the user highlighted text.
-    // TODO(bmahler): This is to avoid the annoying loss of highlighting when
-    // the tables update. Once we can have tighter granularity control on the
-    // angular.js dynamic table updates, we should remove this hack.
-    $scope.time_since_update += $scope.delay;
-
-    if (hasSelectedText() && $scope.time_since_update < 20000) {
-      return true;
-    }
-
-    // Pass this pollTime to all relativeDate calls to make them all relative 
to
-    // the same moment in time.
-    //
-    // If relativeDate is called without a reference time, it instantiates a 
new
-    // Date to be the reference. Since there can be hundreds of dates on a 
given
-    // page, they would all be relative to slightly different moments in time.
-    $scope.pollTime = new Date();
-
-    // Update the maps.
-    $scope.agents = {};
-    $scope.frameworks = {};
-    $scope.offers = {};
-    $scope.completed_frameworks = {};
-    $scope.active_tasks = [];
-    $scope.unreachable_tasks = [];
-    $scope.completed_tasks = [];
-
-    // Update the stats.
-    $scope.cluster = $scope.state.cluster;
-    $scope.total_cpus = 0;
-    $scope.total_gpus = 0;
-    $scope.total_mem = 0;
-    $scope.total_disk = 0;
-    $scope.used_cpus = 0;
-    $scope.used_gpus = 0;
-    $scope.used_mem = 0;
-    $scope.used_disk = 0;
-    $scope.offered_cpus = 0;
-    $scope.offered_gpus = 0;
-    $scope.offered_mem = 0;
-    $scope.offered_disk = 0;
-
-    $scope.activated_agents = $scope.state.activated_slaves;
-    $scope.deactivated_agents = $scope.state.deactivated_slaves;
-    $scope.unreachable_agents = $scope.state.unreachable_slaves;
-
-    _.each($scope.state.slaves, function(agent) {
-      $scope.agents[agent.id] = agent;
-      $scope.total_cpus += agent.resources.cpus;
-      $scope.total_gpus += agent.resources.gpus;
-      $scope.total_mem += agent.resources.mem;
-      $scope.total_disk += agent.resources.disk;
-    });
-
-    var setTaskMetadata = function(task) {
-      if (!task.executor_id) {
-        task.executor_id = task.id;
-      }
-      if (task.statuses.length > 0) {
-          var firstStatus = task.statuses[0];
-          if (!isStateTerminal(firstStatus.state)) {
-              task.start_time = firstStatus.timestamp * 1000;
-          }
-          var lastStatus = task.statuses[task.statuses.length - 1];
-          if (isStateTerminal(task.state)) {
-              task.finish_time = lastStatus.timestamp * 1000;
-          }
-          task.healthy = lastStatus.healthy;
-      }
-    };
-
-    var isStateTerminal = function(taskState) {
-      var terminalStates = [
-          'TASK_ERROR',
-          'TASK_FAILED',
-          'TASK_FINISHED',
-          'TASK_KILLED',
-          'TASK_LOST',
-          'TASK_DROPPED',
-          'TASK_GONE',
-          'TASK_GONE_BY_OPERATOR'
-      ];
-      return terminalStates.indexOf(taskState) > -1;
-    };
-
-    _.each($scope.state.frameworks, function(framework) {
-      $scope.frameworks[framework.id] = framework;
-
-      // Fill in the `roles` field for non-MULTI_ROLE schedulers.
-      if (framework.role) {
-        framework.roles = [framework.role];
-      }
-
-      _.each(framework.offers, function(offer) {
-        $scope.offers[offer.id] = offer;
-        $scope.offered_cpus += offer.resources.cpus;
-        $scope.offered_gpus += offer.resources.gpus;
-        $scope.offered_mem += offer.resources.mem;
-        $scope.offered_disk += offer.resources.disk;
-        offer.framework_name = $scope.frameworks[offer.framework_id].name;
-        offer.hostname = $scope.agents[offer.slave_id].hostname;
-      });
-
-      $scope.used_cpus += framework.resources.cpus;
-      $scope.used_gpus += framework.resources.gpus;
-      $scope.used_mem += framework.resources.mem;
-      $scope.used_disk += framework.resources.disk;
-
-      framework.cpus_share = 0;
-      if ($scope.total_cpus > 0) {
-        framework.cpus_share = framework.used_resources.cpus / 
$scope.total_cpus;
-      }
-
-      framework.gpus_share = 0;
-      if ($scope.total_gpus > 0) {
-        framework.gpus_share = framework.used_resources.gpus / 
$scope.total_gpus;
-      }
-
-      framework.mem_share = 0;
-      if ($scope.total_mem > 0) {
-        framework.mem_share = framework.used_resources.mem / $scope.total_mem;
-      }
-
-      framework.disk_share = 0;
-      if ($scope.total_disk > 0) {
-        framework.disk_share = framework.used_resources.disk / 
$scope.total_disk;
-      }
-
-      framework.max_share = Math.max(
-          framework.cpus_share,
-          framework.gpus_share,
-          framework.mem_share,
-          framework.disk_share);
-
-      // If the executor ID is empty, this is a command executor with an
-      // internal executor ID generated from the task ID.
-      // TODO(brenden): Remove this once
-      // https://issues.apache.org/jira/browse/MESOS-527 is fixed.
-      _.each(framework.tasks, setTaskMetadata);
-      _.each(framework.unreachable_tasks, setTaskMetadata);
-      _.each(framework.completed_tasks, setTaskMetadata);
-
-      // TODO(bmahler): Add per-framework metrics to the master so that
-      // the webui does not need to loop over all tasks!
-      framework.running_tasks = 0;
-      framework.staging_tasks = 0;
-      framework.starting_tasks = 0;
-      framework.killing_tasks = 0;
-
-      _.each(framework.tasks, function(task) {
-        switch (task.state) {
-            case "TASK_STAGING": framework.staging_tasks += 1; break;
-            case "TASK_STARTING": framework.starting_tasks += 1; break;
-            case "TASK_RUNNING": framework.running_tasks += 1; break;
-            case "TASK_KILLING": framework.killing_tasks += 1; break;
-            default: break;
-        }
-      })
-
-      framework.finished_tasks = 0;
-      framework.killed_tasks = 0;
-      framework.failed_tasks = 0;
-      framework.lost_tasks = 0;
-
-      _.each(framework.completed_tasks, function(task) {
-        switch (task.state) {
-            case "TASK_FINISHED": framework.finished_tasks += 1; break;
-            case "TASK_KILLED": framework.killed_tasks += 1; break;
-            case "TASK_FAILED": framework.failed_tasks += 1; break;
-            case "TASK_LOST": framework.lost_tasks += 1; break;
-            default: break;
-        }
-      })
-
-      $scope.active_tasks = $scope.active_tasks.concat(framework.tasks);
-      $scope.unreachable_tasks = 
$scope.unreachable_tasks.concat(framework.unreachable_tasks);
-      $scope.completed_tasks =
-        $scope.completed_tasks.concat(framework.completed_tasks);
-    });
-
-    _.each($scope.state.completed_frameworks, function(framework) {
-      $scope.completed_frameworks[framework.id] = framework;
-
-      // Fill in the `roles` field for non-MULTI_ROLE schedulers.
-      if (framework.role) {
-        framework.roles = [framework.role];
-      }
-
-      _.each(framework.completed_tasks, setTaskMetadata);
-    });
-
-    $scope.used_cpus -= $scope.offered_cpus;
-    $scope.used_gpus -= $scope.offered_gpus;
-    $scope.used_mem -= $scope.offered_mem;
-    $scope.used_disk -= $scope.offered_disk;
-
-    $scope.idle_cpus = $scope.total_cpus - ($scope.offered_cpus + 
$scope.used_cpus);
-    $scope.idle_gpus = $scope.total_gpus - ($scope.offered_gpus + 
$scope.used_gpus);
-    $scope.idle_mem = $scope.total_mem - ($scope.offered_mem + 
$scope.used_mem);
-    $scope.idle_disk = $scope.total_disk - ($scope.offered_disk + 
$scope.used_disk);
-
-    $scope.time_since_update = 0;
-    $scope.$broadcast('state_updated');
-
-    return true; // Continue polling.
-  }
-
-  // Update the outermost scope with the metrics/snapshot endpoint.
-  function updateMetrics($scope, $timeout, metrics) {
-    $scope.staging_tasks = metrics['master/tasks_staging'];
-    $scope.starting_tasks = metrics['master/tasks_starting'];
-    $scope.running_tasks = metrics['master/tasks_running'];
-    $scope.killing_tasks = metrics['master/tasks_killing'];
-    $scope.finished_tasks = metrics['master/tasks_finished'];
-    $scope.killed_tasks = metrics['master/tasks_killed'];
-    $scope.failed_tasks = metrics['master/tasks_failed'];
-    $scope.lost_tasks = metrics['master/tasks_lost'];
-
-    return true; // Continue polling.
-  }
-
-
-  // Main controller that can be used to handle "global" events. E.g.,:
-  //     $scope.$on('$afterRouteChange', function() { ...; });
-  //
-  // In addition, the MainCtrl encapsulates the "view", allowing the
-  // active controller/view to easily access anything in scope (e.g.,
-  // the state).
-  mesosApp.controller('MainCtrl', [
-      '$scope', '$http', '$location', '$timeout', '$modal',
-      function($scope, $http, $location, $timeout, $modal) {
-    $scope.doneLoading = true;
-
-    // Adding bindings into scope so that they can be used from within
-    // AngularJS expressions.
-    $scope._ = _;
-    $scope.stringify = JSON.stringify;
-    $scope.encodeURIComponent = encodeURIComponent;
-    $scope.basename = function(path) {
-      // This is only a basic version of basename that handles the cases we 
care
-      // about, rather than duplicating unix basename functionality perfectly.
-      if (path === '/') {
-        return path;  // Handle '/'.
-      }
-
-      // Strip a trailing '/' if present.
-      if (path.length > 0 && path.lastIndexOf('/') === (path.length - 1)) {
-        path = path.substr(0, path.length - 1);
-      }
-      return path.substr(path.lastIndexOf('/') + 1);
-    };
-
-    $scope.$location = $location;
-    $scope.delay = 2000;
-    $scope.retry = 0;
-    $scope.time_since_update = 0;
-    $scope.isErrorModalOpen = false;
-
-    // Ordered Array of path => activeTab mappings. On successful route 
changes,
-    // the `pathRegexp` values are matched against the current route. The first
-    // match will be used to set the active navbar tab.
-    var NAVBAR_PATHS = [
-      {
-        pathRegexp: /^\/agents/,
-        tab: 'agents'
-      },
-      {
-        pathRegexp: /^\/frameworks/,
-        tab: 'frameworks'
-      },
-      {
-        pathRegexp: /^\/roles/,
-        tab: 'roles'
-      },
-      {
-        pathRegexp: /^\/offers/,
-        tab: 'offers'
-      },
-      {
-        pathRegexp: /^\/maintenance/,
-        tab: 'maintenance'
-      }
-    ];
-
-    // Set the active tab on route changes according to NAVBAR_PATHS.
-    $scope.$on('$routeChangeSuccess', function(event, current) {
-      var path = current.$$route.originalPath;
-
-      // Use _.some so the loop can exit on the first `pathRegexp` match.
-      var matched = _.some(NAVBAR_PATHS, function(nav) {
-        if (path.match(nav.pathRegexp)) {
-          $scope.navbarActiveTab = nav.tab;
-          return true;
-        }
-      });
-
-      if (!matched) $scope.navbarActiveTab = null;
-    });
-
-    var leadingMasterURL = function(path) {
-      // Use current location as address in case we could not find the
-      // leading master.
-      var address = location.hostname + ':' + location.port;
-      if ($scope.state && $scope.state.leader_info) {
-          address = $scope.state.leader_info.hostname + ':' +
-                    $scope.state.leader_info.port;
-      }
-
-      return '//' + address + path;
-    }
-
-    var popupErrorModal = function() {
-      if ($scope.delay >= 128000) {
-        $scope.delay = 2000;
-      } else {
-        $scope.delay = $scope.delay * 2;
-      }
-
-      $scope.isErrorModalOpen = true;
-
-      var errorModal = $modal.open({
-        controller: function($scope, $modalInstance, scope) {
-          // Give the modal reference to the root scope so it can access the
-          // `retry` variable. It needs to be passed by reference, not by
-          // value, since its value is changed outside the scope of the
-          // modal.
-          $scope.rootScope = scope;
-        },
-        resolve: {
-          scope: function() { return $scope; }
-        },
-        templateUrl: "template/dialog/masterGone.html"
-      });
-
-      // Make it such that everytime we hide the error-modal, we stop the
-      // countdown and restart the polling.
-      errorModal.result.then(function() {
-        $scope.isErrorModalOpen = false;
-
-        if ($scope.countdown != null) {
-          if ($timeout.cancel($scope.countdown)) {
-            // Restart since they cancelled the countdown.
-            $scope.delay = 2000;
-          }
-        }
-
-        // Start polling again, but do it asynchronously (and wait at
-        // least a second because otherwise the error-modal won't get
-        // properly shown).
-        $timeout(pollState, 1000);
-        $timeout(pollMetrics, 1000);
-      });
-
-      $scope.retry = $scope.delay;
-      var countdown = function() {
-        if ($scope.retry === 0) {
-          errorModal.close();
-        } else {
-          $scope.retry = $scope.retry - 1000;
-          $scope.countdown = $timeout(countdown, 1000);
-        }
-      };
-      countdown();
-    };
-
-    var pollState = function() {
-      // When the current master is not the leader, the request is redirected 
to
-      // the leading master automatically. This would cause a CORS error if we
-      // use XMLHttpRequest here. To avoid the CORS error, we use JSONP as a
-      // workaround. Please refer to MESOS-5911 for further details.
-      $http.jsonp(leadingMasterURL('/master/state?jsonp=JSON_CALLBACK'))
-        .success(function(response) {
-          if (updateState($scope, $timeout, response)) {
-            $scope.delay = updateInterval(_.size($scope.agents));
-            $timeout(pollState, $scope.delay);
-          }
-        })
-        .error(function() {
-          if ($scope.isErrorModalOpen === false) {
-            popupErrorModal();
-          }
-        });
-    };
-
-    var pollMetrics = function() {
-      $http.jsonp(leadingMasterURL('/metrics/snapshot?jsonp=JSON_CALLBACK'))
-        .success(function(response) {
-          if (updateMetrics($scope, $timeout, response)) {
-            $scope.delay = updateInterval(_.size($scope.agents));
-            $timeout(pollMetrics, $scope.delay);
-          }
-        })
-        .error(function(message, code) {
-          if ($scope.isErrorModalOpen === false) {
-            // If return code is 401 or 403 the user is unauthorized to reach
-            // the endpoint, which is not a connection error.
-            if ([401, 403].indexOf(code) < 0) {
-              popupErrorModal();
-            }
-          }
-        });
-    };
-
-    pollState();
-    pollMetrics();
-  }]);
-
-  mesosApp.controller('HomeCtrl', function($scope, $http) {
-    var hostname = $scope.$location.host() + ':' + $scope.$location.port();
-
-    var update = function() {
-      $scope.streamLogs = function(_$event) {
-        pailer(
-            '//' + hostname,
-            '/master/log',
-            'Mesos Master (' + hostname + ')');
-      };
-
-      // We must query the '/flags' endpoint of *this* master since
-      // `$scope.state` contains the leader master state.
-      $http.jsonp('//' + hostname + '/flags?jsonp=JSON_CALLBACK')
-        .success(function (response) {
-          // The master attaches a "/master/log" file when either
-          // of these flags are set.
-          $scope.log_file_attached = response.flags.external_log_file || 
response.flags.log_dir;
-        })
-        .error(function(reason) {
-          $scope.alert_message = 'Failed to get master flags: ' + reason;
-          $('#alert').show();
-        });
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  });
-
-  mesosApp.controller('FrameworksCtrl', function() {});
-
-  mesosApp.controller('RolesCtrl', function($scope, $http) {
-    var update = function() {
-      // TODO(haosdent): Send requests to the leading master directly
-      // once `leadingMasterURL` is public.
-      $http.jsonp('master/roles?jsonp=JSON_CALLBACK')
-      .success(function(response) {
-        $scope.roles = response;
-      })
-      .error(function() {
-        if ($scope.isErrorModalOpen === false) {
-          popupErrorModal();
-        }
-      });
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  });
-
-  mesosApp.controller('OffersCtrl', function() {});
-
-  mesosApp.controller('MaintenanceCtrl', function($scope, $http) {
-    var update = function() {
-      // TODO(haosdent): Send requests to the leading master directly
-      // once `leadingMasterURL` is public.
-      $http.jsonp('master/maintenance/schedule?jsonp=JSON_CALLBACK')
-      .success(function(response) {
-        $scope.maintenance = response;
-      })
-      .error(function() {
-        if ($scope.isErrorModalOpen === false) {
-          popupErrorModal();
-        }
-      });
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  });
-
-  mesosApp.controller('FrameworkCtrl', function($scope, $routeParams) {
-    var update = function() {
-      if ($routeParams.id in $scope.completed_frameworks) {
-        $scope.framework = $scope.completed_frameworks[$routeParams.id];
-        $scope.alert_message = 'This framework has terminated!';
-        $('#alert').show();
-        $('#framework').show();
-      } else if ($routeParams.id in $scope.frameworks) {
-        $scope.framework = $scope.frameworks[$routeParams.id];
-        $('#framework').show();
-      } else {
-        $scope.alert_message = 'No framework found with ID: ' + 
$routeParams.id;
-        $('#alert').show();
-      }
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  });
-
-
-  mesosApp.controller('AgentsCtrl', function() {});
-
-
-  mesosApp.controller('AgentCtrl', [
-      '$scope', '$routeParams', '$http', '$q', '$timeout', 'top',
-      function($scope, $routeParams, $http, $q, $timeout, $top) {
-    $scope.agent_id = $routeParams.agent_id;
-
-    var update = function() {
-      if (!($routeParams.agent_id in $scope.agents)) {
-        $scope.alert_message = 'No agent found with ID: ' + 
$routeParams.agent_id;
-        $('#alert').show();
-        return;
-      }
-
-      var agent = $scope.agents[$routeParams.agent_id];
-
-      $scope.streamLogs = function(_$event) {
-        pailer(agentURLPrefix(agent, false), '/slave/log', 'Mesos Agent (' + 
agent.id + ')');
-      };
-
-
-      // Set up polling for the monitor if this is the first update.
-      if (!$top.started()) {
-        $top.start(
-          agentURLPrefix(agent, true) + 
'/monitor/statistics?jsonp=JSON_CALLBACK',
-          $scope
-        );
-      }
-
-      $http.jsonp(agentURLPrefix(agent, true) + '/state?jsonp=JSON_CALLBACK')
-        .success(function (response) {
-          $scope.state = response;
-
-          $scope.agent = {};
-          $scope.agent.frameworks = {};
-          $scope.agent.completed_frameworks = {};
-          $scope.agent.url_prefix = agentURLPrefix(agent, false);
-
-          // The agent attaches a "/slave/log" file when either
-          // of these flags are set.
-          $scope.agent.log_file_attached = $scope.state.external_log_file || 
$scope.state.log_dir;
-
-          // Convert the reserved resources map into an array for inclusion
-          // in an `ng-repeat` table.
-          $scope.agent.reserved_resources_as_array = 
_($scope.state.reserved_resources)
-            .map(function(reservation, role) {
-              reservation.role = role;
-              return reservation;
-            });
-
-          // Computes framework stats by setting new attributes on the 
'framework'
-          // object.
-          function computeFrameworkStats(framework) {
-            framework.num_tasks = 0;
-            framework.cpus = 0;
-            framework.gpus = 0;
-            framework.mem = 0;
-            framework.disk = 0;
-
-            _.each(framework.executors, function(executor) {
-              framework.num_tasks += _.size(executor.tasks);
-              framework.cpus += executor.resources.cpus;
-              framework.gpus += executor.resources.gpus;
-              framework.mem += executor.resources.mem;
-              framework.disk += executor.resources.disk;
-            });
-          }
-
-          // Compute framework stats and update agent's mappings of those
-          // frameworks.
-          _.each($scope.state.frameworks, function(framework) {
-            $scope.agent.frameworks[framework.id] = framework;
-            computeFrameworkStats(framework);
-
-            // Fill in the `roles` field for non-MULTI_ROLE schedulers.
-            if (framework.role) {
-              framework.roles = [framework.role];
-            }
-          });
-
-          _.each($scope.state.completed_frameworks, function(framework) {
-            $scope.agent.completed_frameworks[framework.id] = framework;
-            computeFrameworkStats(framework);
-
-            // Fill in the `roles` field for non-MULTI_ROLE schedulers.
-            if (framework.role) {
-              framework.roles = [framework.role];
-            }
-          });
-
-          $scope.state.allocated_resources = {};
-          $scope.state.allocated_resources.cpus = 0;
-          $scope.state.allocated_resources.gpus = 0;
-          $scope.state.allocated_resources.mem = 0;
-          $scope.state.allocated_resources.disk = 0;
-
-          // Currently the agent does not expose the total allocated
-          // resources across all frameworks, so we sum manually.
-          _.each($scope.state.frameworks, function(framework) {
-            $scope.state.allocated_resources.cpus += framework.cpus;
-            $scope.state.allocated_resources.gpus += framework.gpus;
-            $scope.state.allocated_resources.mem += framework.mem;
-            $scope.state.allocated_resources.disk += framework.disk;
-          });
-
-          $('#agent').show();
-        })
-        .error(function(reason) {
-          $scope.alert_message = 'Failed to get agent usage / state: ' + 
reason;
-          $('#alert').show();
-        });
-
-      $http.jsonp(agentURLPrefix(agent, false) + 
'/metrics/snapshot?jsonp=JSON_CALLBACK')
-        .success(function (response) {
-          $scope.staging_tasks = response['slave/tasks_staging'];
-          $scope.starting_tasks = response['slave/tasks_starting'];
-          $scope.running_tasks = response['slave/tasks_running'];
-          $scope.killing_tasks = response['slave/tasks_killing'];
-          $scope.finished_tasks = response['slave/tasks_finished'];
-          $scope.killed_tasks = response['slave/tasks_killed'];
-          $scope.failed_tasks = response['slave/tasks_failed'];
-          $scope.lost_tasks = response['slave/tasks_lost'];
-        })
-        .error(function(reason) {
-          $scope.alert_message = 'Failed to get agent metrics: ' + reason;
-          $('#alert').show();
-        });
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  }]);
-
-
-  mesosApp.controller('AgentFrameworkCtrl', [
-      '$scope', '$routeParams', '$http', '$q', '$timeout', 'top',
-      function($scope, $routeParams, $http, $q, $timeout, $top) {
-    $scope.agent_id = $routeParams.agent_id;
-    $scope.framework_id = $routeParams.framework_id;
-
-    var update = function() {
-      if (!($routeParams.agent_id in $scope.agents)) {
-        $scope.alert_message = 'No agent found with ID: ' + 
$routeParams.agent_id;
-        $('#alert').show();
-        return;
-      }
-
-      var agent = $scope.agents[$routeParams.agent_id];
-
-      // Set up polling for the monitor if this is the first update.
-      if (!$top.started()) {
-        $top.start(
-          agentURLPrefix(agent, true) + 
'/monitor/statistics?jsonp=JSON_CALLBACK',
-          $scope
-        );
-      }
-
-      $http.jsonp(agentURLPrefix(agent, true) + '/state?jsonp=JSON_CALLBACK')
-        .success(function (response) {
-          $scope.state = response;
-
-          $scope.agent = {};
-
-          function matchFramework(framework) {
-            return $scope.framework_id === framework.id;
-          }
-
-          // Find the framework; it's either active or completed.
-          $scope.framework =
-              _.find($scope.state.frameworks, matchFramework) ||
-              _.find($scope.state.completed_frameworks, matchFramework);
-
-          if (!$scope.framework) {
-            $scope.alert_message = 'No framework found with ID: ' + 
$routeParams.framework_id;
-            $('#alert').show();
-            return;
-          }
-
-          // Fill in the `roles` field for non-MULTI_ROLE schedulers.
-          if ($scope.framework.role) {
-            $scope.framework.roles = [$scope.framework.role];
-          }
-
-          // Compute the framework stats.
-          $scope.framework.num_tasks = 0;
-          $scope.framework.cpus = 0;
-          $scope.framework.gpus = 0;
-          $scope.framework.mem = 0;
-          $scope.framework.disk = 0;
-
-          _.each($scope.framework.executors, function(executor) {
-            $scope.framework.num_tasks += _.size(executor.tasks);
-            $scope.framework.cpus += executor.resources.cpus;
-            $scope.framework.gpus += executor.resources.gpus;
-            $scope.framework.mem += executor.resources.mem;
-            $scope.framework.disk += executor.resources.disk;
-
-            // If 'role' is not present in executor, we are talking
-            // to a non-MULTI_ROLE capable agent. This means that we
-            // can use the 'role' of the framework.
-            executor.role = executor.role || $scope.framework.role;
-          });
-
-          $('#agent').show();
-        })
-        .error(function (reason) {
-          $scope.alert_message = 'Failed to get agent usage / state: ' + 
reason;
-          $('#alert').show();
-        });
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  }]);
-
-
-  mesosApp.controller('AgentExecutorCtrl', [
-      '$scope', '$routeParams', '$http', '$q', '$timeout', 'top',
-      function($scope, $routeParams, $http, $q, $timeout, $top) {
-    $scope.agent_id = $routeParams.agent_id;
-    $scope.framework_id = $routeParams.framework_id;
-    $scope.executor_id = $routeParams.executor_id;
-
-    var update = function() {
-      if (!($routeParams.agent_id in $scope.agents)) {
-        $scope.alert_message = 'No agent found with ID: ' + 
$routeParams.agent_id;
-        $('#alert').show();
-        return;
-      }
-
-      var agent = $scope.agents[$routeParams.agent_id];
-
-      // Set up polling for the monitor if this is the first update.
-      if (!$top.started()) {
-        $top.start(
-          agentURLPrefix(agent, true) + 
'/monitor/statistics?jsonp=JSON_CALLBACK',
-          $scope
-        );
-      }
-
-      $http.jsonp(agentURLPrefix(agent, true) + '/state?jsonp=JSON_CALLBACK')
-        .success(function (response) {
-          $scope.state = response;
-
-          $scope.agent = {};
-
-          function matchFramework(framework) {
-            return $scope.framework_id === framework.id;
-          }
-
-          // Find the framework; it's either active or completed.
-          $scope.framework =
-            _.find($scope.state.frameworks, matchFramework) ||
-            _.find($scope.state.completed_frameworks, matchFramework);
-
-          if (!$scope.framework) {
-            $scope.alert_message = 'No framework found with ID: ' + 
$routeParams.framework_id;
-            $('#alert').show();
-            return;
-          }
-
-          function matchExecutor(executor) {
-            return $scope.executor_id === executor.id;
-          }
-
-          function setRole(tasks) {
-            _.each(tasks, function(task) {
-              task.role = $scope.framework.role;
-            });
-          }
-
-          function setHealth(tasks) {
-            _.each(tasks, function(task) {
-              var lastStatus = _.last(task.statuses);
-              if (lastStatus) {
-                task.healthy = lastStatus.healthy;
-              }
-            })
-          }
-
-          // Look for the executor; it's either active or completed.
-          $scope.executor =
-            _.find($scope.framework.executors, matchExecutor) ||
-            _.find($scope.framework.completed_executors, matchExecutor);
-
-          if (!$scope.executor) {
-            $scope.alert_message = 'No executor found with ID: ' + 
$routeParams.executor_id;
-            $('#alert').show();
-            return;
-          }
-
-          // If 'role' is not present in the task, we are talking
-          // to a non-MULTI_ROLE capable agent. This means that we
-          // can use the 'role' of the framework.
-          if (!("role" in $scope.executor)) {
-            $scope.executor.role = $scope.framework.role;
-
-            setRole($scope.executor.tasks);
-            setRole($scope.executor.queued_tasks);
-            setRole($scope.executor.completed_tasks);
-          }
-
-          setHealth($scope.executor.tasks);
-          setTaskSandbox($scope.executor);
-
-          $('#agent').show();
-        })
-        .error(function (reason) {
-          $scope.alert_message = 'Failed to get agent usage / state: ' + 
reason;
-          $('#alert').show();
-        });
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  }]);
-
-
-  // Reroutes requests like:
-  //   * 
'/agents/:agent_id/frameworks/:framework_id/executors/:executor_id/browse'
-  //   * 
'/agents/:agent_id/frameworks/:framework_id/executors/:executor_id/tasks/:task_id/browse'
-  // to the sandbox directory of the executor or the task respectively. This
-  // requires a second request because the directory to browse is known by the
-  // agent but not by the master. Request the directory from the agent, and 
then
-  // redirect to it.
-  //
-  // TODO(ssorallen): Add `executor.directory` to the master's state endpoint
-  // output so this controller of rerouting is no longer necessary.
-  mesosApp.controller('AgentTaskAndExecutorRerouterCtrl',
-      function($alert, $http, $location, $routeParams, $scope, $window) {
-
-    function goBack(flashMessageOrOptions) {
-      if (flashMessageOrOptions) {
-        $alert.danger(flashMessageOrOptions);
-      }
-
-      if ($window.history.length > 1) {
-        // If the browser has something in its history, just go back.
-        $window.history.back();
-      } else {
-        // Otherwise navigate to the framework page, which is likely the
-        // previous page anyway.
-        $location.path('/frameworks/' + $routeParams.framework_id).replace();
-      }
-    }
-
-    var reroute = function() {
-      var agent = $scope.agents[$routeParams.agent_id];
-
-      // If the agent doesn't exist, send the user back.
-      if (!agent) {
-        return goBack("Agent with ID '" + $routeParams.agent_id + "' does not 
exist.");
-      }
-
-      // Request agent details to get access to the route executor's 
"directory"
-      // to navigate directly to the executor's sandbox.
-      var url = agentURLPrefix(agent, true) + '/state?jsonp=JSON_CALLBACK';
-      $http.jsonp(url)
-        .success(function(response) {
-
-          function matchFramework(framework) {
-            return $routeParams.framework_id === framework.id;
-          }
-
-          var framework =
-            _.find(response.frameworks, matchFramework) ||
-            _.find(response.completed_frameworks, matchFramework);
-
-          if (!framework) {
-            return goBack(
-              "Framework with ID '" + $routeParams.framework_id +
-                "' does not exist on agent with ID '" + $routeParams.agent_id +
-                "'."
-            );
-          }
-
-          function matchExecutor(executor) {
-            return $routeParams.executor_id === executor.id;
-          }
-
-          var executor =
-            _.find(framework.executors, matchExecutor) ||
-            _.find(framework.completed_executors, matchExecutor);
-
-          if (!executor) {
-            return goBack(
-              "Executor with ID '" + $routeParams.executor_id +
-                "' does not exist on agent with ID '" + $routeParams.agent_id +
-                "'."
-            );
-          }
-
-          var sandboxDirectory = executor.directory;
-
-          function matchTask(task) {
-            return $routeParams.task_id === task.id;
-          }
-
-          // Continue to navigate to the task's sandbox if the task id is
-          // specified in route parameters.
-          if ($routeParams.task_id) {
-            setTaskSandbox(executor);
-
-            var task =
-              _.find(executor.tasks, matchTask) ||
-              _.find(executor.queued_tasks, matchTask) ||
-              _.find(executor.completed_tasks, matchTask);
-
-            if (!task) {
-              return goBack(
-                "Task with ID '" + $routeParams.task_id +
-                  "' does not exist on agent with ID '" + 
$routeParams.agent_id +
-                  "'."
-              );
-            }
-
-            sandboxDirectory = task.directory;
-          }
-
-          // Navigate to a path like '/agents/:id/browse?path=%2Ftmp%2F', the
-          // recognized "browse" endpoint for an agent.
-          $location.path('/agents/' + $routeParams.agent_id + '/browse')
-            .search({path: sandboxDirectory})
-            .replace();
-        })
-        .error(function(_response) {
-          $alert.danger({
-            bullets: [
-             "The agent is not accessible",
-             "The agent timed out or went offline"
-            ],
-            message: "Potential reasons:",
-            title: "Failed to connect to agent '" + $routeParams.agent_id +
-              "' on '" + url + "'."
-          });
-
-          // Is the agent dead? Navigate home since returning to the agent 
might
-          // end up in an endless loop.
-          $location.path('/').replace();
-        });
-    };
-
-    // When navigating directly to this page, e.g. pasting the URL into the
-    // browser, the previous page is not a page in Mesos. The agents
-    // information may not ready when loading this page, we start to reroute
-    // the sandbox request after the agents information loaded.
-    if ($scope.state) {
-      reroute();
-    }
-
-    // `reroute` is expected to always route away from the current page
-    // and the listener would be removed after the first state update.
-    var removeListener = $scope.$on('state_updated', reroute);
-    $scope.$on('$routeChangeStart', removeListener);
-  });
-
-
-  mesosApp.controller('BrowseCtrl', function($scope, $routeParams, $http) {
-    var update = function() {
-      if ($routeParams.agent_id in $scope.agents && $routeParams.path) {
-        $scope.agent_id = $routeParams.agent_id;
-        $scope.path = $routeParams.path;
-
-        var agent = $scope.agents[$routeParams.agent_id];
-
-        // This variable is used in 'browse.html' to generate the '/files'
-        // links, so we have to pass `includeProcessId=false` (see
-        // `agentURLPrefix`for more details).
-        $scope.agent_url_prefix = agentURLPrefix(agent, false);
-
-        $scope.pail = function($event, path) {
-          pailer(
-            agentURLPrefix(agent, false),
-            path,
-            decodeURIComponent(path) + ' (' + agent.id + ')');
-        };
-
-        var url = agentURLPrefix(agent, false) + 
'/files/browse?jsonp=JSON_CALLBACK';
-
-        // TODO(bmahler): Try to get the error code / body in the error 
callback.
-        // This wasn't working with the current version of angular.
-        $http.jsonp(url, {params: {path: $routeParams.path}})
-          .success(function(data) {
-            $scope.listing = data;
-            $('#listing').show();
-          })
-          .error(function() {
-            $scope.alert_message = 'Error browsing path: ' + $routeParams.path;
-            $('#alert').show();
-          });
-      } else {
-        if (!($routeParams.agent_id in $scope.agents)) {
-          $scope.alert_message = 'No agent found with ID: ' + 
$routeParams.agent_id;
-        } else {
-          $scope.alert_message = 'Missing "path" request parameter.';
-        }
-        $('#alert').show();
-      }
-    };
-
-    if ($scope.state) {
-      update();
-    }
-
-    var removeListener = $scope.$on('state_updated', update);
-    $scope.$on('$routeChangeStart', removeListener);
-  });
-})();

Reply via email to