1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Fix snap module, and module helper behavior on rc != 0 in output (#2912)

* Try some snap fixes.

* Fix logic.

* Try to run tests privileged.

* Prevent failure on rc != 0.

* Fix formatting.

* Revert "Try to run tests privileged."

This reverts commit 77ca91f502.

* Try to run tests on RHEL instead.

* Make sure that snapd is running.

* Add changelog fragment.

* str -> to_native.

* Make sure that installed binary is actually found.

* Add check mode tests.

* Mention #2835 in changelog fragment.
This commit is contained in:
Felix Fontein 2021-07-01 18:53:48 +02:00 committed by GitHub
parent a97d82be88
commit c63dc624b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 111 additions and 45 deletions

View file

@ -0,0 +1,3 @@
bugfixes:
- module_helper module utils - avoid failing when non-zero ``rc`` is present on regular exit (https://github.com/ansible-collections/community.general/pull/2912).
- snap - fix various bugs which prevented the module from working at all, and which resulted in ``state=absent`` fail on absent snaps (https://github.com/ansible-collections/community.general/issues/2835, https://github.com/ansible-collections/community.general/issues/2906, https://github.com/ansible-collections/community.general/pull/2912).

View file

@ -59,4 +59,7 @@ class ModuleHelperBase(object):
self.__init_module__() self.__init_module__()
self.__run__() self.__run__()
self.__quit_module__() self.__quit_module__()
self.module.exit_json(changed=self.has_changed(), **self.output) output = self.output
if 'failed' not in output:
output['failed'] = False
self.module.exit_json(changed=self.has_changed(), **output)

View file

@ -107,6 +107,8 @@ snaps_removed:
import re import re
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.community.general.plugins.module_utils.module_helper import ( from ansible_collections.community.general.plugins.module_utils.module_helper import (
CmdStateModuleHelper, ArgFormat, ModuleHelperException CmdStateModuleHelper, ArgFormat, ModuleHelperException
) )
@ -123,7 +125,7 @@ __state_map = dict(
def _state_map(value): def _state_map(value):
return __state_map[value] return [__state_map[value]]
class Snap(CmdStateModuleHelper): class Snap(CmdStateModuleHelper):
@ -163,20 +165,20 @@ class Snap(CmdStateModuleHelper):
results[i].append(output[i]) results[i].append(output[i])
return [ return [
'; '.join(results[0]), '; '.join([to_native(x) for x in results[0]]),
self._first_non_zero(results[1]), self._first_non_zero(results[1]),
'\n'.join(results[2]), '\n'.join(results[2]),
'\n'.join(results[3]), '\n'.join(results[3]),
] ]
def snap_exists(self, snap_name): def snap_exists(self, snap_name):
return 0 == self.run_command(params=[{'state': 'info'}, {'name': [snap_name]}])[0] return 0 == self.run_command(params=[{'state': 'info'}, {'name': snap_name}])[0]
def is_snap_installed(self, snap_name): def is_snap_installed(self, snap_name):
return 0 == self.run_command(params=[{'state': 'list'}, {'name': [snap_name]}])[0] return 0 == self.run_command(params=[{'state': 'list'}, {'name': snap_name}])[0]
def is_snap_enabled(self, snap_name): def is_snap_enabled(self, snap_name):
rc, out, err = self.run_command(params=[{'state': 'list'}, {'name': [snap_name]}]) rc, out, err = self.run_command(params=[{'state': 'list'}, {'name': snap_name}])
if rc != 0: if rc != 0:
return None return None
result = out.splitlines()[1] result = out.splitlines()[1]
@ -196,7 +198,7 @@ class Snap(CmdStateModuleHelper):
self.validate_input_snaps() # if snap doesnt exist, it will explode when trying to install self.validate_input_snaps() # if snap doesnt exist, it will explode when trying to install
self.vars.meta('classic').set(output=True) self.vars.meta('classic').set(output=True)
self.vars.meta('channel').set(output=True) self.vars.meta('channel').set(output=True)
actionable_snaps = [s for s in self.vars.name if self.is_snap_installed(s)] actionable_snaps = [s for s in self.vars.name if not self.is_snap_installed(s)]
if not actionable_snaps: if not actionable_snaps:
return return
self.changed = True self.changed = True
@ -207,9 +209,9 @@ class Snap(CmdStateModuleHelper):
has_one_pkg_params = bool(self.vars.classic) or self.vars.channel != 'stable' has_one_pkg_params = bool(self.vars.classic) or self.vars.channel != 'stable'
has_multiple_snaps = len(actionable_snaps) > 1 has_multiple_snaps = len(actionable_snaps) > 1
if has_one_pkg_params and has_multiple_snaps: if has_one_pkg_params and has_multiple_snaps:
commands = [params + [s] for s in actionable_snaps] commands = [params + [{'actionable_snaps': [s]}] for s in actionable_snaps]
else: else:
commands = [params + actionable_snaps] commands = [params + [{'actionable_snaps': actionable_snaps}]]
self.vars.cmd, rc, out, err = self._run_multiple_commands(commands) self.vars.cmd, rc, out, err = self._run_multiple_commands(commands)
if rc == 0: if rc == 0:
return return
@ -227,7 +229,7 @@ class Snap(CmdStateModuleHelper):
def state_absent(self): def state_absent(self):
self.validate_input_snaps() # if snap doesnt exist, it will be absent by definition self.validate_input_snaps() # if snap doesnt exist, it will be absent by definition
actionable_snaps = [s for s in self.vars.name if not self.is_snap_installed(s)] actionable_snaps = [s for s in self.vars.name if self.is_snap_installed(s)]
if not actionable_snaps: if not actionable_snaps:
return return
self.changed = True self.changed = True
@ -235,7 +237,7 @@ class Snap(CmdStateModuleHelper):
if self.module.check_mode: if self.module.check_mode:
return return
params = ['classic', 'channel', 'state'] # get base cmd parts params = ['classic', 'channel', 'state'] # get base cmd parts
commands = [params + actionable_snaps] commands = [params + [{'actionable_snaps': actionable_snaps}]]
self.vars.cmd, rc, out, err = self._run_multiple_commands(commands) self.vars.cmd, rc, out, err = self._run_multiple_commands(commands)
if rc == 0: if rc == 0:
return return
@ -253,7 +255,7 @@ class Snap(CmdStateModuleHelper):
if self.module.check_mode: if self.module.check_mode:
return return
params = ['classic', 'channel', 'state'] # get base cmd parts params = ['classic', 'channel', 'state'] # get base cmd parts
commands = [params + actionable_snaps] commands = [params + [{'actionable_snaps': actionable_snaps}]]
self.vars.cmd, rc, out, err = self._run_multiple_commands(commands) self.vars.cmd, rc, out, err = self._run_multiple_commands(commands)
if rc == 0: if rc == 0:
return return
@ -271,7 +273,7 @@ class Snap(CmdStateModuleHelper):
if self.module.check_mode: if self.module.check_mode:
return return
params = ['classic', 'channel', 'state'] # get base cmd parts params = ['classic', 'channel', 'state'] # get base cmd parts
commands = [params + actionable_snaps] commands = [params + [{'actionable_snaps': actionable_snaps}]]
self.vars.cmd, rc, out, err = self._run_multiple_commands(commands) self.vars.cmd, rc, out, err = self._run_multiple_commands(commands)
if rc == 0: if rc == 0:
return return

View file

@ -3,4 +3,4 @@ skip/aix
skip/freebsd skip/freebsd
skip/osx skip/osx
skip/macos skip/macos
disabled #FIXME 2609 skip/docker

View file

@ -0,0 +1,4 @@
has_snap: false
snap_packages:
- snapd

View file

@ -0,0 +1,5 @@
---
- name: Remove snapd
package:
name: "{{ snap_packages }}"
state: absent

View file

@ -0,0 +1,3 @@
dependencies:
- setup_pkg_mgr
- setup_epel

View file

@ -0,0 +1 @@
default.yml

View file

@ -0,0 +1 @@
default.yml

View file

@ -0,0 +1 @@
default.yml

View file

@ -0,0 +1,15 @@
---
- name: Install snapd
package:
name: "{{ snap_packages }}"
state: present
notify: Remove snapd
- name: Make sure that snapd is running
service:
name: snapd
state: started
- name: Inform that snap is installed
set_fact:
has_snap: true

View file

@ -4,28 +4,46 @@
# and should not be used as examples of how to write Ansible roles # # and should not be used as examples of how to write Ansible roles #
#################################################################### ####################################################################
- name: install snapd - name: Include distribution specific tasks
apt: include_tasks: "{{ lookup('first_found', params) }}"
name: snapd vars:
state: present params:
register: snapd_install_ubuntu files:
when: ansible_distribution == 'Ubuntu' - "{{ ansible_facts.distribution }}-{{ ansible_facts.distribution_major_version }}.yml"
- "{{ ansible_facts.os_family }}-{{ ansible_facts.distribution_major_version }}.yml"
- name: install snapd - "{{ ansible_facts.distribution }}.yml"
dnf: - "{{ ansible_facts.os_family }}.yml"
name: snapd - "nothing.yml"
state: present paths:
register: snapd_install_fedora - "{{ role_path }}/tasks"
when: ansible_distribution == 'Fedora'
- block: - block:
- name: install package - name: Make sure package is not installed
community.general.snap:
name: hello-world
state: absent
- name: Install package (check mode)
community.general.snap:
name: hello-world
state: present
register: install_check
check_mode: true
- name: Install package
community.general.snap: community.general.snap:
name: hello-world name: hello-world
state: present state: present
register: install register: install
- name: install package again - name: Install package again (check mode)
community.general.snap:
name: hello-world
state: present
register: install_again_check
check_mode: true
- name: Install package again
community.general.snap: community.general.snap:
name: hello-world name: hello-world
state: present state: present
@ -35,18 +53,36 @@
assert: assert:
that: that:
- install is changed - install is changed
- install_check is changed
- install_again is not changed - install_again is not changed
- install_again_check is not changed
- name: check package has been installed correctly - name: Check package has been installed correctly
command: hello-world command: hello-world
environment:
PATH: /var/lib/snapd/snap/bin/
- name: remove package - name: Remove package (check mode)
community.general.snap:
name: hello-world
state: absent
register: remove_check
check_mode: true
- name: Remove package
community.general.snap: community.general.snap:
name: hello-world name: hello-world
state: absent state: absent
register: remove register: remove
- name: remove package again - name: Remove package again (check mode)
community.general.snap:
name: hello-world
state: absent
register: remove_again_check
check_mode: true
- name: Remove package again
community.general.snap: community.general.snap:
name: hello-world name: hello-world
state: absent state: absent
@ -56,17 +92,7 @@
assert: assert:
that: that:
- remove is changed - remove is changed
- remove_check is changed
- remove_again is not changed - remove_again is not changed
when: ansible_distribution in ['Ubuntu','Fedora'] - remove_again_check is not changed
when: has_snap
- name: Remove snapd in case it was not installed
apt:
name: snapd
state: absent
when: snapd_install_ubuntu is changed and ansible_distribution == 'Ubuntu'
- name: Remove snapd in case it was not installed
dnf:
name: snapd
state: absent
when: snapd_install_fedora is changed and ansible_distribution == 'Fedora'

View file

@ -0,0 +1,2 @@
---
# Do nothing