190 lines
7.8 KiB
JavaScript
190 lines
7.8 KiB
JavaScript
/*
|
|
* This file is part of Cockpit.
|
|
*
|
|
* Copyright (C) 2015 Red Hat, Inc.
|
|
*
|
|
* Cockpit is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Cockpit is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
(function() {
|
|
var angular = require('angular');
|
|
require('angular-route');
|
|
require('kubernetes-topology-graph/dist/topology-graph.js');
|
|
|
|
require('./kube-client');
|
|
require('./details');
|
|
|
|
require('../views/topology-page.html');
|
|
|
|
var icons = {
|
|
Pod: '#vertex-Pod',
|
|
ReplicationController: '#vertex-ReplicationController',
|
|
Node: '#vertex-Node',
|
|
Service: '#vertex-Service',
|
|
DeploymentConfig: "#vertex-DeploymentConfig",
|
|
Route: "#vertex-Route"
|
|
};
|
|
|
|
angular.module('kubernetes.topology', [
|
|
'ngRoute',
|
|
'kubernetesUI',
|
|
'kubeClient',
|
|
'kubernetes.details'
|
|
])
|
|
|
|
.config(['$routeProvider',
|
|
function($routeProvider) {
|
|
$routeProvider.when('/topology/:namespace?', {
|
|
templateUrl: 'views/topology-page.html',
|
|
controller: 'TopologyCtrl'
|
|
});
|
|
}
|
|
])
|
|
|
|
.controller('TopologyCtrl', [
|
|
'$scope',
|
|
'$window',
|
|
'kubeLoader',
|
|
'kubeSelect',
|
|
'KubeDiscoverSettings',
|
|
'itemActions',
|
|
function($scope, $window, loader, select, discoverSettings, actions) {
|
|
$scope.items = { };
|
|
$scope.relations = [ ];
|
|
$scope.selected = null;
|
|
|
|
var ready = false;
|
|
|
|
function link_for_item(kind, namespace, name) {
|
|
var rel = select().kind(kind)
|
|
.name(name)
|
|
.namespace(namespace)
|
|
.one();
|
|
if (rel)
|
|
return rel.metadata.selfLink;
|
|
}
|
|
|
|
function rels_for_item(item) {
|
|
var rels = { };
|
|
var endpoints, subsets;
|
|
var link;
|
|
|
|
/* Lookup which node this pod is scheduled on */
|
|
if (item.kind === "Node") {
|
|
rels = select().kind("Pod")
|
|
.host(item.metadata.name);
|
|
|
|
/* Kubernetes tells us about endpoints, which are service to pod mappings */
|
|
} else if (item.kind === "Service") {
|
|
endpoints = select().kind("Endpoints")
|
|
.namespace(item.metadata.namespace)
|
|
.name(item.metadata.name)
|
|
.one() || { };
|
|
subsets = endpoints.subsets || [ ];
|
|
subsets.forEach(function(subset) {
|
|
var addresses = subset.addresses || [ ];
|
|
addresses.forEach(function(address) {
|
|
if (address.targetRef && address.targetRef.kind == "Pod")
|
|
link = link_for_item("Pod", address.targetRef.namespace,
|
|
address.targetRef.name);
|
|
if (link)
|
|
rels[link] = {};
|
|
});
|
|
});
|
|
|
|
/* For ReplicationControllers we just do the selection ourselves */
|
|
} else if (item.kind === "ReplicationController") {
|
|
rels = select().kind("Pod")
|
|
.namespace(item.metadata.namespace);
|
|
if (item.spec.selector)
|
|
rels = rels.label(item.spec.selector);
|
|
} else if (item.kind === "DeploymentConfig") {
|
|
rels = select().kind("ReplicationController")
|
|
.namespace(item.metadata.namespace)
|
|
.label({ "openshift.io/deployment-config.name" : item.metadata.name });
|
|
/* For Routes just build it out */
|
|
} else if (item.kind === "Route" && item.spec.to) {
|
|
link = link_for_item(item.spec.to.kind, item.metadata.namespace,
|
|
item.spec.to.name);
|
|
if (link)
|
|
rels[link] = {};
|
|
}
|
|
return rels;
|
|
}
|
|
|
|
loader.watch("Node", $scope);
|
|
loader.watch("Pod", $scope);
|
|
loader.watch("ReplicationController", $scope);
|
|
loader.watch("Service", $scope);
|
|
loader.watch("Endpoints", $scope);
|
|
|
|
discoverSettings().then(function(settings) {
|
|
if (settings.flavor === "openshift") {
|
|
loader.watch("DeploymentConfig", $scope);
|
|
loader.watch("Route", $scope);
|
|
}
|
|
});
|
|
|
|
loader.listen(function(changed, removed) {
|
|
var selected_meta;
|
|
var relations = [];
|
|
var item;
|
|
var key;
|
|
|
|
$scope.items = select();
|
|
if ($scope.selected) {
|
|
selected_meta = $scope.selected.metadata || {};
|
|
item = select().kind($scope.selected.kind)
|
|
.name(selected_meta.name);
|
|
if (selected_meta.namespace)
|
|
item = item.namespace(selected_meta.namespace);
|
|
$scope.selected = item.one();
|
|
}
|
|
|
|
for (key in $scope.items) {
|
|
var pkey;
|
|
var rels = rels_for_item($scope.items[key]);
|
|
for (pkey in rels)
|
|
relations.push({ source: key, target: pkey });
|
|
}
|
|
|
|
$scope.relations = relations;
|
|
}, $scope);
|
|
|
|
$scope.$on("select", function(ev, item) {
|
|
$scope.$applyAsync(function () {
|
|
$scope.selected = item;
|
|
});
|
|
});
|
|
|
|
/* Make a copy since we modify */
|
|
$scope.kinds = angular.copy(icons);
|
|
|
|
/* All the actions available on the $scope */
|
|
angular.extend($scope, actions);
|
|
|
|
function resized() {
|
|
$scope.height = { height: (window.innerHeight - 60) + "px" };
|
|
if (ready)
|
|
$scope.$digest();
|
|
}
|
|
|
|
angular.element($window).bind('resize', resized);
|
|
resized();
|
|
|
|
ready = true;
|
|
}
|
|
]);
|
|
}());
|