Add tripleo-yum-config ansible module

This patch adds the tripleo-yum-config module and also
updates its readme file with both ansible and pip information.

Change-Id: I893aac72ee50b389c4d3173fa01bb8d6f74ff38f
This commit is contained in:
Douglas Viroel 2021-06-15 14:46:11 -03:00
parent e012eb0194
commit 82dd143ce8
4 changed files with 300 additions and 7 deletions

View File

@ -12,24 +12,24 @@ repos, yum modules and yum global configuration file.
It is possible to use *tripleo-yum-config* as a standalone module by cloning
its repository and invoking in command line:
* **repo**
This subcommand lets you enable or disable a repo and sets its configuration options.
The *tripleo-yum-config* module will search for the provided repo name in all *.repo* files at REPO_DIR_PATH.
Optionally, you can provide a dir path where your repo files live or specify the full path of the repo file.
By default REPO_DIR_PATH is set to */etc/yum.repod.d/*.
Examples:
```
sudo python -m tripleo_yum_config repo appstream --enable --set-opts baseurl=http://newbaseurl exclude="package*"
sudo python -m tripleo_yum_config repo epel --disable --config-dir-path=/path/to/yum.repos.d
```
* **module**
This subcommand lets you enable, disable, remove, install or reset a module.
Depending on the selected operation and module, the optional parameters 'stream' or 'profile' will also need to be provided:
1. when enabling a module, the *stream* version will be required if the module has zero or more than one default stream.
2. when installing a module, the *profile* will be required if the enabled stream has no default profile set.
Examples:
```
sudo python -m tripleo_yum_config module remove tomcat
@ -38,12 +38,12 @@ its repository and invoking in command line:
sudo python -m tripleo_yum_config module install nginx --profile common
```
* **global**
This subcommand lets you set any global yum/dnf configuration value under *[main]* section.
If no configuration file is found by the module, a new one is created and populated.
Optionally you can also provide the path to the configuration file.
By default CONFIG_FILE_PATH is set to */etc/yum.conf*
Example:
```
sudo python -m tripleo_yum_config global --set-opts keepcache=1 cachedir="/var/cache/dnf"
@ -72,3 +72,14 @@ invoke *tripleo-yum-config --help* to see all the available commands.
```
tripleo-yum-config --help
```
## Ansible Module
An ansible module [tripleo_yum_config](https://opendev.org/openstack/tripleo-repos/src/branch/master/tripleo-yum-config/tripleo_yum_config.py)
is available for you when you install tripleo-yum-config, either by using
setup.py or pip. The module is installed at the relative path
*share/ansible/plugins/modules*, which may land on a different directory,
depending on how you are installing this package. Check your ansible
configuration to see if the directory is included in your ansible library path.
An [example playbook](https://opendev.org/openstack/tripleo-repos/src/branch/master/tripleo-yum-config/example_playbook.yaml)
is available to assist on module usage.

View File

@ -0,0 +1,33 @@
---
- name: Example usage for tripleo_yum_config python module
hosts: localhost
tasks:
- name: Enable fake yum repo and set exclude dirs
become: true
tripleo_yum_config:
type: repo
name: appstream
enabled: true
set_options:
exclude:
- nodejs*
- mariadb*
- name: Enable and install nginx module
become: true
tripleo_yum_config:
type: module
name: nginx
enabled: true
operation: install
profile: common
stream: mainline
- name: Set yum global options in dnf.conf
become: true
tripleo_yum_config:
type: global
file_path: /etc/dnf/dnf.conf
set_options:
skip_if_unavailable: "False"
keepcache: "0"

View File

@ -1,7 +1,7 @@
[metadata]
name = tripleo-yum-config
author = Douglas Viroel
author_email = dviroel@redhat.com
author_email = openstack-discuss@lists.openstack.org
description = Updates yum configuration files (repo, modules, global configuration).
long_description = file: README.md LICENSE
long_description_content_type = text/markdown
@ -22,3 +22,7 @@ python_requires = >=3.6
[options.entry_points]
console_scripts =
tripleo-yum-config = tripleo_yum_config.__main__:cli_entrypoint
[files]
data_files =
share/ansible/plugins/modules/ = tripleo_yum_config.py

View File

@ -0,0 +1,245 @@
#!/usr/bin/python
# Copyright 2021 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from ansible.module_utils.basic import AnsibleModule
import tripleo_yum_config.dnf_manager as dnf_mgr
import tripleo_yum_config.yum_config as cfg
DOCUMENTATION = r'''
---
module: tripleo_yum_config
short_description: Update yum configuration files for TripleO deployments.
version_added: "2.9"
description:
- Update specific options for different yum configuration files like
yum repos, yum modules and yum global configuration.
options:
type:
description:
- The type of yum configuration to be changed.
required: true
type: str
choices: [repo, module, global]
name:
description:
- Name of the repo or module to be changed. This options is
mandatory only for repo and module types.
required: false
type: str
enabled:
description:
- Change the yum repo or module to enabled or disabled.
- This options is ignored for yum global configuration.
required: false
type: bool
operation:
description:
- Operation to be execute within a dnf module.
required: false
type: str
choices: [install, remove, reset]
stream:
description:
- Sets a module stream. This options is recommended when enabling a
module that doesn't have a default stream.
required: false
type: str
profile:
description:
- Sets a module profile. This options is recommended when installing
a module that doesn't have a default profile.
required: false
type: str
set_options:
description:
- Dictionary with options to be updated. All dictionary values must
be string or list of strings.
required: false
type: dict
file_path:
description:
- Absolute path of the configuration file to be changed.
required: false
type: str
dir_path:
description:
- Absolute path of the directory that contains the configuration
file to be changed.
required: false
type: str
author:
- Douglas Viroel (@viroel)
'''
EXAMPLES = r'''
# Set yum 'appstream' repo to enabled and exclude a list of packages
- name: Enable appstream repo and exclude nodejs and mariadb packages
become: true
become_user: root
tripleo_yum_config:
type: repo
name: appstream
enabled: true
set_options:
exclude:
- nodejs*
- mariadb*
# Enable and install a yum/dnf module
- name: Enable nginx module
become: true
become_user: root
tripleo_yum_config:
type: module
name: tomcat
enabled: false
stream: "1.18"
- name: Enable nginx module
become: true
become_user: root
tripleo_yum_config:
type: module
name: nginx
operation: install
profile: common
# Set yum global configuration options
- name: Set yum global options
become: true
become_user: root
tripleo_yum_config:
type: global
file_path: /etc/dnf/dnf.conf
set_options:
skip_if_unavailable: "False"
keepcache: "0"
'''
def run_module():
# define available arguments/parameters a user can pass to the module
supported_config_types = ['repo', 'module', 'global']
supported_module_operations = ['install', 'remove', 'reset']
module_args = dict(
type=dict(type='str', required=True, choices=supported_config_types),
name=dict(type='str', required=False),
enabled=dict(type='bool', required=False),
operation=dict(type='str', required=False,
choices=supported_module_operations),
stream=dict(type='str', required=False),
profile=dict(type='str', required=False),
set_options=dict(type='dict', required=False),
file_path=dict(type='str', required=False),
dir_path=dict(type='str', required=False),
)
result = dict(
changed=False,
msg=''
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
m_type = module.params.get('type')
m_name = module.params.get('name')
m_set_opts = module.params.get('set_options', {})
m_enabled = module.params.get('enabled')
m_file_path = module.params.get('file_path')
m_dir_path = module.params.get('dir_path')
# Sanity checks
if m_type in ['repo', 'module'] and m_name is None:
result['msg'] = (
"The parameter 'name' is mandatory when 'type' is set to 'repo' "
"or 'module'.")
module.fail_json(**result)
# 'set_options' expects a dict that can hold, as value, strings and list
# of strings. List of strings will be converted to a comma-separated list.
invalid_set_opts_msg = (
"The provided value for 'set_options' parameter has an invalid "
"format. All dict values must be string or a list of strings.")
if m_set_opts:
for k, v in m_set_opts.items():
if isinstance(v, list):
if not all(isinstance(elem, str) for elem in v):
result['msg'] = invalid_set_opts_msg
module.fail_json(**result)
m_set_opts[k] = ','.join(v)
elif not isinstance(v, str):
result['msg'] = invalid_set_opts_msg
module.fail_json(**result)
if module.check_mode:
# Checks were already made above
module.exit_json(**result)
# Module execution
try:
if m_type == 'repo':
config_obj = cfg.TripleOYumRepoConfig(
file_path=m_file_path,
dir_path=m_dir_path)
config_obj.update_section(m_name, m_set_opts, enable=m_enabled)
elif m_type == 'module':
dnf_mod_mgr = dnf_mgr.DnfModuleManager()
m_stream = module.params.get('stream')
m_profile = module.params.get('profile')
if m_enabled is True:
dnf_mod_mgr.enable_module(m_name,
stream=m_stream,
profile=m_profile)
elif m_enabled is False:
dnf_mod_mgr.disable_module(m_name,
stream=m_stream,
profile=m_profile)
m_operation = module.params.get('operation')
if m_operation:
dnf_method = getattr(dnf_mod_mgr, m_operation + "_module")
dnf_method(m_name, stream=m_stream, profile=m_profile)
elif m_type == 'global':
config_obj = cfg.TripleOYumGlobalConfig(file_path=m_file_path)
config_obj.update_section('main', m_set_opts)
except Exception as exc:
result['msg'] = str(exc)
module.fail_json(**result)
# Successful module execution
result['changed'] = True
result['msg'] = (
"Yum {} configuration was successfully updated.".format(m_type)
)
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()