<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>The Wombelix Post - Ansible</title><link href="https://dominik.wombacher.cc/" rel="alternate"/><link href="/feeds/tag_ansible.atom.xml" rel="self"/><id>https://dominik.wombacher.cc/</id><updated>2022-12-30T00:00:00+01:00</updated><entry><title>Ansible Hackathon 2021 Contribution: Improved idempotency - zypper_repository</title><link href="https://dominik.wombacher.cc/posts/ansible-hackathon-2021-contribution-improved-idempotency-zypper-repository.html" rel="alternate"/><published>2021-10-01T00:00:00+02:00</published><updated>2021-10-01T00:00:00+02:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2021-10-01:/posts/ansible-hackathon-2021-contribution-improved-idempotency-zypper-repository.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;Parallel to the &lt;a class="reference external" href="https://hackmd.io/@ansible-community/contrib-summit-202109"&gt;Ansible Contributor Summit 2021.09&lt;/a&gt; and the
&lt;a class="reference external" href="https://reg.ansiblefest.redhat.com/flow/redhat/ansible21/regGenAttendee/login"&gt;Ansible Fest 2021&lt;/a&gt;
there was a &lt;strong&gt;Hackathon&lt;/strong&gt; with focus on first time Contributor.
Even though I use Ansible since years  ... &lt;a class="read-more" href="/posts/ansible-hackathon-2021-contribution-improved-idempotency-zypper-repository.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;Parallel to the &lt;a class="reference external" href="https://hackmd.io/&amp;#64;ansible-community/contrib-summit-202109"&gt;Ansible Contributor Summit 2021.09&lt;/a&gt; and the
&lt;a class="reference external" href="https://reg.ansiblefest.redhat.com/flow/redhat/ansible21/regGenAttendee/login"&gt;Ansible Fest 2021&lt;/a&gt;
there was a &lt;strong&gt;Hackathon&lt;/strong&gt; with focus on first time Contributor.
Even though I use Ansible since years, but mainly from a User perspective (Playbooks, Roles, Collections),
I wasn't officially Contributing to a Plugin or Module yet.&lt;/p&gt;
&lt;p&gt;I did some smaller bugfixing or improvements in the past, but mainly for myself or a very unique use case at work.
So far I never worked on one of the GitHub Issues or created a PR for any of the
&lt;a class="reference external" href="https://github.com/ansible-collections/"&gt;community modules&lt;/a&gt;, something I always wanted to change.&lt;/p&gt;
&lt;p&gt;As already mentioned a &lt;a class="reference external" href="https://dominik.wombacher.cc/posts/pipx-behave-different-than-pip-if-package-already-exists.html"&gt;few days ago&lt;/a&gt;,
I started putting all my configs in Ansible Playbook(s).
I'm using openSUSE Tumbleweed with some additional repositories and wanted to managed them also via Ansible.
I prefer &lt;em&gt;.repo&lt;/em&gt; files, they are very convinient, you don't have to manage anything manually.
There is a Module available (&lt;em&gt;community.general.zypper_repository&lt;/em&gt;) but there was a
&lt;a class="reference external" href="https://github.com/ansible-collections/community.general/issues/1791"&gt;bug&lt;/a&gt; regarding the idempotency when using &lt;em&gt;.repo&lt;/em&gt; files.&lt;/p&gt;
&lt;p&gt;You could add a new repository by using a &lt;em&gt;.repo&lt;/em&gt; file but then every future run will fail,
also removing a repository the same way wasn't working either.&lt;/p&gt;
&lt;p&gt;So I decided to work on this Issue during the Hackathon and get some Hands-On Experience contributing to Ansible Collections.&lt;/p&gt;
&lt;p&gt;Due to the fact that you need at least a &lt;cite&gt;name&lt;/cite&gt; and &lt;cite&gt;baseurl&lt;/cite&gt; to identify if something need to be added, changed or removed,
I decided to download the &lt;em&gt;.repo&lt;/em&gt; file, parse it and work with the actual values.
The previous Implementation was calling &lt;cite&gt;zypper&lt;/cite&gt; more or less directly with the URL to the file as Parameter, which caused the reported issues.&lt;/p&gt;
&lt;p&gt;Now the &lt;strong&gt;community.general.zypper_repository&lt;/strong&gt; module supports &lt;em&gt;.repo&lt;/em&gt; files via URL or from a local path,
behave as expected in regards to idempotency and is fully covered by integration tests.&lt;/p&gt;
&lt;p&gt;There were always &lt;a class="reference external" href="https://github.com/ansible-collections/community.general/blob/main/commit-rights.md#people"&gt;Ansible Community.General Maintainer&lt;/a&gt;
available via Matrix to answer questions, pointing into the right direction and assisting in case of any problems.&lt;/p&gt;
&lt;p&gt;It was a great experience for me! I can just recommend such Events, I've learned a lot during these two days and finished my
&lt;a class="reference external" href="https://github.com/ansible-collections/community.general/pull/3474"&gt;Pull Request&lt;/a&gt;,
which also fixes a &lt;a class="reference external" href="https://github.com/ansible-collections/community.general/issues/3466"&gt;second issue&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All CI tests are finally passed, feedback from the first Reviewer is positive,
fingers crossed everything will be fine and the PR merged soon :)&lt;/p&gt;
&lt;p&gt;I will write a little more about the Summit, my expiriences and things learned or found useful,
to get started contributing, within the next days in a separate post.&lt;/p&gt;
&lt;p&gt;Even though you can find all details in my &lt;a class="reference external" href="https://github.com/ansible-collections/community.general/pull/3474"&gt;Pull Request on GitHub&lt;/a&gt;,
I don't want to force navigating to a different site, so let me share the &lt;em&gt;diff&lt;/em&gt; (at time of writing) here as well:&lt;/p&gt;
&lt;pre class="code diff literal-block"&gt;
&lt;span class="pygments-gh"&gt;diff --git a/changelogs/fragments/3474-zypper_repository_improve_repo_file_idempotency.yml b/changelogs/fragments/3474-zypper_repository_improve_repo_file_idempotency.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;new file mode 100644&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gh"&gt;index 00000000000..4f3b56329cb&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;--- /dev/null&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+++ b/changelogs/fragments/3474-zypper_repository_improve_repo_file_idempotency.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -0,0 +1,7 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+bugfixes:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  - zypper_repository - when an URL to a .repo file was provided in option&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    ``repo=`` and ``state=present`` only the first run was successful,&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    future runs failed due to missing checks prior starting zypper.&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    Usage of ``state=absent`` in combination with a .repo file was not&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    working either (https://github.com/ansible-collections/community.general/issues/1791,&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    https://github.com/ansible-collections/community.general/issues/3466).&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gh"&gt;diff --git a/plugins/modules/packaging/os/zypper_repository.py b/plugins/modules/packaging/os/zypper_repository.py&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gh"&gt;index 38aeab618e8..a29650a17ef 100644&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;--- a/plugins/modules/packaging/os/zypper_repository.py&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+++ b/plugins/modules/packaging/os/zypper_repository.py&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -137,6 +137,10 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;

 &lt;/span&gt;from ansible.module_utils.basic import AnsibleModule, missing_required_lib&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gi"&gt;+from ansible.module_utils.urls import fetch_url&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+from ansible.module_utils.common.text.converters import to_text&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+from ansible.module_utils.six.moves import configparser, StringIO&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+from io import open&lt;/span&gt;&lt;span class="pygments-w"&gt;

 &lt;/span&gt;REPO_OPTS = ['alias', 'name', 'priority', 'enabled', 'autorefresh', 'gpgcheck']&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -382,12 +386,62 &amp;#64;&amp;#64; def exit_unchanged():&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;        if not alias and state == &amp;quot;present&amp;quot;:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;            module.fail_json(msg='Name required when adding non-repo files.')&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    # Download / Open and parse .repo file to ensure idempotency&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    if repo and repo.endswith('.repo'):&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if repo.startswith(('http://', 'https://')):&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            response, info = fetch_url(module=module, url=repo, force=True)&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            if not response or info['status'] != 200:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+                module.fail_json(msg='Error downloading .repo file from provided URL')&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            repofile_text = to_text(response.read(), errors='surrogate_or_strict')&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        else:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            try:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+                with open(repo, encoding='utf-8') as file:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+                    repofile_text = file.read()&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            except IOError:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+                module.fail_json(msg='Error opening .repo file from provided path')&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        repofile = configparser.ConfigParser()&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        try:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            repofile.readfp(StringIO(repofile_text))&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        except configparser.Error:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            module.fail_json(msg='Invalid format, .repo file could not be parsed')&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        # No support for .repo file with zero or more than one repository&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if len(repofile.sections()) != 1:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            err = &amp;quot;Invalid format, .repo file contains %s repositories, expected 1&amp;quot; % len(repofile.sections())&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            module.fail_json(msg=err)&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        section = repofile.sections()[0]&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        repofile_items = dict(repofile.items(section))&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        # Only proceed if at least baseurl is available&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if 'baseurl' not in repofile_items:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            module.fail_json(msg='No baseurl found in .repo file')&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        # Set alias (name) and url based on values from .repo file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        alias = section&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        repodata['alias'] = section&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        repodata['url'] = repofile_items['baseurl']&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        # If gpgkey is part of the .repo file, auto import key&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if 'gpgkey' in repofile_items:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            auto_import_keys = True&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        # Map additional values, if available&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if 'name' in repofile_items:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            repodata['name'] = repofile_items['name']&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if 'enabled' in repofile_items:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            repodata['enabled'] = repofile_items['enabled']&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if 'autorefresh' in repofile_items:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            repodata['autorefresh'] = repofile_items['autorefresh']&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        if 'gpgcheck' in repofile_items:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+            repodata['gpgcheck'] = repofile_items['gpgcheck']&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    exists, mod, old_repos = repo_exists(module, repodata, overwrite_multiple)&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-    if repo:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;-        shortname = repo&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;-    else:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    if alias:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;        shortname = alias&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    else:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        shortname = repo&lt;/span&gt;&lt;span class="pygments-w"&gt;

 &lt;/span&gt;    if state == 'present':&lt;span class="pygments-w"&gt;
 &lt;/span&gt;        if exists and not mod:&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gh"&gt;diff --git a/tests/integration/targets/zypper_repository/files/systemsmanagement_Uyuni_Utils.repo b/tests/integration/targets/zypper_repository/files/systemsmanagement_Uyuni_Utils.repo&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;new file mode 100644&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gh"&gt;index 00000000000..1df76802a70&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;--- /dev/null&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+++ b/tests/integration/targets/zypper_repository/files/systemsmanagement_Uyuni_Utils.repo&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -0,0 +1,7 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+[systemsmanagement_Uyuni_Utils]&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+name=Several utilities to develop, build or release Uyuni (openSUSE_Leap_15.3)&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+type=rpm-md&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+baseurl=https://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Utils/openSUSE_Leap_15.3/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+gpgcheck=1&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+gpgkey=https://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Utils/openSUSE_Leap_15.3/repodata/repomd.xml.key&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+enabled=1&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gh"&gt;diff --git a/tests/integration/targets/zypper_repository/meta/main.yml b/tests/integration/targets/zypper_repository/meta/main.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;new file mode 100644&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gh"&gt;index 00000000000..1810d4bec98&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;--- /dev/null&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+++ b/tests/integration/targets/zypper_repository/meta/main.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -0,0 +1,2 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+dependencies:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  - setup_remote_tmp_dir&lt;/span&gt;&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gh"&gt;diff --git a/tests/integration/targets/zypper_repository/tasks/test.yml b/tests/integration/targets/zypper_repository/tasks/test.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gh"&gt;index e2b2f8473b6..1033ee1e7d5 100644&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;--- a/tests/integration/targets/zypper_repository/tasks/test.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+++ b/tests/integration/targets/zypper_repository/tasks/test.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -19,6 +19,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;        - testrefresh&lt;span class="pygments-w"&gt;
 &lt;/span&gt;        - testprio&lt;span class="pygments-w"&gt;
 &lt;/span&gt;        - Apache_PHP_Modules&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        - systemsmanagement_Uyuni_Stable&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+        - systemsmanagement_Uyuni_Utils&lt;/span&gt;&lt;span class="pygments-w"&gt;

 &lt;/span&gt;    - name: collect repo configuration after test&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      shell: &amp;quot;grep . /etc/zypp/repos.d/*&amp;quot;&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gh"&gt;diff --git a/tests/integration/targets/zypper_repository/tasks/zypper_repository.yml b/tests/integration/targets/zypper_repository/tasks/zypper_repository.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gh"&gt;index 4490ddca7db..dbd9bb0064b 100644&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gd"&gt;--- a/tests/integration/targets/zypper_repository/tasks/zypper_repository.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+++ b/tests/integration/targets/zypper_repository/tasks/zypper_repository.yml&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -4,6 +4,11 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    state: absent&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: zypper_result&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify no change on test repo deletion&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    that:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;not zypper_result.changed&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;- name: Add test repo&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  community.general.zypper_repository:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    name: test&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -51,7 +56,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  command: zypper -x lr testrefresh&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: zypper_result&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify autorefresh option set properly&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - '&amp;quot;autorefresh=\&amp;quot;0\&amp;quot;&amp;quot; in zypper_result.stdout'&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -66,7 +72,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  command: zypper -x lr testprio&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: zypper_result&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify priority option set properly&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - '&amp;quot;priority=\&amp;quot;55\&amp;quot;&amp;quot; in zypper_result.stdout'&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -88,7 +95,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  command: zypper lr chrome2&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: zypper_result2&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: ensure same url cause update of existing repo even if name differ&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - &amp;quot;zypper_result1.rc != 0&amp;quot;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - &amp;quot;'not found' in zypper_result1.stderr&amp;quot;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -108,7 +116,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  command: zypper lr samename&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: zypper_result&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: ensure url get updated on repo with same name&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - &amp;quot;'/science/' not in zypper_result.stdout&amp;quot;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - &amp;quot;'/devel:/languages:/ruby/' in zypper_result.stdout&amp;quot;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -140,7 +149,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    state: present&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: add_repo_again&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: no update in case of $releasever usage in url&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - add_repo is changed&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - add_repo_again is not changed&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -151,10 +161,21 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    state: absent&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: remove_repo&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify repo was removed&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - remove_repo is changed&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: get list of files in /etc/zypp/repos.d/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  command: ls /etc/zypp/repos.d/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  changed_when: false&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: releaseverrepo_etc_zypp_reposd&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify removal of file releaseverrepo.repo in /etc/zypp/repos.d/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    that:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;'releaseverrepo' not in releaseverrepo_etc_zypp_reposd.stdout&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;- name: add a repo by basearch&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  community.general.zypper_repository:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    name: basearchrepo&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -169,7 +190,8 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    state: present&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: add_repo_again&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: no update in case of $basearch usage in url&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - add_repo is changed&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - add_repo_again is not changed&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gu"&gt;&amp;#64;&amp;#64; -180,6 +202,74 &amp;#64;&amp;#64;&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    state: absent&lt;span class="pygments-w"&gt;
 &lt;/span&gt;  register: remove_repo&lt;span class="pygments-w"&gt;

&lt;/span&gt;&lt;span class="pygments-gd"&gt;-- assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify repo was removed&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
 &lt;/span&gt;    that:&lt;span class="pygments-w"&gt;
 &lt;/span&gt;      - remove_repo is changed&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: add new repository via url to .repo file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  community.general.zypper_repository:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    repo: http://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Stable/openSUSE_Leap_{{ ansible_distribution_version }}/systemsmanagement:Uyuni:Stable.repo&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    state: present&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: added_by_repo_file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: get repository details from zypper&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  command: zypper lr systemsmanagement_Uyuni_Stable&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: get_repository_details_from_zypper&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify adding via .repo file was successful&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    that:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;added_by_repo_file is changed&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;get_repository_details_from_zypper.rc == 0&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;'/systemsmanagement:/Uyuni:/Stable/' in get_repository_details_from_zypper.stdout&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: add same repository via url to .repo file again to verify idempotency&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  community.general.zypper_repository:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    repo: http://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Stable/openSUSE_Leap_{{ ansible_distribution_version }}/systemsmanagement:Uyuni:Stable.repo&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    state: present&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: added_again_by_repo_file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify nothing was changed adding a repo with the same .repo file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    that:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - added_again_by_repo_file is not changed&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: remove repository via url to .repo file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  community.general.zypper_repository:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    repo: http://download.opensuse.org/repositories/systemsmanagement:/Uyuni:/Stable/openSUSE_Leap_{{ ansible_distribution_version }}/systemsmanagement:Uyuni:Stable.repo&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    state: absent&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: removed_by_repo_file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: get list of files in /etc/zypp/repos.d/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  command: ls /etc/zypp/repos.d/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  changed_when: false&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: etc_zypp_reposd&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify removal via .repo file was successful, including cleanup of local .repo file in /etc/zypp/repos.d/&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    that:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;removed_by_repo_file&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;'/systemsmanagement:/Uyuni:/Stable/' not in etc_zypp_reposd.stdout&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: Copy test .repo file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  copy:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    src: 'files/systemsmanagement_Uyuni_Utils.repo'&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    dest: '{{ remote_tmp_dir }}'&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: add new repository via local path to .repo file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  community.general.zypper_repository:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    repo: &amp;quot;{{ remote_tmp_dir }}/systemsmanagement_Uyuni_Utils.repo&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    state: present&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: added_by_repo_local_file&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: get repository details for systemsmanagement_Uyuni_Utils from zypper&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  command: zypper lr systemsmanagement_Uyuni_Utils&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  register: get_repository_details_from_zypper_for_systemsmanagement_Uyuni_Utils&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+- name: verify adding repository via local .repo file was successful&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+  assert:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+    that:&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;added_by_repo_local_file is changed&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;get_repository_details_from_zypper_for_systemsmanagement_Uyuni_Utils.rc == 0&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;&lt;span class="pygments-gi"&gt;+      - &amp;quot;'/systemsmanagement:/Uyuni:/Utils/' in get_repository_details_from_zypper_for_systemsmanagement_Uyuni_Utils.stdout&amp;quot;&lt;/span&gt;&lt;span class="pygments-w"&gt;
&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Code"/><category term="Ansible"/><category term="Contribution"/><category term="Community"/><category term="Hackathon"/></entry><entry><title>Red Hat Certified Specialist in Advanced Automation: Ansible Best Practices - Ansible 2.8, Tower 3.5 &amp; Enterprise Linux 8</title><link href="https://dominik.wombacher.cc/posts/red-hat-certified-specialist-in-advanced-automation-ansible-best-practices-ansible-28-tower-35-rhel-8.html" rel="alternate"/><published>2021-06-01T00:00:00+02:00</published><updated>2022-12-30T00:00:00+01:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2021-06-01:/posts/red-hat-certified-specialist-in-advanced-automation-ansible-best-practices-ansible-28-tower-35-rhel-8.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;After passing the RHCSA and RHCE Exam already a few weeks ago, I also completed the Red Hat Exam &lt;em&gt;EX447&lt;/em&gt; today and earned the &lt;strong&gt;Red Hat Certified Specialist in Advanced  ... &lt;/strong&gt;&lt;a class="read-more" href="/posts/red-hat-certified-specialist-in-advanced-automation-ansible-best-practices-ansible-28-tower-35-rhel-8.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;After passing the RHCSA and RHCE Exam already a few weeks ago, I also completed the Red Hat Exam &lt;em&gt;EX447&lt;/em&gt; today and earned the &lt;strong&gt;Red Hat Certified Specialist in Advanced Automation: Ansible Best Practices&lt;/strong&gt; Certification.&lt;/p&gt;
&lt;p&gt;It was the next logical Step to finish the Ansible Track before moving on to other Specialist Exams on my way to become a Red Hat Certified Architect (RHCA) one day ;).&lt;/p&gt;
&lt;p&gt;Compared to the RHCE with a more or less 100% Ansible focus, EX447 was roughly 50% Ansible in more depth and 50% Ansible Tower.&lt;/p&gt;
&lt;p&gt;I'm using AWX, the Tower Upstream Project, for quite some time already, I think that expirience helped a lot.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: A Red Hat Certified Specialist in Advanced Automation: Ansible Best Practices is able to automate management of large or complex networks of machines. He demonstrate mastery of Ansible, knowledge of Ansible Tower and an understanding of Ansible best practices.&lt;/p&gt;
&lt;p&gt;Source &amp;amp; Copyright: &lt;a class="reference external" href="https://www.redhat.com"&gt;https://www.redhat.com&lt;/a&gt;&lt;/p&gt;
&lt;div class="section" id="skills"&gt;
&lt;h2&gt;Skills&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Understand and use Git to manage collections of playbooks&lt;/li&gt;
&lt;li&gt;Manage inventory variables&lt;/li&gt;
&lt;li&gt;Manage and Administer Ansible task execution&lt;/li&gt;
&lt;li&gt;Transform data with filters and plugins&lt;/li&gt;
&lt;li&gt;Delegate tasks&lt;/li&gt;
&lt;li&gt;Install Ansible Tower&lt;/li&gt;
&lt;li&gt;Manage access for Ansible Tower&lt;/li&gt;
&lt;li&gt;Manage inventories, advanced inventories and credentials&lt;/li&gt;
&lt;li&gt;Manage projects&lt;/li&gt;
&lt;li&gt;Manage job workflows&lt;/li&gt;
&lt;li&gt;Work with the Ansible Tower API&lt;/li&gt;
&lt;li&gt;Backup and Restore Ansible Tower&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Source &amp;amp; Copyright: &lt;a class="reference external" href="https://www.redhat.com"&gt;https://www.redhat.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="certificate"&gt;
&lt;h2&gt;Certificate&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Downloads&lt;ul&gt;
&lt;li&gt;&lt;a class="reference external" href="/certificates/Red_Hat_Certificate_RHCS_ansible_best_practices_Dominik_Wombacher.pdf"&gt;Certificate&lt;/a&gt; (PDF, 856.2K)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="/certificates/Red_Hat_Certificate_RHCS_ansible_best_practices_Dominik_Wombacher.png"&gt;Badge&lt;/a&gt; (PNG, 59.4K)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Links&lt;ul&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.credly.com/badges/80688745-a3b8-4d01-bce6-63fb2490e4af/public_url"&gt;Verify Credly Badge&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20221230161213/https://www.credly.com/badges/80688745-a3b8-4d01-bce6-63fb2490e4af/public_url"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.12.30-161426/https://www.credly.com/badges/80688745-a3b8-4d01-bce6-63fb2490e4af/public_url"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://rhtapps.redhat.com/certifications/badge/verify/YB2FOP3QSCV3PTZRLMFMRR54AUAEQU3CUPSQX2KSDXT6RW46LQ37KLSOOPEYMJDAE5EJIF3JZ6D665JFQCX7XVXXH5DT452GL3CMQ36Q77GFTUQMZCEY6URHUQ5UKSGZOKOWYMJRGQPNI2LHBGN6LLA2MI======"&gt;Verify Red Hat Badge&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20210609042040/https://rhtapps.redhat.com/certifications/badge/verify/YB2FOP3QSCV3PTZRLMFMRR54AUAEQU3CUPSQX2KSDXT6RW46LQ37KLSOOPEYMJDAE5EJIF3JZ6D665JFQCX7XVXXH5DT452GL3CMQ36Q77GFTUQMZCEY6URHUQ5UKSGZOKOWYMJRGQPNI2LHBGN6LLA2MI======"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2021.06.09-042129/https://rhtapps.redhat.com/certifications/badge/verify/YB2FOP3QSCV3PTZRLMFMRR54AUAEQU3CUPSQX2KSDXT6RW46LQ37KLSOOPEYMJDAE5EJIF3JZ6D665JFQCX7XVXXH5DT452GL3CMQ36Q77GFTUQMZCEY6URHUQ5UKSGZOKOWYMJRGQPNI2LHBGN6LLA2MI======"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://rhtapps.redhat.com/verify/?certId=210-065-546"&gt;Verify Certificate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Certification"/><category term="RedHat"/><category term="Certification"/><category term="Administration"/><category term="RHEL8"/><category term="Ansible"/><category term="Tower"/><category term="Exam"/></entry><entry><title>Red Hat Certified Engineer - Ansible 2.8 &amp; Enterprise Linux 8</title><link href="https://dominik.wombacher.cc/posts/red-hat-certified-engineer-ansible-28-rhel-8.html" rel="alternate"/><published>2021-05-25T00:00:00+02:00</published><updated>2022-12-30T00:00:00+01:00</updated><author><name>Dominik Wombacher</name></author><id>tag:dominik.wombacher.cc,2021-05-25:/posts/red-hat-certified-engineer-ansible-28-rhel-8.html</id><summary type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;Today I earned the &lt;strong&gt;Red Hat Certified Engineer&lt;/strong&gt; Certification by passing the Red Hat Exam &lt;em&gt;EX294&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It's the Version 8 RHCE Exam which quite differ from the "old" one by  ... &lt;a class="read-more" href="/posts/red-hat-certified-engineer-ansible-28-rhel-8.html"&gt; [read more]&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;!-- SPDX-FileCopyrightText: 2023 Dominik Wombacher &lt;dominik@wombacher.cc&gt; --&gt;
&lt;!--  --&gt;
&lt;!-- SPDX-License-Identifier: CC-BY-SA-4.0 --&gt;
&lt;p&gt;Today I earned the &lt;strong&gt;Red Hat Certified Engineer&lt;/strong&gt; Certification by passing the Red Hat Exam &lt;em&gt;EX294&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It's the Version 8 RHCE Exam which quite differ from the &amp;quot;old&amp;quot; one by focussing on Ansible.&lt;/p&gt;
&lt;p&gt;So during the performance-based Exam you have to create a lot of Ansible Playbooks and Roles to solve the Tasks. It's a tough Exam but fair and preparing for it improved my Ansible Skills a lot, even though I was using Ansible quite often within the last years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: A Red Hat® Certified Engineer (RHCE®) is a Red Hat Certified System Administrator (RHCSA) who is ready to automate Red Hat® Enterprise Linux® tasks, integrate Red Hat emerging technologies, and apply learned automation skills for efficiency and innovation.&lt;/p&gt;
&lt;p&gt;Source &amp;amp; Copyright: &lt;a class="reference external" href="https://www.redhat.com"&gt;https://www.redhat.com&lt;/a&gt;&lt;/p&gt;
&lt;div class="section" id="skills"&gt;
&lt;h2&gt;Skills&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Be able to perform all tasks expected of a Red Hat Certified System Administrator&lt;/li&gt;
&lt;li&gt;Understand core components of Ansible&lt;/li&gt;
&lt;li&gt;Install and configure an Ansible control node&lt;/li&gt;
&lt;li&gt;Configure Ansible managed nodes&lt;/li&gt;
&lt;li&gt;Script administration tasks&lt;/li&gt;
&lt;li&gt;Create Ansible plays and playbooks&lt;/li&gt;
&lt;li&gt;Use Ansible modules for system administration tasks&lt;/li&gt;
&lt;li&gt;Work with roles&lt;/li&gt;
&lt;li&gt;Use advanced Ansible features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Source &amp;amp; Copyright: &lt;a class="reference external" href="https://www.redhat.com"&gt;https://www.redhat.com&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="certificate"&gt;
&lt;h2&gt;Certificate&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Downloads&lt;ul&gt;
&lt;li&gt;&lt;a class="reference external" href="/certificates/Red_Hat_Certificate_RHCE-rhel_Dominik_Wombacher.pdf"&gt;Certificate&lt;/a&gt; (PDF, 855.9K)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="/certificates/Red_Hat_Certificate_RHCE-rhel_Dominik_Wombacher.png"&gt;Badge&lt;/a&gt; (PNG, 51.8K)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Links&lt;ul&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.credly.com/badges/9199278c-2a14-4c19-8319-fcc8425c4c43/public_url"&gt;Verify Credly Badge&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20221230161242/https://www.credly.com/badges/9199278c-2a14-4c19-8319-fcc8425c4c43/public_url"&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2022.12.30-161251/https://www.credly.com/badges/9199278c-2a14-4c19-8319-fcc8425c4c43/public_url"&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://rhtapps.redhat.com/certifications/badge/verify/YB2FOP3QSCV3PTZRLMFMRR54AUAEQU3CUPSQX2KSDXT6RW46LQ3XCZJWRJNV7ILTXVE4I6VB7OTCG4U5NQYTCNA62RUWOCM34WWBUYQ="&gt;Verify Red Hat Badge&lt;/a&gt;
(Archive: &lt;a class="reference external" href="https://web.archive.org/web/20210609042432/https://rhtapps.redhat.com/certifications/badge/verify/YB2FOP3QSCV3PTZRLMFMRR54AUAEQU3CUPSQX2KSDXT6RW46LQ3XCZJWRJNV7ILTXVE4I6VB7OTCG4U5NQYTCNA62RUWOCM34WWBUYQ="&gt;[1]&lt;/a&gt;,
&lt;a class="reference external" href="https://archive.today/2021.06.09-042435/https://rhtapps.redhat.com/certifications/badge/verify/YB2FOP3QSCV3PTZRLMFMRR54AUAEQU3CUPSQX2KSDXT6RW46LQ3XCZJWRJNV7ILTXVE4I6VB7OTCG4U5NQYTCNA62RUWOCM34WWBUYQ="&gt;[2]&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://rhtapps.redhat.com/verify/?certId=210-065-546"&gt;Verify Certificate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Certification"/><category term="RedHat"/><category term="Certification"/><category term="Administration"/><category term="RHEL8"/><category term="Ansible"/><category term="Exam"/></entry></feed>