Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package crmsh for openSUSE:Factory checked in at 2022-05-05 23:06:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/crmsh (Old) and /work/SRC/openSUSE:Factory/.crmsh.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "crmsh" Thu May 5 23:06:47 2022 rev:244 rq:975021 version:4.4.0+20220505.a3a00365 Changes: -------- --- /work/SRC/openSUSE:Factory/crmsh/crmsh.changes 2022-04-19 09:59:54.403692360 +0200 +++ /work/SRC/openSUSE:Factory/.crmsh.new.1538/crmsh.changes 2022-05-05 23:07:21.137629120 +0200 @@ -1,0 +2,7 @@ +Thu May 05 02:12:49 UTC 2022 - xli...@suse.com + +- Update to version 4.4.0+20220505.a3a00365: + * Dev: unittest: Adjust unit test for previous changes + * Fix: crm report: Read data in a save way, to avoid UnicodeDecodeError(bsc#1198180) + +------------------------------------------------------------------- Old: ---- crmsh-4.4.0+20220418.cbf7a09e.tar.bz2 New: ---- crmsh-4.4.0+20220505.a3a00365.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ crmsh.spec ++++++ --- /var/tmp/diff_new_pack.tlwU19/_old 2022-05-05 23:07:22.549630883 +0200 +++ /var/tmp/diff_new_pack.tlwU19/_new 2022-05-05 23:07:22.553630887 +0200 @@ -36,7 +36,7 @@ Summary: High Availability cluster command-line interface License: GPL-2.0-or-later Group: %{pkg_group} -Version: 4.4.0+20220418.cbf7a09e +Version: 4.4.0+20220505.a3a00365 Release: 0 URL: http://crmsh.github.io Source0: %{name}-%{version}.tar.bz2 ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.tlwU19/_old 2022-05-05 23:07:22.597630943 +0200 +++ /var/tmp/diff_new_pack.tlwU19/_new 2022-05-05 23:07:22.597630943 +0200 @@ -9,7 +9,7 @@ </service> <service name="tar_scm"> <param name="url">https://github.com/ClusterLabs/crmsh.git</param> - <param name="changesrevision">682c8132161630cc4c2af4bc249c40f93d995bae</param> + <param name="changesrevision">a3a0036532f5b37b6cc6b659f89ac9dcb08f2896</param> </service> </servicedata> (No newline at EOF) ++++++ crmsh-4.4.0+20220418.cbf7a09e.tar.bz2 -> crmsh-4.4.0+20220505.a3a00365.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/corosync.py new/crmsh-4.4.0+20220505.a3a00365/crmsh/corosync.py --- old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/corosync.py 2022-04-18 08:32:05.000000000 +0200 +++ new/crmsh-4.4.0+20220505.a3a00365/crmsh/corosync.py 2022-05-05 03:52:21.000000000 +0200 @@ -446,26 +446,22 @@ def get_all_paths(): - f = open(conf()).read() - p = Parser(f) + p = Parser(utils.read_from_file(conf())) return p.all_paths() def get_value(path): - f = open(conf()).read() - p = Parser(f) + p = Parser(utils.read_from_file(conf())) return p.get(path) def get_values(path): - f = open(conf()).read() - p = Parser(f) + p = Parser(utils.read_from_file(conf())) return p.get_all(path) def set_value(path, value): - f = open(conf()).read() - p = Parser(f) + p = Parser(utils.read_from_file(conf())) p.set(path, value) utils.str2file(p.to_string(), conf()) @@ -479,9 +475,7 @@ find if the same IP already configured If so, raise IPAlreadyConfiguredError """ - with open(conf()) as f: - p = Parser(f.read()) - + p = Parser(utils.read_from_file(conf())) # get exist ip list from corosync.conf corosync_iplist = [] for path in set(p.all_paths()): @@ -509,9 +503,7 @@ find_configured_ip(ip_list) - with open(conf()) as f: - p = Parser(f.read()) - + p = Parser(utils.read_from_file(conf())) if node_id is None: node_id = get_free_nodeid(p) node_value = [] @@ -558,8 +550,7 @@ logger.warning("%s already in configuration" % (name)) return - f = open(conf()).read() - p = Parser(f) + p = Parser(utils.read_from_file(conf())) node_addr = addr node_id = get_free_nodeid(p) @@ -596,8 +587,7 @@ ''' Remove node from corosync ''' - f = open(conf()).read() - p = Parser(f) + p = Parser(utils.read_from_file(conf())) nth = p.remove_section_where('nodelist.node', 'ring0_addr', addr) if nth == -1: return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/qdevice.py new/crmsh-4.4.0+20220505.a3a00365/crmsh/qdevice.py --- old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/qdevice.py 2022-04-18 08:32:05.000000000 +0200 +++ new/crmsh-4.4.0+20220505.a3a00365/crmsh/qdevice.py 2022-05-05 03:52:21.000000000 +0200 @@ -543,9 +543,7 @@ """ Write qdevice attributes to config file """ - with open(corosync.conf()) as f: - p = corosync.Parser(f.read()) - + p = corosync.Parser(utils.read_from_file(corosync.conf())) p.remove("quorum.device") p.add('quorum', corosync.make_section('quorum.device', [])) p.set('quorum.device.votes', '1') @@ -570,9 +568,8 @@ """ Remove configuration of qdevice """ - with open(corosync.conf()) as f: - p = corosync.Parser(f.read()) - p.remove("quorum.device") + p = corosync.Parser(utils.read_from_file(corosync.conf())) + p.remove("quorum.device") utils.str2file(p.to_string(), corosync.conf()) @staticmethod diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/report/utillib.py new/crmsh-4.4.0+20220505.a3a00365/crmsh/report/utillib.py --- old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/report/utillib.py 2022-04-18 08:32:05.000000000 +0200 +++ new/crmsh-4.4.0+20220505.a3a00365/crmsh/report/utillib.py 2022-05-05 03:52:21.000000000 +0200 @@ -794,10 +794,10 @@ def get_conf_var(option, default=None): ret = default if os.path.isfile(constants.CONF): - with open(constants.CONF, 'r') as f: - for line in f.read().split('\n'): - if re.match("^\s*%s\s*:" % option, line): - ret = line.split(':')[1].lstrip() + data = read_from_file(constants.CONF) + for line in data.split('\n'): + if re.match("^\s*%s\s*:" % option, line): + ret = line.split(':')[1].lstrip() return ret @@ -1020,15 +1020,15 @@ def is_conf_set(option, subsys=None): subsys_start = 0 if os.path.isfile(constants.CONF): - with open(constants.CONF, 'r') as f: - for line in f.read().split('\n'): - if re.search("^\s*subsys\s*:\s*%s$" % subsys, line): - subsys_start = 1 - if subsys_start == 1 and re.search("^\s*}", line): - subsys_start = 0 - if re.match("^\s*%s\s*:\s*(on|yes)$" % option, line): - if not subsys or subsys_start == 1: - return True + data = read_from_file(constants.CONF) + for line in data.split('\n'): + if re.search("^\s*subsys\s*:\s*%s$" % subsys, line): + subsys_start = 1 + if subsys_start == 1 and re.search("^\s*}", line): + subsys_start = 0 + if re.match("^\s*%s\s*:\s*(on|yes)$" % option, line): + if not subsys or subsys_start == 1: + return True return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/utils.py new/crmsh-4.4.0+20220505.a3a00365/crmsh/utils.py --- old/crmsh-4.4.0+20220418.cbf7a09e/crmsh/utils.py 2022-04-18 08:32:05.000000000 +0200 +++ new/crmsh-4.4.0+20220505.a3a00365/crmsh/utils.py 2022-05-05 03:52:21.000000000 +0200 @@ -3095,4 +3095,14 @@ logger.error("Failed to patch") return False return True + + +def read_from_file(infile): + """ + Read data from file in a save way, to avoid UnicodeDecodeError + """ + data = None + with open(infile, 'rt', encoding='utf-8', errors='replace') as f: + data = f.read() + return to_ascii(data) # vim:ts=4:sw=4:et: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.0+20220418.cbf7a09e/test/unittests/test_corosync.py new/crmsh-4.4.0+20220505.a3a00365/test/unittests/test_corosync.py --- old/crmsh-4.4.0+20220418.cbf7a09e/test/unittests/test_corosync.py 2022-04-18 08:32:05.000000000 +0200 +++ new/crmsh-4.4.0+20220505.a3a00365/test/unittests/test_corosync.py 2022-05-05 03:52:21.000000000 +0200 @@ -334,12 +334,13 @@ @mock.patch("re.search") @mock.patch("crmsh.corosync.Parser") @mock.patch("crmsh.corosync.conf") - @mock.patch("builtins.open", new_callable=mock.mock_open, read_data="corosync conf data") - def test_find_configured_ip_no_exception(self, mock_open_file, mock_conf, mock_parser, mock_search, mock_isv6, mock_ip_local): + @mock.patch("crmsh.utils.read_from_file") + def test_find_configured_ip_no_exception(self, mock_read_file, mock_conf, mock_parser, mock_search, mock_isv6, mock_ip_local): mock_conf.return_value = "/etc/corosync/corosync.conf" mock_parser_inst = mock.Mock() mock_parser.return_value = mock_parser_inst mock_parser_inst.all_paths.return_value = ["nodelist.node.ring0_addr"] + mock_read_file.return_value = "data" mock_search.return_value = mock.Mock() mock_parser_inst.get_all.return_value = ["10.10.10.1"] mock_isv6.return_value = False @@ -348,9 +349,9 @@ corosync.find_configured_ip(["10.10.10.2"]) mock_conf.assert_called_once_with() + mock_parser.assert_called_once_with("data") mock_parser_inst.all_paths.assert_called_once_with() mock_parser_inst.get_all.assert_called_once_with("nodelist.node.ring0_addr") - mock_open_file.assert_called_once_with(mock_conf.return_value) mock_isv6.assert_called_once_with("10.10.10.2") mock_ip_local.assert_called_once_with(False) mock_search.assert_called_once_with("nodelist.node.ring[0-9]*_addr", "nodelist.node.ring0_addr") @@ -360,12 +361,13 @@ @mock.patch("re.search") @mock.patch("crmsh.corosync.Parser") @mock.patch("crmsh.corosync.conf") - @mock.patch("builtins.open", new_callable=mock.mock_open, read_data="corosync conf data") - def test_find_configured_ip_exception(self, mock_open_file, mock_conf, mock_parser, mock_search, mock_isv6, mock_ip_local): + @mock.patch("crmsh.utils.read_from_file") + def test_find_configured_ip_exception(self, mock_read_file, mock_conf, mock_parser, mock_search, mock_isv6, mock_ip_local): mock_conf.return_value = "/etc/corosync/corosync.conf" mock_parser_inst = mock.Mock() mock_parser.return_value = mock_parser_inst mock_parser_inst.all_paths.return_value = ["nodelist.node.ring0_addr"] + mock_read_file.return_value = "data" mock_search.return_value = mock.Mock() mock_parser_inst.get_all.return_value = ["10.10.10.1", "10.10.10.2"] mock_isv6.return_value = False @@ -376,9 +378,9 @@ self.assertEqual("IP 10.10.10.2 was already configured", str(err.exception)) mock_conf.assert_called_once_with() + mock_parser.assert_called_once_with("data") mock_parser_inst.all_paths.assert_called_once_with() mock_parser_inst.get_all.assert_called_once_with("nodelist.node.ring0_addr") - mock_open_file.assert_called_once_with(mock_conf.return_value) mock_isv6.assert_called_once_with("10.10.10.2") mock_ip_local.assert_called_once_with(False) # For some reason mock_search.assert_called_once_with does not work @@ -390,17 +392,14 @@ @mock.patch("crmsh.corosync.make_value") @mock.patch("crmsh.corosync.get_free_nodeid") @mock.patch("crmsh.corosync.Parser") - @mock.patch("builtins.open", create=True) + @mock.patch("crmsh.utils.read_from_file") @mock.patch("crmsh.corosync.conf") @mock.patch("crmsh.corosync.find_configured_ip") - def test_add_node_ucast(self, mock_find_ip, mock_conf, mock_open_file, mock_parser, + def test_add_node_ucast(self, mock_find_ip, mock_conf, mock_read_file, mock_parser, mock_free_id, mock_make_value, mock_get_values, mock_make_section, mock_str2file): mock_parser_inst = mock.Mock() mock_conf.side_effect = ["corosync.conf", "corosync.conf"] - mock_open_read = mock.mock_open(read_data="read data") - mock_open_file.side_effect = [ - mock_open_read.return_value, - ] + mock_read_file.return_value = "data" mock_parser.return_value = mock_parser_inst mock_free_id.return_value = 2 mock_make_value.side_effect = [["value1"], ["value2"]] @@ -413,12 +412,7 @@ corosync.add_node_ucast(['10.10.10.1']) mock_find_ip.assert_called_once_with(['10.10.10.1']) - mock_open_file.assert_has_calls([ - mock.call("corosync.conf"), - ]) - file_handle = mock_open_read.return_value.__enter__.return_value - file_handle.read.assert_called_once_with() - mock_parser.assert_called_once_with("read data") + mock_parser.assert_called_once_with("data") mock_free_id.assert_called_once_with(mock_parser_inst) mock_make_value.assert_has_calls([ mock.call('nodelist.node.ring0_addr', '10.10.10.1'), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/crmsh-4.4.0+20220418.cbf7a09e/test/unittests/test_qdevice.py new/crmsh-4.4.0+20220505.a3a00365/test/unittests/test_qdevice.py --- old/crmsh-4.4.0+20220418.cbf7a09e/test/unittests/test_qdevice.py 2022-04-18 08:32:05.000000000 +0200 +++ new/crmsh-4.4.0+20220505.a3a00365/test/unittests/test_qdevice.py 2022-05-05 03:52:21.000000000 +0200 @@ -840,16 +840,13 @@ @mock.patch("crmsh.corosync.make_section") @mock.patch("crmsh.corosync.Parser") @mock.patch("crmsh.corosync.conf") - @mock.patch("builtins.open") - def test_write_qdevice_config(self, mock_open_file, mock_conf, mock_parser, mock_mksection, mock_str2file): - open_return_value_1 = mock.mock_open(read_data=F2).return_value - mock_open_file.side_effect = [ - open_return_value_1, - ] + @mock.patch("crmsh.utils.read_from_file") + def test_write_qdevice_config(self, mock_read_file, mock_conf, mock_parser, mock_mksection, mock_str2file): mock_mksection.side_effect = [ ["device {", "}"], ["net {", "}"] ] + mock_read_file.return_value = "data" mock_conf.side_effect = ["corosync.conf", "corosync.conf"] mock_instance = mock.Mock() mock_parser.return_value = mock_instance @@ -857,11 +854,8 @@ self.qdevice_with_ip.write_qdevice_config() - mock_open_file.assert_has_calls([ - mock.call("corosync.conf"), - ]) mock_conf.assert_has_calls([mock.call(), mock.call()]) - mock_parser.assert_called_once_with(F2) + mock_parser.assert_called_once_with("data") mock_instance.remove.assert_called_once_with("quorum.device") mock_instance.add.assert_has_calls([ mock.call('quorum', ["device {", "}"]), @@ -886,24 +880,18 @@ @mock.patch("crmsh.utils.str2file") @mock.patch("crmsh.corosync.Parser") @mock.patch("crmsh.corosync.conf") - @mock.patch("builtins.open") - def test_remove_qdevice_config(self, mock_open_file, mock_conf, mock_parser, mock_str2file): - open_return_value_1 = mock.mock_open(read_data=F4).return_value - mock_open_file.side_effect = [ - open_return_value_1, - ] + @mock.patch("crmsh.utils.read_from_file") + def test_remove_qdevice_config(self, mock_read_file, mock_conf, mock_parser, mock_str2file): mock_conf.side_effect = ["corosync.conf", "corosync.conf"] + mock_read_file.return_value = "data" mock_instance = mock.Mock() mock_parser.return_value = mock_instance mock_instance.to_string.return_value = "string data" self.qdevice_with_ip.remove_qdevice_config() - mock_open_file.assert_has_calls([ - mock.call("corosync.conf"), - ]) mock_conf.assert_has_calls([mock.call(), mock.call()]) - mock_parser.assert_called_once_with(F4) + mock_parser.assert_called_once_with("data") mock_instance.remove.assert_called_once_with("quorum.device") mock_instance.to_string.assert_called_once_with() mock_str2file.assert_called_once_with("string data", "corosync.conf")