/**========================================================= * Module: Group * Visualizer for groups =========================================================*/ app.controller('GroupCtrl', [ '$scope', '$route', '$interval', '$routeParams', 'k8sApi', '$rootScope', '$location', 'lodash', function($scope, $route, $interval, $routeParams, k8sApi, $rootScope, $location, _) { 'use strict'; $scope.doTheBack = function() { window.history.back(); }; $scope.capitalize = function(s) { return _.capitalize(s); }; $rootScope.doTheBack = $scope.doTheBack; $scope.resetGroupLayout = function(group) { delete group.settings; }; $scope.handlePath = function(path) { var parts = path.split("/"); // split leaves an empty string at the beginning. parts = parts.slice(1); if (parts.length === 0) { return; } this.handleGroups(parts.slice(1)); }; $scope.getState = function(obj) { return Object.keys(obj)[0]; }; $scope.clearSelector = function(grouping) { $location.path("/dashboard/groups/" + grouping + "/selector/"); }; $scope.changeGroupBy = function() { var grouping = encodeURIComponent($scope.selectedGroupBy); var s = _.clone($location.search()); if ($scope.routeParams.grouping != grouping) $location.path("/dashboard/groups/" + grouping + "/selector/").search(s); }; $scope.createBarrier = function(count, callback) { var barrier = count; var barrierFunction = angular.bind(this, function(data) { // JavaScript is single threaded so this is safe. barrier--; if (barrier === 0) { if (callback) { callback(); } } }); return barrierFunction; }; $scope.handleGroups = function(parts, selector) { $scope.groupBy = parts; $scope.loading = true; $scope.selector = selector; $scope.selectorName = decodeURIComponent(selector); var args = []; var type = ""; var selectedHost = ""; if (selector && selector.length > 0) { $scope.selectorPieces = selector.split(","); var labels = []; var fields = []; for (var i = 0; i < $scope.selectorPieces.length; i++) { var piece = decodeURIComponent($scope.selectorPieces[i]); if (piece[0] == '$') { fields.push(piece.slice(2)); } else { if (piece.indexOf("type=") === 0) { var labelParts = piece.split("="); if (labelParts.length > 1) { type = labelParts[1]; } } else if (piece.indexOf("host=") === 0){ var labelParts = piece.split("="); if (labelParts.length > 1) { selectedHost = labelParts[1]; } } else { labels.push(piece); } } } if (labels.length > 0) { args.push("labelSelector=" + encodeURI(labels.join(","))); } if (fields.length > 0) { args.push("fields=" + encodeURI(fields.join(","))); } } var query = "?" + args.join("&"); var list = []; var count = type.length > 0 ? 1 : 3; $scope.selectedGroupByName = decodeURIComponent($routeParams.grouping) var barrier = $scope.createBarrier(count, function() { $scope.groups = $scope.groupData(list, 0); $scope.loading = false; $scope.groupByOptions = buildGroupByOptions(); $scope.selectedGroupBy = $routeParams.grouping; }); if (type === "" || type == "pod") { k8sApi.getPods(query).success(function(data) { $scope.addLabel("type", "pod", data.items); for (var i = 0; data.items && i < data.items.length; ++i) { data.items[i].metadata.labels.host = data.items[i].spec.nodeName; if(selectedHost.length == 0 || selectedHost == data.items[i].metadata.labels.host) list.push(data.items[i]); } barrier(); }).error($scope.handleError); } if (type === "" || type == "service") { k8sApi.getServices(query).success(function(data) { $scope.addLabel("type", "service", data.items); for (var i = 0; data.items && i < data.items.length; ++i) { list.push(data.items[i]); } barrier(); }).error($scope.handleError); } if (type === "" || type == "replicationController") { k8sApi.getReplicationControllers(query).success(angular.bind(this, function(data) { $scope.addLabel("type", "replicationController", data.items); for (var i = 0; data.items && i < data.items.length; ++i) { list.push(data.items[i]); } barrier(); })).error($scope.handleError); } }; $scope.addLabel = function(key, value, items) { if (!items) { return; } for (var i = 0; i < items.length; i++) { if (!items[i].metadata.labels) { items[i].metadata.labels = {}; } items[i].metadata.labels[key] = value; } }; $scope.groupData = function(items, index) { var result = { "items": {}, "kind": "grouping" }; for (var i = 0; i < items.length; i++) { key = items[i].metadata.labels[decodeURIComponent($scope.groupBy[index])]; if (!key) { key = ""; } var list = result.items[key]; if (!list) { list = []; result.items[key] = list; } list.push(items[i]); } if (index + 1 < $scope.groupBy.length) { for (var key in result.items) { result.items[key] = $scope.groupData(result.items[key], index + 1); } } return result; }; $scope.getGroupColor = function(type) { if (type === 'pod') { return '#6193F0'; } else if (type === 'replicationController') { return '#E008FE'; } else if (type === 'service') { return '#7C43FF'; } }; var groups = $routeParams.grouping; if (!groups) { groups = ''; } $scope.routeParams = $routeParams; $scope.route = $route; $scope.handleGroups(groups.split('/'), $routeParams.selector); $scope.handleError = function(data, status, headers, config) { console.log("Error (" + status + "): " + data); $scope_.loading = false; }; function getDefaultGroupByOptions() { return [{name: 'Type', value: 'type'}, {name: 'Name', value: 'name'}]; } function buildGroupByOptions() { var g = $scope.groups; var options = getDefaultGroupByOptions(); var newOptions = _.map(g.items, function(vals) { return _.map(vals, function(v) { return _.keys(v.metadata.labels); }); }); newOptions = _.reject(_.uniq(_.flattenDeep(newOptions)), function(o) { return o == 'name' || o == 'type' || o == ""; }); newOptions = _.map(newOptions, function(o) { return { name: o, value: o }; }); options = options.concat(newOptions); return options; } $scope.changeFilterBy = function(selector) { var grouping = $scope.selectedGroupBy; var s = _.clone($location.search()); if ($scope.routeParams.selector != selector) $location.path("/dashboard/groups/" + $scope.routeParams.grouping + "/selector/" + selector).search(s); }; } ]);