* Tue Jun 25 2024 Miroslav Rezanina <mrezanin@redhat.com> - 23.4-13

- ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch [RHEL-17961]
- ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch [RHEL-44337]
- ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch [RHEL-44337]
- ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch [RHEL-44598]
- ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch [RHEL-44598]
- ci-Update-pylint-version-to-support-python-3.12-5338.patch [RHEL-44598]
- Resolves: RHEL-17961
  ([RHEL-9] cloud-init fails to configure DNS search domains)
- Resolves: RHEL-44337
  ([rhel-9] fix `SUDO` configuration schema for users and groups)
- Resolves: RHEL-44598
  (fix pylint error and support python 3.12)
This commit is contained in:
Miroslav Rezanina 2024-06-25 02:58:27 -04:00
parent 3affac864f
commit f1f4c0a890
7 changed files with 922 additions and 1 deletions

View File

@ -0,0 +1,235 @@
From c34f5c4275c3ef7bee9a99e87bf6e37c5886b160 Mon Sep 17 00:00:00 2001
From: Ani Sinha <anisinha@redhat.com>
Date: Wed, 29 May 2024 03:34:38 +0530
Subject: [PATCH 6/6] Update pylint version to support python 3.12 (#5338)
RH-Author: Ani Sinha <anisinha@redhat.com>
RH-MergeRequest: 92: Update pylint version to support python 3.12
RH-Jira: RHEL-44598
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [3/3] d6185e0a126e1589260ee59709fe933b5a780b78 (anisinha/cloud-init)
Fedora 39 and above comes with python version 3.12. When running `tox -e pylint`
on cloud-init, we may experience issue such as the one reported here:
https://github.com/pylint-dev/pylint/issues/8782
Minimum version of pylint required in order to support python 3.12 is 3.0.2.
Please see https://github.com/pylint-dev/astroid/issues/2201 . Upon further
experimentation, it is seen that we need minimum pylint version 3.2.0 for
cloud-init. Update tox.ini in order to use this pylint version.
Signed-off-by: Ani Sinha <anisinha@redhat.com>
(cherry picked from commit 5ad609ffdf4bb76c5665e12e34e1867b72bd4435)
Conflicts:
cloudinit/sources/DataSourceWSL.py (does not exist)
cloudinit/util.py (doc added upstream)
---
cloudinit/config/cc_mounts.py | 4 ++++
cloudinit/distros/bsd.py | 2 ++
cloudinit/distros/netbsd.py | 2 +-
cloudinit/sources/DataSourceAzure.py | 2 +-
cloudinit/sources/DataSourceEc2.py | 3 ++-
cloudinit/sources/DataSourceLXD.py | 2 +-
tests/integration_tests/conftest.py | 6 +++---
tests/integration_tests/util.py | 2 +-
tests/unittests/config/test_cc_ntp.py | 2 ++
tests/unittests/sources/test_gce.py | 1 +
tests/unittests/test_util.py | 2 ++
tox.ini | 2 +-
12 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index 4efa2a29..d445b440 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -304,6 +304,10 @@ def create_swapfile(fname: str, size: str) -> None:
"bs=1M",
"count=%s" % size,
]
+ else:
+ raise subp.ProcessExecutionError(
+ "Missing dependency: 'dd' and 'fallocate' are not available"
+ )
try:
subp.subp(cmd, capture=True)
diff --git a/cloudinit/distros/bsd.py b/cloudinit/distros/bsd.py
index 761cf5c4..77e0385f 100644
--- a/cloudinit/distros/bsd.py
+++ b/cloudinit/distros/bsd.py
@@ -120,6 +120,8 @@ class BSD(distros.Distro):
if not self.pkg_cmd_upgrade_prefix:
return
cmd = self.pkg_cmd_upgrade_prefix
+ else:
+ cmd = []
if args and isinstance(args, str):
cmd.append(args)
diff --git a/cloudinit/distros/netbsd.py b/cloudinit/distros/netbsd.py
index a5678907..b7f3f3d8 100644
--- a/cloudinit/distros/netbsd.py
+++ b/cloudinit/distros/netbsd.py
@@ -12,7 +12,7 @@ import cloudinit.distros.bsd
from cloudinit import subp, util
try:
- import crypt
+ import crypt # pylint: disable=W4901
salt = crypt.METHOD_BLOWFISH # pylint: disable=E1101
blowfish_hash: Any = functools.partial(
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index 11c14e20..eb0304c3 100644
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -51,7 +51,7 @@ from cloudinit.sources.helpers.azure import (
from cloudinit.url_helper import UrlError
try:
- import crypt
+ import crypt # pylint: disable=W4901
blowfish_hash: Any = functools.partial(
crypt.crypt, salt=f"$6${util.rand_str(strlen=16)}"
diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py
index 9e6bfbd1..384e4074 100644
--- a/cloudinit/sources/DataSourceEc2.py
+++ b/cloudinit/sources/DataSourceEc2.py
@@ -312,6 +312,8 @@ class DataSourceEc2(sources.DataSource):
return None
def wait_for_metadata_service(self):
+ urls = []
+ start_time = 0
mcfg = self.ds_cfg
url_params = self.get_url_params()
@@ -345,7 +347,6 @@ class DataSourceEc2(sources.DataSource):
and self.cloud_name not in IDMSV2_SUPPORTED_CLOUD_PLATFORMS
):
# if we can't get a token, use instance-id path
- urls = []
url2base = {}
url_path = "{ver}/meta-data/instance-id".format(
ver=self.min_metadata_version
diff --git a/cloudinit/sources/DataSourceLXD.py b/cloudinit/sources/DataSourceLXD.py
index cd316101..4c95b907 100644
--- a/cloudinit/sources/DataSourceLXD.py
+++ b/cloudinit/sources/DataSourceLXD.py
@@ -331,7 +331,7 @@ class MetaDataKeys(Flag):
CONFIG = auto()
DEVICES = auto()
META_DATA = auto()
- ALL = CONFIG | DEVICES | META_DATA
+ ALL = CONFIG | DEVICES | META_DATA # pylint: disable=E1131
class _MetaDataReader:
diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py
index fa729b7d..ec211a00 100644
--- a/tests/integration_tests/conftest.py
+++ b/tests/integration_tests/conftest.py
@@ -241,7 +241,7 @@ def _client(
@pytest.fixture
-def client(
+def client( # pylint: disable=W0135
request, fixture_utils, session_cloud, setup_image
) -> Iterator[IntegrationInstance]:
"""Provide a client that runs for every test."""
@@ -250,7 +250,7 @@ def client(
@pytest.fixture(scope="module")
-def module_client(
+def module_client( # pylint: disable=W0135
request, fixture_utils, session_cloud, setup_image
) -> Iterator[IntegrationInstance]:
"""Provide a client that runs once per module."""
@@ -259,7 +259,7 @@ def module_client(
@pytest.fixture(scope="class")
-def class_client(
+def class_client( # pylint: disable=W0135
request, fixture_utils, session_cloud, setup_image
) -> Iterator[IntegrationInstance]:
"""Provide a client that runs once per class."""
diff --git a/tests/integration_tests/util.py b/tests/integration_tests/util.py
index 0a15203c..e26e466c 100644
--- a/tests/integration_tests/util.py
+++ b/tests/integration_tests/util.py
@@ -182,7 +182,7 @@ def wait_for_cloud_init(client: IntegrationInstance, num_retries: int = 30):
except Exception as e:
last_exception = e
time.sleep(1)
- raise Exception(
+ raise Exception( # pylint: disable=W0719
"cloud-init status did not return successfully."
) from last_exception
diff --git a/tests/unittests/config/test_cc_ntp.py b/tests/unittests/config/test_cc_ntp.py
index a9444ec5..c9ce5daa 100644
--- a/tests/unittests/config/test_cc_ntp.py
+++ b/tests/unittests/config/test_cc_ntp.py
@@ -248,6 +248,7 @@ class TestNtp(FilesystemMockingTestCase):
)
def _get_expected_pools(self, pools, distro, client):
+ expected_pools = None
if client in ["ntp", "chrony"]:
if client == "ntp" and distro == "alpine":
# NTP for Alpine Linux is Busybox's ntp which does not
@@ -263,6 +264,7 @@ class TestNtp(FilesystemMockingTestCase):
return expected_pools
def _get_expected_servers(self, servers, distro, client):
+ expected_servers = None
if client in ["ntp", "chrony"]:
if client == "ntp" and distro == "alpine":
# NTP for Alpine Linux is Busybox's ntp which only supports
diff --git a/tests/unittests/sources/test_gce.py b/tests/unittests/sources/test_gce.py
index c0b19d3c..30a50236 100644
--- a/tests/unittests/sources/test_gce.py
+++ b/tests/unittests/sources/test_gce.py
@@ -101,6 +101,7 @@ class TestDataSourceGCE(test_helpers.ResponsesTestCase):
gce_meta = GCE_META
def _request_callback(request):
+ recursive = False
url_path = urlparse(request.url).path
if url_path.startswith("/computeMetadata/v1/"):
path = url_path.split("/computeMetadata/v1/")[1:][0]
diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py
index 519ef63c..de1326d4 100644
--- a/tests/unittests/test_util.py
+++ b/tests/unittests/test_util.py
@@ -1677,6 +1677,8 @@ class TestRedirectOutputPreexecFn:
args = (test_string, None)
elif request.param == "errfmt":
args = (None, test_string)
+ else:
+ args = (None, None)
with mock.patch(M_PATH + "subprocess.Popen") as m_popen:
util.redirect_output(*args)
diff --git a/tox.ini b/tox.ini
index 5f01a9a8..5199ca13 100644
--- a/tox.ini
+++ b/tox.ini
@@ -25,7 +25,7 @@ hypothesis==6.31.6
hypothesis_jsonschema==0.20.1
isort==5.10.1
mypy==0.950
-pylint==2.13.9
+pylint==3.2.0
pytest==7.0.1
ruff==0.0.285
types-jsonschema==4.4.2
--
2.39.3

View File

@ -0,0 +1,51 @@
From 52c04e1a523a450dfce70bc441963eb6a026eb59 Mon Sep 17 00:00:00 2001
From: Ani Sinha <anisinha@redhat.com>
Date: Thu, 20 Jun 2024 11:18:40 +0530
Subject: [PATCH 3/6] doc: update examples to reflect alternative ways to
provide `sudo` option (#5418)
RH-Author: Ani Sinha <anisinha@redhat.com>
RH-MergeRequest: 90: fix(jsonschema): Add missing sudo definition (#5418)
RH-Jira: RHEL-44337
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [2/2] 62eac6d731cb725c32cd0beac0219ecc2b407198 (anisinha/cloud-init)
For creating users and groups, it is possible to pass a `sudo` option to the
config file that accepts a sudo rule. The option can be a sudo rule string,
a list of sudo rule strings or `False` to explicitly deny sudo usage. Update
examples to show how a list of strings can be used with `sudo` option.
Signed-off-by: Ani Sinha <anisinha@redhat.com>
(cherry picked from commit cbcb05349e35023ee6e81ccaf13e79adb8f65f63)
---
doc/examples/cloud-config-user-groups.txt | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/doc/examples/cloud-config-user-groups.txt b/doc/examples/cloud-config-user-groups.txt
index 87fc52e8..56eb674f 100644
--- a/doc/examples/cloud-config-user-groups.txt
+++ b/doc/examples/cloud-config-user-groups.txt
@@ -35,6 +35,10 @@ users:
lock_passwd: true
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSL7uWGj8cgWyIOaspgKdVy0cKJ+UTjfv7jBOjG2H/GN8bJVXy72XAvnhM0dUM+CCs8FOf0YlPX+Frvz2hKInrmRhZVwRSL129PasD12MlI3l44u6IwS1o/W86Q+tkQYEljtqDOo0a+cOsaZkvUNzUyEXUwz/lmYa6G4hMKZH4NBj7nbAAF96wsMCoyNwbWryBnDYUr6wMbjRR1J9Pw7Xh7WRC73wy4Va2YuOgbD3V/5ZrFPLbWZW/7TFXVrql04QVbyei4aiFR5n//GvoqwQDNe58LmbzX/xvxyKJYdny2zXmdAhMxbrpFQsfpkJ9E/H5w0yOdSvnWbUoG5xNGoOB csmith@fringe
+ - name: testuser
+ gecos: Mr. Test
+ homedir: /local/testdir
+ sudo: ["ALL=(ALL) NOPASSWD:ALL"]
- name: cloudy
gecos: Magic Cloud App Daemon User
inactive: '5'
@@ -100,6 +104,8 @@ users:
#
# Allow a user unrestricted sudo access.
# sudo: ALL=(ALL) NOPASSWD:ALL
+# or
+# sudo: ["ALL=(ALL) NOPASSWD:ALL"]
#
# Adding multiple sudo rule strings.
# sudo:
--
2.39.3

View File

@ -0,0 +1,351 @@
From 6b32b371bfd37759ddce3d7f29d15546500698e6 Mon Sep 17 00:00:00 2001
From: Ani Sinha <anisinha@redhat.com>
Date: Thu, 20 Jun 2024 22:27:03 +0530
Subject: [PATCH 1/6] feat(sysconfig): Add DNS from interface config to
resolv.conf (#5401)
RH-Author: Ani Sinha <anisinha@redhat.com>
RH-MergeRequest: 88: feat(sysconfig): Add DNS from interface config to resolv.conf (#5401)
RH-Jira: RHEL-17961
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [1/1] f353b73cc0f4bb9e1aee037708a1d3cb23b83cc3 (anisinha/cloud-init)
sysconfig renderer currently only uses global dns and search domain
configuration in order to populate /etc/resolv.conf. This means it ignores
interface specific dns configuration completely. This means, when global dns
information is absent and only interface specific dns configuration is present,
/etc/resolv.conf will not have complete dns information. Fix this so that
per interface dns information is also taken into account along with global dns
configuration in order to populate /etc/resolv.conf.
Fixes: GH-5400
Signed-off-by: Ani Sinha <anisinha@redhat.com>
(cherry picked from commit 1b8030e0c7fd6fbff7e38ad1e3e6266ae50c83a5)
---
cloudinit/net/sysconfig.py | 52 +++++++++-
tests/unittests/test_net.py | 184 +++++++++++++++++++++++++++++++++++-
2 files changed, 230 insertions(+), 6 deletions(-)
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index d39f4fe3..7eb430ed 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -825,20 +825,62 @@ class Renderer(renderer.Renderer):
@staticmethod
def _render_dns(network_state, existing_dns_path=None):
- # skip writing resolv.conf if network_state doesn't include any input.
+
+ found_nameservers = []
+ found_dns_search = []
+
+ for iface in network_state.iter_interfaces():
+ for subnet in iface["subnets"]:
+ # Add subnet-level DNS
+ if "dns_nameservers" in subnet:
+ found_nameservers.extend(subnet["dns_nameservers"])
+ if "dns_search" in subnet:
+ found_dns_search.extend(subnet["dns_search"])
+
+ # Add interface-level DNS
+ if "dns" in iface:
+ found_nameservers += [
+ dns
+ for dns in iface["dns"]["nameservers"]
+ if dns not in found_nameservers
+ ]
+ found_dns_search += [
+ search
+ for search in iface["dns"]["search"]
+ if search not in found_dns_search
+ ]
+
+ # When both global and interface specific entries are present,
+ # use them both to generate /etc/resolv.conf eliminating duplicate
+ # entries. Otherwise use global or interface specific entries whichever
+ # is provided.
+ if network_state.dns_nameservers:
+ found_nameservers += [
+ nameserver
+ for nameserver in network_state.dns_nameservers
+ if nameserver not in found_nameservers
+ ]
+ if network_state.dns_searchdomains:
+ found_dns_search += [
+ search
+ for search in network_state.dns_searchdomains
+ if search not in found_dns_search
+ ]
+
+ # skip writing resolv.conf if no dns information is provided in conf.
if not any(
[
- len(network_state.dns_nameservers),
- len(network_state.dns_searchdomains),
+ len(found_nameservers),
+ len(found_dns_search),
]
):
return None
content = resolv_conf.ResolvConf("")
if existing_dns_path and os.path.isfile(existing_dns_path):
content = resolv_conf.ResolvConf(util.load_file(existing_dns_path))
- for nameserver in network_state.dns_nameservers:
+ for nameserver in found_nameservers:
content.add_nameserver(nameserver)
- for searchdomain in network_state.dns_searchdomains:
+ for searchdomain in found_dns_search:
content.add_search_domain(searchdomain)
header = _make_header(";")
content_str = str(content)
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index d7c9a414..2d716f4b 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -516,6 +516,8 @@ OS_SAMPLES = [
}
],
"ip_address": "172.19.1.34",
+ "dns_search": ["testweb.com"],
+ "dns_nameservers": ["172.19.0.13"],
"id": "network0",
}
],
@@ -550,7 +552,9 @@ STARTMODE=auto
"""
; Created by cloud-init automatically, do not edit.
;
+nameserver 172.19.0.13
nameserver 172.19.0.12
+search testweb.com
""".lstrip(),
),
(
@@ -582,6 +586,8 @@ AUTOCONNECT_PRIORITY=120
BOOTPROTO=none
DEFROUTE=yes
DEVICE=eth0
+DNS1=172.19.0.13
+DOMAIN=testweb.com
GATEWAY=172.19.3.254
HWADDR=fa:16:3e:ed:9a:59
IPADDR=172.19.1.34
@@ -596,7 +602,174 @@ USERCTL=no
"""
; Created by cloud-init automatically, do not edit.
;
+nameserver 172.19.0.13
nameserver 172.19.0.12
+search testweb.com
+""".lstrip(),
+ ),
+ (
+ "etc/NetworkManager/conf.d/99-cloud-init.conf",
+ """
+# Created by cloud-init automatically, do not edit.
+#
+[main]
+dns = none
+""".lstrip(),
+ ),
+ (
+ "etc/udev/rules.d/70-persistent-net.rules",
+ "".join(
+ [
+ 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
+ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n',
+ ]
+ ),
+ ),
+ ],
+ "expected_network_manager": [
+ (
+ "".join(
+ [
+ "etc/NetworkManager/system-connections",
+ "/cloud-init-eth0.nmconnection",
+ ]
+ ),
+ """
+# Generated by cloud-init. Changes will be lost.
+
+[connection]
+id=cloud-init eth0
+uuid=1dd9a779-d327-56e1-8454-c65e2556c12c
+autoconnect-priority=120
+type=ethernet
+
+[user]
+org.freedesktop.NetworkManager.origin=cloud-init
+
+[ethernet]
+mac-address=FA:16:3E:ED:9A:59
+
+[ipv4]
+method=manual
+may-fail=false
+address1=172.19.1.34/22
+route1=0.0.0.0/0,172.19.3.254
+dns=172.19.0.13;
+dns-search=testweb.com;
+
+""".lstrip(),
+ ),
+ ],
+ },
+ {
+ "in_data": {
+ "services": [
+ {
+ "type": "dns",
+ "address": "172.19.0.12",
+ "search": ["example1.com", "example2.com"],
+ }
+ ],
+ "networks": [
+ {
+ "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4",
+ "type": "ipv4",
+ "netmask": "255.255.252.0",
+ "link": "eth0",
+ "routes": [
+ {
+ "netmask": "0.0.0.0",
+ "network": "0.0.0.0",
+ "gateway": "172.19.3.254",
+ }
+ ],
+ "ip_address": "172.19.1.34",
+ "dns_search": ["example3.com"],
+ "dns_nameservers": ["172.19.0.12"],
+ "id": "network0",
+ }
+ ],
+ "links": [
+ {
+ "ethernet_mac_address": "fa:16:3e:ed:9a:59",
+ "mtu": None,
+ "type": "physical",
+ "id": "eth0",
+ },
+ ],
+ },
+ "in_macs": {
+ "fa:16:3e:ed:9a:59": "eth0",
+ },
+ "out_sysconfig_opensuse": [
+ (
+ "etc/sysconfig/network/ifcfg-eth0",
+ """
+# Created by cloud-init automatically, do not edit.
+#
+BOOTPROTO=static
+IPADDR=172.19.1.34
+LLADDR=fa:16:3e:ed:9a:59
+NETMASK=255.255.252.0
+STARTMODE=auto
+""".lstrip(),
+ ),
+ (
+ "etc/resolv.conf",
+ """
+; Created by cloud-init automatically, do not edit.
+;
+nameserver 172.19.0.12
+search example3.com example1.com example2.com
+""".lstrip(),
+ ),
+ (
+ "etc/NetworkManager/conf.d/99-cloud-init.conf",
+ """
+# Created by cloud-init automatically, do not edit.
+#
+[main]
+dns = none
+""".lstrip(),
+ ),
+ (
+ "etc/udev/rules.d/85-persistent-net-cloud-init.rules",
+ "".join(
+ [
+ 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ',
+ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n',
+ ]
+ ),
+ ),
+ ],
+ "out_sysconfig_rhel": [
+ (
+ "etc/sysconfig/network-scripts/ifcfg-eth0",
+ """
+# Created by cloud-init automatically, do not edit.
+#
+AUTOCONNECT_PRIORITY=120
+BOOTPROTO=none
+DEFROUTE=yes
+DEVICE=eth0
+DNS1=172.19.0.12
+DOMAIN=example3.com
+GATEWAY=172.19.3.254
+HWADDR=fa:16:3e:ed:9a:59
+IPADDR=172.19.1.34
+NETMASK=255.255.252.0
+ONBOOT=yes
+TYPE=Ethernet
+USERCTL=no
+""".lstrip(),
+ ),
+ (
+ "etc/resolv.conf",
+ """
+; Created by cloud-init automatically, do not edit.
+;
+nameserver 172.19.0.12
+search example3.com example1.com example2.com
""".lstrip(),
),
(
@@ -647,6 +820,7 @@ may-fail=false
address1=172.19.1.34/22
route1=0.0.0.0/0,172.19.3.254
dns=172.19.0.12;
+dns-search=example3.com;
""".lstrip(),
),
@@ -654,7 +828,13 @@ dns=172.19.0.12;
},
{
"in_data": {
- "services": [{"type": "dns", "address": "172.19.0.12"}],
+ "services": [
+ {
+ "type": "dns",
+ "address": "172.19.0.12",
+ "search": "example.com",
+ }
+ ],
"networks": [
{
"network_id": "public-ipv4",
@@ -715,6 +895,7 @@ STARTMODE=auto
; Created by cloud-init automatically, do not edit.
;
nameserver 172.19.0.12
+search example.com
""".lstrip(),
),
(
@@ -763,6 +944,7 @@ USERCTL=no
; Created by cloud-init automatically, do not edit.
;
nameserver 172.19.0.12
+search example.com
""".lstrip(),
),
(
--
2.39.3

View File

@ -0,0 +1,73 @@
From 8ead44cb39f7726a695aa21a34820f6d40270829 Mon Sep 17 00:00:00 2001
From: James Falcon <james.falcon@canonical.com>
Date: Mon, 12 Feb 2024 14:48:01 -0600
Subject: [PATCH 5/6] fix: Address TIOBE abstract interpretation issues (#4866)
RH-Author: Ani Sinha <anisinha@redhat.com>
RH-MergeRequest: 92: Update pylint version to support python 3.12
RH-Jira: RHEL-44598
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [2/3] 3ca11206fa159ab45b2db21e78c4cfaf358b1e01 (anisinha/cloud-init)
These involve operations on possibly null variables or impossible logic.
(cherry picked from commit 5e7ef1032a12267a9a518358fbf89da0a88ddb99)
---
cloudinit/config/cc_lxd.py | 2 +-
cloudinit/distros/parsers/ifconfig.py | 6 ++++++
cloudinit/util.py | 1 +
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py
index cb9fc4f3..9f267b4c 100644
--- a/cloudinit/config/cc_lxd.py
+++ b/cloudinit/config/cc_lxd.py
@@ -432,7 +432,7 @@ def bridge_to_cmd(bridge_cfg):
% (bridge_cfg.get("ipv6_address"), bridge_cfg.get("ipv6_netmask"))
)
- if bridge_cfg.get("ipv6_nat", "false") == "true":
+ if bridge_cfg.get("ipv6_nat") == "true":
cmd_create.append("ipv6.nat=true")
else:
diff --git a/cloudinit/distros/parsers/ifconfig.py b/cloudinit/distros/parsers/ifconfig.py
index 516b5eb5..d671df1f 100644
--- a/cloudinit/distros/parsers/ifconfig.py
+++ b/cloudinit/distros/parsers/ifconfig.py
@@ -102,6 +102,7 @@ class Ifconfig:
"""
ifindex = 0
ifs_by_mac = defaultdict(list)
+ dev = None
for line in text.splitlines():
if len(line) == 0:
continue
@@ -119,6 +120,11 @@ class Ifconfig:
dev.index = ifindex
self._ifs_by_name[curif] = dev
+ if not dev:
+ # This shouldn't happen with normal ifconfig output, but
+ # if it does, ensure we don't Traceback
+ continue
+
toks = line.lower().strip().split()
if len(toks) > 1 and toks[1].startswith("flags="):
diff --git a/cloudinit/util.py b/cloudinit/util.py
index 3295735c..5f787c5c 100644
--- a/cloudinit/util.py
+++ b/cloudinit/util.py
@@ -1417,6 +1417,7 @@ def find_devs_with_netbsd(
devlist = []
label = None
_type = None
+ mscdlabel_out = ""
if criteria:
if criteria.startswith("LABEL="):
label = criteria.lstrip("LABEL=")
--
2.39.3

View File

@ -0,0 +1,132 @@
From 2b74b0eb94edfd7caa42bc0d8affc37311ba041b Mon Sep 17 00:00:00 2001
From: Brett Holman <brett.holman@canonical.com>
Date: Wed, 3 Jan 2024 09:11:21 -0700
Subject: [PATCH 4/6] fix(dhcp): Guard against FileNotFoundError and NameError
exceptions
RH-Author: Ani Sinha <anisinha@redhat.com>
RH-MergeRequest: 92: Update pylint version to support python 3.12
RH-Jira: RHEL-44598
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [1/3] 730b8de9ceb2c380d3b15573d83691ab95a1487e (anisinha/cloud-init)
(cherry picked from commit 53eb8555e091474803b724700815adc09aa84f05)
---
cloudinit/net/dhcp.py | 20 ++++++++++------
tests/unittests/net/test_dhcp.py | 40 ++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py
index 07c13390..a0aee98c 100644
--- a/cloudinit/net/dhcp.py
+++ b/cloudinit/net/dhcp.py
@@ -5,15 +5,15 @@
# This file is part of cloud-init. See LICENSE file for license information.
import abc
-import contextlib
import glob
import logging
import os
import re
import signal
import time
+from contextlib import suppress
from io import StringIO
-from typing import Any, Dict, List
+from typing import Any, Dict, List, Optional
import configobj
@@ -268,7 +268,7 @@ class IscDhclient(DhcpClient):
# this function waits for these files to exist, clean previous runs
# to avoid false positive in wait_for_files
- with contextlib.suppress(FileNotFoundError):
+ with suppress(FileNotFoundError):
os.remove(pid_file)
os.remove(lease_file)
@@ -514,9 +514,15 @@ class IscDhclient(DhcpClient):
return latest_file
@staticmethod
- def parse_dhcp_server_from_lease_file(lease_file):
- with open(lease_file, "r") as fd:
- for line in fd:
+ def parse_dhcp_server_from_lease_file(lease_file) -> Optional[str]:
+ """Parse a lease file for the dhcp server address
+
+ @param lease_file: Name of a file to be parsed
+ @return: An address if found, or None
+ """
+ latest_address = None
+ with suppress(FileNotFoundError), open(lease_file, "r") as file:
+ for line in file:
if "dhcp-server-identifier" in line:
words = line.strip(" ;\r\n").split(" ")
if len(words) > 2:
@@ -561,7 +567,7 @@ class Udhcpc(DhcpClient):
tmp_dir = temp_utils.get_tmp_ancestor(needs_exe=True)
lease_file = os.path.join(tmp_dir, interface + ".lease.json")
- with contextlib.suppress(FileNotFoundError):
+ with suppress(FileNotFoundError):
os.remove(lease_file)
# udhcpc needs the interface up to send initial discovery packets
diff --git a/tests/unittests/net/test_dhcp.py b/tests/unittests/net/test_dhcp.py
index a7b62312..8ec96eef 100644
--- a/tests/unittests/net/test_dhcp.py
+++ b/tests/unittests/net/test_dhcp.py
@@ -32,6 +32,46 @@ LEASE_F = "/run/dhclient.lease"
DHCLIENT = "/sbin/dhclient"
+@pytest.mark.parametrize(
+ "server_address,lease_file_content",
+ (
+ pytest.param(None, None, id="no_server_addr_on_absent_lease_file"),
+ pytest.param(None, "", id="no_server_addr_on_empty_lease_file"),
+ pytest.param(
+ None,
+ "lease {\n fixed-address: 10.1.2.3;\n}\n",
+ id="no_server_addr_when_no_server_ident",
+ ),
+ pytest.param(
+ "10.4.5.6",
+ "lease {\n fixed-address: 10.1.2.3;\n"
+ " option dhcp-server-identifier 10.4.5.6;\n"
+ " option dhcp-renewal-time 1800;\n}\n",
+ id="server_addr_found_when_server_ident_present",
+ ),
+ ),
+)
+class TestParseDHCPServerFromLeaseFile:
+ def test_find_server_address_when_present(
+ self, server_address, lease_file_content, tmp_path
+ ):
+ """Test that we return None in the case of no file or file contains no
+ server address, otherwise return the address.
+ """
+ lease_file = tmp_path / "dhcp.leases"
+ if server_address:
+ if lease_file_content:
+ lease_file.write_text(lease_file_content)
+ assert (
+ server_address
+ == IscDhclient.parse_dhcp_server_from_lease_file(lease_file)
+ )
+ else:
+ assert not IscDhclient.parse_dhcp_server_from_lease_file(
+ lease_file
+ )
+
+
class TestParseDHCPLeasesFile(CiTestCase):
def test_parse_empty_lease_file_errors(self):
"""parse_dhcp_lease_file errors when file content is empty."""
--
2.39.3

View File

@ -0,0 +1,53 @@
From b7fddab36d805099639358736dab474d2924906b Mon Sep 17 00:00:00 2001
From: Brett Holman <brett.holman@canonical.com>
Date: Wed, 19 Jun 2024 17:07:56 -0600
Subject: [PATCH 2/6] fix(jsonschema): Add missing sudo definition (#5418)
RH-Author: Ani Sinha <anisinha@redhat.com>
RH-MergeRequest: 90: fix(jsonschema): Add missing sudo definition (#5418)
RH-Jira: RHEL-44337
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [1/2] 9e56c7ab35744c6530c8cef2f122ffdcc0480d29 (anisinha/cloud-init)
This configuration:
```
users:
- name: osadmin
lock_passwd: false
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
```
Is valid syntax but is missing from the jsonschema definition.
Fixes GH-5399
(cherry picked from commit b533fa51acb850ed754e2b1925e276ff8e5f3507)
---
cloudinit/config/schemas/schema-cloud-config-v1.json | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json
index a553c52c..8b10fe70 100644
--- a/cloudinit/config/schemas/schema-cloud-config-v1.json
+++ b/cloudinit/config/schemas/schema-cloud-config-v1.json
@@ -299,6 +299,15 @@
],
"description": "Sudo rule to use or false. Absence of a sudo value or ``null`` will result in no sudo rules added for this user."
},
+ {
+ "type": "array",
+ "items": {
+ "type": [
+ "string",
+ "null"
+ ]
+ }
+ },
{
"type": "boolean",
"changed": true,
--
2.39.3

View File

@ -1,6 +1,6 @@
Name: cloud-init Name: cloud-init
Version: 23.4 Version: 23.4
Release: 12%{?dist} Release: 13%{?dist}
Summary: Cloud instance init scripts Summary: Cloud instance init scripts
License: ASL 2.0 or GPLv3 License: ASL 2.0 or GPLv3
URL: http://launchpad.net/cloud-init URL: http://launchpad.net/cloud-init
@ -35,6 +35,18 @@ Patch16: ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch
Patch17: ci-fix-Always-use-single-datasource-if-specified-5098.patch Patch17: ci-fix-Always-use-single-datasource-if-specified-5098.patch
# For RHEL-40217 - [Cloud-init] CloudstackDataSource cannot work with NetworkManager # For RHEL-40217 - [Cloud-init] CloudstackDataSource cannot work with NetworkManager
Patch18: ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch Patch18: ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch
# For RHEL-17961 - [RHEL-9] cloud-init fails to configure DNS search domains
Patch19: ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch
# For RHEL-44337 - [rhel-9] fix `SUDO` configuration schema for users and groups
Patch20: ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch
# For RHEL-44337 - [rhel-9] fix `SUDO` configuration schema for users and groups
Patch21: ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch
# For RHEL-44598 - fix pylint error and support python 3.12
Patch22: ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch
# For RHEL-44598 - fix pylint error and support python 3.12
Patch23: ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch
# For RHEL-44598 - fix pylint error and support python 3.12
Patch24: ci-Update-pylint-version-to-support-python-3.12-5338.patch
BuildArch: noarch BuildArch: noarch
@ -249,6 +261,20 @@ fi
%config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf
%changelog %changelog
* Tue Jun 25 2024 Miroslav Rezanina <mrezanin@redhat.com> - 23.4-13
- ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch [RHEL-17961]
- ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch [RHEL-44337]
- ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch [RHEL-44337]
- ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch [RHEL-44598]
- ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch [RHEL-44598]
- ci-Update-pylint-version-to-support-python-3.12-5338.patch [RHEL-44598]
- Resolves: RHEL-17961
([RHEL-9] cloud-init fails to configure DNS search domains)
- Resolves: RHEL-44337
([rhel-9] fix `SUDO` configuration schema for users and groups)
- Resolves: RHEL-44598
(fix pylint error and support python 3.12)
* Mon Jun 17 2024 Miroslav Rezanina <mrezanin@redhat.com> - 23.4-12 * Mon Jun 17 2024 Miroslav Rezanina <mrezanin@redhat.com> - 23.4-12
- ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch [RHEL-40217] - ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch [RHEL-40217]
- Resolves: RHEL-40217 - Resolves: RHEL-40217