mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-08 06:12:51 +00:00
zypper_repository: allow state=absent when .repo URL/file is unreachable (#11947)
* fix(zypper_repository): allow state=absent when .repo URL/file is unreachable When removing a repository by .repo URL, a download failure used to cause an unconditional fail_json. Now, for state=absent, the module warns and falls back to deriving the alias from the .repo filename basename. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(changelog): add fragment for PR 11947 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
bugfixes:
|
||||||
|
- zypper_repository - allow unreachable ``.repo`` URLs and missing local paths when using ``state=absent`` (https://github.com/ansible-collections/community.general/issues/5769, https://github.com/ansible-collections/community.general/pull/11947).
|
||||||
@@ -394,53 +394,69 @@ def main():
|
|||||||
|
|
||||||
# Download / Open and parse .repo file to ensure idempotency
|
# Download / Open and parse .repo file to ensure idempotency
|
||||||
if repo and repo.endswith(".repo"):
|
if repo and repo.endswith(".repo"):
|
||||||
|
repofile_text = None
|
||||||
if repo.startswith(("http://", "https://")):
|
if repo.startswith(("http://", "https://")):
|
||||||
response, info = fetch_url(module=module, url=repo, force=True)
|
response, info = fetch_url(module=module, url=repo, force=True)
|
||||||
if not response or info["status"] != 200:
|
if not response or info["status"] != 200:
|
||||||
module.fail_json(msg="Error downloading .repo file from provided URL")
|
if state == "absent":
|
||||||
repofile_text = to_text(response.read(), errors="surrogate_or_strict")
|
# Fall back to alias derived from URL filename (convention: section == basename)
|
||||||
|
module.warn(
|
||||||
|
f"Could not download .repo file from '{repo}'; will try to identify repository by alias"
|
||||||
|
)
|
||||||
|
alias = alias or repo.rsplit("/", 1)[-1][:-5]
|
||||||
|
repodata["alias"] = alias
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Error downloading .repo file from provided URL")
|
||||||
|
else:
|
||||||
|
repofile_text = to_text(response.read(), errors="surrogate_or_strict")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
with open(repo, encoding="utf-8") as file:
|
with open(repo, encoding="utf-8") as file:
|
||||||
repofile_text = file.read()
|
repofile_text = file.read()
|
||||||
except OSError:
|
except OSError:
|
||||||
module.fail_json(msg="Error opening .repo file from provided path")
|
if state == "absent":
|
||||||
|
module.warn(f"Could not open .repo file at '{repo}'; will try to identify repository by alias")
|
||||||
|
alias = alias or repo.rsplit("/", 1)[-1][:-5]
|
||||||
|
repodata["alias"] = alias
|
||||||
|
else:
|
||||||
|
module.fail_json(msg="Error opening .repo file from provided path")
|
||||||
|
|
||||||
repofile = configparser.ConfigParser()
|
if repofile_text is not None:
|
||||||
try:
|
repofile = configparser.ConfigParser()
|
||||||
repofile.read_file(StringIO(repofile_text))
|
try:
|
||||||
except configparser.Error:
|
repofile.read_file(StringIO(repofile_text))
|
||||||
module.fail_json(msg="Invalid format, .repo file could not be parsed")
|
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
|
# No support for .repo file with zero or more than one repository
|
||||||
if len(repofile.sections()) != 1:
|
if len(repofile.sections()) != 1:
|
||||||
err = f"Invalid format, .repo file contains {len(repofile.sections())} repositories, expected 1"
|
err = f"Invalid format, .repo file contains {len(repofile.sections())} repositories, expected 1"
|
||||||
module.fail_json(msg=err)
|
module.fail_json(msg=err)
|
||||||
|
|
||||||
section = repofile.sections()[0]
|
section = repofile.sections()[0]
|
||||||
repofile_items = dict(repofile.items(section))
|
repofile_items = dict(repofile.items(section))
|
||||||
# Only proceed if at least baseurl is available
|
# Only proceed if at least baseurl is available
|
||||||
if "baseurl" not in repofile_items:
|
if "baseurl" not in repofile_items:
|
||||||
module.fail_json(msg="No baseurl found in .repo file")
|
module.fail_json(msg="No baseurl found in .repo file")
|
||||||
|
|
||||||
# Set alias (name) and url based on values from .repo file
|
# Set alias (name) and url based on values from .repo file
|
||||||
alias = section
|
alias = section
|
||||||
repodata["alias"] = section
|
repodata["alias"] = section
|
||||||
repodata["url"] = repofile_items["baseurl"]
|
repodata["url"] = repofile_items["baseurl"]
|
||||||
|
|
||||||
# If gpgkey is part of the .repo file, auto import key
|
# If gpgkey is part of the .repo file, auto import key
|
||||||
if "gpgkey" in repofile_items:
|
if "gpgkey" in repofile_items:
|
||||||
auto_import_keys = True
|
auto_import_keys = True
|
||||||
|
|
||||||
# Map additional values, if available
|
# Map additional values, if available
|
||||||
if "name" in repofile_items:
|
if "name" in repofile_items:
|
||||||
repodata["name"] = repofile_items["name"]
|
repodata["name"] = repofile_items["name"]
|
||||||
if "enabled" in repofile_items:
|
if "enabled" in repofile_items:
|
||||||
repodata["enabled"] = repofile_items["enabled"]
|
repodata["enabled"] = repofile_items["enabled"]
|
||||||
if "autorefresh" in repofile_items:
|
if "autorefresh" in repofile_items:
|
||||||
repodata["autorefresh"] = repofile_items["autorefresh"]
|
repodata["autorefresh"] = repofile_items["autorefresh"]
|
||||||
if "gpgcheck" in repofile_items:
|
if "gpgcheck" in repofile_items:
|
||||||
repodata["gpgcheck"] = repofile_items["gpgcheck"]
|
repodata["gpgcheck"] = repofile_items["gpgcheck"]
|
||||||
|
|
||||||
exists, mod, old_repos = repo_exists(module, repodata, overwrite_multiple)
|
exists, mod, old_repos = repo_exists(module, repodata, overwrite_multiple)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user