File implement-network.fqdns-module-function-bsc-1134860-.patch of Package salt

From ac34a8d839f91285f4ced605250422a1ecf5cb55 Mon Sep 17 00:00:00 2001
From: EricS <54029547+ESiebigteroth@users.noreply.github.com>
Date: Tue, 3 Sep 2019 11:22:53 +0200
Subject: [PATCH] Implement network.fqdns module function (bsc#1134860)
 (#172)

* Duplicate fqdns logic in module.network
* Move _get_interfaces to utils.network
* Reuse network.fqdns in grains.core.fqdns
* Return empty list when fqdns grains is disabled

Co-authored-by: Eric Siebigteroth <eric.siebigteroth@suse.de>
---
 salt/grains/core.py            | 58 +++-------------------------------
 salt/modules/network.py        | 12 +++----
 salt/utils/network.py          |  2 +-
 tests/unit/grains/test_core.py | 55 ++++++++++++--------------------
 4 files changed, 31 insertions(+), 96 deletions(-)

diff --git a/salt/grains/core.py b/salt/grains/core.py
index 5f18ba4a58..0dc1d97f97 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -23,7 +23,6 @@ import uuid
 import warnings
 import zlib
 from errno import EACCES, EPERM
-from multiprocessing.pool import ThreadPool
 
 import distro
 import salt.exceptions
@@ -2406,59 +2405,10 @@ def fqdns():
     then trying to reverse resolve them (excluding 'lo' interface).
     To disable the fqdns grain, set enable_fqdns_grains: False in the minion configuration file.
     """
-    # Provides:
-    # fqdns
-
-    grains = {}
-    fqdns = set()
-
-    def _lookup_fqdn(ip):
-        try:
-            name, aliaslist, addresslist = socket.gethostbyaddr(ip)
-            return [socket.getfqdn(name)] + [
-                als for als in aliaslist if salt.utils.network.is_fqdn(als)
-            ]
-        except socket.herror as err:
-            if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
-                # No FQDN for this IP address, so we don't need to know this all the time.
-                log.debug("Unable to resolve address %s: %s", ip, err)
-            else:
-                log.error(err_message, ip, err)
-        except (OSError, socket.gaierror, socket.timeout) as err:
-            log.error(err_message, ip, err)
-
-    start = time.time()
-
-    addresses = salt.utils.network.ip_addrs(
-        include_loopback=False, interface_data=_get_interfaces()
-    )
-    addresses.extend(
-        salt.utils.network.ip_addrs6(
-            include_loopback=False, interface_data=_get_interfaces()
-        )
-    )
-    err_message = "Exception during resolving address: %s"
-
-    # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel.
-    # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
-    # that "socket.timeout" was reached multiple times secuencially, blocking execution for several seconds.
-
-    try:
-        pool = ThreadPool(8)
-        results = pool.map(_lookup_fqdn, addresses)
-        pool.close()
-        pool.join()
-    except Exception as exc:
-        log.error("Exception while creating a ThreadPool for resolving FQDNs: %s", exc)
-
-    for item in results:
-        if item:
-            fqdns.update(item)
-
-    elapsed = time.time() - start
-    log.debug("Elapsed time getting FQDNs: {} seconds".format(elapsed))
-
-    return {"fqdns": sorted(list(fqdns))}
+    opt = {"fqdns": []}
+    if __opts__.get("enable_fqdns_grains", True) == True:
+        opt = __salt__["network.fqdns"]()
+    return opt
 
 
 def ip_fqdn():
diff --git a/salt/modules/network.py b/salt/modules/network.py
index 2e1410c288..59ed43bba6 100644
--- a/salt/modules/network.py
+++ b/salt/modules/network.py
@@ -2,7 +2,6 @@
 Module for gathering and managing network information
 """
 
-# Import python libs
 import datetime
 import hashlib
 import logging
@@ -12,7 +11,6 @@ import socket
 import time
 from multiprocessing.pool import ThreadPool
 
-# Import salt libs
 import salt.utils.decorators.path
 import salt.utils.functools
 import salt.utils.network
@@ -20,8 +18,6 @@ import salt.utils.platform
 import salt.utils.validate.net
 from salt._compat import ipaddress
 from salt.exceptions import CommandExecutionError
-
-# Import 3rd-party libs
 from salt.ext.six.moves import range
 
 log = logging.getLogger(__name__)
@@ -2076,7 +2072,10 @@ def fqdns():
 
     def _lookup_fqdn(ip):
         try:
-            return [socket.getfqdn(socket.gethostbyaddr(ip)[0])]
+            name, aliaslist, addresslist = socket.gethostbyaddr(ip)
+            return [socket.getfqdn(name)] + [
+                als for als in aliaslist if salt.utils.network.is_fqdn(als)
+            ]
         except socket.herror as err:
             if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
                 # No FQDN for this IP address, so we don't need to know this all the time.
@@ -2102,13 +2101,12 @@ def fqdns():
     # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
     # that "socket.timeout" was reached multiple times secuencially, blocking execution for several seconds.
 
-    results = []
     try:
         pool = ThreadPool(8)
         results = pool.map(_lookup_fqdn, addresses)
         pool.close()
         pool.join()
-    except Exception as exc:  # pylint: disable=broad-except
+    except Exception as exc:
         log.error("Exception while creating a ThreadPool for resolving FQDNs: %s", exc)
 
     for item in results:
diff --git a/salt/utils/network.py b/salt/utils/network.py
index d253ded3ab..25b2d06758 100644
--- a/salt/utils/network.py
+++ b/salt/utils/network.py
@@ -49,7 +49,7 @@ except (ImportError, OSError, AttributeError, TypeError):
 _INTERFACES = {}
 
 
-def _get_interfaces():
+def _get_interfaces():  #! function
     """
     Provide a dict of the connected interfaces and their ip addresses
     """
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index d760e57a54..a5ceeb8317 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -18,6 +18,7 @@ import salt.utils.network
 import salt.utils.path
 import salt.utils.platform
 from salt._compat import ipaddress
+from salt.ext import six
 from tests.support.mixins import LoaderModuleMockMixin
 from tests.support.mock import MagicMock, Mock, mock_open, patch
 from tests.support.unit import TestCase, skipIf
@@ -1293,14 +1294,14 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
         ):
             assert core.dns() == ret
 
-    def test_enable_fqdns_false(self):
+    def test_enablefqdnsFalse(self):
         """
         tests enable_fqdns_grains is set to False
         """
         with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": False}):
             assert core.fqdns() == {"fqdns": []}
 
-    def test_enable_fqdns_true(self):
+    def test_enablefqdnsTrue(self):
         """
         testing that grains uses network.fqdns module
         """
@@ -1311,14 +1312,14 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
             with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": True}):
                 assert core.fqdns() == "my.fake.domain"
 
-    def test_enable_fqdns_none(self):
+    def test_enablefqdnsNone(self):
         """
         testing default fqdns grains is returned when enable_fqdns_grains is None
         """
         with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": None}):
             assert core.fqdns() == {"fqdns": []}
 
-    def test_enable_fqdns_without_patching(self):
+    def test_enablefqdnswithoutpaching(self):
         """
         testing fqdns grains is enabled by default
         """
@@ -1326,23 +1327,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
             "salt.grains.core.__salt__",
             {"network.fqdns": MagicMock(return_value="my.fake.domain")},
         ):
-            # fqdns is disabled by default on Windows
-            if salt.utils.platform.is_windows():
-                assert core.fqdns() == {"fqdns": []}
-            else:
-                assert core.fqdns() == "my.fake.domain"
-
-    def test_enable_fqdns_false_is_proxy(self):
-        """
-        testing fqdns grains is disabled by default for proxy minions
-        """
-        with patch("salt.utils.platform.is_proxy", return_value=True, autospec=True):
-            with patch.dict(
-                "salt.grains.core.__salt__",
-                {"network.fqdns": MagicMock(return_value="my.fake.domain")},
-            ):
-                # fqdns is disabled by default on proxy minions
-                assert core.fqdns() == {"fqdns": []}
+            assert core.fqdns() == "my.fake.domain"
 
     @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
     @patch(
@@ -1367,11 +1352,12 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
             ("bluesniff.foo.bar", [], ["fe80::a8b2:93ff:dead:beef"]),
         ]
         ret = {"fqdns": ["bluesniff.foo.bar", "foo.bar.baz", "rinzler.evil-corp.com"]}
-        with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
-            fqdns = core.fqdns()
-            assert "fqdns" in fqdns
-            assert len(fqdns["fqdns"]) == len(ret["fqdns"])
-            assert set(fqdns["fqdns"]) == set(ret["fqdns"])
+        with patch.dict(core.__salt__, {"network.fqdns": salt.modules.network.fqdns}):
+            with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
+                fqdns = core.fqdns()
+                assert "fqdns" in fqdns
+                assert len(fqdns["fqdns"]) == len(ret["fqdns"])
+                assert set(fqdns["fqdns"]) == set(ret["fqdns"])
 
     @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
     @patch("salt.utils.network.ip_addrs", MagicMock(return_value=["1.2.3.4"]))
@@ -1437,14 +1423,15 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
                 ["fe80::a8b2:93ff:dead:beef"],
             ),
         ]
-        with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
-            fqdns = core.fqdns()
-            assert "fqdns" in fqdns
-            for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
-                assert alias in fqdns["fqdns"]
-
-            for alias in ["throwmeaway", "false-hostname", "badaliass"]:
-                assert alias not in fqdns["fqdns"]
+        with patch.dict(core.__salt__, {"network.fqdns": salt.modules.network.fqdns}):
+            with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
+                fqdns = core.fqdns()
+                assert "fqdns" in fqdns
+                for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
+                    assert alias in fqdns["fqdns"]
+
+                for alias in ["throwmeaway", "false-hostname", "badaliass"]:
+                    assert alias not in fqdns["fqdns"]
 
     def test_core_virtual(self):
         """
-- 
2.29.2
openSUSE Build Service is sponsored by