mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 12:50:22 -07:00
zypper_repository: Improve .repo file idempotency (#3474)
* If repo option points to .repo file, download for later parsing * Parse downloaded .repo file content (ini format) * Validate downloaded file, map values to repodata, workaround to ignore old .repo related code * Integration Test adjusted to install python package 'requests' first * Revert "Integration Test adjusted to install python package 'requests' first" This reverts commit 0d18352c2238d098831ba6d59b66e731fa8f0cd9. Not allowed to introduce new dependencies at this point, module_utils usage required * Remove python 'requests' dependency, using 'fetch_url' and 'to_text' from 'ansible.module_utils' instead * Prefer alias (name) if given instead repo (url) * If gpgkey was given in .repo file ensure key get automatically imported * ConfigParser Import made Python2 compatible * New .repo code moved below existing run-time parameters checks to keep previous logic * Obsolete workaround removed * two pylint/pep8 errors fixed * name added to autorefresh assert * Missing assert for 'Delete test repo' added * name added to priority option assert * name added to check repo is updated by url assert * name added to check repo is updated by name assert * name added to check add a repo by releasever assert * name added to check remove added repo assert * name added to check add a repo by basearch assert * name added to check remove added repo #2 assert * Bugfix to avoid 'KeyError' Exception in if statements * Refactoring of configparser related code, usage of module_utils, py2 compatibility * Removal of some leftover from earlier testing * Integration tests for add/remove repositories by url to .repo file added * Additional name added to list of test repos that has to be removed * Test added to verify cleanup of local .repo file after removal via zypper * Changelog fragment related to PR #3474 added * yamllint error resolved * Refactoring to reduce indentation and removal of else statements * Integration tests added for loading .repo file from local path * Test .repo file added * Dependency to setup_remote_tmp_dir added * New entry added to 'remove repositories added during test' * Support for .repo file from local path * Changelog: Ref to https://github.com/ansible-collections/community.general/issues/3466 added Co-authored-by: Felix Fontein <felix@fontein.de> Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
80bb42325b
commit
f0fcb221cd
6 changed files with 173 additions and 11 deletions
|
@ -137,6 +137,10 @@ from distutils.version import LooseVersion
|
|||
|
||||
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
||||
|
||||
from ansible.module_utils.urls import fetch_url
|
||||
from ansible.module_utils.common.text.converters import to_text
|
||||
from ansible.module_utils.six.moves import configparser, StringIO
|
||||
from io import open
|
||||
|
||||
REPO_OPTS = ['alias', 'name', 'priority', 'enabled', 'autorefresh', 'gpgcheck']
|
||||
|
||||
|
@ -382,12 +386,62 @@ def main():
|
|||
if not alias and state == "present":
|
||||
module.fail_json(msg='Name required when adding non-repo files.')
|
||||
|
||||
# Download / Open and parse .repo file to ensure idempotency
|
||||
if repo and repo.endswith('.repo'):
|
||||
if repo.startswith(('http://', 'https://')):
|
||||
response, info = fetch_url(module=module, url=repo, force=True)
|
||||
if not response or info['status'] != 200:
|
||||
module.fail_json(msg='Error downloading .repo file from provided URL')
|
||||
repofile_text = to_text(response.read(), errors='surrogate_or_strict')
|
||||
else:
|
||||
try:
|
||||
with open(repo, encoding='utf-8') as file:
|
||||
repofile_text = file.read()
|
||||
except IOError:
|
||||
module.fail_json(msg='Error opening .repo file from provided path')
|
||||
|
||||
repofile = configparser.ConfigParser()
|
||||
try:
|
||||
repofile.readfp(StringIO(repofile_text))
|
||||
except configparser.Error:
|
||||
module.fail_json(msg='Invalid format, .repo file could not be parsed')
|
||||
|
||||
# No support for .repo file with zero or more than one repository
|
||||
if len(repofile.sections()) != 1:
|
||||
err = "Invalid format, .repo file contains %s repositories, expected 1" % len(repofile.sections())
|
||||
module.fail_json(msg=err)
|
||||
|
||||
section = repofile.sections()[0]
|
||||
repofile_items = dict(repofile.items(section))
|
||||
# Only proceed if at least baseurl is available
|
||||
if 'baseurl' not in repofile_items:
|
||||
module.fail_json(msg='No baseurl found in .repo file')
|
||||
|
||||
# Set alias (name) and url based on values from .repo file
|
||||
alias = section
|
||||
repodata['alias'] = section
|
||||
repodata['url'] = repofile_items['baseurl']
|
||||
|
||||
# If gpgkey is part of the .repo file, auto import key
|
||||
if 'gpgkey' in repofile_items:
|
||||
auto_import_keys = True
|
||||
|
||||
# Map additional values, if available
|
||||
if 'name' in repofile_items:
|
||||
repodata['name'] = repofile_items['name']
|
||||
if 'enabled' in repofile_items:
|
||||
repodata['enabled'] = repofile_items['enabled']
|
||||
if 'autorefresh' in repofile_items:
|
||||
repodata['autorefresh'] = repofile_items['autorefresh']
|
||||
if 'gpgcheck' in repofile_items:
|
||||
repodata['gpgcheck'] = repofile_items['gpgcheck']
|
||||
|
||||
exists, mod, old_repos = repo_exists(module, repodata, overwrite_multiple)
|
||||
|
||||
if repo:
|
||||
shortname = repo
|
||||
else:
|
||||
if alias:
|
||||
shortname = alias
|
||||
else:
|
||||
shortname = repo
|
||||
|
||||
if state == 'present':
|
||||
if exists and not mod:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue