Hello community,
here is the log from the commit of package salt for openSUSE:Factory checked in at 2018-04-30 22:58:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/salt (Old)
and /work/SRC/openSUSE:Factory/.salt.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "salt"
Mon Apr 30 22:58:17 2018 rev:75 rq:602524 version:2018.3.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/salt/salt.changes 2018-04-16 12:48:11.246861936 +0200
+++ /work/SRC/openSUSE:Factory/.salt.new/salt.changes 2018-04-30 22:59:33.495104654 +0200
@@ -1,0 +2,41 @@
+Wed Apr 25 14:50:36 UTC 2018 - Pablo Suárez Hernández
+
+- Fix minion scheduler to return a 'retcode' attribute (bsc#1089112)
+- Fix for logging during network interface querying (bsc#1087581)
+- Fix rhel packages requires both net-tools and iproute (bsc#1087055)
+
+- Added:
+ * initialize-__context__-retcode-for-functions-handled.patch
+
+- Modified:
+ * fix-for-errno-0-resolver-error-0-no-error-bsc-108758.patch
+
+-------------------------------------------------------------------
+Wed Apr 18 17:09:41 UTC 2018 - Pablo Suárez Hernández
+
+- Fix patchinstall on yum module. Bad comparison (bsc#1087278)
+
+- Added:
+ * provide-kwargs-to-pkg_resource.parse_targets-require.patch
+
+-------------------------------------------------------------------
+Wed Apr 18 16:55:28 UTC 2018 - Pablo Suárez Hernández
+
+- Strip trailing commas on Linux user's GECOS fields (bsc#1089362)
+- Fallback to PyMySQL (bsc#1087891)
+- Improved test for fqdns
+- Update SaltSSH patch
+- Fix for [Errno 0] Resolver Error 0 (no error) (bsc#1087581)
+ * Lintfix: PEP8 ident
+ * Use proper levels of the error handling, use proper log formatting.
+ * Fix unit test for reversed fqdns return data
+
+- Added:
+ * strip-trailing-commas-on-linux-user-gecos-fields.patch
+ * fall-back-to-pymysql.patch
+ * fix-for-errno-0-resolver-error-0-no-error-bsc-108758.patch
+
+- Modified:
+ * add-saltssh-multi-version-support-across-python-inte.patch
+
+-------------------------------------------------------------------
New:
----
fall-back-to-pymysql.patch
fix-for-errno-0-resolver-error-0-no-error-bsc-108758.patch
initialize-__context__-retcode-for-functions-handled.patch
provide-kwargs-to-pkg_resource.parse_targets-require.patch
strip-trailing-commas-on-linux-user-gecos-fields.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ salt.spec ++++++
--- /var/tmp/diff_new_pack.IdNY7V/_old 2018-04-30 22:59:34.455069625 +0200
+++ /var/tmp/diff_new_pack.IdNY7V/_new 2018-04-30 22:59:34.459069478 +0200
@@ -86,6 +86,17 @@
Patch13: explore-module.run-response-to-catch-the-result-in-d.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/46684
Patch14: add-saltssh-multi-version-support-across-python-inte.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/46635
+Patch15: fix-for-errno-0-resolver-error-0-no-error-bsc-108758.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/46890
+Patch16: fall-back-to-pymysql.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/47149
+Patch17: strip-trailing-commas-on-linux-user-gecos-fields.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/47155
+Patch18: provide-kwargs-to-pkg_resource.parse_targets-require.patch
+# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/47270
+Patch19: initialize-__context__-retcode-for-functions-handled.patch
+
# BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -116,12 +127,12 @@
%if 0%{?suse_version} >= 1500
Requires: iproute2
%else
+%if 0%{?suse_version}
Requires: net-tools
-%endif
-
-%if 0%{?rhel}
+%else
Requires: iproute
%endif
+%endif
%if %{with systemd}
BuildRequires: systemd
@@ -558,6 +569,11 @@
%patch12 -p1
%patch13 -p1
%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
%build
%if 0%{?build_py2}
++++++ _lastrevision ++++++
--- /var/tmp/diff_new_pack.IdNY7V/_old 2018-04-30 22:59:34.503067873 +0200
+++ /var/tmp/diff_new_pack.IdNY7V/_new 2018-04-30 22:59:34.503067873 +0200
@@ -1 +1 @@
-f43b8fb2425e3371decf3cde040c70ed15de375d
\ No newline at end of file
+057b96d7f072dc69b61ca9e3b8d04a890003e58f
\ No newline at end of file
++++++ _service ++++++
--- /var/tmp/diff_new_pack.IdNY7V/_old 2018-04-30 22:59:34.523067143 +0200
+++ /var/tmp/diff_new_pack.IdNY7V/_new 2018-04-30 22:59:34.523067143 +0200
@@ -3,7 +3,7 @@
<param name="url">https://github.com/openSUSE/salt-packaging.git</param>
<param name="subdir">salt</param>
<param name="filename">package</param>
- <param name="revision">oxygen-rc1</param>
+ <param name="revision">2018.3.0</param>
<param name="scm">git</param>
</service>
<service name="extract_file" mode="disabled">
++++++ add-saltssh-multi-version-support-across-python-inte.patch ++++++
++++ 603 lines (skipped)
++++ between /work/SRC/openSUSE:Factory/salt/add-saltssh-multi-version-support-across-python-inte.patch
++++ and /work/SRC/openSUSE:Factory/.salt.new/add-saltssh-multi-version-support-across-python-inte.patch
++++++ fall-back-to-pymysql.patch ++++++
From f7ba683153e11be401a5971ba029d0a3964b1ecb Mon Sep 17 00:00:00 2001
From: Maximilian Meister
Date: Thu, 5 Apr 2018 13:23:23 +0200
Subject: [PATCH] fall back to PyMySQL
same is already done in modules (see #26803)
Signed-off-by: Maximilian Meister
---
salt/auth/mysql.py | 25 ++++++++++++++++++++++---
salt/cache/mysql_cache.py | 28 +++++++++++++++++++---------
salt/modules/mysql.py | 22 ++++++++++------------
salt/pillar/mysql.py | 21 ++++++++++++++++-----
salt/returners/mysql.py | 29 +++++++++++++++++++++--------
tests/unit/pillar/test_mysql.py | 2 +-
6 files changed, 89 insertions(+), 38 deletions(-)
diff --git a/salt/auth/mysql.py b/salt/auth/mysql.py
index 8bc18a4101..86d00a4373 100644
--- a/salt/auth/mysql.py
+++ b/salt/auth/mysql.py
@@ -55,10 +55,29 @@ import logging
log = logging.getLogger(__name__)
try:
+ # Trying to import MySQLdb
import MySQLdb
- HAS_MYSQL = True
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ from MySQLdb.connections import OperationalError
except ImportError:
- HAS_MYSQL = False
+ try:
+ # MySQLdb import failed, try to import PyMySQL
+ import pymysql
+ pymysql.install_as_MySQLdb()
+ import MySQLdb
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ from MySQLdb.err import OperationalError
+ except ImportError:
+ MySQLdb = None
+
+
+def __virtual__():
+ '''
+ Confirm that a python mysql client is installed.
+ '''
+ return bool(MySQLdb), 'No python mysql client installed.' if MySQLdb is None else ''
def __get_connection_info():
@@ -95,7 +114,7 @@ def auth(username, password):
_info['username'],
_info['password'],
_info['database'])
- except MySQLdb.OperationalError as e:
+ except OperationalError as e:
log.error(e)
return False
diff --git a/salt/cache/mysql_cache.py b/salt/cache/mysql_cache.py
index 9d6aa17987..8b0a942310 100644
--- a/salt/cache/mysql_cache.py
+++ b/salt/cache/mysql_cache.py
@@ -46,11 +46,24 @@ value to ``mysql``:
from __future__ import absolute_import, print_function, unicode_literals
from time import sleep
import logging
+
try:
+ # Trying to import MySQLdb
import MySQLdb
- HAS_MYSQL = True
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ from MySQLdb.connections import OperationalError
except ImportError:
- HAS_MYSQL = False
+ try:
+ # MySQLdb import failed, try to import PyMySQL
+ import pymysql
+ pymysql.install_as_MySQLdb()
+ import MySQLdb
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ from MySQLdb.err import OperationalError
+ except ImportError:
+ MySQLdb = None
from salt.exceptions import SaltCacheError
@@ -71,12 +84,9 @@ __func_alias__ = {'ls': 'list'}
def __virtual__():
'''
- Confirm that python-mysql package is installed.
+ Confirm that a python mysql client is installed.
'''
- if not HAS_MYSQL:
- return (False, "Please install python-mysql package to use mysql data "
- "cache driver")
- return __virtualname__
+ return bool(MySQLdb), 'No python mysql client installed.' if MySQLdb is None else ''
def run_query(conn, query, retries=3):
@@ -84,13 +94,13 @@ def run_query(conn, query, retries=3):
Get a cursor and run a query. Reconnect up to `retries` times if
needed.
Returns: cursor, affected rows counter
- Raises: SaltCacheError, AttributeError, MySQLdb.OperationalError
+ Raises: SaltCacheError, AttributeError, OperationalError
'''
try:
cur = conn.cursor()
out = cur.execute(query)
return cur, out
- except (AttributeError, MySQLdb.OperationalError) as e:
+ except (AttributeError, OperationalError) as e:
if retries == 0:
raise
# reconnect creating new client
diff --git a/salt/modules/mysql.py b/salt/modules/mysql.py
index 0625b02a96..8b17e461ea 100644
--- a/salt/modules/mysql.py
+++ b/salt/modules/mysql.py
@@ -51,13 +51,14 @@ import salt.utils.stringutils
from salt.ext import six
# pylint: disable=import-error
from salt.ext.six.moves import range, zip # pylint: disable=no-name-in-module,redefined-builtin
+
try:
- # Try to import MySQLdb
+ # Trying to import MySQLdb
import MySQLdb
import MySQLdb.cursors
import MySQLdb.converters
from MySQLdb.constants import FIELD_TYPE, FLAG
- HAS_MYSQLDB = True
+ from MySQLdb.connections import OperationalError
except ImportError:
try:
# MySQLdb import failed, try to import PyMySQL
@@ -67,10 +68,9 @@ except ImportError:
import MySQLdb.cursors
import MySQLdb.converters
from MySQLdb.constants import FIELD_TYPE, FLAG
- HAS_MYSQLDB = True
+ from MySQLdb.err import OperationalError
except ImportError:
- # No MySQL Connector installed, return False
- HAS_MYSQLDB = False
+ MySQLdb = None
log = logging.getLogger(__name__)
@@ -195,11 +195,9 @@ And theses could be mixed, in a like query value with args: 'f\_o\%%o`b\'a"r'
def __virtual__():
'''
- Only load this module if the mysql libraries exist
+ Confirm that a python mysql client is installed.
'''
- if HAS_MYSQLDB:
- return True
- return (False, 'The mysql execution module cannot be loaded: neither MySQLdb nor PyMySQL is available.')
+ return bool(MySQLdb), 'No python mysql client installed.' if MySQLdb is None else ''
def __check_table(name, table, **connection_args):
@@ -331,7 +329,7 @@ def _connect(**kwargs):
connargs.pop('passwd')
try:
dbc = MySQLdb.connect(**connargs)
- except MySQLdb.OperationalError as exc:
+ except OperationalError as exc:
err = 'MySQL Error {0}: {1}'.format(*exc)
__context__['mysql.error'] = err
log.error(err)
@@ -647,7 +645,7 @@ def query(database, query, **connection_args):
log.debug('Using db: %s to run query %s', database, query)
try:
affected = _execute(cur, query)
- except MySQLdb.OperationalError as exc:
+ except OperationalError as exc:
err = 'MySQL Error {0}: {1}'.format(*exc)
__context__['mysql.error'] = err
log.error(err)
@@ -772,7 +770,7 @@ def status(**connection_args):
qry = 'SHOW STATUS'
try:
_execute(cur, qry)
- except MySQLdb.OperationalError as exc:
+ except OperationalError as exc:
err = 'MySQL Error {0}: {1}'.format(*exc)
__context__['mysql.error'] = err
log.error(err)
diff --git a/salt/pillar/mysql.py b/salt/pillar/mysql.py
index 8029e5c197..d3f9619ad5 100644
--- a/salt/pillar/mysql.py
+++ b/salt/pillar/mysql.py
@@ -59,16 +59,27 @@ log = logging.getLogger(__name__)
# Import third party libs
try:
+ # Trying to import MySQLdb
import MySQLdb
- HAS_MYSQL = True
+ import MySQLdb.cursors
+ import MySQLdb.converters
except ImportError:
- HAS_MYSQL = False
+ try:
+ # MySQLdb import failed, try to import PyMySQL
+ import pymysql
+ pymysql.install_as_MySQLdb()
+ import MySQLdb
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ except ImportError:
+ MySQLdb = None
def __virtual__():
- if not HAS_MYSQL:
- return False
- return True
+ '''
+ Confirm that a python mysql client is installed.
+ '''
+ return bool(MySQLdb), 'No python mysql client installed.' if MySQLdb is None else ''
class MySQLExtPillar(SqlBaseExtPillar):
diff --git a/salt/returners/mysql.py b/salt/returners/mysql.py
index af6698142b..85892cb06c 100644
--- a/salt/returners/mysql.py
+++ b/salt/returners/mysql.py
@@ -155,11 +155,24 @@ import salt.exceptions
# Import 3rd-party libs
from salt.ext import six
+
try:
+ # Trying to import MySQLdb
import MySQLdb
- HAS_MYSQL = True
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ from MySQLdb.connections import OperationalError
except ImportError:
- HAS_MYSQL = False
+ try:
+ # MySQLdb import failed, try to import PyMySQL
+ import pymysql
+ pymysql.install_as_MySQLdb()
+ import MySQLdb
+ import MySQLdb.cursors
+ import MySQLdb.converters
+ from MySQLdb.err import OperationalError
+ except ImportError:
+ MySQLdb = None
log = logging.getLogger(__name__)
@@ -168,10 +181,10 @@ __virtualname__ = 'mysql'
def __virtual__():
- if not HAS_MYSQL:
- return False, 'Could not import mysql returner; ' \
- 'mysql python client is not installed.'
- return True
+ '''
+ Confirm that a python mysql client is installed.
+ '''
+ return bool(MySQLdb), 'No python mysql client installed.' if MySQLdb is None else ''
def _get_options(ret=None):
@@ -228,7 +241,7 @@ def _get_serv(ret=None, commit=False):
conn = __context__['mysql_returner_conn']
conn.ping()
connect = False
- except MySQLdb.connections.OperationalError as exc:
+ except OperationalError as exc:
log.debug('OperationalError on ping: %s', exc)
if connect:
@@ -254,7 +267,7 @@ def _get_serv(ret=None, commit=False):
__context__['mysql_returner_conn'] = conn
except TypeError:
pass
- except MySQLdb.connections.OperationalError as exc:
+ except OperationalError as exc:
raise salt.exceptions.SaltMasterError('MySQL returner could not connect to database: {exc}'.format(exc=exc))
cursor = conn.cursor()
diff --git a/tests/unit/pillar/test_mysql.py b/tests/unit/pillar/test_mysql.py
index 8d49ac24e2..b72988673d 100644
--- a/tests/unit/pillar/test_mysql.py
+++ b/tests/unit/pillar/test_mysql.py
@@ -12,7 +12,7 @@ import salt.pillar.mysql as mysql
@skipIf(NO_MOCK, NO_MOCK_REASON)
-@skipIf(not mysql.HAS_MYSQL, 'MySQL-python module not installed')
+@skipIf(mysql.MySQLdb is None, 'MySQL-python module not installed')
class MysqlPillarTestCase(TestCase):
maxDiff = None
--
2.13.6
++++++ fix-for-errno-0-resolver-error-0-no-error-bsc-108758.patch ++++++
From b9cc71639d4e918ef14635124f6991917150de46 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk
Date: Wed, 21 Mar 2018 11:10:23 +0100
Subject: [PATCH] Fix for [Errno 0] Resolver Error 0 (no error)
(bsc#1087581)
* Lintfix: PEP8 ident
* Use proper levels of the error handling, use proper log formatting.
* Fix unit test for reversed fqdns return data
---
salt/grains/core.py | 19 ++++++++++++-------
tests/unit/grains/test_core.py | 32 ++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 17a7d9819a..cd9ba1f29c 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1900,16 +1900,21 @@ def fqdns():
fqdns = set()
addresses = salt.utils.network.ip_addrs(include_loopback=False,
- interface_data=_INTERFACES)
+ interface_data=_INTERFACES)
addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False,
- interface_data=_INTERFACES))
-
+ interface_data=_INTERFACES))
+ err_message = 'Exception during resolving address: %s'
for ip in addresses:
try:
- fqdns.add(socket.gethostbyaddr(ip)[0])
- except (socket.error, socket.herror,
- socket.gaierror, socket.timeout) as e:
- log.info("Exception during resolving address: " + str(e))
+ fqdns.add(socket.getfqdn(socket.gethostbyaddr(ip)[0]))
+ except socket.herror as err:
+ if err.errno == 0:
+ # 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, err)
+ except (socket.error, socket.gaierror, socket.timeout) as err:
+ log.error(err_message, err)
grains['fqdns'] = list(fqdns)
return grains
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 47c9cdd35b..c604df6c57 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -784,3 +784,35 @@ SwapTotal: 4789244 kB'''
[]}}
with patch.object(salt.utils.dns, 'parse_resolv', MagicMock(return_value=resolv_mock)):
assert core.dns() == ret
+
+ def _run_dns_test(self, resolv_mock, ret):
+ with patch.object(salt.utils, 'is_windows',
+ MagicMock(return_value=False)):
+ with patch.dict(core.__opts__, {'ipv6': False}):
+ with patch.object(salt.utils.dns, 'parse_resolv',
+ MagicMock(return_value=resolv_mock)):
+ get_dns = core.dns()
+ self.assertEqual(get_dns, ret)
+
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
+ @patch.object(salt.utils, 'is_windows', MagicMock(return_value=False))
+ @patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8']))
+ @patch('salt.utils.network.ip_addrs6',
+ MagicMock(return_value=['fe80::a8b2:93ff:fe00:0', 'fe80::a8b2:93ff:dead:beef']))
+ @patch('salt.utils.network.socket.getfqdn', MagicMock(side_effect=lambda v: v)) # Just pass-through
+ def test_fqdns_return(self):
+ '''
+ test the return for a dns grain. test for issue:
+ https://github.com/saltstack/salt/issues/41230
+ '''
+ reverse_resolv_mock = [('foo.bar.baz', [], ['1.2.3.4']),
+ ('rinzler.evil-corp.com', [], ['5.6.7.8']),
+ ('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
+ ('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()
+ self.assertIn('fqdns', fqdns)
+ self.assertEqual(len(fqdns['fqdns']), len(ret['fqdns']))
+ self.assertEqual(set(fqdns['fqdns']), set(ret['fqdns']))
+
--
2.13.6
++++++ initialize-__context__-retcode-for-functions-handled.patch ++++++
From c374feb62af75dfe18e8c81fb9cb556d678487ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
Date: Tue, 24 Apr 2018 13:50:49 +0100
Subject: [PATCH] Initialize __context__ retcode for functions handled
via schedule util module
---
salt/utils/schedule.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/salt/utils/schedule.py b/salt/utils/schedule.py
index de057477a3..6cb3ce0ef8 100644
--- a/salt/utils/schedule.py
+++ b/salt/utils/schedule.py
@@ -701,6 +701,7 @@ class Schedule(object):
for global_key, value in six.iteritems(func_globals):
self.functions[mod_name].__globals__[global_key] = value
+ self.functions.pack['__context__']['retcode'] = 0
ret['return'] = self.functions[func](*args, **kwargs)
if not self.standalone:
--
2.15.1
++++++ provide-kwargs-to-pkg_resource.parse_targets-require.patch ++++++
From f7af1739a5795de6f98cfe2856372c755711e6dc Mon Sep 17 00:00:00 2001
From: Michael Calmer
Date: Wed, 18 Apr 2018 17:19:18 +0200
Subject: [PATCH] provide kwargs to pkg_resource.parse_targets required
to detect advisory type
fix invalid string compare
---
salt/modules/yumpkg.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index 39abb77fbc..9eb27e7701 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -1322,7 +1322,7 @@ def install(name=None,
try:
pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](
- name, pkgs, sources, saltenv=saltenv, normalize=normalize
+ name, pkgs, sources, saltenv=saltenv, normalize=normalize, **kwargs
)
except MinionError as exc:
raise CommandExecutionError(exc)
@@ -1620,7 +1620,7 @@ def install(name=None,
if _yum() == 'dnf':
cmd.extend(['--best', '--allowerasing'])
_add_common_args(cmd)
- cmd.append('install' if pkg_type is not 'advisory' else 'update')
+ cmd.append('install' if pkg_type != 'advisory' else 'update')
cmd.extend(targets)
out = __salt__['cmd.run_all'](
cmd,
--
2.15.1
++++++ strip-trailing-commas-on-linux-user-gecos-fields.patch ++++++
From f9fb3639bb3c44babd92d9499bdde83a0a81d6ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
Date: Wed, 18 Apr 2018 12:05:35 +0100
Subject: [PATCH] Strip trailing commas on Linux user GECOS fields
Add unit tests for GECOS fields
---
salt/modules/useradd.py | 2 +-
tests/unit/modules/test_useradd.py | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/salt/modules/useradd.py b/salt/modules/useradd.py
index 545fe2a6f1..a61ba0e960 100644
--- a/salt/modules/useradd.py
+++ b/salt/modules/useradd.py
@@ -81,7 +81,7 @@ def _build_gecos(gecos_dict):
return '{0},{1},{2},{3}'.format(gecos_dict.get('fullname', ''),
gecos_dict.get('roomnumber', ''),
gecos_dict.get('workphone', ''),
- gecos_dict.get('homephone', ''))
+ gecos_dict.get('homephone', '')).rstrip(',')
def _update_gecos(name, key, value, root=None):
diff --git a/tests/unit/modules/test_useradd.py b/tests/unit/modules/test_useradd.py
index eb983685bb..fa30a0df71 100644
--- a/tests/unit/modules/test_useradd.py
+++ b/tests/unit/modules/test_useradd.py
@@ -393,3 +393,21 @@ class UserAddTestCase(TestCase, LoaderModuleMockMixin):
mock = MagicMock(side_effect=[{'name': ''}, False, {'name': ''}])
with patch.object(useradd, 'info', mock):
self.assertFalse(useradd.rename('salt', 'salt'))
+
+ def test_build_gecos_field(self):
+ '''
+ Test if gecos fields are built correctly (removing trailing commas)
+ '''
+ test_gecos = {'fullname': 'Testing',
+ 'roomnumber': 1234,
+ 'workphone': 22222,
+ 'homephone': 99999}
+ expected_gecos_fields = 'Testing,1234,22222,99999'
+ self.assertEqual(useradd._build_gecos(test_gecos), expected_gecos_fields)
+ test_gecos.pop('roomnumber')
+ test_gecos.pop('workphone')
+ expected_gecos_fields = 'Testing,,,99999'
+ self.assertEqual(useradd._build_gecos(test_gecos), expected_gecos_fields)
+ test_gecos.pop('homephone')
+ expected_gecos_fields = 'Testing'
+ self.assertEqual(useradd._build_gecos(test_gecos), expected_gecos_fields)
--
2.15.1