diff --git a/.gitignore b/.gitignore index b080a56..1386e9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,28 @@ -SOURCES/ansible-posix-1.4.0.tar.gz -SOURCES/ansible-sshd-9766d9097a87a130d4c8abde2247aaad5c925ecf.tar.gz -SOURCES/auto-maintenance-c22eff88d40972158cd5c413b7468b4e904cc76c.tar.gz -SOURCES/certificate-1.1.6.tar.gz -SOURCES/cockpit-1.3.0.tar.gz -SOURCES/community-general-5.4.0.tar.gz -SOURCES/crypto_policies-1.2.6.tar.gz -SOURCES/firewall-1.4.0.tar.gz -SOURCES/ha_cluster-1.7.4.tar.gz -SOURCES/kdump-1.2.5.tar.gz -SOURCES/kernel_settings-1.1.10.tar.gz -SOURCES/logging-1.10.0.tar.gz -SOURCES/metrics-1.7.3.tar.gz -SOURCES/nbde_client-1.2.6.tar.gz -SOURCES/nbde_server-1.1.5.tar.gz -SOURCES/network-1.9.1.tar.gz -SOURCES/postfix-1.2.4.tar.gz -SOURCES/selinux-1.4.0.tar.gz -SOURCES/ssh-1.1.9.tar.gz -SOURCES/storage-1.9.1.tar.gz -SOURCES/timesync-1.6.9.tar.gz -SOURCES/tlog-1.2.9.tar.gz -SOURCES/vpn-1.3.5.tar.gz +SOURCES/ad_integration-1.0.2.tar.gz +SOURCES/ansible-posix-1.5.1.tar.gz +SOURCES/ansible-sshd-v0.18.1.tar.gz +SOURCES/auto-maintenance-d6a8e0167e9ed8d089093b7ead1e298241b534e1.tar.gz +SOURCES/certificate-1.1.9.tar.gz +SOURCES/cockpit-1.4.3.tar.gz +SOURCES/community-general-6.4.0.tar.gz +SOURCES/containers-podman-1.10.1.tar.gz +SOURCES/crypto_policies-1.2.7.tar.gz +SOURCES/firewall-1.4.2.tar.gz +SOURCES/ha_cluster-1.8.7.tar.gz +SOURCES/journald-1.0.0.tar.gz +SOURCES/kdump-1.2.6.tar.gz +SOURCES/kernel_settings-1.1.11.tar.gz +SOURCES/logging-1.11.5.tar.gz +SOURCES/metrics-1.8.1.tar.gz +SOURCES/nbde_client-1.2.10.tar.gz +SOURCES/nbde_server-1.3.3.tar.gz +SOURCES/network-1.11.2.tar.gz +SOURCES/podman-1.1.2.tar.gz +SOURCES/postfix-1.3.3.tar.gz +SOURCES/rhc-1.1.1.tar.gz +SOURCES/selinux-1.5.6.tar.gz +SOURCES/ssh-1.1.12.tar.gz +SOURCES/storage-1.9.6.tar.gz +SOURCES/timesync-1.7.2.tar.gz +SOURCES/tlog-1.2.11.tar.gz +SOURCES/vpn-1.5.3.tar.gz diff --git a/.rhel-system-roles.metadata b/.rhel-system-roles.metadata index 9b1ba8a..ed4a059 100644 --- a/.rhel-system-roles.metadata +++ b/.rhel-system-roles.metadata @@ -1,23 +1,28 @@ -bca451fd997be80be30f106e49f1bf550d2e609c SOURCES/ansible-posix-1.4.0.tar.gz -c47e62ecf6502d952378206626ba66e456a73513 SOURCES/ansible-sshd-9766d9097a87a130d4c8abde2247aaad5c925ecf.tar.gz -453a44d1259addc4f702ea79da7b810b420e21f1 SOURCES/auto-maintenance-c22eff88d40972158cd5c413b7468b4e904cc76c.tar.gz -25e2045c8fc9d6455d7c5b0c7d32d4976ebc5178 SOURCES/certificate-1.1.6.tar.gz -77b34cce8b416fec3a50900b47cbe6b8216e3036 SOURCES/cockpit-1.3.0.tar.gz -58f117fafe36a19425b3a9bc0ba69f33e5fa81ee SOURCES/community-general-5.4.0.tar.gz -56bc0763e0b549c3499a80e95d0953ee6769136a SOURCES/crypto_policies-1.2.6.tar.gz -4ee58deb2a514edd81dbcc56508be4ca9fd49089 SOURCES/firewall-1.4.0.tar.gz -6ac7fbfa996fd4425415601d28e5b7b0790682ae SOURCES/ha_cluster-1.7.4.tar.gz -6ae0614d51db00957943fad6967674c0de88862c SOURCES/kdump-1.2.5.tar.gz -17f28f701d7842499b232a7b28daae5f51ea631b SOURCES/kernel_settings-1.1.10.tar.gz -042ba1183db4d36742a21c92111d68415c7c951a SOURCES/logging-1.10.0.tar.gz -4ebbf457b9f0d767d19b7ef322b848e5e4da50ef SOURCES/metrics-1.7.3.tar.gz -80baf489aea9052ad11c84df7a6adfca75ce7a7b SOURCES/nbde_client-1.2.6.tar.gz -2e2ad1b455da8c0a198524a08ffe16f2c954f131 SOURCES/nbde_server-1.1.5.tar.gz -cb01d5d59afdf4f514de5fda2220ea8271ecb699 SOURCES/network-1.9.1.tar.gz -4a31ac4e7d4de65c2a74cfc6f3c4ff852d5a578c SOURCES/postfix-1.2.4.tar.gz -a54aee1fa1b0ee023e4168d0abe880ad6ea64dcb SOURCES/selinux-1.4.0.tar.gz -fcdbd369bcc41df028f842e49ebff28370d3adb4 SOURCES/ssh-1.1.9.tar.gz -10b9bf8f3b16fc99d6070af6dbf82f9f889a8ff6 SOURCES/storage-1.9.1.tar.gz -c0af2701a0f8db1d721bf6df4ba257888be0fe87 SOURCES/timesync-1.6.9.tar.gz -53fd0059c1da4c42228a9c0df592a96cd5a5060f SOURCES/tlog-1.2.9.tar.gz -ec3e9a88af360861ea3ef4be92fbb6776690272d SOURCES/vpn-1.3.5.tar.gz +c531e83edf95f96389a6c1c10ea80ccd2b42cc75 SOURCES/ad_integration-1.0.2.tar.gz +f36cb7b1662ecda55c27f5bc15e0a22a1f11a361 SOURCES/ansible-posix-1.5.1.tar.gz +71c988d6ad9b916727cd93b8e2a2154183f5035a SOURCES/ansible-sshd-v0.18.1.tar.gz +a59d5ba01d5e536e800bc847528f16c16b961375 SOURCES/auto-maintenance-d6a8e0167e9ed8d089093b7ead1e298241b534e1.tar.gz +0e3826af628625ef7b16e3f57b6156128fd982c0 SOURCES/certificate-1.1.9.tar.gz +05148744a2d69d469dc3c678bb1a9fb9747dea26 SOURCES/cockpit-1.4.3.tar.gz +687a4e36e9d8f73a8a44a448da1c205eb0ce5f1c SOURCES/community-general-6.4.0.tar.gz +ccb070885fd455bb6e7f2b8ca050d40d30609fec SOURCES/containers-podman-1.10.1.tar.gz +47e3a2db8790c98fd5c09ab1887318b6ba56ce49 SOURCES/crypto_policies-1.2.7.tar.gz +1c414411b4960040eebcef2ddd528eea0b47f05f SOURCES/firewall-1.4.2.tar.gz +7cfd7d6fa2164fcb757a316e123cbe048f8f0ac9 SOURCES/ha_cluster-1.8.7.tar.gz +97edc58624de8ccb3f4b628a48811094a0dc1513 SOURCES/journald-1.0.0.tar.gz +439ea600c242c914c90933f287f3caf8c7869c12 SOURCES/kdump-1.2.6.tar.gz +49f4bc8f273339cde0cdecccffa7b902359b2601 SOURCES/kernel_settings-1.1.11.tar.gz +7fe83b26f954e55a282a4d5398e3064a7783a83a SOURCES/logging-1.11.5.tar.gz +e217af697b4e3205177360726f579d01b145be77 SOURCES/metrics-1.8.1.tar.gz +cf27267d3d54f1537ddda89f6d4db7abbe55b357 SOURCES/nbde_client-1.2.10.tar.gz +274986399c55eb35f281173621e75eb2d7ae00e6 SOURCES/nbde_server-1.3.3.tar.gz +857b1c3ea5a1a48dc964fb5c139861ba01c9e732 SOURCES/network-1.11.2.tar.gz +fe48a68775bcb87daf3f62ab58a1998ffaa4e6be SOURCES/podman-1.1.2.tar.gz +9244301089661fecca31dfee431b32d4876063be SOURCES/postfix-1.3.3.tar.gz +d96fbd17bc40b40787cc77be61499ea1b15e07fd SOURCES/rhc-1.1.1.tar.gz +bac983e0dcc5041a4c7d4d25849ed31aaf462df7 SOURCES/selinux-1.5.6.tar.gz +1bb35bc413249ce3209e471687afd60e0e25dddb SOURCES/ssh-1.1.12.tar.gz +0eea1b45136cb807740fa12435b02eccdb35a7ac SOURCES/storage-1.9.6.tar.gz +fefc5b4bd9635bb8fe70a9af9fc178cb5d3e8193 SOURCES/timesync-1.7.2.tar.gz +07c42ba749c110a87469a5c477579582c4d0c538 SOURCES/tlog-1.2.11.tar.gz +5b5ee7283092a16e9ec1aba47ee651274f784416 SOURCES/vpn-1.5.3.tar.gz diff --git a/SOURCES/0001-ssh-Add-final-version-of-the-option-RequiredRSASize-53.patch b/SOURCES/0001-ssh-Add-final-version-of-the-option-RequiredRSASize-53.patch deleted file mode 100644 index b8b9941..0000000 --- a/SOURCES/0001-ssh-Add-final-version-of-the-option-RequiredRSASize-53.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 1bda31d2d07ed9042b09b0596904dd4f317d8f48 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 26 Sep 2022 20:20:47 +0200 -Subject: [PATCH] Add final version of the option RequiredRSASize (#53) - -* Update source template to match generated template - -* Add final name of the RequiredRSASize parameter - -keeping the old version for backward compatibility. - -Upstream commit: -https://github.com/openssh/openssh-portable/commit/54b333d1 ---- - .dev-tools/10_top.j2 | 4 ++-- - .dev-tools/options_body | 1 + - templates/ssh_config.j2 | 3 +++ - 3 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/.dev-tools/10_top.j2 b/.dev-tools/10_top.j2 -index 99704bd..8411de8 100644 ---- a/.dev-tools/10_top.j2 -+++ b/.dev-tools/10_top.j2 -@@ -7,10 +7,10 @@ - {% elif value is sameas false %} - {{ key }} no - {% elif value is string or value is number %} --{{ key }} {{ value }} -+{{ key }} {{ value | string }} - {% else %} - {% for i in value %} --{{ key }} {{ i }} -+{{ key }} {{ i | string }} - {% endfor %} - {% endif %} - {% endif %} -diff --git a/.dev-tools/options_body b/.dev-tools/options_body -index 176879d..8cc382f 100644 ---- a/.dev-tools/options_body -+++ b/.dev-tools/options_body -@@ -84,6 +84,7 @@ RekeyLimit - RemoteCommand - RemoteForward - RequestTTY -+RequiredRSASize - RevokedHostKeys - RhostsRSAAuthentication - RSAAuthentication -diff --git a/templates/ssh_config.j2 b/templates/ssh_config.j2 -index fab57de..7f277c7 100644 ---- a/templates/ssh_config.j2 -+++ b/templates/ssh_config.j2 -@@ -119,6 +119,7 @@ Match {{ match["Condition"] }} - {{ render_option("RemoteCommand",match["RemoteCommand"],true) -}} - {{ render_option("RemoteForward",match["RemoteForward"],true) -}} - {{ render_option("RequestTTY",match["RequestTTY"],true) -}} -+{{ render_option("RequiredRSASize",match["RequiredRSASize"],true) -}} - {{ render_option("RevokedHostKeys",match["RevokedHostKeys"],true) -}} - {{ render_option("RhostsRSAAuthentication",match["RhostsRSAAuthentication"],true) -}} - {{ render_option("RSAAuthentication",match["RSAAuthentication"],true) -}} -@@ -240,6 +241,7 @@ Host {{ host["Condition"] }} - {{ render_option("RemoteCommand",host["RemoteCommand"],true) -}} - {{ render_option("RemoteForward",host["RemoteForward"],true) -}} - {{ render_option("RequestTTY",host["RequestTTY"],true) -}} -+{{ render_option("RequiredRSASize",host["RequiredRSASize"],true) -}} - {{ render_option("RevokedHostKeys",host["RevokedHostKeys"],true) -}} - {{ render_option("RhostsRSAAuthentication",host["RhostsRSAAuthentication"],true) -}} - {{ render_option("RSAAuthentication",host["RSAAuthentication"],true) -}} -@@ -354,6 +356,7 @@ Host {{ host["Condition"] }} - {{ body_option("RemoteCommand",ssh_RemoteCommand) -}} - {{ body_option("RemoteForward",ssh_RemoteForward) -}} - {{ body_option("RequestTTY",ssh_RequestTTY) -}} -+{{ body_option("RequiredRSASize",ssh_RequiredRSASize) -}} - {{ body_option("RevokedHostKeys",ssh_RevokedHostKeys) -}} - {{ body_option("RhostsRSAAuthentication",ssh_RhostsRSAAuthentication) -}} - {{ body_option("RSAAuthentication",ssh_RSAAuthentication) -}} --- -2.37.3 - diff --git a/SOURCES/0001-sshd-Add-final-version-of-RequiredRSASize.patch b/SOURCES/0001-sshd-Add-final-version-of-RequiredRSASize.patch deleted file mode 100644 index e1072c2..0000000 --- a/SOURCES/0001-sshd-Add-final-version-of-RequiredRSASize.patch +++ /dev/null @@ -1,83 +0,0 @@ -From 1408f489240dca04f086e4b32b253313eea28ea8 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Mon, 26 Sep 2022 15:26:12 +0200 -Subject: [PATCH] Add final version of RequiredRSASize - -Keep the old version for backward compatibility - -Upstream commit: -https://github.com/openssh/openssh-portable/commit/1875042c ---- - meta/options_body | 1 + - meta/options_match | 1 + - templates/sshd_config.j2 | 2 ++ - templates/sshd_config_snippet.j2 | 2 ++ - 4 files changed, 6 insertions(+) - -diff --git a/meta/options_body b/meta/options_body -index 8681269..23a00f4 100644 ---- a/meta/options_body -+++ b/meta/options_body -@@ -89,6 +89,7 @@ PubkeyAuthentication - RSAAuthentication - RSAMinSize - RekeyLimit -+RequiredRSASize - RevokedKeys - RDomain - RhostsRSAAuthentication -diff --git a/meta/options_match b/meta/options_match -index 6ef9214..5ec1413 100644 ---- a/meta/options_match -+++ b/meta/options_match -@@ -47,6 +47,7 @@ PubkeyAuthentication - RDomain - RekeyLimit - RevokedKeys -+RequiredRSASize - RhostsRSAAuthentication - RSAAuthentication - RSAMinSize -diff --git a/templates/sshd_config.j2 b/templates/sshd_config.j2 -index 2899f0a..a3b2465 100644 ---- a/templates/sshd_config.j2 -+++ b/templates/sshd_config.j2 -@@ -89,6 +89,7 @@ Match {{ match["Condition"] }} - {{ render_option("RDomain",match["RDomain"],true) -}} - {{ render_option("RekeyLimit",match["RekeyLimit"],true) -}} - {{ render_option("RevokedKeys",match["RevokedKeys"],true) -}} -+{{ render_option("RequiredRSASize",match["RequiredRSASize"],true) -}} - {{ render_option("RhostsRSAAuthentication",match["RhostsRSAAuthentication"],true) -}} - {{ render_option("RSAAuthentication",match["RSAAuthentication"],true) -}} - {{ render_option("RSAMinSize",match["RSAMinSize"],true) -}} -@@ -203,6 +204,7 @@ Match {{ match["Condition"] }} - {{ body_option("RSAAuthentication",sshd_RSAAuthentication) -}} - {{ body_option("RSAMinSize",sshd_RSAMinSize) -}} - {{ body_option("RekeyLimit",sshd_RekeyLimit) -}} -+{{ body_option("RequiredRSASize",sshd_RequiredRSASize) -}} - {{ body_option("RevokedKeys",sshd_RevokedKeys) -}} - {{ body_option("RDomain",sshd_RDomain) -}} - {{ body_option("RhostsRSAAuthentication",sshd_RhostsRSAAuthentication) -}} -diff --git a/templates/sshd_config_snippet.j2 b/templates/sshd_config_snippet.j2 -index 0ece8ed..a12cb3b 100644 ---- a/templates/sshd_config_snippet.j2 -+++ b/templates/sshd_config_snippet.j2 -@@ -88,6 +88,7 @@ Match {{ match["Condition"] }} - {{ render_option("RDomain",match["RDomain"],true) -}} - {{ render_option("RekeyLimit",match["RekeyLimit"],true) -}} - {{ render_option("RevokedKeys",match["RevokedKeys"],true) -}} -+{{ render_option("RequiredRSASize",match["RequiredRSASize"],true) -}} - {{ render_option("RhostsRSAAuthentication",match["RhostsRSAAuthentication"],true) -}} - {{ render_option("RSAAuthentication",match["RSAAuthentication"],true) -}} - {{ render_option("RSAMinSize",match["RSAMinSize"],true) -}} -@@ -202,6 +203,7 @@ Match {{ match["Condition"] }} - {{ body_option("RSAAuthentication",sshd_RSAAuthentication) -}} - {{ body_option("RSAMinSize",sshd_RSAMinSize) -}} - {{ body_option("RekeyLimit",sshd_RekeyLimit) -}} -+{{ body_option("RequiredRSASize",sshd_RequiredRSASize) -}} - {{ body_option("RevokedKeys",sshd_RevokedKeys) -}} - {{ body_option("RDomain",sshd_RDomain) -}} - {{ body_option("RhostsRSAAuthentication",sshd_RhostsRSAAuthentication) -}} --- -2.37.3 - diff --git a/SOURCES/CHANGELOG.md b/SOURCES/CHANGELOG.md index 0530187..1974631 100644 --- a/SOURCES/CHANGELOG.md +++ b/SOURCES/CHANGELOG.md @@ -1,16 +1,52 @@ Changelog ========= -[1.20.1] - 2022-09-27 + +[1.21.1] - 2023-03-16 ---------------------------- ### New Features -- [ssh,sshd - Sync on final OpenSSH option name RequiredRSASize in ssh and sshd roles](https://bugzilla.redhat.com/show_bug.cgi?id=2129875) +- [rhc - New Role - Red Hat subscription management, insights management](https://bugzilla.redhat.com/show_bug.cgi?id=2144877) ### Bug Fixes - none +[1.21.0] - 2023-02-20 +---------------------------- + +### New Features + +- [ad_integration - [RFE] new role to support AD integration, join to AD domain](https://bugilla.redhat.com/show_bug.cgi?id=2144876) +- [cockpit - [RFE] convert cockpit role to use firewall, selinux role, and certificate role](https://bugzilla.redhat.com/show_bug.cgi?id=2137667) +- [ha_cluster - Allow quorum device configuration](https://bugzilla.redhat.com/show_bug.cgi?id=2143814) +- [ha_cluster - [RFE] convert ha_cluster role to use firewall, selinux and certificate role](https://bugzilla.redhat.com/show_bug.cgi?id=2130019) +- [journald - New role - journald - manage systemd-journald](https://bugzilla.redhat.com/show_bug.cgi?id=2165176) +- [logging - [RFE] convert logging role to use firewall, selinux role, and certificate role](https://bugzilla.redhat.com/show_bug.cgi?id=2130362) +- [metrics - [RFE] convert metrics role to use firewall and selinux role](https://bugzilla.redhat.com/show_bug.cgi?id=2133532) +- [nbde_server - [RFE] convert nbde_server role to use firewall and selinux role](https://bugzilla.redhat.com/show_bug.cgi?id=2133931) +- [network - Support cloned MAC address](https://bugzilla.redhat.com/show_bug.cgi?id=2143458) +- [network - [RFE] Support setting the metric of the default route for initscripts provider](https://bugzilla.redhat.com/show_bug.cgi?id=2134201) +- [network - [RFE] Support the DNS priority](https://bugzilla.redhat.com/show_bug.cgi?id=2133856) +- [network - Support looking up named route table in routing rule](https://bugzilla.redhat.com/show_bug.cgi?id=2129620) +- [podman - [RFE] role for managing podman containers and systemd](https://bugzilla.redhat.com/show_bug.cgi?id=2066864) +- [postfix - [RFE] convert postfix role to use firewall and selinux role](https://bugzilla.redhat.com/show_bug.cgi?id=2130332) +- [selinux - add support for the 'local' parameter](https://bugzilla.redhat.com/show_bug.cgi?id=2143385) +- [vpn - Add parameters shared_key_content, ike, esp, type, leftid, rightid](https://bugzilla.redhat.com/show_bug.cgi?id=2119600) +- [vpn - [RFE] convert vpn role to use firewall and selinux role](https://bugzilla.redhat.com/show_bug.cgi?id=2130345) + +### Bug Fixes + +- [ha_cluster - Fix stonith watchdog timeout](https://bugzilla.redhat.com/show_bug.cgi?id=2167941) +- [ha_cluster - Allow enabled SBD on disabled cluster](https://bugzilla.redhat.com/show_bug.cgi?id=2153081) +- [ha_cluster - use no_log in tasks looping over pot. secret parameters](https://bugzilla.redhat.com/show_bug.cgi?id=2127497) +- [nbde_client - nbde_client_clevis fails with a traceback and prints sensitive data](https://bugzilla.redhat.com/show_bug.cgi?id=2159972) +- [nbde_client - must handle clevis-luks-askpass and clevis-luks-askpass@ systemd unit names](https://bugzilla.redhat.com/show_bug.cgi?id=2126960) +- [network - should route traffic via correct bond](https://bugzilla.redhat.com/show_bug.cgi?id=2168733) +- [selinux - managing modules is not idempotent](https://bugzilla.redhat.com/show_bug.cgi?id=2164879) +- [sshd,ssh,timesync - Unexpected templating type error - expected str instance, int found](https://bugzilla.redhat.com/show_bug.cgi?id=2143401) +- [tlog - Unconditionally enable the files provider](https://bugzilla.redhat.com/show_bug.cgi?id=2153080) + [1.20.0] - 2022-08-09 ---------------------------- diff --git a/SOURCES/CHANGELOG.rst b/SOURCES/CHANGELOG.rst new file mode 100644 index 0000000..cf9ac93 --- /dev/null +++ b/SOURCES/CHANGELOG.rst @@ -0,0 +1 @@ +See docs/CHANGELOG.md diff --git a/SOURCES/extrasources.inc b/SOURCES/extrasources.inc new file mode 100644 index 0000000..d2d3175 --- /dev/null +++ b/SOURCES/extrasources.inc @@ -0,0 +1,10 @@ +Source801: https://galaxy.ansible.com/download/ansible-posix-1.5.1.tar.gz +Source901: https://galaxy.ansible.com/download/community-general-6.4.0.tar.gz +Source902: https://galaxy.ansible.com/download/containers-podman-1.10.1.tar.gz + +Provides: bundled(ansible-collection(ansible.posix)) = 1.5.1 +Provides: bundled(ansible-collection(community.general)) = 6.4.0 +Provides: bundled(ansible-collection(containers.podman)) = 1.10.1 + +Source996: CHANGELOG.rst +Source998: collection_readme.sh diff --git a/SOURCES/network-disable-bondtests.diff b/SOURCES/network-disable-bondtests.diff deleted file mode 100644 index 81db978..0000000 --- a/SOURCES/network-disable-bondtests.diff +++ /dev/null @@ -1,65 +0,0 @@ -From d6c8319f52f3859b28044841063adf0013df878b Mon Sep 17 00:00:00 2001 -From: Rich Megginson -Date: Thu, 25 Mar 2021 13:57:45 -0600 -Subject: [PATCH 3/4] Patch53: network-disable-bondtests.diff - ---- - tests/playbooks/tests_bond.yml | 2 ++ - tests/playbooks/tests_bond_deprecated.yml | 2 ++ - tests/tests_bond_deprecated_initscripts.yml | 1 + - tests/tests_bond_initscripts.yml | 1 + - 4 files changed, 6 insertions(+) - -diff --git a/tests/playbooks/tests_bond.yml b/tests/playbooks/tests_bond.yml -index 1e45788..d3005a6 100644 ---- a/tests/playbooks/tests_bond.yml -+++ b/tests/playbooks/tests_bond.yml -@@ -8,6 +8,8 @@ - dhcp_interface1: test1 - port2_profile: bond0.1 - dhcp_interface2: test2 -+ tags: -+ - "tests::expfail" - tasks: - - name: "INIT Prepare setup" - debug: -diff --git a/tests/playbooks/tests_bond_deprecated.yml b/tests/playbooks/tests_bond_deprecated.yml -index f37e19a..ae475c4 100644 ---- a/tests/playbooks/tests_bond_deprecated.yml -+++ b/tests/playbooks/tests_bond_deprecated.yml -@@ -8,6 +8,8 @@ - dhcp_interface1: test1 - port2_profile: bond0.1 - dhcp_interface2: test2 -+ tags: -+ - "tests::expfail" - tasks: - - name: "INIT Prepare setup" - debug: -diff --git a/tests/tests_bond_deprecated_initscripts.yml b/tests/tests_bond_deprecated_initscripts.yml -index 383b488..cdf3de0 100644 ---- a/tests/tests_bond_deprecated_initscripts.yml -+++ b/tests/tests_bond_deprecated_initscripts.yml -@@ -10,6 +10,7 @@ - network_provider: initscripts - tags: - - always -+ - "tests::expfail" - - - import_playbook: playbooks/tests_bond_deprecated.yml - when: (ansible_distribution in ['CentOS','RedHat'] and -diff --git a/tests/tests_bond_initscripts.yml b/tests/tests_bond_initscripts.yml -index 8fa74c5..6a231c4 100644 ---- a/tests/tests_bond_initscripts.yml -+++ b/tests/tests_bond_initscripts.yml -@@ -10,6 +10,7 @@ - network_provider: initscripts - tags: - - always -+ - "tests::expfail" - - - import_playbook: playbooks/tests_bond.yml - when: (ansible_distribution in ['CentOS','RedHat'] and --- -2.30.2 - diff --git a/SOURCES/redhat_subscription.py b/SOURCES/redhat_subscription.py new file mode 100644 index 0000000..2995e5a --- /dev/null +++ b/SOURCES/redhat_subscription.py @@ -0,0 +1,1187 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) James Laska (jlaska@redhat.com) +# +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: redhat_subscription +short_description: Manage registration and subscriptions to RHSM using C(subscription-manager) +description: + - Manage registration and subscription to the Red Hat Subscription Management entitlement platform using the C(subscription-manager) command, + registering using D-Bus if possible. +author: "Barnaby Court (@barnabycourt)" +notes: + - In order to register a system, subscription-manager requires either a username and password, or an activationkey and an Organization ID. + - Since 2.5 values for I(server_hostname), I(server_insecure), I(rhsm_baseurl), + I(server_proxy_hostname), I(server_proxy_port), I(server_proxy_user) and + I(server_proxy_password) are no longer taken from the C(/etc/rhsm/rhsm.conf) + config file and default to None. +requirements: + - subscription-manager + - Optionally the C(dbus) Python library; this is usually included in the OS + as it is used by C(subscription-manager). +extends_documentation_fragment: + - community.general.attributes +attributes: + check_mode: + support: none + diff_mode: + support: none +options: + state: + description: + - whether to register and subscribe (C(present)), or unregister (C(absent)) a system + choices: [ "present", "absent" ] + default: "present" + type: str + username: + description: + - access.redhat.com or Red Hat Satellite or Katello username + type: str + password: + description: + - access.redhat.com or Red Hat Satellite or Katello password + type: str + token: + description: + - sso.redhat.com API access token. + type: str + version_added: 6.3.0 + server_hostname: + description: + - Specify an alternative Red Hat Subscription Management or Red Hat Satellite or Katello server + type: str + server_insecure: + description: + - Enable or disable https server certificate verification when connecting to C(server_hostname) + type: str + server_prefix: + description: + - Specify the prefix when registering to the Red Hat Subscription Management or Red Hat Satellite or Katello server. + type: str + version_added: 3.3.0 + server_port: + description: + - Specify the port when registering to the Red Hat Subscription Management or Red Hat Satellite or Katello server. + type: str + version_added: 3.3.0 + rhsm_baseurl: + description: + - Specify CDN baseurl + type: str + rhsm_repo_ca_cert: + description: + - Specify an alternative location for a CA certificate for CDN + type: str + server_proxy_hostname: + description: + - Specify an HTTP proxy hostname. + type: str + server_proxy_scheme: + description: + - Specify an HTTP proxy scheme, for example C(http) or C(https). + type: str + version_added: 6.2.0 + server_proxy_port: + description: + - Specify an HTTP proxy port. + type: str + server_proxy_user: + description: + - Specify a user for HTTP proxy with basic authentication + type: str + server_proxy_password: + description: + - Specify a password for HTTP proxy with basic authentication + type: str + auto_attach: + description: + - Upon successful registration, auto-consume available subscriptions + - Added in favor of deprecated autosubscribe in 2.5. + type: bool + aliases: [autosubscribe] + activationkey: + description: + - supply an activation key for use with registration + type: str + org_id: + description: + - Organization ID to use in conjunction with activationkey + type: str + environment: + description: + - Register with a specific environment in the destination org. Used with Red Hat Satellite or Katello + type: str + pool: + description: + - | + Specify a subscription pool name to consume. Regular expressions accepted. Use I(pool_ids) instead if + possible, as it is much faster. Mutually exclusive with I(pool_ids). + default: '^$' + type: str + pool_ids: + description: + - | + Specify subscription pool IDs to consume. Prefer over I(pool) when possible as it is much faster. + A pool ID may be specified as a C(string) - just the pool ID (ex. C(0123456789abcdef0123456789abcdef)), + or as a C(dict) with the pool ID as the key, and a quantity as the value (ex. + C(0123456789abcdef0123456789abcdef: 2). If the quantity is provided, it is used to consume multiple + entitlements from a pool (the pool must support this). Mutually exclusive with I(pool). + default: [] + type: list + elements: raw + consumer_type: + description: + - The type of unit to register, defaults to system + type: str + consumer_name: + description: + - Name of the system to register, defaults to the hostname + type: str + consumer_id: + description: + - | + References an existing consumer ID to resume using a previous registration + for this system. If the system's identity certificate is lost or corrupted, + this option allows it to resume using its previous identity and subscriptions. + The default is to not specify a consumer ID so a new ID is created. + type: str + force_register: + description: + - Register the system even if it is already registered + type: bool + default: false + release: + description: + - Set a release version + type: str + syspurpose: + description: + - Set syspurpose attributes in file C(/etc/rhsm/syspurpose/syspurpose.json) + and synchronize these attributes with RHSM server. Syspurpose attributes help attach + the most appropriate subscriptions to the system automatically. When C(syspurpose.json) file + already contains some attributes, then new attributes overwrite existing attributes. + When some attribute is not listed in the new list of attributes, the existing + attribute will be removed from C(syspurpose.json) file. Unknown attributes are ignored. + type: dict + suboptions: + usage: + description: Syspurpose attribute usage + type: str + role: + description: Syspurpose attribute role + type: str + service_level_agreement: + description: Syspurpose attribute service_level_agreement + type: str + addons: + description: Syspurpose attribute addons + type: list + elements: str + sync: + description: + - When this option is true, then syspurpose attributes are synchronized with + RHSM server immediately. When this option is false, then syspurpose attributes + will be synchronized with RHSM server by rhsmcertd daemon. + type: bool + default: false +''' + +EXAMPLES = ''' +- name: Register as user (joe_user) with password (somepass) and auto-subscribe to available content. + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + auto_attach: true + +- name: Same as above but subscribe to a specific pool by ID. + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + pool_ids: 0123456789abcdef0123456789abcdef + +- name: Register and subscribe to multiple pools. + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + pool_ids: + - 0123456789abcdef0123456789abcdef + - 1123456789abcdef0123456789abcdef + +- name: Same as above but consume multiple entitlements. + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + pool_ids: + - 0123456789abcdef0123456789abcdef: 2 + - 1123456789abcdef0123456789abcdef: 4 + +- name: Register and pull existing system data. + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + consumer_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + +- name: Register with activationkey and consume subscriptions matching Red Hat Enterprise Server or Red Hat Virtualization + community.general.redhat_subscription: + state: present + activationkey: 1-222333444 + org_id: 222333444 + pool: '^(Red Hat Enterprise Server|Red Hat Virtualization)$' + +- name: Update the consumed subscriptions from the previous example (remove Red Hat Virtualization subscription) + community.general.redhat_subscription: + state: present + activationkey: 1-222333444 + org_id: 222333444 + pool: '^Red Hat Enterprise Server$' + +- name: Register as user credentials into given environment (against Red Hat Satellite or Katello), and auto-subscribe. + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + environment: Library + auto_attach: true + +- name: Register as user (joe_user) with password (somepass) and a specific release + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + release: 7.4 + +- name: Register as user (joe_user) with password (somepass), set syspurpose attributes and synchronize them with server + community.general.redhat_subscription: + state: present + username: joe_user + password: somepass + auto_attach: true + syspurpose: + usage: "Production" + role: "Red Hat Enterprise Server" + service_level_agreement: "Premium" + addons: + - addon1 + - addon2 + sync: true +''' + +RETURN = ''' +subscribed_pool_ids: + description: List of pool IDs to which system is now subscribed + returned: success + type: dict + sample: { + "8a85f9815ab905d3015ab928c7005de4": "1" + } +''' + +from os.path import isfile +from os import unlink +import re +import shutil +import tempfile +import json + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.text.converters import to_native +from ansible.module_utils.six.moves import configparser +from ansible.module_utils import distro + + +SUBMAN_CMD = None + + +class RegistrationBase(object): + + REDHAT_REPO = "/etc/yum.repos.d/redhat.repo" + + def __init__(self, module, username=None, password=None, token=None): + self.module = module + self.username = username + self.password = password + self.token = token + + def configure(self): + raise NotImplementedError("Must be implemented by a sub-class") + + def enable(self): + # Remove any existing redhat.repo + if isfile(self.REDHAT_REPO): + unlink(self.REDHAT_REPO) + + def register(self): + raise NotImplementedError("Must be implemented by a sub-class") + + def unregister(self): + raise NotImplementedError("Must be implemented by a sub-class") + + def unsubscribe(self): + raise NotImplementedError("Must be implemented by a sub-class") + + def update_plugin_conf(self, plugin, enabled=True): + plugin_conf = '/etc/yum/pluginconf.d/%s.conf' % plugin + + if isfile(plugin_conf): + tmpfd, tmpfile = tempfile.mkstemp() + shutil.copy2(plugin_conf, tmpfile) + cfg = configparser.ConfigParser() + cfg.read([tmpfile]) + + if enabled: + cfg.set('main', 'enabled', '1') + else: + cfg.set('main', 'enabled', '0') + + fd = open(tmpfile, 'w+') + cfg.write(fd) + fd.close() + self.module.atomic_move(tmpfile, plugin_conf) + + def subscribe(self, **kwargs): + raise NotImplementedError("Must be implemented by a sub-class") + + +class Rhsm(RegistrationBase): + def __init__(self, module, username=None, password=None, token=None): + RegistrationBase.__init__(self, module, username, password, token) + self.module = module + + def enable(self): + ''' + Enable the system to receive updates from subscription-manager. + This involves updating affected yum plugins and removing any + conflicting yum repositories. + ''' + RegistrationBase.enable(self) + self.update_plugin_conf('rhnplugin', False) + self.update_plugin_conf('subscription-manager', True) + + def configure(self, **kwargs): + ''' + Configure the system as directed for registration with RHSM + Raises: + * Exception - if error occurs while running command + ''' + + args = [SUBMAN_CMD, 'config'] + + # Pass supplied **kwargs as parameters to subscription-manager. Ignore + # non-configuration parameters and replace '_' with '.'. For example, + # 'server_hostname' becomes '--server.hostname'. + options = [] + for k, v in sorted(kwargs.items()): + if re.search(r'^(server|rhsm)_', k) and v is not None: + options.append('--%s=%s' % (k.replace('_', '.', 1), v)) + + # When there is nothing to configure, then it is not necessary + # to run config command, because it only returns current + # content of current configuration file + if len(options) == 0: + return + + args.extend(options) + + self.module.run_command(args, check_rc=True) + + @property + def is_registered(self): + ''' + Determine whether the current system + Returns: + * Boolean - whether the current system is currently registered to + RHSM. + ''' + + args = [SUBMAN_CMD, 'identity'] + rc, stdout, stderr = self.module.run_command(args, check_rc=False) + if rc == 0: + return True + else: + return False + + def _can_connect_to_dbus(self): + """ + Checks whether it is possible to connect to the system D-Bus bus. + + :returns: bool -- whether it is possible to connect to the system D-Bus bus. + """ + + try: + # Technically speaking, subscription-manager uses dbus-python + # as D-Bus library, so this ought to work; better be safe than + # sorry, I guess... + import dbus + except ImportError: + self.module.debug('dbus Python module not available, will use CLI') + return False + + try: + bus = dbus.SystemBus() + msg = dbus.lowlevel.SignalMessage('/', 'com.example', 'test') + bus.send_message(msg) + bus.flush() + + except dbus.exceptions.DBusException as e: + self.module.debug('Failed to connect to system D-Bus bus, will use CLI: %s' % e) + return False + + self.module.debug('Verified system D-Bus bus as usable') + return True + + def register(self, username, password, token, auto_attach, activationkey, org_id, + consumer_type, consumer_name, consumer_id, force_register, environment, + release): + ''' + Register the current system to the provided RHSM or Red Hat Satellite + or Katello server + + Raises: + * Exception - if any error occurs during the registration + ''' + # There is no support for token-based registration in the D-Bus API + # of rhsm, so always use the CLI in that case. + if not token and self._can_connect_to_dbus(): + self._register_using_dbus(username, password, auto_attach, + activationkey, org_id, consumer_type, + consumer_name, consumer_id, + force_register, environment, release) + return + self._register_using_cli(username, password, token, auto_attach, + activationkey, org_id, consumer_type, + consumer_name, consumer_id, + force_register, environment, release) + + def _register_using_cli(self, username, password, token, auto_attach, + activationkey, org_id, consumer_type, consumer_name, + consumer_id, force_register, environment, release): + ''' + Register using the 'subscription-manager' command + + Raises: + * Exception - if error occurs while running command + ''' + args = [SUBMAN_CMD, 'register'] + + # Generate command arguments + if force_register: + args.extend(['--force']) + + if org_id: + args.extend(['--org', org_id]) + + if auto_attach: + args.append('--auto-attach') + + if consumer_type: + args.extend(['--type', consumer_type]) + + if consumer_name: + args.extend(['--name', consumer_name]) + + if consumer_id: + args.extend(['--consumerid', consumer_id]) + + if environment: + args.extend(['--environment', environment]) + + if activationkey: + args.extend(['--activationkey', activationkey]) + elif token: + args.extend(['--token', token]) + else: + if username: + args.extend(['--username', username]) + if password: + args.extend(['--password', password]) + + if release: + args.extend(['--release', release]) + + rc, stderr, stdout = self.module.run_command(args, check_rc=True, expand_user_and_vars=False) + + def _register_using_dbus(self, username, password, auto_attach, + activationkey, org_id, consumer_type, consumer_name, + consumer_id, force_register, environment, release): + ''' + Register using D-Bus (connecting to the rhsm service) + + Raises: + * Exception - if error occurs during the D-Bus communication + ''' + import dbus + + SUBSCRIPTION_MANAGER_LOCALE = 'C' + # Seconds to wait for Registration to complete over DBus; + # 10 minutes should be a pretty generous timeout. + REGISTRATION_TIMEOUT = 600 + + def str2int(s, default=0): + try: + return int(s) + except ValueError: + return default + + distro_id = distro.id() + distro_version = tuple(str2int(p) for p in distro.version_parts()) + + # Stop the rhsm service when using systemd (which means Fedora or + # RHEL 7+): this is because the service may not use new configuration bits + # - with subscription-manager < 1.26.5-1 (in RHEL < 8.2); + # fixed later by https://github.com/candlepin/subscription-manager/pull/2175 + # - sporadically: https://bugzilla.redhat.com/show_bug.cgi?id=2049296 + if distro_id == 'fedora' or distro_version[0] >= 7: + cmd = ['systemctl', 'stop', 'rhsm'] + self.module.run_command(cmd, check_rc=True, expand_user_and_vars=False) + + # While there is a 'force' options for the registration, it is actually + # not implemented (and thus it does not work) + # - in RHEL 7 and earlier + # - in RHEL 8 before 8.8: https://bugzilla.redhat.com/show_bug.cgi?id=2118486 + # - in RHEL 9 before 9.2: https://bugzilla.redhat.com/show_bug.cgi?id=2121350 + # Hence, use it only when implemented, manually unregistering otherwise. + # Match it on RHEL, since we know about it; other distributions + # will need their own logic. + dbus_force_option_works = False + if (distro_id == 'rhel' and + ((distro_version[0] == 8 and distro_version[1] >= 8) or + (distro_version[0] == 9 and distro_version[1] >= 2) or + distro_version[0] > 9)): + dbus_force_option_works = True + + if force_register and not dbus_force_option_works: + self.unregister() + + register_opts = {} + if consumer_type: + register_opts['consumer_type'] = consumer_type + if consumer_name: + register_opts['name'] = consumer_name + if consumer_id: + register_opts['consumerid'] = consumer_id + if environment: + # The option for environments used to be 'environment' in versions + # of RHEL before 8.6, and then it changed to 'environments'; since + # the Register*() D-Bus functions reject unknown options, we have + # to pass the right option depending on the version -- funky. + environment_key = 'environment' + if distro_id == 'fedora' or \ + (distro_id == 'rhel' and + ((distro_version[0] == 8 and distro_version[1] >= 6) or + distro_version[0] >= 9)): + environment_key = 'environments' + register_opts[environment_key] = environment + if force_register and dbus_force_option_works: + register_opts['force'] = True + # Wrap it as proper D-Bus dict + register_opts = dbus.Dictionary(register_opts, signature='sv', variant_level=1) + + connection_opts = {} + # Wrap it as proper D-Bus dict + connection_opts = dbus.Dictionary(connection_opts, signature='sv', variant_level=1) + + bus = dbus.SystemBus() + register_server = bus.get_object('com.redhat.RHSM1', + '/com/redhat/RHSM1/RegisterServer') + address = register_server.Start( + SUBSCRIPTION_MANAGER_LOCALE, + dbus_interface='com.redhat.RHSM1.RegisterServer', + ) + + try: + # Use the private bus to register the system + self.module.debug('Connecting to the private DBus') + private_bus = dbus.connection.Connection(address) + + try: + if activationkey: + args = ( + org_id, + [activationkey], + register_opts, + connection_opts, + SUBSCRIPTION_MANAGER_LOCALE, + ) + private_bus.call_blocking( + 'com.redhat.RHSM1', + '/com/redhat/RHSM1/Register', + 'com.redhat.RHSM1.Register', + 'RegisterWithActivationKeys', + 'sasa{sv}a{sv}s', + args, + timeout=REGISTRATION_TIMEOUT, + ) + else: + args = ( + org_id or '', + username, + password, + register_opts, + connection_opts, + SUBSCRIPTION_MANAGER_LOCALE, + ) + private_bus.call_blocking( + 'com.redhat.RHSM1', + '/com/redhat/RHSM1/Register', + 'com.redhat.RHSM1.Register', + 'Register', + 'sssa{sv}a{sv}s', + args, + timeout=REGISTRATION_TIMEOUT, + ) + + except dbus.exceptions.DBusException as e: + # Sometimes we get NoReply but the registration has succeeded. + # Check the registration status before deciding if this is an error. + if e.get_dbus_name() == 'org.freedesktop.DBus.Error.NoReply': + if not self.is_registered(): + # Host is not registered so re-raise the error + raise + else: + raise + # Host was registered so continue + finally: + # Always shut down the private bus + self.module.debug('Shutting down private DBus instance') + register_server.Stop( + SUBSCRIPTION_MANAGER_LOCALE, + dbus_interface='com.redhat.RHSM1.RegisterServer', + ) + + # Make sure to refresh all the local data: this will fetch all the + # certificates, update redhat.repo, etc. + self.module.run_command([SUBMAN_CMD, 'refresh'], + check_rc=True, expand_user_and_vars=False) + + if auto_attach: + args = [SUBMAN_CMD, 'attach', '--auto'] + self.module.run_command(args, check_rc=True, expand_user_and_vars=False) + + # There is no support for setting the release via D-Bus, so invoke + # the CLI for this. + if release: + args = [SUBMAN_CMD, 'release', '--set', release] + self.module.run_command(args, check_rc=True, expand_user_and_vars=False) + + def unsubscribe(self, serials=None): + ''' + Unsubscribe a system from subscribed channels + Args: + serials(list or None): list of serials to unsubscribe. If + serials is none or an empty list, then + all subscribed channels will be removed. + Raises: + * Exception - if error occurs while running command + ''' + items = [] + if serials is not None and serials: + items = ["--serial=%s" % s for s in serials] + if serials is None: + items = ["--all"] + + if items: + args = [SUBMAN_CMD, 'remove'] + items + rc, stderr, stdout = self.module.run_command(args, check_rc=True) + return serials + + def unregister(self): + ''' + Unregister a currently registered system + Raises: + * Exception - if error occurs while running command + ''' + args = [SUBMAN_CMD, 'unregister'] + rc, stderr, stdout = self.module.run_command(args, check_rc=True) + self.update_plugin_conf('rhnplugin', False) + self.update_plugin_conf('subscription-manager', False) + + def subscribe(self, regexp): + ''' + Subscribe current system to available pools matching the specified + regular expression. It matches regexp against available pool ids first. + If any pool ids match, subscribe to those pools and return. + + If no pool ids match, then match regexp against available pool product + names. Note this can still easily match many many pools. Then subscribe + to those pools. + + Since a pool id is a more specific match, we only fallback to matching + against names if we didn't match pool ids. + + Raises: + * Exception - if error occurs while running command + ''' + # See https://github.com/ansible/ansible/issues/19466 + + # subscribe to pools whose pool id matches regexp (and only the pool id) + subscribed_pool_ids = self.subscribe_pool(regexp) + + # If we found any matches, we are done + # Don't attempt to match pools by product name + if subscribed_pool_ids: + return subscribed_pool_ids + + # We didn't match any pool ids. + # Now try subscribing to pools based on product name match + # Note: This can match lots of product names. + subscribed_by_product_pool_ids = self.subscribe_product(regexp) + if subscribed_by_product_pool_ids: + return subscribed_by_product_pool_ids + + # no matches + return [] + + def subscribe_by_pool_ids(self, pool_ids): + """ + Try to subscribe to the list of pool IDs + """ + available_pools = RhsmPools(self.module) + + available_pool_ids = [p.get_pool_id() for p in available_pools] + + for pool_id, quantity in sorted(pool_ids.items()): + if pool_id in available_pool_ids: + args = [SUBMAN_CMD, 'attach', '--pool', pool_id] + if quantity is not None: + args.extend(['--quantity', to_native(quantity)]) + rc, stderr, stdout = self.module.run_command(args, check_rc=True) + else: + self.module.fail_json(msg='Pool ID: %s not in list of available pools' % pool_id) + return pool_ids + + def subscribe_pool(self, regexp): + ''' + Subscribe current system to available pools matching the specified + regular expression + Raises: + * Exception - if error occurs while running command + ''' + + # Available pools ready for subscription + available_pools = RhsmPools(self.module) + + subscribed_pool_ids = [] + for pool in available_pools.filter_pools(regexp): + pool.subscribe() + subscribed_pool_ids.append(pool.get_pool_id()) + return subscribed_pool_ids + + def subscribe_product(self, regexp): + ''' + Subscribe current system to available pools matching the specified + regular expression + Raises: + * Exception - if error occurs while running command + ''' + + # Available pools ready for subscription + available_pools = RhsmPools(self.module) + + subscribed_pool_ids = [] + for pool in available_pools.filter_products(regexp): + pool.subscribe() + subscribed_pool_ids.append(pool.get_pool_id()) + return subscribed_pool_ids + + def update_subscriptions(self, regexp): + changed = False + consumed_pools = RhsmPools(self.module, consumed=True) + pool_ids_to_keep = [p.get_pool_id() for p in consumed_pools.filter_pools(regexp)] + pool_ids_to_keep.extend([p.get_pool_id() for p in consumed_pools.filter_products(regexp)]) + + serials_to_remove = [p.Serial for p in consumed_pools if p.get_pool_id() not in pool_ids_to_keep] + serials = self.unsubscribe(serials=serials_to_remove) + + subscribed_pool_ids = self.subscribe(regexp) + + if subscribed_pool_ids or serials: + changed = True + return {'changed': changed, 'subscribed_pool_ids': subscribed_pool_ids, + 'unsubscribed_serials': serials} + + def update_subscriptions_by_pool_ids(self, pool_ids): + changed = False + consumed_pools = RhsmPools(self.module, consumed=True) + + existing_pools = {} + serials_to_remove = [] + for p in consumed_pools: + pool_id = p.get_pool_id() + quantity_used = p.get_quantity_used() + existing_pools[pool_id] = quantity_used + + quantity = pool_ids.get(pool_id, 0) + if quantity is not None and quantity != quantity_used: + serials_to_remove.append(p.Serial) + + serials = self.unsubscribe(serials=serials_to_remove) + + missing_pools = {} + for pool_id, quantity in sorted(pool_ids.items()): + quantity_used = existing_pools.get(pool_id, 0) + if quantity is None and quantity_used == 0 or quantity not in (None, 0, quantity_used): + missing_pools[pool_id] = quantity + + self.subscribe_by_pool_ids(missing_pools) + + if missing_pools or serials: + changed = True + return {'changed': changed, 'subscribed_pool_ids': list(missing_pools.keys()), + 'unsubscribed_serials': serials} + + def sync_syspurpose(self): + """ + Try to synchronize syspurpose attributes with server + """ + args = [SUBMAN_CMD, 'status'] + rc, stdout, stderr = self.module.run_command(args, check_rc=False) + + +class RhsmPool(object): + ''' + Convenience class for housing subscription information + ''' + + def __init__(self, module, **kwargs): + self.module = module + for k, v in kwargs.items(): + setattr(self, k, v) + + def __str__(self): + return str(self.__getattribute__('_name')) + + def get_pool_id(self): + return getattr(self, 'PoolId', getattr(self, 'PoolID')) + + def get_quantity_used(self): + return int(getattr(self, 'QuantityUsed')) + + def subscribe(self): + args = "subscription-manager attach --pool %s" % self.get_pool_id() + rc, stdout, stderr = self.module.run_command(args, check_rc=True) + if rc == 0: + return True + else: + return False + + +class RhsmPools(object): + """ + This class is used for manipulating pools subscriptions with RHSM + """ + + def __init__(self, module, consumed=False): + self.module = module + self.products = self._load_product_list(consumed) + + def __iter__(self): + return self.products.__iter__() + + def _load_product_list(self, consumed=False): + """ + Loads list of all available or consumed pools for system in data structure + + Args: + consumed(bool): if True list consumed pools, else list available pools (default False) + """ + args = "subscription-manager list" + if consumed: + args += " --consumed" + else: + args += " --available" + lang_env = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C') + rc, stdout, stderr = self.module.run_command(args, check_rc=True, environ_update=lang_env) + + products = [] + for line in stdout.split('\n'): + # Remove leading+trailing whitespace + line = line.strip() + # An empty line implies the end of a output group + if len(line) == 0: + continue + # If a colon ':' is found, parse + elif ':' in line: + (key, value) = line.split(':', 1) + key = key.strip().replace(" ", "") # To unify + value = value.strip() + if key in ['ProductName', 'SubscriptionName']: + # Remember the name for later processing + products.append(RhsmPool(self.module, _name=value, key=value)) + elif products: + # Associate value with most recently recorded product + products[-1].__setattr__(key, value) + # FIXME - log some warning? + # else: + # warnings.warn("Unhandled subscription key/value: %s/%s" % (key,value)) + return products + + def filter_pools(self, regexp='^$'): + ''' + Return a list of RhsmPools whose pool id matches the provided regular expression + ''' + r = re.compile(regexp) + for product in self.products: + if r.search(product.get_pool_id()): + yield product + + def filter_products(self, regexp='^$'): + ''' + Return a list of RhsmPools whose product name matches the provided regular expression + ''' + r = re.compile(regexp) + for product in self.products: + if r.search(product._name): + yield product + + +class SysPurpose(object): + """ + This class is used for reading and writing to syspurpose.json file + """ + + SYSPURPOSE_FILE_PATH = "/etc/rhsm/syspurpose/syspurpose.json" + + ALLOWED_ATTRIBUTES = ['role', 'usage', 'service_level_agreement', 'addons'] + + def __init__(self, path=None): + """ + Initialize class used for reading syspurpose json file + """ + self.path = path or self.SYSPURPOSE_FILE_PATH + + def update_syspurpose(self, new_syspurpose): + """ + Try to update current syspurpose with new attributes from new_syspurpose + """ + syspurpose = {} + syspurpose_changed = False + for key, value in new_syspurpose.items(): + if key in self.ALLOWED_ATTRIBUTES: + if value is not None: + syspurpose[key] = value + elif key == 'sync': + pass + else: + raise KeyError("Attribute: %s not in list of allowed attributes: %s" % + (key, self.ALLOWED_ATTRIBUTES)) + current_syspurpose = self._read_syspurpose() + if current_syspurpose != syspurpose: + syspurpose_changed = True + # Update current syspurpose with new values + current_syspurpose.update(syspurpose) + # When some key is not listed in new syspurpose, then delete it from current syspurpose + # and ignore custom attributes created by user (e.g. "foo": "bar") + for key in list(current_syspurpose): + if key in self.ALLOWED_ATTRIBUTES and key not in syspurpose: + del current_syspurpose[key] + self._write_syspurpose(current_syspurpose) + return syspurpose_changed + + def _write_syspurpose(self, new_syspurpose): + """ + This function tries to update current new_syspurpose attributes to + json file. + """ + with open(self.path, "w") as fp: + fp.write(json.dumps(new_syspurpose, indent=2, ensure_ascii=False, sort_keys=True)) + + def _read_syspurpose(self): + """ + Read current syspurpuse from json file. + """ + current_syspurpose = {} + try: + with open(self.path, "r") as fp: + content = fp.read() + except IOError: + pass + else: + current_syspurpose = json.loads(content) + return current_syspurpose + + +def main(): + + # Load RHSM configuration from file + rhsm = Rhsm(None) + + # Note: the default values for parameters are: + # 'type': 'str', 'default': None, 'required': False + # So there is no need to repeat these values for each parameter. + module = AnsibleModule( + argument_spec={ + 'state': {'default': 'present', 'choices': ['present', 'absent']}, + 'username': {}, + 'password': {'no_log': True}, + 'token': {'no_log': True}, + 'server_hostname': {}, + 'server_insecure': {}, + 'server_prefix': {}, + 'server_port': {}, + 'rhsm_baseurl': {}, + 'rhsm_repo_ca_cert': {}, + 'auto_attach': {'aliases': ['autosubscribe'], 'type': 'bool'}, + 'activationkey': {'no_log': True}, + 'org_id': {}, + 'environment': {}, + 'pool': {'default': '^$'}, + 'pool_ids': {'default': [], 'type': 'list', 'elements': 'raw'}, + 'consumer_type': {}, + 'consumer_name': {}, + 'consumer_id': {}, + 'force_register': {'default': False, 'type': 'bool'}, + 'server_proxy_hostname': {}, + 'server_proxy_scheme': {}, + 'server_proxy_port': {}, + 'server_proxy_user': {}, + 'server_proxy_password': {'no_log': True}, + 'release': {}, + 'syspurpose': { + 'type': 'dict', + 'options': { + 'role': {}, + 'usage': {}, + 'service_level_agreement': {}, + 'addons': {'type': 'list', 'elements': 'str'}, + 'sync': {'type': 'bool', 'default': False} + } + } + }, + required_together=[['username', 'password'], + ['server_proxy_hostname', 'server_proxy_port'], + ['server_proxy_user', 'server_proxy_password']], + mutually_exclusive=[['activationkey', 'username'], + ['activationkey', 'token'], + ['token', 'username'], + ['activationkey', 'consumer_id'], + ['activationkey', 'environment'], + ['activationkey', 'auto_attach'], + ['pool', 'pool_ids']], + required_if=[['state', 'present', ['username', 'activationkey', 'token'], True]], + ) + + rhsm.module = module + state = module.params['state'] + username = module.params['username'] + password = module.params['password'] + token = module.params['token'] + server_hostname = module.params['server_hostname'] + server_insecure = module.params['server_insecure'] + server_prefix = module.params['server_prefix'] + server_port = module.params['server_port'] + rhsm_baseurl = module.params['rhsm_baseurl'] + rhsm_repo_ca_cert = module.params['rhsm_repo_ca_cert'] + auto_attach = module.params['auto_attach'] + activationkey = module.params['activationkey'] + org_id = module.params['org_id'] + if activationkey and not org_id: + module.fail_json(msg='org_id is required when using activationkey') + environment = module.params['environment'] + pool = module.params['pool'] + pool_ids = {} + for value in module.params['pool_ids']: + if isinstance(value, dict): + if len(value) != 1: + module.fail_json(msg='Unable to parse pool_ids option.') + pool_id, quantity = list(value.items())[0] + else: + pool_id, quantity = value, None + pool_ids[pool_id] = quantity + consumer_type = module.params["consumer_type"] + consumer_name = module.params["consumer_name"] + consumer_id = module.params["consumer_id"] + force_register = module.params["force_register"] + server_proxy_hostname = module.params['server_proxy_hostname'] + server_proxy_port = module.params['server_proxy_port'] + server_proxy_user = module.params['server_proxy_user'] + server_proxy_password = module.params['server_proxy_password'] + release = module.params['release'] + syspurpose = module.params['syspurpose'] + + global SUBMAN_CMD + SUBMAN_CMD = module.get_bin_path('subscription-manager', True) + + syspurpose_changed = False + if syspurpose is not None: + try: + syspurpose_changed = SysPurpose().update_syspurpose(syspurpose) + except Exception as err: + module.fail_json(msg="Failed to update syspurpose attributes: %s" % to_native(err)) + + # Ensure system is registered + if state == 'present': + + # Register system + if rhsm.is_registered and not force_register: + if syspurpose and 'sync' in syspurpose and syspurpose['sync'] is True: + try: + rhsm.sync_syspurpose() + except Exception as e: + module.fail_json(msg="Failed to synchronize syspurpose attributes: %s" % to_native(e)) + if pool != '^$' or pool_ids: + try: + if pool_ids: + result = rhsm.update_subscriptions_by_pool_ids(pool_ids) + else: + result = rhsm.update_subscriptions(pool) + except Exception as e: + module.fail_json(msg="Failed to update subscriptions for '%s': %s" % (server_hostname, to_native(e))) + else: + module.exit_json(**result) + else: + if syspurpose_changed is True: + module.exit_json(changed=True, msg="Syspurpose attributes changed.") + else: + module.exit_json(changed=False, msg="System already registered.") + else: + try: + rhsm.enable() + rhsm.configure(**module.params) + rhsm.register(username, password, token, auto_attach, activationkey, org_id, + consumer_type, consumer_name, consumer_id, force_register, + environment, release) + if syspurpose and 'sync' in syspurpose and syspurpose['sync'] is True: + rhsm.sync_syspurpose() + if pool_ids: + subscribed_pool_ids = rhsm.subscribe_by_pool_ids(pool_ids) + elif pool != '^$': + subscribed_pool_ids = rhsm.subscribe(pool) + else: + subscribed_pool_ids = [] + except Exception as e: + module.fail_json(msg="Failed to register with '%s': %s" % (server_hostname, to_native(e))) + else: + module.exit_json(changed=True, + msg="System successfully registered to '%s'." % server_hostname, + subscribed_pool_ids=subscribed_pool_ids) + + # Ensure system is *not* registered + if state == 'absent': + if not rhsm.is_registered: + module.exit_json(changed=False, msg="System already unregistered.") + else: + try: + rhsm.unsubscribe() + rhsm.unregister() + except Exception as e: + module.fail_json(msg="Failed to unregister: %s" % to_native(e)) + else: + module.exit_json(changed=True, msg="System successfully unregistered from %s." % server_hostname) + + +if __name__ == '__main__': + main() diff --git a/SOURCES/spec-to-changelog-md.sh b/SOURCES/spec-to-changelog-md.sh deleted file mode 100644 index e69de29..0000000 diff --git a/SPECS/rhel-system-roles.spec b/SPECS/rhel-system-roles.spec index 28cc510..3575c39 100644 --- a/SPECS/rhel-system-roles.spec +++ b/SPECS/rhel-system-roles.spec @@ -3,14 +3,13 @@ # ansible-core as a build_dep on RHEL8 %if 0%{?fedora} || 0%{?rhel} >= 9 %bcond_without ansible -%global ansible_build_dep ansible-core >= 2.11.0 +%if 0%{?fedora} +BuildRequires: ansible-packaging %else -%if 0%{?rhel} && ! 0%{?epel} -%bcond_with ansible -%else -%bcond_without ansible -%global ansible_build_dep ansible >= 2.9.10 +BuildRequires: ansible-core >= 2.11.0 %endif +%else +%bcond_with ansible %endif %bcond_with collection_artifact @@ -30,23 +29,12 @@ Name: linux-system-roles %endif Url: https://github.com/linux-system-roles Summary: Set of interfaces for unified system management -Version: 1.20.1 +Version: 1.21.1 Release: 1%{?dist} -#Group: Development/Libraries License: GPLv3+ and MIT and BSD and Python -%global installbase %{_datadir}/linux-system-roles %global _pkglicensedir %{_licensedir}/%{name} -%global rolealtprefix linux-system-roles. -%global roleprefix %{name}. -%global roleinstprefix %{nil} -%global rolealtrelpath ../../linux-system-roles/ -%if 0%{?rhel} -%global roleinstprefix %{roleprefix} -%global installbase %{_datadir}/ansible/roles -%global rolealtrelpath %{nil} -%endif - +%global roleinstprefix %{name}. %if 0%{?rhel} %global collection_namespace redhat %global collection_name rhel_system_roles @@ -58,19 +46,25 @@ License: GPLv3+ and MIT and BSD and Python %global collection_version %{version} # Helper macros originally from macros.ansible by Igor Raits -# Not available on RHEL, so we must define those macros locally here without using ansible-galaxy - +# On RHEL, not available, so we must define those macros locally +# On Fedora, provided by ansible-packager # Not used (yet). Could be made to point to AH in RHEL - but what about CentOS Stream? #%%{!?ansible_collection_url:%%define ansible_collection_url() https://galaxy.ansible.com/%%{collection_namespace}/%%{collection_name}} - -%if 0%{?fedora} || 0%{?rhel} >= 8 -%{!?ansible_collection_files:%define ansible_collection_files %{_datadir}/ansible/collections/ansible_collections/%{collection_namespace}/} +%if 0%{?rhel} +Provides: ansible-collection(%{collection_namespace}.%{collection_name}) = %{collection_version} +%global ansible_collection_files %{_datadir}/ansible/collections/ansible_collections/%{collection_namespace}/ +%define ansible_roles_dir %{_datadir}/ansible/roles +%if %{without ansible} +# Untar and copy everything instead of galaxy-installing the built artifact when ansible is not available +%define ansible_collection_build() tar -cf %{_tmppath}/%{collection_namespace}-%{collection_name}-%{version}.tar.gz . +%define ansible_collection_install() mkdir -p %{buildroot}%{ansible_collection_files}%{collection_name}; (cd %{buildroot}%{ansible_collection_files}%{collection_name}; tar -xf %{_tmppath}/%{collection_namespace}-%{collection_name}-%{version}.tar.gz) %else -# Define undefined macro using "!?ansible_collection_files:..." does not work for rhel-7 -%if %{?ansible_collection_files:0}%{!?ansible_collection_files:1} -%define ansible_collection_files %{_datadir}/ansible/collections/ansible_collections/%{collection_namespace}/ +%define ansible_collection_build() ansible-galaxy collection build +%define ansible_collection_install() ansible-galaxy collection install -n -p %{buildroot}%{_datadir}/ansible/collections %{collection_namespace}-%{collection_name}-%{version}.tar.gz %endif %endif +# be compatible with the usual Fedora Provides: +Provides: ansible-collection-%{collection_namespace}-%{collection_name} = %{collection_version}-%{release} # ansible-core is in rhel 8.6 and later - default to ansible-core, but allow # the use of ansible if present - we may revisit this if the automatic dependency @@ -83,18 +77,6 @@ License: GPLv3+ and MIT and BSD and Python Requires: (ansible-core >= 2.11.0 or ansible >= 2.9.0) %endif -%if %{with ansible} -BuildRequires: %{ansible_build_dep} -%endif - -%if %{without ansible} -# We don't have ansible-galaxy. -# Simply copy everything instead of galaxy-installing the built artifact. -%define ansible_collection_build_install() tar -cf %{_tmppath}/%{collection_namespace}-%{collection_name}-%{version}.tar.gz .; mkdir -p %{buildroot}%{ansible_collection_files}%{collection_name}; (cd %{buildroot}%{ansible_collection_files}%{collection_name}; tar -xf %{_tmppath}/%{collection_namespace}-%{collection_name}-%{version}.tar.gz) -%else -%define ansible_collection_build_install() ansible-galaxy collection build; ansible-galaxy collection install -n -p %{buildroot}%{_datadir}/ansible/collections %{collection_namespace}-%{collection_name}-%{version}.tar.gz -%endif - # For each role, call either defcommit() or deftag(). The other macros # (%%id and %%shortid) can be then used in the same way in both cases. # This way the rest of the spec file des not need to know whether we are @@ -125,88 +107,84 @@ BuildRequires: %{ansible_build_dep} %%global rolestodir %%{?rolestodir} %%{roletodir%{1}} } -#%%defcommit 1 14314822b529520ac12964e0d2938c4bb18ab895 +%global mainid d6a8e0167e9ed8d089093b7ead1e298241b534e1 +Source: %{url}/auto-maintenance/archive/%{mainid}/auto-maintenance-%{mainid}.tar.gz + +# BEGIN AUTOGENERATED SOURCES %global rolename1 postfix -%deftag 1 1.2.4 +%deftag 1 1.3.3 -#%%defcommit 2 9fe6eb36772e83b53dcfb8ceb73608fd4f72eeda %global rolename2 selinux -%deftag 2 1.4.0 +%deftag 2 1.5.6 -#%%defcommit 3 cbe4bf262bffae3bf53e531662237741954c4182 %global rolename3 timesync -%deftag 3 1.6.9 +%deftag 3 1.7.2 -#%%defcommit 4 02fc72b482e165472624b2f68eecd2ddce1d93b1 %global rolename4 kdump -%deftag 4 1.2.5 +%deftag 4 1.2.6 -#%%defcommit 5 a74092634adfe45f76cf761138abab1811692b4b %global rolename5 network -%deftag 5 1.9.1 +%deftag 5 1.11.2 -#%%defcommit 6 50d2b8ccc98a8f4cb9d1d550d21adc227181e9fa %global rolename6 storage -%deftag 6 1.9.1 +%deftag 6 1.9.6 -#%%defcommit 7 d57caa8ca506d8cbc7ca0f96f7cb62b7e965f163 %global rolename7 metrics -%deftag 7 1.7.3 +%deftag 7 1.8.1 -#%%defcommit 8 2b9e53233ee3a68bdb532e62f289733e436a6106 %global rolename8 tlog -%deftag 8 1.2.9 +%deftag 8 1.2.11 -#%%defcommit 9 9373303b98e09ef38df7afc8d06e5e55812096c7 %global rolename9 kernel_settings -%deftag 9 1.1.10 +%deftag 9 1.1.11 -#%%defcommit 10 20dd3e5520ca06dcccaa9b3f1fb428d055e0c23f %global rolename10 logging -%deftag 10 1.10.0 +%deftag 10 1.11.5 -#%%defcommit 11 c57d0b1f3384c525738fa26ba4bdca485e162567 %global rolename11 nbde_server -%deftag 11 1.1.5 +%deftag 11 1.3.3 -#%%defcommit 12 bef2fad5e365712d1f40e53662490ba2550a253f %global rolename12 nbde_client -%deftag 12 1.2.6 +%deftag 12 1.2.10 -#%%defcommit 13 310fc53db04e8d3134524afb7a89b0477a2ffb83 %global rolename13 certificate -%deftag 13 1.1.6 +%deftag 13 1.1.9 -#%%defcommit 14 b2a9857ac661fa32e66666e444b73bfdb34cdf95 %global rolename14 crypto_policies -%deftag 14 1.2.6 +%deftag 14 1.2.7 %global forgeorg15 https://github.com/willshersystems %global repo15 ansible-sshd %global rolename15 sshd -%defcommit 15 9766d9097a87a130d4c8abde2247aaad5c925ecf -#%%deftag 15 v0.15.1 +%deftag 15 v0.18.1 -#%%defcommit 16 59b9fd7b25607d8bd33bdb082748955f2652846a %global rolename16 ssh -%deftag 16 1.1.9 +%deftag 16 1.1.12 -#%%defcommit 17 f901239cb91878719c9e7461760ef8d4789d626d %global rolename17 ha_cluster -%deftag 17 1.7.4 +%deftag 17 1.8.7 -#%%defcommit 18 5f6cb73e6753fbdbb219b7d3079f0378b2d3bdb3 %global rolename18 vpn -%deftag 18 1.3.5 +%deftag 18 1.5.3 %global rolename19 firewall -%deftag 19 1.4.0 +%deftag 19 1.4.2 %global rolename20 cockpit -%deftag 20 1.3.0 +%deftag 20 1.4.3 + +%global rolename21 podman +%deftag 21 1.1.2 + +%global rolename22 ad_integration +%deftag 22 1.0.2 + +%global rolename23 rhc +%deftag 23 1.1.1 + +%global rolename24 journald +%deftag 24 1.0.0 -%global mainid c22eff88d40972158cd5c413b7468b4e904cc76c -Source: %{url}/auto-maintenance/archive/%{mainid}/auto-maintenance-%{mainid}.tar.gz Source1: %{archiveurl1} Source2: %{archiveurl2} Source3: %{archiveurl3} @@ -227,31 +205,19 @@ Source17: %{archiveurl17} Source18: %{archiveurl18} Source19: %{archiveurl19} Source20: %{archiveurl20} +Source21: %{archiveurl21} +Source22: %{archiveurl22} +Source23: %{archiveurl23} +Source24: %{archiveurl24} +# END AUTOGENERATED SOURCES -# Collection tarballs from Automation Hub -# Not used on Fedora. -Source801: ansible-posix-1.4.0.tar.gz +# Includes with definitions/tags that differ between RHEL and Fedora +Source2301: redhat_subscription.py +Source1001: extrasources.inc -# Collection tarballs from Galaxy -# Not used on Fedora. -Source901: community-general-5.4.0.tar.gz +%include %{SOURCE1001} -# changelog is auto generated on Fedora -Source996: CHANGELOG.md - -# Script to convert spec %changelog into collection CHANGELOG.md -# only used on Fedora -Source997: spec-to-changelog-md.sh - -# Script to convert the collection README to Automation Hub. -# Not used on Fedora. -Source998: collection_readme.sh - -Patch51: network-disable-bondtests.diff - -Patch1501: 0001-sshd-Add-final-version-of-RequiredRSASize.patch - -Patch1601: 0001-ssh-Add-final-version-of-the-option-RequiredRSASize-53.patch +Source995: CHANGELOG.md BuildArch: noarch @@ -268,22 +234,9 @@ BuildRequires: highlight # Requirements for galaxy_transform.py BuildRequires: python3 -%if 0%{?fedora} || 0%{?rhel} >= 8 -BuildRequires: %{py3_dist ruamel.yaml} -%else -BuildRequires: python3-ruamel-yaml -%endif +BuildRequires: python%{python3_pkgversion}-ruamel-yaml -Obsoletes: rhel-system-roles-techpreview < 1.0-3 - -%if %{undefined __ansible_provides} -Provides: ansible-collection(%{collection_namespace}.%{collection_name}) = %{collection_version} -%endif -# be compatible with the usual Fedora Provides: -Provides: ansible-collection-%{collection_namespace}-%{collection_name} = %{version}-%{release} - -# We need to put %%description within the if block to avoid empty -# lines showing up. +# We must put %%description within the if block to avoid empty lines showing up. %if 0%{?rhel} %description Collection of Ansible roles and modules that provide a stable and @@ -304,11 +257,32 @@ Summary: Collection artifact to import to Automation Hub / Ansible Galaxy Collection artifact for %{name}. This package contains %{collection_namespace}-%{collection_name}-%{version}.tar.gz %endif -%prep -%setup -q -a1 -a2 -a3 -a4 -a5 -a6 -a7 -a8 -a9 -a10 -a11 -a12 -a13 -a14 -a15 -a16 -a17 -a18 -a19 -a20 -n %{getarchivedir 0} +# Fix issue with package update introduce with changing symlink to directory +# in 1.21.1-5 +%pretrans -p +roles = { + "certificate", "cockpit", "crypto_policies", "firewall", "ha_cluster", + "kdump", "kernel_settings", "logging", "metrics", "nbde_client", + "nbde_server", "network", "postfix", "selinux", "ssh", "sshd", "storage", + "timesync", "tlog", "vpn" +} +for i,v in ipairs(roles) do + path = "/usr/share/ansible/roles/linux-system-roles." .. v + st = posix.stat(path) + if st and st.type == "link" then + os.remove(path) + end +end -for file in %_sourcedir/*.tar.gz; do - if [[ "$file" =~ %_sourcedir/([^-]+)-([^-]+)-(.+).tar.gz ]]; then +%prep +# BEGIN AUTOGENERATED SETUP +%setup -q -a1 -a2 -a3 -a4 -a5 -a6 -a7 -a8 -a9 -a10 -a11 -a12 -a13 -a14 -a15 -a16 -a17 -a18 -a19 -a20 -a21 -a22 -a23 -a24 -n %{getarchivedir 0} +# END AUTOGENERATED SETUP + +%if 0%{?rhel} +# Untar vendored collection tarballs to corresponding directories +for file in %{SOURCE801} %{SOURCE901} %{SOURCE902}; do + if [[ "$(basename $file)" =~ ([^-]+)-([^-]+)-(.+).tar.gz ]]; then ns=${BASH_REMATCH[1]} name=${BASH_REMATCH[2]} ver=${BASH_REMATCH[3]} @@ -318,6 +292,7 @@ for file in %_sourcedir/*.tar.gz; do popd > /dev/null fi done +%endif declare -A ROLESTODIR=(%{rolestodir}) for rolename in %{rolenames}; do @@ -334,16 +309,15 @@ for rolename in %{rolenames}; do mv "$dir_from_archive" ${rolename} done +%if 0%{?rhel} cd %{rolename2}/tests # this test causes avcs we want to ignore sed -r -i -e '/hosts: all/a\ tags:\ - tests::avc' tests_selinux_disabled.yml cd ../.. +%endif -cd %{rolename5} -%patch51 -p1 -cd .. cd %{rolename15} find -P tests examples -name \*.yml | while read file; do sed -r -i -e "s/ansible-sshd/linux-system-roles.sshd/" \ @@ -366,21 +340,13 @@ if [ "$rolesdir" != "$realrolesdir" ]; then fi cd .. -cd %{rolename15} -%patch1501 -p1 -cd .. - -cd %{rolename16} -%patch1601 -p1 -cd .. - %if 0%{?rhel} # Unpack tar.gz to retrieve to be vendored modules and place them in the roles library. # ansible.posix: # - library: # - Module selinux and seboolean for the selinux role # - Module mount for the storage role -declare -A module_map=( ["selinux.py"]="selinux" ["seboolean.py"]="selinux" ["mount.py"]="storage" ) +declare -A module_map=( ["selinux.py"]="selinux" ["seboolean.py"]="selinux" ["mount.py"]="storage" ) for module in "${!module_map[@]}"; do role="${module_map[${module}]}" if [ ! -d $role/library ]; then @@ -400,14 +366,15 @@ for module in "${!module_map[@]}"; do mkdir -p $role/module_utils/${role}_lsr fi cp -pL .external/ansible/posix/plugins/module_utils/$module $role/module_utils/${role}_lsr/$module - sed -i -e ':a;N;$!ba;s/description:\n\( *\)/description:\n\1- WARNING: Do not use this module directly! It is only for role internal use.\n\1/' $role/library/$module done # community.general: # - library: # - Module seport, sefcontext and selogin for the selinux role rolename2 # - Module ini_file for role tlog -module_map=( ["seport.py"]="selinux" ["sefcontext.py"]="selinux" ["selogin.py"]="selinux" ["ini_file.py"]="tlog" ) +# - rhc modules +module_map=( ["seport.py"]="selinux" ["sefcontext.py"]="selinux" ["selogin.py"]="selinux" ["ini_file.py"]="tlog" + ["redhat_subscription.py"]="rhc" ["rhsm_release.py"]="rhc" ["rhsm_repository.py"]="rhc" ) for module in "${!module_map[@]}"; do role="${module_map[${module}]}" if [ ! -d $role/library ]; then @@ -425,13 +392,56 @@ for module in "${!module_map[@]}"; do ls -alrtF $role/library/$module sed -i -e ':a;N;$!ba;s/description:\n\( *\)/description:\n\1- WARNING: Do not use this module directly! It is only for role internal use.\n\1/' $role/library/$module done -%endif + +# Fix until the updated redhat_subscription.py is in community.general +cp %{SOURCE2301} rhc/library/redhat_subscription.py +sed -i -e ':a;N;$!ba;s/description:\n\( *\)/description:\n\1- WARNING: Do not use this module directly! It is only for role internal use.\n\1/' rhc/library/redhat_subscription.py + +# containers.podman: +# - library: +# - Module podman_container_info, podman_image and podman_play for the podman role +module_map=( ["podman_container_info.py"]="podman" ["podman_image.py"]="podman" ["podman_play.py"]="podman" ) +for module in "${!module_map[@]}"; do + role="${module_map[${module}]}" + if [ ! -d $role/library ]; then + mkdir $role/library + fi + moduledir=.external/containers/podman/plugins/modules + cp -pL $moduledir/$module $role/library/$module + ls -alrtF $role/library/$module + sed -i -e ':a;N;$!ba;s/description:\n\( *\)/description:\n\1- WARNING: Do not use this module directly! It is only for role internal use.\n\1/' \ + -e "s/ansible_collections.containers.podman.plugins.module_utils.podman/ansible.module_utils.${role}_lsr/" \ + $role/library/$module +done + +# containers.podman: +# - module_utils: +# - Module_util common for the podman role +module_map=( ["common.py"]="podman" ) +for module in "${!module_map[@]}"; do + role="${module_map[${module}]}" + if [ ! -d $role/module_utils/${role}_lsr ]; then + mkdir -p $role/module_utils/${role}_lsr + fi + cp -pL .external/containers/podman/plugins/module_utils/podman/$module $role/module_utils/${role}_lsr/$module +done + +# remove the temporary .external directory after vendoring +rm -rf .external # Replacing "linux-system-roles.rolename" with "rhel-system-roles.rolename" in each role -%if "%{roleprefix}" != "linux-system-roles." +# Replacing "fedora.linux_system_roles." with "redhat.rhel_system_roles" in each role +# This is for the "roles calling other roles" case +# for podman, change the FQCN - using a non-FQCN module name doesn't seem to work, +# even for the legacy role format +# replace community.general for rhc for rolename in %{rolenames}; do find $rolename -type f -exec \ - sed "s/linux-system-roles[.]${rolename}\\>/%{roleprefix}${rolename}/g" -i {} \; + sed -e "s/linux-system-roles[.]${rolename}\\>/%{roleinstprefix}${rolename}/g" \ + -e "s/fedora[.]linux_system_roles[.]/%{collection_namespace}.%{collection_name}./g" \ + -e "s/containers[.]podman[.]/%{collection_namespace}.%{collection_name}./g" \ + -e "s/community[.]general[.]/%{collection_namespace}.%{collection_name}./g" \ + -i {} \; done %endif @@ -494,13 +504,20 @@ for role in %{rolenames}; do includes="$includes --include $role" %if 0%{?rhel} # we vendor-in all of the dependencies on rhel, so remove them - rm -f "$role/meta/requirements.yml" "$role/meta/collection-requirements.yml" + rm -f "$role/meta/requirements.yml" "$role/meta/collection-requirements.yml" \ + "$role/tests/collection-requirements.yml" %endif done -LANG=en_US.utf-8 LC_ALL=en_US.utf-8 python3 release_collection.py --galaxy-yml galaxy.yml \ +# do not process changelogs on RHEL +%if 0%{?rhel} +extra_mapping="--extra-mapping fedora.linux_system_roles:%{collection_namespace}.%{collection_name}" +%else +extra_mapping="" +%endif +LANG=C.utf-8 LC_ALL=C.utf-8 python3 release_collection.py --galaxy-yml galaxy.yml \ --src-path $(pwd) --dest-path $(pwd)/.collections $includes --force --no-update \ - --src-owner %{name} --skip-git --skip-check --debug + --src-owner %{name} --skip-git --skip-check --skip-changelog $extra_mapping --debug # Remove table of contents from logging README.md # It is not needed for html and AH/Galaxy @@ -516,51 +533,61 @@ for role in %{rolenames}; do .collections/ansible_collections/%{collection_namespace}/%{collection_name}/roles/$role/README.md done +# Remove test only collection dependencies +# NOTE: These should not be in meta/collection-requirements.yml, they should be +# in tests/collection-requirements.yml, but they can't be moved yet +sed -i -e '/community[.]mysql:/d' -e '/community[.]postgresql:/d' \ + .collections/ansible_collections/%{collection_namespace}/%{collection_name}/galaxy.yml + +cp %{SOURCE995} \ + .collections/ansible_collections/%{collection_namespace}/%{collection_name}/docs/CHANGELOG.md %if 0%{?rhel} cp %{SOURCE996} \ - .collections/ansible_collections/%{collection_namespace}/%{collection_name}/docs/CHANGELOG.md -%else -# Build the collection CHANGELOG.md -%{SOURCE997} %{_specdir}/%{name}.spec \ - .collections/ansible_collections/%{collection_namespace}/%{collection_name}/docs/CHANGELOG.md + .collections/ansible_collections/%{collection_namespace}/%{collection_name}/CHANGELOG.rst %endif +# Build the collection +pushd .collections/ansible_collections/%{collection_namespace}/%{collection_name}/ +%ansible_collection_build +popd + %install -mkdir -p $RPM_BUILD_ROOT%{installbase} -mkdir -p $RPM_BUILD_ROOT%{_datadir}/ansible/roles +mkdir -p %{buildroot}%{ansible_roles_dir} for role in %{rolenames}; do - cp -pR "$role" "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role" + cp -pR "$role" "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role" done -%if 0%{?rolealtprefix:1} +%if 0%{?rhel} +# Create symlinks for roles in /usr/share/ansible/roles/linux-system-roles.$rolename +# That's required to make roles work with upstream naming too for role in %{rolenames}; do - ln -s "%{rolealtrelpath}%{roleinstprefix}$role" "$RPM_BUILD_ROOT%{_datadir}/ansible/roles/%{rolealtprefix}$role" + ln -s "%{name}.$role" "%{buildroot}%{ansible_roles_dir}/linux-system-roles.$role" done %endif -mkdir -p $RPM_BUILD_ROOT%{_pkglicensedir} -rm $RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}network/examples/roles +mkdir -p %{buildroot}%{_pkglicensedir} +rm %{buildroot}%{ansible_roles_dir}/%{roleinstprefix}network/examples/roles for role in %{rolenames}; do - mkdir -p "$RPM_BUILD_ROOT%{_pkgdocdir}/$role" - cp -p "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/CHANGELOG.md" \ - "$RPM_BUILD_ROOT%{_pkgdocdir}/$role" - cp -p "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/README.md" \ - "$RPM_BUILD_ROOT%{_pkgdocdir}/$role" + mkdir -p "%{buildroot}%{_pkgdocdir}/$role" + ln -sr "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/CHANGELOG.md" \ + "%{buildroot}%{_pkgdocdir}/$role" + ln -sr "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/README.md" \ + "%{buildroot}%{_pkgdocdir}/$role" %if %{with html} - cp -p "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/README.html" \ - "$RPM_BUILD_ROOT%{_pkgdocdir}/$role" + ln -sr "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/README.html" \ + "%{buildroot}%{_pkgdocdir}/$role" %endif - if [ -f "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/COPYING" ]; then - cp -p "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/COPYING" \ - "$RPM_BUILD_ROOT%{_pkglicensedir}/$role.COPYING" + if [ -f "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/COPYING" ]; then + ln -sr "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/COPYING" \ + "%{buildroot}%{_pkglicensedir}/$role.COPYING" fi - if [ -f "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/LICENSE" ]; then - cp -p "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/LICENSE" \ - "$RPM_BUILD_ROOT%{_pkglicensedir}/$role.LICENSE" + if [ -f "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/LICENSE" ]; then + ln -sr "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/LICENSE" \ + "%{buildroot}%{_pkglicensedir}/$role.LICENSE" fi - if [ -d "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/examples" ]; then - for file in "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/examples/"*.yml ; do + if [ -d "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/examples" ]; then + for file in "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/examples/"*.yml ; do basename=$(basename "$file" .yml) newname="$basename" if [[ "$newname" != example-* ]]; then @@ -569,57 +596,58 @@ for role in %{rolenames}; do if [[ "$newname" != *-playbook ]]; then newname="${newname}-playbook" fi - cp "$file" "$RPM_BUILD_ROOT%{_pkgdocdir}/$role/${newname}.yml" + cp "$file" "%{buildroot}%{_pkgdocdir}/$role/${newname}.yml" rm "$file" done - if [ -f "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/examples/inventory" ]; then - cp "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/examples/inventory" \ - "$RPM_BUILD_ROOT%{_pkgdocdir}/$role/example-inventory" - rm "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/examples/inventory" + if [ -f "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/examples/inventory" ]; then + cp "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/examples/inventory" \ + "%{buildroot}%{_pkgdocdir}/$role/example-inventory" + rm "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/examples/inventory" fi # special case for network # this will error if the directory is unexpectedly empty - rmdir "$RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}$role/examples" + rmdir "%{buildroot}%{ansible_roles_dir}/%{roleinstprefix}$role/examples" fi done -rm $RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}*/semaphore -rm -r $RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}*/molecule +rm %{buildroot}%{ansible_roles_dir}/%{roleinstprefix}*/semaphore +rm -r %{buildroot}%{ansible_roles_dir}/%{roleinstprefix}*/molecule -rm -r $RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}*/.[A-Za-z]* -rm $RPM_BUILD_ROOT%{installbase}/%{roleinstprefix}*/tests/.git* +rm -r %{buildroot}%{ansible_roles_dir}/%{roleinstprefix}*/.[A-Za-z]* +rm %{buildroot}%{ansible_roles_dir}/%{roleinstprefix}*/tests/.git* # NOTE: sshd/examples/example-root-login.yml is # referenced in the configuring-openssh-servers-using-the-sshd-system-role documentation module # must be updated if changing the file path +# Install the collection pushd .collections/ansible_collections/%{collection_namespace}/%{collection_name}/ -%ansible_collection_build_install +%ansible_collection_install popd -mkdir -p $RPM_BUILD_ROOT%{_pkgdocdir}/collection -mkdir -p $RPM_BUILD_ROOT%{_pkgdocdir}/collection/roles +mkdir -p %{buildroot}%{_pkgdocdir}/collection +mkdir -p %{buildroot}%{_pkgdocdir}/collection/roles -cp -p %{buildroot}%{ansible_collection_files}%{collection_name}/README.md \ - $RPM_BUILD_ROOT%{_pkgdocdir}/collection +ln -sr %{buildroot}%{ansible_collection_files}%{collection_name}/README.md \ + %{buildroot}%{_pkgdocdir}/collection for rolename in %{rolenames}; do for file in CHANGELOG.md README.md; do if [ -f %{buildroot}%{ansible_collection_files}%{collection_name}/roles/${rolename}/$file ]; then - if [ ! -d $RPM_BUILD_ROOT%{_pkgdocdir}/collection/roles/${rolename} ]; then - mkdir -p $RPM_BUILD_ROOT%{_pkgdocdir}/collection/roles/${rolename} + if [ ! -d %{buildroot}%{_pkgdocdir}/collection/roles/${rolename} ]; then + mkdir -p %{buildroot}%{_pkgdocdir}/collection/roles/${rolename} fi - cp -p %{buildroot}%{ansible_collection_files}%{collection_name}/roles/${rolename}/$file \ - $RPM_BUILD_ROOT%{_pkgdocdir}/collection/roles/${rolename} + ln -sr %{buildroot}%{ansible_collection_files}%{collection_name}/roles/${rolename}/$file \ + %{buildroot}%{_pkgdocdir}/collection/roles/${rolename} fi done done %if %{with html} -# converting README.md to README.html for collection in $RPM_BUILD_ROOT%{_pkgdocdir}/collection -readmes="$RPM_BUILD_ROOT%{_pkgdocdir}/collection/README.md" +# converting README.md to README.html for collection in %%{buildroot}%%{_pkgdocdir}/collection +readmes="%{buildroot}%{_pkgdocdir}/collection/README.md" for role in %{rolenames}; do - readmes="${readmes} $RPM_BUILD_ROOT%{_pkgdocdir}/collection/roles/${role}/README.md" + readmes="${readmes} %{buildroot}%{_pkgdocdir}/collection/roles/${role}/README.md" done sh md2html.sh $readmes %endif @@ -627,21 +655,21 @@ sh md2html.sh $readmes %if %{with collection_artifact} # Copy collection artifact to /usr/share/ansible/collections/ for collection-artifact pushd .collections/ansible_collections/%{collection_namespace}/%{collection_name}/ -if [ -f %{collection_namespace}-%{collection_name}-%{version}.tar.gz ]; then mv %{collection_namespace}-%{collection_name}-%{version}.tar.gz \ - $RPM_BUILD_ROOT%{_datadir}/ansible/collections/ -fi + %{buildroot}%{_datadir}/ansible/collections/ popd %endif -# generate the %files section in the file files_section.txt +# Generate the %%files section in files_section.txt +# Bulk files inclusion is not possible because roles store doc and licence +# files together with other files format_item_for_files() { # $1 is directory or file name in buildroot - # $2 - if true, and item is a directory, use %dir + # $2 - if true, and item is a directory, use %%dir local item local files_item - item="$1" - files_item=${item##"%{buildroot}"} + item="$1" # full path including buildroot + files_item=${item##"%{buildroot}"} # path with cut buildroot to be added to %%files if [ -L "$item" ]; then echo "$files_item" elif [ -d "$item" ]; then @@ -654,14 +682,14 @@ format_item_for_files() { fi elif [[ "$item" == */README.md ]] || [[ "$item" == */README.html ]] || [[ "$item" == */CHANGELOG.md ]]; then if [[ "$item" == */private_* ]]; then - # mark as regular file, not %doc + # mark as regular file, not %%doc echo "$files_item" else echo "%doc $files_item" fi - elif [[ "$item" != */COPYING* ]] && [[ "$item" != */LICENSE* ]]; then - # Avoid dynamically using the license macro since the license macro - # is replaced with the value of License directive in the older rpmbuild. + elif [[ "$item" == */COPYING* ]] || [[ "$item" == */LICENSE* ]]; then + echo "%""%""license" "$files_item" + else echo "$files_item" fi } @@ -669,15 +697,7 @@ format_item_for_files() { files_section=files_section.txt rm -f $files_section touch $files_section -%if %{without ansible} -echo '%dir %{_datadir}/ansible' >> $files_section -echo '%dir %{_datadir}/ansible/roles' >> $files_section -%endif -%if "%{installbase}" != "%{_datadir}/ansible/roles" -echo '%dir %{installbase}' >> $files_section -%endif -echo '%dir %{ansible_collection_files}' >> $files_section -echo '%dir %{ansible_collection_files}%{collection_name}' >> $files_section +# Dynamically generate files section entries for %%{ansible_collection_files} find %{buildroot}%{ansible_collection_files}%{collection_name} -mindepth 1 -maxdepth 1 | \ while read item; do if [[ "$item" == */roles ]]; then @@ -693,7 +713,8 @@ find %{buildroot}%{ansible_collection_files}%{collection_name} -mindepth 1 -maxd fi done -find %{buildroot}%{installbase} -mindepth 1 -maxdepth 1 | \ +# Dynamically generate files section entries for %%{ansible_roles_dir} +find %{buildroot}%{ansible_roles_dir} -mindepth 1 -maxdepth 1 | \ while read item; do if [ -d "$item" ]; then format_item_for_files "$item" true >> $files_section @@ -704,48 +725,23 @@ find %{buildroot}%{installbase} -mindepth 1 -maxdepth 1 | \ format_item_for_files "$item" >> $files_section fi done -if [ "%{installbase}" != "%{_datadir}/ansible/roles" ]; then - find %{buildroot}%{_datadir}/ansible/roles -mindepth 1 -maxdepth 1 | \ - while read item; do - if [ -d "$item" ]; then - format_item_for_files "$item" true >> $files_section - find "$item" -mindepth 1 -maxdepth 1 | while read roles_item; do - format_item_for_files "$roles_item" >> $files_section - done - else - format_item_for_files "$item" >> $files_section - fi - done -fi -# cat files_section.txt -# done with files_section.txt generation - %files -f files_section.txt -%{_pkgdocdir}/*/CHANGELOG.md -%{_pkgdocdir}/*/README.md -%if %{with html} -%{_pkgdocdir}/*/README.html -%endif -%{_pkgdocdir}/*/example-* -%{_pkgdocdir}/collection/roles/*/CHANGELOG.md -%{_pkgdocdir}/collection/roles/*/README.md -%if %{with html} -%{_pkgdocdir}/collection/roles/*/README.html -%endif -%license %{_pkglicensedir}/* -%license %{installbase}/*/COPYING* -%license %{installbase}/*/LICENSE* -%license %{ansible_collection_files}/%{collection_name}/COPYING* -%license %{ansible_collection_files}/%{collection_name}/LICENSE* -%if 0%{?rhel} < 8 +%dir %{_datadir}/ansible +%dir %{ansible_roles_dir} +%dir %{ansible_collection_files} +%dir %{ansible_collection_files}%{collection_name} +%doc %{_pkgdocdir} +%license %{_pkglicensedir} + +%if 0%{?rhel} && 0%{?rhel} < 8 # Needs to list excluded files in this hardcoded style since when # format_item_for_files is executed, brp-python-bytecompile is not # executed yet. -%exclude %{installbase}/*/*.py? -%exclude %{installbase}/*/*/*.py? -%exclude %{installbase}/*/*/*/*.py? -%exclude %{installbase}/*/*/*/*/*.py? +%exclude %{ansible_roles_dir}/*/*.py? +%exclude %{ansible_roles_dir}/*/*/*.py? +%exclude %{ansible_roles_dir}/*/*/*/*.py? +%exclude %{ansible_roles_dir}/*/*/*/*/*.py? %exclude %{ansible_collection_files}/%{collection_name}/*/*/*.py? %exclude %{ansible_collection_files}/%{collection_name}/*/*/*/*.py? %exclude %{ansible_collection_files}/%{collection_name}/*/*/*/*/*.py? @@ -757,8 +753,110 @@ fi %endif %changelog -* Tue Sep 27 2022 Rich Megginson - 1.20.1-1 -- Resolves:rhbz#2129875 : ssh,sshd - Sync on final OpenSSH option name RequiredRSASize in ssh and sshd roles +* Thu Mar 16 2023 Rich Megginson - 1.21.1-1 +- Resolves:rhbz#2144877 : rhc - new role for subscription management/registration/insights +- includes the fix for tests_proxy.yml selinux and some test refactoring + +* Wed Feb 22 2023 Rich Megginson - 1.21.0-2 +- Resolves:rhbz#2144877 : rhc - new role for subscription management/registration/insights +- remove role until https://bugzilla.redhat.com/show_bug.cgi?id=2171829 is fixed + +* Mon Feb 20 2023 Rich Megginson - 1.21.0-1 +- Resolves:rhbz#2168733 : network - RedHat Role rhel-system-roles.network should route traffic via correct bond + +* Thu Feb 16 2023 Rich Megginson - 1.21.0-0.19 +- Resolves:rhbz#2144877 : rhc - new role for subscription management/registration/insights +- vendor in modules required by rhc role +- Resolves:rhbz#2167941 : ha_cluster - Fix stonith watchdog timeout + +* Wed Feb 15 2023 Rich Megginson - 1.21.0-0.18 +- Resolves:rhbz#2144877 : rhc - new role for subscription management/registration/insights +- ad_integration - fix issue with using the network role to configure DNS + +* Thu Feb 09 2023 Rich Megginson - 1.21.0-0.17 +- Resolves:rhbz#2164879 : selinux - managing modules is not idempotent +- Fix nbde_server test issue + +* Fri Feb 03 2023 Rich Megginson - 1.21.0-0.16 +- Resolves:rhbz#2165176 : journald - New role - journald - manage systemd-journald +- Resolves:rhbz#2159972 : nbde_client - nbde_client_clevis fails with a traceback and prints sensitive data +- Resolves:rhbz#2164879 : selinux - managing modules is not idempotent +- fix storage tests_swap and tests_misc - swap size < 128GB on EL7 +- fix podman general-meta issue +- ha_cluster non-x86_64 tests issue +- certificate non-x86_64 tests issue + +* Fri Jan 20 2023 Rich Megginson - 1.21.0-0.15 +- Resolves:rhbz#2162788 : network - role should support running tests with ANSIBLE_GATHERING=explicit +- Resolves:rhbz#2149683 : Synchronize automation-related changes from Fedora spec file +- Fix ansible-test issues in several roles +- Fix nbde_server tang test failure + +* Fri Jan 13 2023 Rich Megginson - 1.21.0-0.14 +- Resolves:rhbz#2143814 : ha_cluster - Allow quorum device configuration +- Resolves:rhbz#2153081 : ha_cluster - Allow enabled SBD on disabled cluster +- Resolves:rhbz#2127497 : ha_cluster - use no_log in tasks looping over pot. secret parameters +- community.general 6.2.0 +- replace community.general with namespace.name for rhc role + +* Thu Dec 15 2022 Rich Megginson - 1.21.0-0.13 +- Resolves:rhbz#2151355 : storage - [RHEL8] disks_needed need to be set for the raid test cases +- Resolves:rhbz#2154143 : storage - [RHEL8] tests_create_thinp_then_remove_scsi_generated.yml failed at "assertion": "(storage_test_expected_size|int - storage_test_actual_size.bytes)|abs / storage_test_expected_size|int < 0.01" +- Resolves:rhbz#2151342 : storage - [RHEL9] ansible.parsing.yaml.objects.AnsibleUnicode object' has no attribute 'bytes' +- Resolves:rhbz#2151351 : storage - [RHEL9 system role] storage role vdo tests failed about "VDO deduplication is off but it should not" + +* Thu Dec 15 2022 Rich Megginson - 1.21.0-0.12 +- Resolves:rhbz#2153080 - tlog - Unconditionally enable the files provider + +* Tue Dec 13 2022 Rich Megginson - 1.21.0-0.11 +- Resolves:rhbz#2130362 : logging - [RFE] convert logging role to use firewall, selinux role, and certificate role + fix basic-smoke-test failures + +* Mon Dec 12 2022 Rich Megginson - 1.21.0-0.10 +- Resolves:rhbz#2130019 : ha_cluster - [RFE] convert ha_cluster role to use firewall, selinux and certificate role +- Resolves:rhbz#2143458 : network - Support cloned MAC address +- Resolves:rhbz#2066864 : podman - [RFE] role for managing podman containers and systemd + +* Tue Dec 06 2022 Rich Megginson - 1.21.0-0.9 +- Resolves:rhbz#2144876 : ad_integration - [RFE] new role to support AD integration, join to AD domain + +* Mon Dec 05 2022 Rich Megginson - 1.21.0-0.8 +- Resolves:rhbz#2130362 : logging - [RFE] convert logging role to use firewall, selinux role, and certificate role + fix tests - tests_relp now uses logging_purge_confs + +* Tue Nov 29 2022 Rich Megginson - 1.21.0-0.7 +- Resolves:rhbz#2126960 : nbde_client - must handle clevis-luks-askpass and clevis-luks-askpass@ systemd unit names + +* Tue Nov 29 2022 Rich Megginson - 1.21.0-0.6 +- Resolves:rhbz#2133931 : nbde_server - [RFE] convert nbde_server role to use firewall and selinux role + previous fix was not complete - needed additional fixes - ansible-lint 6.x fixes + +* Tue Nov 22 2022 Rich Megginson - 1.21.0-0.5 +- Resolves:rhbz#2137667 : cockpit - [RFE] convert cockpit role to use firewall, selinux role, and certificate role +- Resolves:rhbz#2130362 : logging - [RFE] convert logging role to use firewall, selinux role, and certificate role +- Resolves:rhbz#2133532 : metrics - [RFE] convert metrics role to use firewall and selinux role +- Resolves:rhbz#2133931 : nbde_server - [RFE] convert nbde_server role to use firewall and selinux role +- Resolves:rhbz#2130332 : postfix - [RFE] convert postfix role to use firewall and selinux role +- Resolves:rhbz#2119600 : vpn - Add parameters shared_key_content, ike, esp, type, leftid, rightid +- Resolves:rhbz#2130345 : vpn - [RFE] convert vpn role to use firewall and selinux role + +* Tue Nov 22 2022 Rich Megginson - 1.21.0-0.4.podman +- Resolves:rhbz#2066864 : podman - [RFE] role for managing podman containers and systemd + +* Tue Nov 22 2022 Rich Megginson - 1.21.0-0.3.ssh_sshd_selinux_timesync +- Resolves:rhbz#2143385 : selinux - add support for the 'local' parameter +- Resolves:rhbz#2143401 : sshd,ssh,timesync - Unexpected templating type error - expected str instance, int found +- Resolves:rhbz#2130921 : ssh,sshd - Sync on final OpenSSH option name RequiredRSASize in ssh and sshd roles [rhel-8.7] [rhel-8.8.0] + +* Tue Nov 15 2022 Rich Megginson - 1.21.0-0.2.network +- Resolves:rhbz#2134201 : network - [RFE] Support setting the metric of the default route for initscripts provider +- Resolves:rhbz#2133856 : network - [RFE] Support the DNS priority +- Resolves:rhbz#2129620 : network - Support looking up named route table in routing rule +- includes ha_cluster, vpn - README.md had headings that were too long causing problems + for md to adoc to html conversion on el8 +- includes changing network role to support ansible-core 2.14 +- includes community.general 6.0.1 +- adds back network bondtests patch - bond tests still failing in beaker * Tue Aug 09 2022 Rich Megginson - 1.20.0-1 - Resolves:rhbz#2115159 : cockpit - Add customization of port