Getting Ansible tdnf Module to work for Photon OS Targets - CloudCommandos/JohnChan GitHub Wiki
Create tdnf.py
at /usr/lib/python2.7/site-packages/ansible/modules/packaging/os/tdnf.py
tdnf.py - Original link
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2019, Anish Swaminathan <https://github.com/suezzelur>
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['stableinterface'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tdnf
short_description: Tiny DNF package manager
description:
- Manages rpm packages for VMware Photon OS.
author: "Anish Swaminathan"
version_added: "2.9"
options:
name:
description:
- A package name, like C(foo), or multiple packages, like C(foo, bar).
aliases:
- pkg
state:
description:
- Indicates the desired package(s) state.
- C(present) ensures the package(s) is/are present.
- C(absent) ensures the package(s) is/are absent.
- C(latest) ensures the package(s) is/are present and the latest version(s).
default: present
choices: [ "present", "absent", "latest" ]
update_cache:
description:
- Update repo metadata cache. Can be run with other steps or on it's own.
type: bool
default: 'no'
upgrade:
description:
- Upgrade all installed packages to their latest version.
type: bool
default: 'no'
enablerepo:
description:
- I(Repoid) of repositories to enable for the install/update operation.
When specifying multiple repos, separate them with a ",".
disablerepo:
description:
- I(Repoid) of repositories to disable for the install/update operation.
When specifying multiple repos, separate them with a ",".
conf_file:
description:
- The tdnf configuration file to use for the transaction.
disable_gpg_check:
description:
- Whether to disable the GPG checking of signatures of packages being
installed. Has an effect only if state is I(present) or I(latest).
type: bool
default: 'no'
installroot:
description:
- Specifies an alternative installroot, relative to which all packages
will be installed.
default: "/"
security_severity:
description:
- Specifies the CVSS v3 score above which to install updates for packages
releasever:
description:
- Specifies an alternative release from which all packages will be
installed.
exclude:
description:
- Package name(s) to exclude when state=present, or latest. This can be a
list or a comma separated string.
notes:
- '"name" and "upgrade" are mutually exclusive.'
- When used with a `loop:` each package will be processed individually, it is much more efficient to pass the list directly to the `name` option.
'''
EXAMPLES = '''
# Update repositories and install "foo" package
- tdnf:
name: foo
update_cache: yes
# Update repositories and install "foo" and "bar" packages
- tdnf:
name: foo,bar
update_cache: yes
# Remove "foo" package
- tdnf:
name: foo
state: absent
# Remove "foo" and "bar" packages
- tdnf:
name: foo,bar
state: absent
# Install the package "foo"
- tdnf:
name: foo
state: present
# Install the packages "foo" and "bar"
- tdnf:
name: foo,bar
state: present
# Update repositories and update package "foo" to latest version
- tdnf:
name: foo
state: latest
update_cache: yes
# Update repositories and update packages "foo" and "bar" to latest versions
- tdnf:
name: foo,bar
state: latest
update_cache: yes
# Update all installed packages to the latest versions
- tdnf:
upgrade: yes
# Update repositories as a separate step
- tdnf:
update_cache: yes
'''
import re
# Import module snippets.
from ansible.module_utils.basic import AnsibleModule
def update_package_db(module, exit):
cmd = "%s makecache" % (TDNF_PATH)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0:
module.fail_json(msg="could not update package db", stdout=stdout, stderr=stderr)
elif exit:
module.exit_json(changed=True, msg='updated package db', stdout=stdout, stderr=stderr)
else:
return True
def upgrade_packages(
module,
excludelist,
disable_gpg_check,
security_severity,
releasever,
conf_file):
cmd = "%s upgrade -y" % (TDNF_PATH)
if excludelist:
cmd = "%s --exclude %s" % (cmd, ",".join(excludelist))
if disable_gpg_check:
cmd = "%s --nogpgcheck" % cmd
if security_severity:
cmd = "%s --sec-severity %s" % (cmd, security_severity)
if releasever:
cmd = "%s --releasever %s" % (cmd, releasever)
if conf_file:
cmd = "%s -c %s" % (cmd, conf_file)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0:
module.fail_json(msg="failed to upgrade packages", stdout=stdout, stderr=stderr)
was_changed = True
end_message = "%s package(s) upgraded"
if 'Nothing to do' in stderr:
was_changed = False
end_message = "%s packages(s) already at latest"
module.exit_json(changed=was_changed, msg=end_message, stdout=stdout, stderr=stderr)
def install_packages(
module,
pkglist,
enablerepolist,
disablerepolist,
excludelist,
disable_gpg_check,
installroot,
releasever,
conf_file):
packages = " ".join(pkglist)
cmd = "%s install -y" % (TDNF_PATH)
if excludelist:
cmd = "%s --exclude %s" % (cmd, ",".join(excludelist))
if disable_gpg_check:
cmd = "%s --nogpgcheck" % cmd
if releasever:
cmd = "%s --releasever %s" % (cmd, releasever)
if conf_file:
cmd = "%s -c %s" % (cmd, conf_file)
if enablerepolist:
for repo in enablerepolist:
cmd = "%s --enablerepo=%s" % (cmd, repo)
if disablerepolist:
for repo in disablerepolist:
cmd = "%s --disablerepo=%s" % (cmd, repo)
cmd = "%s %s" % (cmd, packages)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0:
module.fail_json(msg="failed to install %s" % (packages), stdout=stdout, stderr=stderr)
was_changed = True
end_message = "installed %s package(s)"
if 'Nothing to do' in stderr:
was_changed = False
end_message = "%s packages(s) already installed"
module.exit_json(changed=was_changed, msg=end_message % (packages), stdout=stdout, stderr=stderr)
def remove_packages(module, pkglist):
packages = " ".join(pkglist)
cmd = "%s remove -y %s" % (TDNF_PATH, packages)
rc, stdout, stderr = module.run_command(cmd, check_rc=False)
if rc != 0:
module.fail_json(msg="failed to remove %s package(s)" % (packages), stdout=stdout, stderr=stderr)
module.exit_json(changed=True, msg="removed %s package(s)" % (packages), stdout=stdout, stderr=stderr)
def convert_to_list(input_list):
if input_list is None:
input_list = []
flat_list1 = [item for sublist in input_list for item in sublist if isinstance(sublist,list)]
flat_list2 = [item for item in input_list if not isinstance(item,list)]
return flat_list1 + flat_list2
# ==========================================
# Main control flow.
def main():
module = AnsibleModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'installed', 'absent', 'removed', 'latest']),
name=dict(type='list'),
repository=dict(type='list'),
update_cache=dict(default=False, type='bool'),
upgrade=dict(default=False, type='bool'),
enablerepo=dict(type='list', default=[]),
disablerepo=dict(type='list', default=[]),
disable_gpg_check=dict(type='bool', default=False),
exclude=dict(type='list', default=[]),
installroot=dict(type='str', default="/"),
security_severity=dict(type='str', default=None),
releasever=dict(default=None),
conf_file=dict(type='str', default=None),
),
required_one_of=['name', 'update_cache', 'upgrade', 'security_severity'](/CloudCommandos/JohnChan/wiki/'name',-'update_cache',-'upgrade',-'security_severity'),
mutually_exclusive=['name', 'upgrade'], ['name', 'security_severity'](/CloudCommandos/JohnChan/wiki/'name',-'upgrade'],-['name',-'security_severity'),
supports_check_mode=True
)
# Set LANG env since we parse stdout
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
global TDNF_PATH
TDNF_PATH = module.get_bin_path('tdnf', required=True)
p = module.params
pkglist = convert_to_list(p['name'])
enablerepolist = convert_to_list(p['enablerepo'])
disablerepolist = convert_to_list(p['disablerepo'])
excludelist = convert_to_list(p['exclude'])
# normalize the state parameter
if p['state'] in ['present', 'installed', 'latest']:
p['state'] = 'present'
if p['state'] in ['absent', 'removed']:
p['state'] = 'absent'
if p['update_cache']:
update_package_db(module, not p['name'] and not p['upgrade'] and not p['security_severity'])
if p['upgrade']:
upgrade_packages(
module,
excludelist,
p['disable_gpg_check'],
p['security_severity'],
p['releasever'],
p['conf_file'])
if p['state'] in ['present', 'latest']:
install_packages(
module,
pkglist,
enablerepolist,
disablerepolist,
excludelist,
p['disable_gpg_check'],
p['installroot'],
p['releasever'],
p['conf_file'])
elif p['state'] == 'absent':
remove_packages(module, pkglist)
if __name__ == '__main__':
main()
Then compile the python script
python
import py_compile
py_compile.compile('tdnf.py')
exit()