|
|
86baa9 |
From 4b853e8c2f57034c9a72b96fc028e66aa3175a07 Mon Sep 17 00:00:00 2001
|
|
|
86baa9 |
From: Serhii Tsymbaliuk <stsymbal@redhat.com>
|
|
|
86baa9 |
Date: Tue, 12 Feb 2019 10:44:33 +0100
|
|
|
86baa9 |
Subject: [PATCH] Web UI (topology graph): Show FQDN for nodes if they have no
|
|
|
86baa9 |
common DNS zone
|
|
|
86baa9 |
|
|
|
86baa9 |
It allows to avoid confusion with identical short hostnames.
|
|
|
86baa9 |
|
|
|
86baa9 |
There are two cases implemented:
|
|
|
86baa9 |
- no common DNS zone: graph shows FQDN for all nodes
|
|
|
86baa9 |
- all nodes have one common DNS zone: graph shows DN relatively to the common zone
|
|
|
86baa9 |
|
|
|
86baa9 |
https://pagure.io/freeipa/issue/7206
|
|
|
86baa9 |
|
|
|
86baa9 |
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
|
|
|
86baa9 |
---
|
|
|
86baa9 |
install/ui/src/freeipa/topology.js | 64 +++++++++
|
|
|
86baa9 |
install/ui/src/freeipa/topology_graph.js | 3 +-
|
|
|
86baa9 |
install/ui/test/all_tests.html | 4 +-
|
|
|
86baa9 |
install/ui/test/index.html | 1 +
|
|
|
86baa9 |
install/ui/test/topology_tests.html | 25 ++++
|
|
|
86baa9 |
install/ui/test/topology_tests.js | 158 +++++++++++++++++++++++
|
|
|
86baa9 |
6 files changed, 252 insertions(+), 3 deletions(-)
|
|
|
86baa9 |
create mode 100644 install/ui/test/topology_tests.html
|
|
|
86baa9 |
create mode 100644 install/ui/test/topology_tests.js
|
|
|
86baa9 |
|
|
|
86baa9 |
diff --git a/install/ui/src/freeipa/topology.js b/install/ui/src/freeipa/topology.js
|
|
|
86baa9 |
index e98cb1e0ace1874056d3affa98c9518509f90558..fd7a2833abc04ffe7c3f8405bde4df0e6b942349 100644
|
|
|
86baa9 |
--- a/install/ui/src/freeipa/topology.js
|
|
|
86baa9 |
+++ b/install/ui/src/freeipa/topology.js
|
|
|
86baa9 |
@@ -1374,6 +1374,33 @@ topology.TopologyGraphWidget = declare([Stateful, Evented], {
|
|
|
86baa9 |
return deferred.promise;
|
|
|
86baa9 |
},
|
|
|
86baa9 |
|
|
|
86baa9 |
+ _find_common_domain: function(nodes) {
|
|
|
86baa9 |
+ if (nodes.length < 2) {
|
|
|
86baa9 |
+ return '';
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var common_labels = null;
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ for (var i=0, l=nodes.length; i
|
|
|
86baa9 |
+ var node = nodes[i];
|
|
|
86baa9 |
+ var labels = node.id.split('.').reverse();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ if (common_labels === null) {
|
|
|
86baa9 |
+ common_labels = labels;
|
|
|
86baa9 |
+ continue;
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ for (var j=0; j
|
|
|
86baa9 |
+ if (labels[j] !== common_labels[j]) {
|
|
|
86baa9 |
+ common_labels = common_labels.slice(0, j);
|
|
|
86baa9 |
+ break;
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ return common_labels.reverse().join('.');
|
|
|
86baa9 |
+ },
|
|
|
86baa9 |
+
|
|
|
86baa9 |
/**
|
|
|
86baa9 |
* @param {Object} size - dict contains height and width value. (optional)
|
|
|
86baa9 |
*/
|
|
|
86baa9 |
@@ -1383,6 +1410,43 @@ topology.TopologyGraphWidget = declare([Stateful, Evented], {
|
|
|
86baa9 |
if (IPA.domain_level < topology.required_domain_level) return;
|
|
|
86baa9 |
|
|
|
86baa9 |
when(this._get_data()).then(function(data) {
|
|
|
86baa9 |
+ // remove common domain labels from node FQDN
|
|
|
86baa9 |
+ // Example #1:
|
|
|
86baa9 |
+ // nodes:
|
|
|
86baa9 |
+ // - master.ipa.example.com
|
|
|
86baa9 |
+ // - replica.ipa.example.com
|
|
|
86baa9 |
+ // common domain: ipa.example.com
|
|
|
86baa9 |
+ // captions: master, replica
|
|
|
86baa9 |
+ //
|
|
|
86baa9 |
+ // Example #2:
|
|
|
86baa9 |
+ // nodes:
|
|
|
86baa9 |
+ // - master.net1.example.com
|
|
|
86baa9 |
+ // - replica.net1.example.com
|
|
|
86baa9 |
+ // - replica.net2.example.com
|
|
|
86baa9 |
+ // common domain: example.com
|
|
|
86baa9 |
+ // captions: master.net1, replica.net1, replica.net2
|
|
|
86baa9 |
+ //
|
|
|
86baa9 |
+ var common_domain = this._find_common_domain(data.nodes);
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ if (this.parent) {
|
|
|
86baa9 |
+ var title = this.parent.title;
|
|
|
86baa9 |
+ if (common_domain) {
|
|
|
86baa9 |
+ title += ' (' + common_domain + ')';
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+ this.parent.header.title_widget.update({text: title});
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ for (var i=0,l=data.nodes.length; i
|
|
|
86baa9 |
+ var node = data.nodes[i];
|
|
|
86baa9 |
+ if (l > 1 && common_domain.length > 0) {
|
|
|
86baa9 |
+ node.caption = node.id.substring(
|
|
|
86baa9 |
+ 0, node.id.length - common_domain.length - 1
|
|
|
86baa9 |
+ );
|
|
|
86baa9 |
+ } else {
|
|
|
86baa9 |
+ node.caption = node.id;
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+
|
|
|
86baa9 |
if (!this.graph) {
|
|
|
86baa9 |
this.graph = new topology_graph.TopoGraph({
|
|
|
86baa9 |
nodes: data.nodes,
|
|
|
86baa9 |
diff --git a/install/ui/src/freeipa/topology_graph.js b/install/ui/src/freeipa/topology_graph.js
|
|
|
86baa9 |
index 9f549133b516dbfe471080714845b457fd62ab1a..b736a22f63aa9a5685ac5840f60f9e2c89fb4525 100644
|
|
|
86baa9 |
--- a/install/ui/src/freeipa/topology_graph.js
|
|
|
86baa9 |
+++ b/install/ui/src/freeipa/topology_graph.js
|
|
|
86baa9 |
@@ -180,7 +180,6 @@ topology_graph.TopoGraph = declare([Evented], {
|
|
|
86baa9 |
this._target_node = null;
|
|
|
86baa9 |
this.restart();
|
|
|
86baa9 |
},
|
|
|
86baa9 |
-
|
|
|
86baa9 |
_create_svg: function(container) {
|
|
|
86baa9 |
var self = this;
|
|
|
86baa9 |
|
|
|
86baa9 |
@@ -804,7 +803,7 @@ topology_graph.TopoGraph = declare([Evented], {
|
|
|
86baa9 |
.attr('class', 'id')
|
|
|
86baa9 |
.attr('fill', '#002235')
|
|
|
86baa9 |
.text(function(d) {
|
|
|
86baa9 |
- return d.id.split('.')[0];
|
|
|
86baa9 |
+ return d.caption;
|
|
|
86baa9 |
});
|
|
|
86baa9 |
|
|
|
86baa9 |
// remove old nodes
|
|
|
86baa9 |
diff --git a/install/ui/test/all_tests.html b/install/ui/test/all_tests.html
|
|
|
86baa9 |
index cdb04b395a878db4338da7458b8f52f13514ead9..f85ae3390a923ad3083779e1ddfcdca6afa2377e 100644
|
|
|
86baa9 |
--- a/install/ui/test/all_tests.html
|
|
|
86baa9 |
+++ b/install/ui/test/all_tests.html
|
|
|
86baa9 |
@@ -26,7 +26,8 @@
|
|
|
86baa9 |
'test/utils_tests',
|
|
|
86baa9 |
'test/build_tests',
|
|
|
86baa9 |
'test/binding_tests',
|
|
|
86baa9 |
- ], function(om, ipa, details, entity, as, nav, cert, aci, wid, ip, ut, bt, bi){
|
|
|
86baa9 |
+ 'test/topology_tests',
|
|
|
86baa9 |
+ ], function(om, ipa, details, entity, as, nav, cert, aci, wid, ip, ut, bt, bi, topo){
|
|
|
86baa9 |
om();
|
|
|
86baa9 |
ipa();
|
|
|
86baa9 |
details();
|
|
|
86baa9 |
@@ -40,6 +41,7 @@
|
|
|
86baa9 |
ut();
|
|
|
86baa9 |
bt();
|
|
|
86baa9 |
bi();
|
|
|
86baa9 |
+ topo();
|
|
|
86baa9 |
});
|
|
|
86baa9 |
</script>
|
|
|
86baa9 |
</head>
|
|
|
86baa9 |
diff --git a/install/ui/test/index.html b/install/ui/test/index.html
|
|
|
86baa9 |
index 89af3211cd9791ee3055ca85ddae6afdf5b9edcf..0fd5b83d696e7e368f5ca7d726c5e4301b05acfe 100644
|
|
|
86baa9 |
--- a/install/ui/test/index.html
|
|
|
86baa9 |
+++ b/install/ui/test/index.html
|
|
|
86baa9 |
@@ -37,6 +37,7 @@
|
|
|
86baa9 |
Utils Test Suite
|
|
|
86baa9 |
Build Test Suite
|
|
|
86baa9 |
Binding Test Suite
|
|
|
86baa9 |
+ Topology Test Suite
|
|
|
86baa9 |
|
|
|
86baa9 |
|
|
|
86baa9 |
|
|
|
86baa9 |
diff --git a/install/ui/test/topology_tests.html b/install/ui/test/topology_tests.html
|
|
|
86baa9 |
new file mode 100644
|
|
|
86baa9 |
index 0000000000000000000000000000000000000000..29ca44ddcc004efbdad9860276906b7111bb40b0
|
|
|
86baa9 |
--- /dev/null
|
|
|
86baa9 |
+++ b/install/ui/test/topology_tests.html
|
|
|
86baa9 |
@@ -0,0 +1,25 @@
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+<html>
|
|
|
86baa9 |
+<head>
|
|
|
86baa9 |
+ <title>Topology Test Suite</title>
|
|
|
86baa9 |
+ <link rel="stylesheet" href="qunit.css" type="text/css" media="screen">
|
|
|
86baa9 |
+ <script type="text/javascript" src="qunit.js"></script>
|
|
|
86baa9 |
+ <script type="text/javascript" src="../js/libs/loader.js"></script>
|
|
|
86baa9 |
+ <script type="text/javascript" src="../js/libs/jquery.js"></script>
|
|
|
86baa9 |
+ <script type="text/javascript" src="../js/libs/jquery.ordered-map.js"></script>
|
|
|
86baa9 |
+ <script type="text/javascript" src="config.js"></script>
|
|
|
86baa9 |
+ <script type="text/javascript" src="../js/dojo/dojo.js"></script>
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ <script type="text/javascript">
|
|
|
86baa9 |
+ require(['test/topology_tests'], function(tests){ tests() });
|
|
|
86baa9 |
+ </script>
|
|
|
86baa9 |
+</head>
|
|
|
86baa9 |
+<body>
|
|
|
86baa9 |
+ Topology Test Suite
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+</body>
|
|
|
86baa9 |
+</html>
|
|
|
86baa9 |
diff --git a/install/ui/test/topology_tests.js b/install/ui/test/topology_tests.js
|
|
|
86baa9 |
new file mode 100644
|
|
|
86baa9 |
index 0000000000000000000000000000000000000000..6458a83f2794969e2916899975707b6c554ac314
|
|
|
86baa9 |
--- /dev/null
|
|
|
86baa9 |
+++ b/install/ui/test/topology_tests.js
|
|
|
86baa9 |
@@ -0,0 +1,158 @@
|
|
|
86baa9 |
+/**
|
|
|
86baa9 |
+ * Copyright (C) 2019 FreeIPA Contributors see COPYING for license
|
|
|
86baa9 |
+ */
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+define([
|
|
|
86baa9 |
+ 'freeipa/ipa',
|
|
|
86baa9 |
+ 'freeipa/topology',
|
|
|
86baa9 |
+ 'freeipa/jquery'],
|
|
|
86baa9 |
+ function(IPA, topology, $) {
|
|
|
86baa9 |
+ return function() {
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+var widget;
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+function inject_data(widget, data) {
|
|
|
86baa9 |
+ widget._get_data = function() {
|
|
|
86baa9 |
+ return data;
|
|
|
86baa9 |
+ };
|
|
|
86baa9 |
+}
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+QUnit.module('topology', {
|
|
|
86baa9 |
+ beforeEach: function(assert) {
|
|
|
86baa9 |
+ widget = new topology.TopologyGraphWidget(
|
|
|
86baa9 |
+ topology.topology_graph_facet_spec
|
|
|
86baa9 |
+ );
|
|
|
86baa9 |
+ widget.render();
|
|
|
86baa9 |
+ }
|
|
|
86baa9 |
+});
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+QUnit.test('Testing TopoGraph nodes', function(assert) {
|
|
|
86baa9 |
+ var nodes = [
|
|
|
86baa9 |
+ { id: 'master.ipa.test' },
|
|
|
86baa9 |
+ { id: 'replica.ipa.test' }
|
|
|
86baa9 |
+ ];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var suffixes = [
|
|
|
86baa9 |
+ { cn: ['ca'] },
|
|
|
86baa9 |
+ { cn: ['domain'] }
|
|
|
86baa9 |
+ ];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ inject_data(widget, { nodes: nodes, links: [], suffixes: suffixes });
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ widget.update();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ assert.ok($('circle.node', widget.el).length === nodes.length,
|
|
|
86baa9 |
+ 'Checking rendered nodes count');
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ assert.ok($('text.id:eq(0)', widget.el).text() === 'master',
|
|
|
86baa9 |
+ 'Checking "master" node label');
|
|
|
86baa9 |
+ assert.ok($('text.id:eq(1)', widget.el).text() === 'replica',
|
|
|
86baa9 |
+ 'Checking "replica" node label');
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ assert.ok($('text.suffix:eq(0)', widget.el).text() === 'ca',
|
|
|
86baa9 |
+ 'Checking "ca" suffix');
|
|
|
86baa9 |
+ assert.ok($('text.suffix:eq(1)', widget.el).text() === 'domain',
|
|
|
86baa9 |
+ 'Checking "domain" suffix');
|
|
|
86baa9 |
+});
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+QUnit.test('Testing TopoGraph links', function(assert) {
|
|
|
86baa9 |
+ var nodes = [
|
|
|
86baa9 |
+ { id: 'master.ipa.test', targets: { 'replica.ipa.test': [] } },
|
|
|
86baa9 |
+ { id: 'replica.ipa.test' }
|
|
|
86baa9 |
+ ];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var suffixes = [
|
|
|
86baa9 |
+ { cn: ['ca'] },
|
|
|
86baa9 |
+ { cn: ['domain'] }
|
|
|
86baa9 |
+ ];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var links = [{
|
|
|
86baa9 |
+ source: 0,
|
|
|
86baa9 |
+ target: 1,
|
|
|
86baa9 |
+ left: false,
|
|
|
86baa9 |
+ right: true,
|
|
|
86baa9 |
+ suffix: suffixes[0]
|
|
|
86baa9 |
+ }];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ inject_data(widget, { nodes: nodes, links: links, suffixes: suffixes });
|
|
|
86baa9 |
+ widget.update();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ assert.ok($('circle.node', widget.el).length === nodes.length,
|
|
|
86baa9 |
+ 'Checking rendered nodes count');
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var rendered_links = $('path.link', widget.el).not('.dragline');
|
|
|
86baa9 |
+ assert.ok(rendered_links.length === 1,
|
|
|
86baa9 |
+ 'Checking right direction link is rendered');
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var marker = rendered_links.first().css('marker-end');
|
|
|
86baa9 |
+ assert.ok(marker && marker !== 'none',
|
|
|
86baa9 |
+ 'Checking right direction link has proper marker');
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ links.push({
|
|
|
86baa9 |
+ source: 0,
|
|
|
86baa9 |
+ target: 1,
|
|
|
86baa9 |
+ left: true,
|
|
|
86baa9 |
+ right: false,
|
|
|
86baa9 |
+ suffix: suffixes[1]
|
|
|
86baa9 |
+ })
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ inject_data(widget, {
|
|
|
86baa9 |
+ nodes: nodes,
|
|
|
86baa9 |
+ links: links,
|
|
|
86baa9 |
+ suffixes: suffixes
|
|
|
86baa9 |
+ });
|
|
|
86baa9 |
+ widget.update();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ rendered_links = $('path.link', widget.el).not('.dragline')
|
|
|
86baa9 |
+ assert.ok(rendered_links.length === 2,
|
|
|
86baa9 |
+ 'Checking left direction link is rendered');
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ marker = rendered_links.last().css('marker-start');
|
|
|
86baa9 |
+ assert.ok(marker && marker !== 'none',
|
|
|
86baa9 |
+ 'Checking left direction link has proper marker');
|
|
|
86baa9 |
+});
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+QUnit.test('Testing TopoGraph for multiple DNS zones', function(assert) {
|
|
|
86baa9 |
+ var nodes = [
|
|
|
86baa9 |
+ { id: 'master.ipa.zone1' },
|
|
|
86baa9 |
+ { id: 'replica.ipa.zone1' },
|
|
|
86baa9 |
+ { id: 'master.ipa.zone2' },
|
|
|
86baa9 |
+ { id: 'master.ipa.zone1.common' },
|
|
|
86baa9 |
+ { id: 'replica.ipa.zone2.common' },
|
|
|
86baa9 |
+ ];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ var suffixes = [
|
|
|
86baa9 |
+ { cn: ['ca'] },
|
|
|
86baa9 |
+ { cn: ['domain'] }
|
|
|
86baa9 |
+ ];
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ inject_data(widget, { nodes: nodes, links: [], suffixes: suffixes });
|
|
|
86baa9 |
+ widget.update();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ $('text.id', widget.el).each(function(i) {
|
|
|
86baa9 |
+ assert.ok($(this).text() === nodes[i].id,
|
|
|
86baa9 |
+ 'Checking node label "' + $(this).text() + '" is FQDN');
|
|
|
86baa9 |
+ });
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ nodes = nodes.filter(function(node) { return /\.common$/.test(node.id) });
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ inject_data(widget, { nodes: nodes, links: [], suffixes: suffixes });
|
|
|
86baa9 |
+ widget.update();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ $('text.id', widget.el).each(function(i) {
|
|
|
86baa9 |
+ assert.ok($(this).text().indexOf('common') < 0,
|
|
|
86baa9 |
+ 'Checking node label "' + $(this).text() + '" is relative');
|
|
|
86baa9 |
+ });
|
|
|
86baa9 |
+});
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+QUnit.test('Testing TopoGraph with one node', function(assert) {
|
|
|
86baa9 |
+ var node = { id: 'master.ipa.test' };
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ inject_data(widget, { nodes: [node], links: [], suffixes: [] });
|
|
|
86baa9 |
+ widget.update();
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+ assert.ok($('text.id:eq(0)', widget.el).text() === node.id,
|
|
|
86baa9 |
+ 'Checking node label is FQDN');
|
|
|
86baa9 |
+});
|
|
|
86baa9 |
+
|
|
|
86baa9 |
+};});
|
|
|
86baa9 |
--
|
|
|
86baa9 |
2.20.1
|
|
|
86baa9 |
|