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