Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apt_rpm: add clean, dist_upgrade and update_kernel #5867

Merged
merged 1 commit into from
Mar 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/5867-apt_rpm-add-clean-and-upgrade.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- apt_rpm - adds ``clean``, ``dist_upgrade`` and ``update_kernel`` parameters for clear caches, complete upgrade system, and upgrade kernel packages (https://github.com/ansible-collections/community.general/pull/5867).
119 changes: 102 additions & 17 deletions plugins/modules/apt_rpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
options:
package:
description:
- list of packages to install, upgrade or remove.
required: true
- List of packages to install, upgrade, or remove.
aliases: [ name, pkg ]
type: list
elements: str
Expand All @@ -33,9 +32,30 @@
type: str
update_cache:
description:
- update the package database first C(apt-get update).
- Run the equivalent of C(apt-get update) before the operation. Can be run as part of the package installation or as a separate step.
- Default is not to update the cache.
type: bool
default: false
clean:
description:
- Run the equivalent of C(apt-get clean) to clear out the local repository of retrieved package files. It removes everything but
the lock file from C(/var/cache/apt/archives/) and C(/var/cache/apt/archives/partial/).
- Can be run as part of the package installation (clean runs before install) or as a separate step.
type: bool
default: false
version_added: 6.5.0
dist_upgrade:
description:
- If true performs an C(apt-get dist-upgrade) to upgrade system.
type: bool
default: false
version_added: 6.5.0
update_kernel:
description:
- If true performs an C(update-kernel) to upgrade kernel packages.
type: bool
default: false
version_added: 6.5.0
author:
- Evgenii Terechkov (@evgkrsk)
'''
Expand Down Expand Up @@ -69,6 +89,16 @@
name: bar
state: present
update_cache: true

- name: Run the equivalent of "apt-get clean" as a separate step
community.general.apt_rpm:
clean: true

- name: Perform cache update and complete system upgrade (includes kernel)
community.general.apt_rpm:
update_cache: true
dist_upgrade: true
update_kernel: true
'''

import os
Expand All @@ -77,6 +107,8 @@

APT_PATH = "/usr/bin/apt-get"
RPM_PATH = "/usr/bin/rpm"
APT_GET_ZERO = "\n0 upgraded, 0 newly installed"
UPDATE_KERNEL_ZERO = "\nTry to install new kernel "


def query_package(module, name):
Expand All @@ -97,44 +129,72 @@ def query_package_provides(module, name):


def update_package_db(module):
rc, out, err = module.run_command("%s update" % APT_PATH)
rc, update_out, err = module.run_command([APT_PATH, "update"], check_rc=True, environ_update={"LANG": "C"})
return (False, update_out)

if rc != 0:
module.fail_json(msg="could not update package db: %s" % err)

def dir_size(module, path):
total_size = 0
for path, dirs, files in os.walk(path):
for f in files:
total_size += os.path.getsize(os.path.join(path, f))
return total_size


def clean(module):
t = dir_size(module, "/var/cache/apt/archives")
rc, out, err = module.run_command([APT_PATH, "clean"], check_rc=True)
return (t != dir_size(module, "/var/cache/apt/archives"), out)


def dist_upgrade(module):
rc, out, err = module.run_command([APT_PATH, "-y", "dist-upgrade"], check_rc=True, environ_update={"LANG": "C"})
return (APT_GET_ZERO not in out, out)


def update_kernel(module):
rc, out, err = module.run_command(["/usr/sbin/update-kernel", "-y"], check_rc=True, environ_update={"LANG": "C"})
return (UPDATE_KERNEL_ZERO not in out, out)


def remove_packages(module, packages):

if packages is None:
return (False, "Empty package list")

remove_c = 0
# Using a for loop in case of error, we can report the package that failed
for package in packages:
# Query the package first, to see if we even need to remove
if not query_package(module, package):
continue

rc, out, err = module.run_command("%s -y remove %s" % (APT_PATH, package))
rc, out, err = module.run_command("%s -y remove %s" % (APT_PATH, package), environ_update={"LANG": "C"})

if rc != 0:
module.fail_json(msg="failed to remove %s: %s" % (package, err))

remove_c += 1

if remove_c > 0:
module.exit_json(changed=True, msg="removed %s package(s)" % remove_c)
return (True, "removed %s package(s)" % remove_c)

module.exit_json(changed=False, msg="package(s) already absent")
return (False, "package(s) already absent")


def install_packages(module, pkgspec):

if pkgspec is None:
return (False, "Empty package list")

packages = ""
for package in pkgspec:
if not query_package_provides(module, package):
packages += "'%s' " % package

if len(packages) != 0:

rc, out, err = module.run_command("%s -y install %s" % (APT_PATH, packages))
rc, out, err = module.run_command("%s -y install %s" % (APT_PATH, packages), environ_update={"LANG": "C"})

installed = True
for packages in pkgspec:
Expand All @@ -145,35 +205,60 @@ def install_packages(module, pkgspec):
if rc or not installed:
module.fail_json(msg="'apt-get -y install %s' failed: %s" % (packages, err))
else:
module.exit_json(changed=True, msg="%s present(s)" % packages)
return (True, "%s present(s)" % packages)
else:
module.exit_json(changed=False)
return (False, "Nothing to install")


def main():
module = AnsibleModule(
argument_spec=dict(
state=dict(type='str', default='present', choices=['absent', 'installed', 'present', 'removed']),
update_cache=dict(type='bool', default=False),
package=dict(type='list', elements='str', required=True, aliases=['name', 'pkg']),
clean=dict(type='bool', default=False),
dist_upgrade=dict(type='bool', default=False),
update_kernel=dict(type='bool', default=False),
package=dict(type='list', elements='str', aliases=['name', 'pkg']),
),
)

if not os.path.exists(APT_PATH) or not os.path.exists(RPM_PATH):
module.fail_json(msg="cannot find /usr/bin/apt-get and/or /usr/bin/rpm")

p = module.params
modified = False
output = ""

if p['update_cache']:
update_package_db(module)

packages = p['package']
if p['clean']:
(m, out) = clean(module)
modified = modified or m

if p['dist_upgrade']:
(m, out) = dist_upgrade(module)
modified = modified or m
output += out

if p['update_kernel']:
(m, out) = update_kernel(module)
modified = modified or m
output += out

packages = p['package']
if p['state'] in ['installed', 'present']:
install_packages(module, packages)
(m, out) = install_packages(module, packages)
modified = modified or m
output += out

if p['state'] in ['absent', 'removed']:
(m, out) = remove_packages(module, packages)
modified = modified or m
output += out

elif p['state'] in ['absent', 'removed']:
remove_packages(module, packages)
# Return total modification status and output of all commands
module.exit_json(changed=modified, msg=output)


if __name__ == '__main__':
Expand Down