ansible-collections / community.general

Ansible Community General Collection
https://galaxy.ansible.com/ui/repo/published/community/general/
GNU General Public License v3.0
821 stars 1.52k forks source link

zypper remove ignored which LANG=fr_FR #1168

Closed xenlo closed 3 years ago

xenlo commented 4 years ago
SUMMARY

The zypper module does not remove packages with state: absent when the local is set something other than 'en_US'.

ISSUE TYPE
COMPONENT NAME
ANSIBLE VERSION
ansible 2.9.14
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/xenlo/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.8/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.6 (default, Sep 25 2020, 00:00:00) [GCC 10.2.1 20200723 (Red Hat 10.2.1-1)]
CONFIGURATION
DEFAULT_STDOUT_CALLBACK(/etc/ansible/ansible.cfg) = yaml
DEFAULT_VAULT_PASSWORD_FILE(env: ANSIBLE_VAULT_PASSWORD_FILE) = /home/xenlo/.ansible/vault_keyring
OS / ENVIRONMENT

Controler:

Target host:

STEPS TO REPRODUCE

On a target SLES (or openSUSE) host ensure that a rpm package is installed with zypper:

target:~ # zypper install libwbclient0
[…]
target:~ # zypper search libwbclient0
[…]
S | Nom          | Résumé                    | Type  
--+--------------+---------------------------+-------
i | libwbclient0 | Samba libwbclient Library | paquet

And from there try to remove from an Ansible controle with an other LANG than 'en_US' (either with ansible ad-hoc or `ansible-playbook):

controler:~/Projects/344$ LANG=fr_FR.UTF8  ansible -i inventories/ target -m zypper -a "name=libwbclient0 state=absent" -u root
target | SUCCESS => {​​​​​​​
    "changed": false,
    "name": [
        "libwbclient0"
    ],
    "rc": 0,
    "state": "absent",
    "update_cache": false
}​​​​​​​

You get "changed": false, and "state": "absent",.

EXPECTED RESULTS

I expect to have the package removed from the target and as output "changed: true". Just like if I run the same ansible command but with 'en_US'.

controler:~/Projects/344$ LANG=en_US.UTF8 ansible -i inventories/ target -m zypper -a "name=colordiff state=absent" -u root
target | CHANGED => {
    "changed": true,
    "cmd": [
        "/usr/bin/zypper",
        "--quiet",
        "--non-interactive",
        "--xmlout",
        "remove",
        "--type",
        "package",
        "colordiff"
    ],
    "name": [
        "colordiff"
    ],
    "rc": 0,
    "state": "absent",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "<?xml version='1.0'?>\n<stream>\n<install-summary download-size=\"0\" space-usage-diff=\"-54086\">\n<to-remove>\n<solvable type=\"package\" name=\"colordiff\" edition=\"1.0.18-bp150.2.4\" arch=\"noarch\" summary=\"Colour-highlighted &apos;diff&apos; output\">\n<description>The Perl script colordiff is a wrapper for &apos;diff&apos; and produces the same\noutput but with pretty &apos;syntax&apos; highlighting. Colour schemes can be\ncustomized.</description></solvable>\n</to-remove>\n</install-summary>\n<prompt id=\"0\">\n<text>Continue?</text>\n<option default=\"1\" value=\"y\" desc=\"Yes, accept the summary and proceed with installation/removal of packages.\"/>\n<option value=\"n\" desc=\"No, cancel the operation.\"/>\n<option value=\"v\" desc=\"Toggle display of package versions.\"/>\n<option value=\"a\" desc=\"Toggle display of package architectures.\"/>\n<option value=\"r\" desc=\"Toggle display of repositories from which the packages will be installed.\"/>\n<option value=\"m\" desc=\"Toggle display of package vendor names.\"/>\n<option value=\"d\" desc=\"Toggle between showing all details and as few details as possible.\"/>\n<option value=\"g\" desc=\"View the summary in pager.\"/>\n</prompt>\n</stream>\n",
    "stdout_lines": [
        "<?xml version='1.0'?>",
        "<stream>",
        "<install-summary download-size=\"0\" space-usage-diff=\"-54086\">",
        "<to-remove>",
        "<solvable type=\"package\" name=\"colordiff\" edition=\"1.0.18-bp150.2.4\" arch=\"noarch\" summary=\"Colour-highlighted &apos;diff&apos; output\">",
        "<description>The Perl script colordiff is a wrapper for &apos;diff&apos; and produces the same",
        "output but with pretty &apos;syntax&apos; highlighting. Colour schemes can be",
        "customized.</description></solvable>",
        "</to-remove>",
        "</install-summary>",
        "<prompt id=\"0\">",
        "<text>Continue?</text>",
        "<option default=\"1\" value=\"y\" desc=\"Yes, accept the summary and proceed with installation/removal of packages.\"/>",
        "<option value=\"n\" desc=\"No, cancel the operation.\"/>",
        "<option value=\"v\" desc=\"Toggle display of package versions.\"/>",
        "<option value=\"a\" desc=\"Toggle display of package architectures.\"/>",
        "<option value=\"r\" desc=\"Toggle display of repositories from which the packages will be installed.\"/>",
        "<option value=\"m\" desc=\"Toggle display of package vendor names.\"/>",
        "<option value=\"d\" desc=\"Toggle between showing all details and as few details as possible.\"/>",
        "<option value=\"g\" desc=\"View the summary in pager.\"/>",
        "</prompt>",
        "</stream>"
    ],
    "update_cache": false
ACTUAL RESULTS

Output with -vvvv in this gist.

ansibullbot commented 4 years ago

Files identified in the description:

If these files are inaccurate, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot commented 4 years ago

cc @AnderEnder @alxgu @andytom @commel @dcermak @evrardjp @lrupp @toabctl click here for bot help

xenlo commented 4 years ago

According to my colleague's investigations, the zypper module use the xml output of zypper to check the state of a package. It looks for attribute 'name' when in French it get translated form: 'nom'.

Which explains the strange behaviour.

Is it possible to enforce en_US LANG on the module execution on the target host to ensure that the output check catch what it expect to catch?

felixfontein commented 4 years ago

I'd rather set it to C, as the en_US locale is not available everywhere. It should be easy to do that, similar to here: https://github.com/ansible-collections/community.general/blob/main/plugins/modules/cloud/atomic/atomic_image.py#L93

In any case, 'translating' XML property names looks like a bug to me. This should probably also be reported as a bug in zypper.

xenlo commented 4 years ago

Indeed, I will look on Monday if I can manage to propose PR. And also have look where I can open an issue upstream to escalate the xml proprties translation.

mator commented 4 years ago

i can't reproduce on opensuse leap 15.2 (don't have SLES installed) , but probably the following patch fixes the issue?

diff --git a/plugins/modules/packaging/os/zypper.py b/plugins/modules/packaging/os/zypper.py
index 5997cfa4..f6c623ef 100644
--- a/plugins/modules/packaging/os/zypper.py
+++ b/plugins/modules/packaging/os/zypper.py
@@ -515,6 +515,8 @@ def main():
         supports_check_mode=True
     )

+    module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')
+
     name = module.params['name']
     state = module.params['state']
     update_cache = module.params['update_cache']
xenlo commented 3 years ago

I just give it a try and was able to reporduce on a OpenSUSE 15.1.

xenlo commented 3 years ago

So indeed the fix works. Thanks @felixfontein and @mator.

I created a PR with that change: #1175. Next task, escalate the topic upstream.

evrardjp commented 3 years ago

Thanks @xenlo @felixfontein and @mator !

xenlo commented 3 years ago

@evrardjp, you're welcome.

As I see that you works for Suse, maybe you can advice me where to open a discussion about the translation of attribute in xml output? I assume that https://github.com/openSUSE/zypper is a good start?

evrardjp commented 3 years ago

I work for SUSE, but I don't work on zypper. Yes, that would be one place. The alternative would be the bugzilla. Let's start with the github issue and file a bugzilla issue if necessary.

xenlo commented 3 years ago

Thanks @evrardjp.

FYI: openSUSE/zypper#361

mator commented 3 years ago

still can't reproduce with opensuse 15.2 . Set system locale to fr_FR.UTF-8 via yast :

opensuse$ cat /etc/locale.conf
LANG=fr_FR.UTF-8

archlinux$ ssh opensuse locale
LANG=fr_FR.UTF-8
LC_CTYPE="fr_FR.UTF-8"
LC_NUMERIC="fr_FR.UTF-8"
LC_TIME="fr_FR.UTF-8"
LC_COLLATE="fr_FR.UTF-8"
LC_MONETARY="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
LC_PAPER="fr_FR.UTF-8"
LC_NAME="fr_FR.UTF-8"
LC_ADDRESS="fr_FR.UTF-8"
LC_TELEPHONE="fr_FR.UTF-8"
LC_MEASUREMENT="fr_FR.UTF-8"
LC_IDENTIFICATION="fr_FR.UTF-8"
LC_ALL=

even set ROOT_USES_LANG :

opensuse:~> grep ROOT_U /etc/sysconfig/language 
# Root uses this variable only if ROOT_USES_LANG is set to "yes".
# Again, ROOT_USES_LANG must be set to "yes", if an effect on the superuser
ROOT_USES_LANG="yes"

first check:

$ ansible opensuse -m setup -a 'filter=ansible_env' | grep LANG
            "LANG": "fr_FR.utf8",

test with mtr package installed/removed:

opensuse:~> rpm -q mtr
le paquet mtr n'est pas installé

archlinux$ ansible opensuse -b -m zypper -a 'name=mtr state=absent'
opensuse | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3.6"
    },
    "changed": false,
    "name": [
        "mtr"
    ],
    "rc": 0,
    "state": "absent",
    "update_cache": false
}

archlinux$ ansible opensuse -b -m zypper -a 'name=mtr state=installed'
opensuse | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3.6"
    },
    "changed": true,
    "cmd": [
        "/usr/bin/zypper",
        "--quiet",
        "--non-interactive",
        "--xmlout",
        "install",
        "--type",
        "package",
        "--auto-agree-with-licenses",
        "--no-recommends",
        "--",
        "+mtr"
    ],
    "name": [
        "mtr"
    ],
    "rc": 0,
    "state": "installed",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "<?xml version='1.0'?>\n<stream>\n<install-summary download-size=\"80828\" space-usage-diff=\"181267\" packages-to-change=\"1\">\n<to-install>\n<solvable type=\"package\" name=\"mtr\" edition=\"0.92-lp152.4.3\" arch=\"x86_64\" summary=\"Ping and Traceroute Network Diagnostic Tool\">\n<description>Mtr is a network diagnostic tool that combines Ping and Traceroute into\none program. This package contains the mtr version with an ncurses\ninterface, in other words, the text mode version is usable in a shell\n(telnet or SSH session, for example).\n\nFind the graphical version in the mtr-gtk package.</description></solvable>\n</to-install>\n</install-summary>\n<prompt id=\"0\">\n<text>Continue?</text>\n<option default=\"1\" value=\"y\" desc=\"Yes, accept the summary and proceed with installation/removal of packages.\"/>\n<option value=\"n\" desc=\"No, cancel the operation.\"/>\n<option value=\"v\" desc=\"Toggle display of package versions.\"/>\n<option value=\"a\" desc=\"Toggle display of package architectures.\"/>\n<option value=\"r\" desc=\"Toggle display of repositories from which the packages will be installed.\"/>\n<option value=\"m\" desc=\"Toggle display of package vendor names.\"/>\n<option value=\"d\" desc=\"Toggle between showing all details and as few details as possible.\"/>\n<option value=\"g\" desc=\"View the summary in pager.\"/>\n</prompt>\n<download url=\"http://download.opensuse.org/distribution/leap/15.2/repo/oss/x86_64/mtr-0.92-lp152.4.3.x86_64.rpm\" percent=\"-1\" rate=\"-1\"/>\n<download url=\"http://download.opensuse.org/distribution/leap/15.2/repo/oss/x86_64/mtr-0.92-lp152.4.3.x86_64.rpm\" rate=\"-1\" done=\"1\"/>\n</stream>\n",
    "stdout_lines": [
        "<?xml version='1.0'?>",
        "<stream>",
        "<install-summary download-size=\"80828\" space-usage-diff=\"181267\" packages-to-change=\"1\">",
        "<to-install>",
        "<solvable type=\"package\" name=\"mtr\" edition=\"0.92-lp152.4.3\" arch=\"x86_64\" summary=\"Ping and Traceroute Network Diagnostic Tool\">",
        "<description>Mtr is a network diagnostic tool that combines Ping and Traceroute into",
        "one program. This package contains the mtr version with an ncurses",
        "interface, in other words, the text mode version is usable in a shell",
        "(telnet or SSH session, for example).",
        "",
        "Find the graphical version in the mtr-gtk package.</description></solvable>",
        "</to-install>",
        "</install-summary>",
        "<prompt id=\"0\">",
        "<text>Continue?</text>",
        "<option default=\"1\" value=\"y\" desc=\"Yes, accept the summary and proceed with installation/removal of packages.\"/>",
        "<option value=\"n\" desc=\"No, cancel the operation.\"/>",
        "<option value=\"v\" desc=\"Toggle display of package versions.\"/>",
        "<option value=\"a\" desc=\"Toggle display of package architectures.\"/>",
        "<option value=\"r\" desc=\"Toggle display of repositories from which the packages will be installed.\"/>",
        "<option value=\"m\" desc=\"Toggle display of package vendor names.\"/>",
        "<option value=\"d\" desc=\"Toggle between showing all details and as few details as possible.\"/>",
        "<option value=\"g\" desc=\"View the summary in pager.\"/>",
        "</prompt>",
        "<download url=\"http://download.opensuse.org/distribution/leap/15.2/repo/oss/x86_64/mtr-0.92-lp152.4.3.x86_64.rpm\" percent=\"-1\" rate=\"-1\"/>",
        "<download url=\"http://download.opensuse.org/distribution/leap/15.2/repo/oss/x86_64/mtr-0.92-lp152.4.3.x86_64.rpm\" rate=\"-1\" done=\"1\"/>",
        "</stream>"
    ],
    "update_cache": false
}

opensuse:~> rpm -q mtr
mtr-0.92-lp152.4.3.x86_64
xenlo commented 3 years ago

@mator, the issue occurs the other way around. So having the ansible controller (so the archlinux in your detailed case here above). The locale config on the openSUSE target does not matter as it will open a session with the locale from the source of the ssh connection.