diff options
Diffstat (limited to 'lib/ansible/modules/apt.py')
-rw-r--r-- | lib/ansible/modules/apt.py | 114 |
1 files changed, 78 insertions, 36 deletions
diff --git a/lib/ansible/modules/apt.py b/lib/ansible/modules/apt.py index 1b7c5d2..336eadd 100644 --- a/lib/ansible/modules/apt.py +++ b/lib/ansible/modules/apt.py @@ -20,15 +20,15 @@ version_added: "0.0.2" options: name: description: - - A list of package names, like C(foo), or package specifier with version, like C(foo=1.0) or C(foo>=1.0). - Name wildcards (fnmatch) like C(apt*) and version wildcards like C(foo=1.0*) are also supported. + - A list of package names, like V(foo), or package specifier with version, like V(foo=1.0) or V(foo>=1.0). + Name wildcards (fnmatch) like V(apt*) and version wildcards like V(foo=1.0*) are also supported. aliases: [ package, pkg ] type: list elements: str state: description: - - Indicates the desired package state. C(latest) ensures that the latest version is installed. C(build-dep) ensures the package build dependencies - are installed. C(fixed) attempt to correct a system with broken dependencies in place. + - Indicates the desired package state. V(latest) ensures that the latest version is installed. V(build-dep) ensures the package build dependencies + are installed. V(fixed) attempt to correct a system with broken dependencies in place. type: str default: present choices: [ absent, build-dep, latest, present, fixed ] @@ -40,25 +40,25 @@ options: type: bool update_cache_retries: description: - - Amount of retries if the cache update fails. Also see I(update_cache_retry_max_delay). + - Amount of retries if the cache update fails. Also see O(update_cache_retry_max_delay). type: int default: 5 version_added: '2.10' update_cache_retry_max_delay: description: - - Use an exponential backoff delay for each retry (see I(update_cache_retries)) up to this max delay in seconds. + - Use an exponential backoff delay for each retry (see O(update_cache_retries)) up to this max delay in seconds. type: int default: 12 version_added: '2.10' cache_valid_time: description: - - Update the apt cache if it is older than the I(cache_valid_time). This option is set in seconds. - - As of Ansible 2.4, if explicitly set, this sets I(update_cache=yes). + - Update the apt cache if it is older than the O(cache_valid_time). This option is set in seconds. + - As of Ansible 2.4, if explicitly set, this sets O(update_cache=yes). type: int default: 0 purge: description: - - Will force purging of configuration files if the module state is set to I(absent). + - Will force purging of configuration files if O(state=absent) or O(autoremove=yes). type: bool default: 'no' default_release: @@ -68,13 +68,13 @@ options: type: str install_recommends: description: - - Corresponds to the C(--no-install-recommends) option for I(apt). C(true) installs recommended packages. C(false) does not install + - Corresponds to the C(--no-install-recommends) option for I(apt). V(true) installs recommended packages. V(false) does not install recommended packages. By default, Ansible will use the same defaults as the operating system. Suggested packages are never installed. aliases: [ install-recommends ] type: bool force: description: - - 'Corresponds to the C(--force-yes) to I(apt-get) and implies C(allow_unauthenticated: yes) and C(allow_downgrade: yes)' + - 'Corresponds to the C(--force-yes) to I(apt-get) and implies O(allow_unauthenticated=yes) and O(allow_downgrade=yes)' - "This option will disable checking both the packages' signatures and the certificates of the web servers they are downloaded from." - 'This option *is not* the equivalent of passing the C(-f) flag to I(apt-get) on the command line' @@ -93,7 +93,7 @@ options: allow_unauthenticated: description: - Ignore if packages cannot be authenticated. This is useful for bootstrapping environments that manage their own apt-key setup. - - 'C(allow_unauthenticated) is only supported with state: I(install)/I(present)' + - 'O(allow_unauthenticated) is only supported with O(state): V(install)/V(present)' aliases: [ allow-unauthenticated ] type: bool default: 'no' @@ -102,8 +102,9 @@ options: description: - Corresponds to the C(--allow-downgrades) option for I(apt). - This option enables the named package and version to replace an already installed higher version of that package. - - Note that setting I(allow_downgrade=true) can make this module behave in a non-idempotent way. + - Note that setting O(allow_downgrade=true) can make this module behave in a non-idempotent way. - (The task could end up with a set of packages that does not match the complete list of specified packages to install). + - 'O(allow_downgrade) is only supported by C(apt) and will be ignored if C(aptitude) is detected or specified.' aliases: [ allow-downgrade, allow_downgrades, allow-downgrades ] type: bool default: 'no' @@ -141,14 +142,14 @@ options: version_added: "1.6" autoremove: description: - - If C(true), remove unused dependency packages for all module states except I(build-dep). It can also be used as the only option. + - If V(true), remove unused dependency packages for all module states except V(build-dep). It can also be used as the only option. - Previous to version 2.4, autoclean was also an alias for autoremove, now it is its own separate command. See documentation for further information. type: bool default: 'no' version_added: "2.1" autoclean: description: - - If C(true), cleans the local repository of retrieved package files that can no longer be downloaded. + - If V(true), cleans the local repository of retrieved package files that can no longer be downloaded. type: bool default: 'no' version_added: "2.4" @@ -157,7 +158,7 @@ options: - Force the exit code of /usr/sbin/policy-rc.d. - For example, if I(policy_rc_d=101) the installed package will not trigger a service start. - If /usr/sbin/policy-rc.d already exists, it is backed up and restored after the package installation. - - If C(null), the /usr/sbin/policy-rc.d isn't created/changed. + - If V(null), the /usr/sbin/policy-rc.d isn't created/changed. type: int default: null version_added: "2.8" @@ -170,8 +171,9 @@ options: fail_on_autoremove: description: - 'Corresponds to the C(--no-remove) option for C(apt).' - - 'If C(true), it is ensured that no packages will be removed or the task will fail.' - - 'C(fail_on_autoremove) is only supported with state except C(absent)' + - 'If V(true), it is ensured that no packages will be removed or the task will fail.' + - 'O(fail_on_autoremove) is only supported with O(state) except V(absent).' + - 'O(fail_on_autoremove) is only supported by C(apt) and will be ignored if C(aptitude) is detected or specified.' type: bool default: 'no' version_added: "2.11" @@ -202,15 +204,15 @@ attributes: platform: platforms: debian notes: - - Three of the upgrade modes (C(full), C(safe) and its alias C(true)) required C(aptitude) up to 2.3, since 2.4 C(apt-get) is used as a fall-back. + - Three of the upgrade modes (V(full), V(safe) and its alias V(true)) required C(aptitude) up to 2.3, since 2.4 C(apt-get) is used as a fall-back. - In most cases, packages installed with apt will start newly installed services by default. Most distributions have mechanisms to avoid this. For example when installing Postgresql-9.5 in Debian 9, creating an excutable shell script (/usr/sbin/policy-rc.d) that throws a return code of 101 will stop Postgresql 9.5 starting up after install. Remove the file or remove its execute permission afterwards. - The apt-get commandline supports implicit regex matches here but we do not because it can let typos through easier (If you typo C(foo) as C(fo) apt-get would install packages that have "fo" in their name with a warning and a prompt for the user. Since we don't have warnings and prompts before installing we disallow this.Use an explicit fnmatch pattern if you want wildcarding) - - When used with a C(loop:) each package will be processed individually, it is much more efficient to pass the list directly to the I(name) option. - - When C(default_release) is used, an implicit priority of 990 is used. This is the same behavior as C(apt-get -t). + - When used with a C(loop:) each package will be processed individually, it is much more efficient to pass the list directly to the O(name) option. + - When O(default_release) is used, an implicit priority of 990 is used. This is the same behavior as C(apt-get -t). - When an exact version is specified, an implicit priority of 1001 is used. ''' @@ -314,6 +316,11 @@ EXAMPLES = ''' ansible.builtin.apt: autoremove: yes +- name: Remove dependencies that are no longer required and purge their configuration files + ansible.builtin.apt: + autoremove: yes + purge: true + - name: Run the equivalent of "apt-get clean" as a separate step apt: clean: yes @@ -353,7 +360,7 @@ warnings.filterwarnings('ignore', "apt API not stable yet", FutureWarning) import datetime import fnmatch -import itertools +import locale as locale_module import os import random import re @@ -365,7 +372,7 @@ import time from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.locale import get_best_parsable_locale from ansible.module_utils.common.respawn import has_respawned, probe_interpreters_for_module, respawn_module -from ansible.module_utils._text import to_native, to_text +from ansible.module_utils.common.text.converters import to_native, to_text from ansible.module_utils.six import PY3, string_types from ansible.module_utils.urls import fetch_file @@ -445,7 +452,7 @@ class PolicyRcD(object): def __exit__(self, type, value, traceback): """ - This method will be called when we enter the context, before we call `apt-get …` + This method will be called when we exit the context, after `apt-get …` is done """ # if policy_rc_d is null then we don't need to modify policy-rc.d @@ -929,7 +936,8 @@ def install_deb( def remove(m, pkgspec, cache, purge=False, force=False, - dpkg_options=expand_dpkg_options(DPKG_OPTIONS), autoremove=False): + dpkg_options=expand_dpkg_options(DPKG_OPTIONS), autoremove=False, + allow_change_held_packages=False): pkg_list = [] pkgspec = expand_pkgspec_from_fnmatches(m, pkgspec, cache) for package in pkgspec: @@ -962,7 +970,21 @@ def remove(m, pkgspec, cache, purge=False, force=False, else: check_arg = '' - cmd = "%s -q -y %s %s %s %s %s remove %s" % (APT_GET_CMD, dpkg_options, purge, force_yes, autoremove, check_arg, packages) + if allow_change_held_packages: + allow_change_held_packages = '--allow-change-held-packages' + else: + allow_change_held_packages = '' + + cmd = "%s -q -y %s %s %s %s %s %s remove %s" % ( + APT_GET_CMD, + dpkg_options, + purge, + force_yes, + autoremove, + check_arg, + allow_change_held_packages, + packages + ) with PolicyRcD(m): rc, out, err = m.run_command(cmd) @@ -1016,15 +1038,13 @@ def cleanup(m, purge=False, force=False, operation=None, def aptclean(m): clean_rc, clean_out, clean_err = m.run_command(['apt-get', 'clean']) - if m._diff: - clean_diff = parse_diff(clean_out) - else: - clean_diff = {} + clean_diff = parse_diff(clean_out) if m._diff else {} + if clean_rc: m.fail_json(msg="apt-get clean failed", stdout=clean_out, rc=clean_rc) if clean_err: m.fail_json(msg="apt-get clean failed: %s" % clean_err, stdout=clean_out, rc=clean_rc) - return clean_out, clean_err + return (clean_out, clean_err, clean_diff) def upgrade(m, mode="yes", force=False, default_release=None, @@ -1073,13 +1093,24 @@ def upgrade(m, mode="yes", force=False, default_release=None, force_yes = '' if fail_on_autoremove: - fail_on_autoremove = '--no-remove' + if apt_cmd == APT_GET_CMD: + fail_on_autoremove = '--no-remove' + else: + m.warn("APTITUDE does not support '--no-remove', ignoring the 'fail_on_autoremove' parameter.") + fail_on_autoremove = '' else: fail_on_autoremove = '' allow_unauthenticated = '--allow-unauthenticated' if allow_unauthenticated else '' - allow_downgrade = '--allow-downgrades' if allow_downgrade else '' + if allow_downgrade: + if apt_cmd == APT_GET_CMD: + allow_downgrade = '--allow-downgrades' + else: + m.warn("APTITUDE does not support '--allow-downgrades', ignoring the 'allow_downgrade' parameter.") + allow_downgrade = '' + else: + allow_downgrade = '' if apt_cmd is None: if use_apt_get: @@ -1203,6 +1234,7 @@ def main(): # to make sure we use the best parsable locale when running commands # also set apt specific vars for desired behaviour locale = get_best_parsable_locale(module) + locale_module.setlocale(locale_module.LC_ALL, locale) # APT related constants APT_ENV_VARS = dict( DEBIAN_FRONTEND='noninteractive', @@ -1277,7 +1309,7 @@ def main(): p = module.params if p['clean'] is True: - aptclean_stdout, aptclean_stderr = aptclean(module) + aptclean_stdout, aptclean_stderr, aptclean_diff = aptclean(module) # If there is nothing else to do exit. This will set state as # changed based on if the cache was updated. if not p['package'] and not p['upgrade'] and not p['deb']: @@ -1285,7 +1317,8 @@ def main(): changed=True, msg=aptclean_stdout, stdout=aptclean_stdout, - stderr=aptclean_stderr + stderr=aptclean_stderr, + diff=aptclean_diff ) if p['upgrade'] == 'no': @@ -1470,7 +1503,16 @@ def main(): else: module.fail_json(**retvals) elif p['state'] == 'absent': - remove(module, packages, cache, p['purge'], force=force_yes, dpkg_options=dpkg_options, autoremove=autoremove) + remove( + module, + packages, + cache, + p['purge'], + force=force_yes, + dpkg_options=dpkg_options, + autoremove=autoremove, + allow_change_held_packages=allow_change_held_packages + ) except apt.cache.LockFailedException as lockFailedException: if time.time() < deadline: |