forked from pool/cloud-init
Compare commits
17 Commits
Author | SHA256 | Date | |
---|---|---|---|
fb205e0def | |||
b3d3a8bcbd | |||
55263e441e | |||
333e9dfd77 | |||
45e0874bb7 | |||
9d54ca0906 | |||
b1469b941b | |||
f155ed52a6 | |||
1a0cecdf92 | |||
e330242ba5 | |||
ae07dd3a29 | |||
d2277ce376 | |||
0338649d15 | |||
14e9c00f78 | |||
fb5493d9e8 | |||
882510dff4 | |||
26859a25ae |
BIN
cloud-init-23.3.tar.gz
(Stored with Git LFS)
BIN
cloud-init-23.3.tar.gz
(Stored with Git LFS)
Binary file not shown.
BIN
cloud-init-25.1.3.tar.gz
(Stored with Git LFS)
Normal file
BIN
cloud-init-25.1.3.tar.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -1,54 +0,0 @@
|
|||||||
--- tests/unittests/test_ds_identify.py.orig
|
|
||||||
+++ tests/unittests/test_ds_identify.py
|
|
||||||
@@ -1488,7 +1488,6 @@ VALID_CFG = {
|
|
||||||
},
|
|
||||||
"IBMCloud-metadata": {
|
|
||||||
"ds": "IBMCloud",
|
|
||||||
- "policy_dmi": POLICY_FOUND_ONLY,
|
|
||||||
"mocks": [
|
|
||||||
MOCK_VIRT_IS_XEN,
|
|
||||||
{"name": "is_ibm_provisioning", "ret": shell_false},
|
|
||||||
@@ -1555,7 +1554,6 @@ VALID_CFG = {
|
|
||||||
},
|
|
||||||
"IBMCloud-nodisks": {
|
|
||||||
"ds": "IBMCloud",
|
|
||||||
- "policy_dmi": POLICY_FOUND_ONLY,
|
|
||||||
"mocks": [
|
|
||||||
MOCK_VIRT_IS_XEN,
|
|
||||||
{"name": "is_ibm_provisioning", "ret": shell_false},
|
|
||||||
@@ -1642,7 +1640,6 @@ VALID_CFG = {
|
|
||||||
},
|
|
||||||
"VMware-NoValidTransports": {
|
|
||||||
"ds": "VMware",
|
|
||||||
- "policy_dmi": POLICY_FOUND_ONLY,
|
|
||||||
"mocks": [
|
|
||||||
MOCK_VIRT_IS_VMWARE,
|
|
||||||
],
|
|
||||||
@@ -1665,7 +1662,6 @@ VALID_CFG = {
|
|
||||||
},
|
|
||||||
"VMware-EnvVar-NoData": {
|
|
||||||
"ds": "VMware",
|
|
||||||
- "policy_dmi": POLICY_FOUND_ONLY,
|
|
||||||
"mocks": [
|
|
||||||
{
|
|
||||||
"name": "vmware_has_envvar_vmx_guestinfo",
|
|
||||||
@@ -1775,7 +1771,6 @@ VALID_CFG = {
|
|
||||||
},
|
|
||||||
"VMware-GuestInfo-NoData": {
|
|
||||||
"ds": "VMware",
|
|
||||||
- "policy_dmi": POLICY_FOUND_ONLY,
|
|
||||||
"mocks": [
|
|
||||||
{
|
|
||||||
"name": "vmware_has_rpctool",
|
|
||||||
--- tools/ds-identify.orig
|
|
||||||
+++ tools/ds-identify
|
|
||||||
@@ -739,9 +739,6 @@ probe_floppy() {
|
|
||||||
dscheck_CloudStack() {
|
|
||||||
is_container && return ${DS_NOT_FOUND}
|
|
||||||
dmi_product_name_matches "CloudStack*" && return $DS_FOUND
|
|
||||||
- if [ "$DI_VIRT" = "vmware" ] || [ "$DI_VIRT" = "xen" ]; then
|
|
||||||
- return $DS_MAYBE
|
|
||||||
- fi
|
|
||||||
return $DS_NOT_FOUND
|
|
||||||
}
|
|
||||||
|
|
@@ -1,11 +0,0 @@
|
|||||||
--- tools/run-lint.orig
|
|
||||||
+++ tools/run-lint
|
|
||||||
@@ -11,7 +11,7 @@ else
|
|
||||||
files=( "$@" )
|
|
||||||
fi
|
|
||||||
|
|
||||||
-cmd=( "python3" -m "ruff" "${files[@]}" )
|
|
||||||
+cmd=( "python3" -m "flake8" "${files[@]}" )
|
|
||||||
|
|
||||||
echo "Running: " "${cmd[@]}" 1>&2
|
|
||||||
exec "${cmd[@]}"
|
|
553
cloud-init-lint-fix.patch
Normal file
553
cloud-init-lint-fix.patch
Normal file
@@ -0,0 +1,553 @@
|
|||||||
|
--- cloudinit/cmd/main.py.orig
|
||||||
|
+++ cloudinit/cmd/main.py
|
||||||
|
@@ -684,7 +684,7 @@ def di_report_warn(datasource, cfg):
|
||||||
|
# where Name is the thing that shows up in datasource_list.
|
||||||
|
modname = datasource.__module__.rpartition(".")[2]
|
||||||
|
if modname.startswith(sources.DS_PREFIX):
|
||||||
|
- modname = modname[len(sources.DS_PREFIX) :]
|
||||||
|
+ modname = modname[len(sources.DS_PREFIX):]
|
||||||
|
else:
|
||||||
|
LOG.warning(
|
||||||
|
"Datasource '%s' came from unexpected module '%s'.",
|
||||||
|
--- cloudinit/config/cc_apt_configure.py.orig
|
||||||
|
+++ cloudinit/config/cc_apt_configure.py
|
||||||
|
@@ -270,7 +270,7 @@ def mirrorurl_to_apt_fileprefix(mirror):
|
||||||
|
string = string[0:-1]
|
||||||
|
pos = string.find("://")
|
||||||
|
if pos >= 0:
|
||||||
|
- string = string[pos + 3 :]
|
||||||
|
+ string = string[pos + 3:]
|
||||||
|
string = string.replace("/", "_")
|
||||||
|
return string
|
||||||
|
|
||||||
|
--- cloudinit/config/cc_mounts.py.orig
|
||||||
|
+++ cloudinit/config/cc_mounts.py
|
||||||
|
@@ -414,7 +414,7 @@ def sanitize_mounts_configuration(
|
||||||
|
updated_line[index] = str(updated_line[index])
|
||||||
|
|
||||||
|
# fill remaining values with defaults from defvals above
|
||||||
|
- updated_line += default_fields[len(updated_line) :]
|
||||||
|
+ updated_line += default_fields[len(updated_line):]
|
||||||
|
|
||||||
|
updated_lines.append(updated_line)
|
||||||
|
return updated_lines
|
||||||
|
--- cloudinit/config/cc_ssh_authkey_fingerprints.py.orig
|
||||||
|
+++ cloudinit/config/cc_ssh_authkey_fingerprints.py
|
||||||
|
@@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
|
||||||
|
def _split_hash(bin_hash):
|
||||||
|
split_up = []
|
||||||
|
for i in range(0, len(bin_hash), 2):
|
||||||
|
- split_up.append(bin_hash[i : i + 2])
|
||||||
|
+ split_up.append(bin_hash[i:i + 2])
|
||||||
|
return split_up
|
||||||
|
|
||||||
|
|
||||||
|
--- cloudinit/config/modules.py.orig
|
||||||
|
+++ cloudinit/config/modules.py
|
||||||
|
@@ -57,7 +57,7 @@ class ModuleDetails(NamedTuple):
|
||||||
|
def form_module_name(name):
|
||||||
|
canon_name = name.replace("-", "_")
|
||||||
|
if canon_name.lower().endswith(".py"):
|
||||||
|
- canon_name = canon_name[0 : (len(canon_name) - 3)]
|
||||||
|
+ canon_name = canon_name[0:(len(canon_name) - 3)]
|
||||||
|
canon_name = canon_name.strip()
|
||||||
|
if not canon_name:
|
||||||
|
return None
|
||||||
|
--- cloudinit/distros/parsers/ifconfig.py.orig
|
||||||
|
+++ cloudinit/distros/parsers/ifconfig.py
|
||||||
|
@@ -143,7 +143,7 @@ class Ifconfig:
|
||||||
|
dev.index = int(toks[1])
|
||||||
|
|
||||||
|
if toks[0] == "description:":
|
||||||
|
- dev.description = line[line.index(":") + 2 :]
|
||||||
|
+ dev.description = line[line.index(":") + 2:]
|
||||||
|
|
||||||
|
if (
|
||||||
|
toks[0].startswith("options=")
|
||||||
|
@@ -168,7 +168,7 @@ class Ifconfig:
|
||||||
|
dev.groups += toks[1:]
|
||||||
|
|
||||||
|
if toks[0] == "media:":
|
||||||
|
- dev.media = line[line.index(": ") + 2 :]
|
||||||
|
+ dev.media = line[line.index(": ") + 2:]
|
||||||
|
|
||||||
|
if toks[0] == "nd6":
|
||||||
|
nd6_opts = re.split(r"<|>", toks[0])
|
||||||
|
--- cloudinit/net/dhcp.py.orig
|
||||||
|
+++ cloudinit/net/dhcp.py
|
||||||
|
@@ -495,24 +495,24 @@ class IscDhclient(DhcpClient):
|
||||||
|
if len(tokens[idx:]) < req_toks:
|
||||||
|
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
||||||
|
return static_routes
|
||||||
|
- net_address = ".".join(tokens[idx + 1 : idx + 5])
|
||||||
|
- gateway = ".".join(tokens[idx + 5 : idx + req_toks])
|
||||||
|
+ net_address = ".".join(tokens[idx + 1:idx + 5])
|
||||||
|
+ gateway = ".".join(tokens[idx + 5:idx + req_toks])
|
||||||
|
current_idx = idx + req_toks
|
||||||
|
elif net_length in range(17, 25):
|
||||||
|
req_toks = 8
|
||||||
|
if len(tokens[idx:]) < req_toks:
|
||||||
|
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
||||||
|
return static_routes
|
||||||
|
- net_address = ".".join(tokens[idx + 1 : idx + 4] + ["0"])
|
||||||
|
- gateway = ".".join(tokens[idx + 4 : idx + req_toks])
|
||||||
|
+ net_address = ".".join(tokens[idx + 1:idx + 4] + ["0"])
|
||||||
|
+ gateway = ".".join(tokens[idx + 4:idx + req_toks])
|
||||||
|
current_idx = idx + req_toks
|
||||||
|
elif net_length in range(9, 17):
|
||||||
|
req_toks = 7
|
||||||
|
if len(tokens[idx:]) < req_toks:
|
||||||
|
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
||||||
|
return static_routes
|
||||||
|
- net_address = ".".join(tokens[idx + 1 : idx + 3] + ["0", "0"])
|
||||||
|
- gateway = ".".join(tokens[idx + 3 : idx + req_toks])
|
||||||
|
+ net_address = ".".join(tokens[idx + 1:idx + 3] + ["0", "0"])
|
||||||
|
+ gateway = ".".join(tokens[idx + 3:idx + req_toks])
|
||||||
|
current_idx = idx + req_toks
|
||||||
|
elif net_length in range(1, 9):
|
||||||
|
req_toks = 6
|
||||||
|
@@ -520,9 +520,9 @@ class IscDhclient(DhcpClient):
|
||||||
|
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
||||||
|
return static_routes
|
||||||
|
net_address = ".".join(
|
||||||
|
- tokens[idx + 1 : idx + 2] + ["0", "0", "0"]
|
||||||
|
+ tokens[idx + 1:idx + 2] + ["0", "0", "0"]
|
||||||
|
)
|
||||||
|
- gateway = ".".join(tokens[idx + 2 : idx + req_toks])
|
||||||
|
+ gateway = ".".join(tokens[idx + 2:idx + req_toks])
|
||||||
|
current_idx = idx + req_toks
|
||||||
|
elif net_length == 0:
|
||||||
|
req_toks = 5
|
||||||
|
@@ -530,7 +530,7 @@ class IscDhclient(DhcpClient):
|
||||||
|
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
||||||
|
return static_routes
|
||||||
|
net_address = "0.0.0.0"
|
||||||
|
- gateway = ".".join(tokens[idx + 1 : idx + req_toks])
|
||||||
|
+ gateway = ".".join(tokens[idx + 1:idx + req_toks])
|
||||||
|
current_idx = idx + req_toks
|
||||||
|
else:
|
||||||
|
LOG.error(
|
||||||
|
@@ -767,7 +767,7 @@ class Dhcpcd(DhcpClient):
|
||||||
|
while len(data) >= index + 2:
|
||||||
|
code = data[index]
|
||||||
|
length = data[1 + index]
|
||||||
|
- option = data[2 + index : 2 + index + length]
|
||||||
|
+ option = data[2 + index:2 + index + length]
|
||||||
|
yield code, option
|
||||||
|
index = 2 + length + index
|
||||||
|
|
||||||
|
--- cloudinit/net/network_manager.py.orig
|
||||||
|
+++ cloudinit/net/network_manager.py
|
||||||
|
@@ -175,7 +175,8 @@ class NMConnection:
|
||||||
|
self.config[family]["method"] = method
|
||||||
|
|
||||||
|
# Network Manager sets the value of `may-fail` to `True` by default.
|
||||||
|
- # Please see https://www.networkmanager.dev/docs/api/1.32.10/settings-ipv6.html.
|
||||||
|
+ # Please see
|
||||||
|
+ # https://www.networkmanager.dev/docs/api/1.32.10/settings-ipv6.html.
|
||||||
|
# Therefore, when no configuration for ipv4 or ipv6 is specified,
|
||||||
|
# `may-fail = True` applies. When the user explicitly configures ipv4
|
||||||
|
# or ipv6, `may-fail` is set to `False`. This is so because it is
|
||||||
|
--- cloudinit/reporting/handlers.py.orig
|
||||||
|
+++ cloudinit/reporting/handlers.py
|
||||||
|
@@ -295,13 +295,13 @@ class HyperVKvpReportingHandler(Reportin
|
||||||
|
)
|
||||||
|
)
|
||||||
|
k = (
|
||||||
|
- record_data[0 : self.HV_KVP_EXCHANGE_MAX_KEY_SIZE]
|
||||||
|
+ record_data[0:self.HV_KVP_EXCHANGE_MAX_KEY_SIZE]
|
||||||
|
.decode("utf-8")
|
||||||
|
.strip("\x00")
|
||||||
|
)
|
||||||
|
v = (
|
||||||
|
record_data[
|
||||||
|
- self.HV_KVP_EXCHANGE_MAX_KEY_SIZE : self.HV_KVP_RECORD_SIZE
|
||||||
|
+ self.HV_KVP_EXCHANGE_MAX_KEY_SIZE:self.HV_KVP_RECORD_SIZE
|
||||||
|
]
|
||||||
|
.decode("utf-8")
|
||||||
|
.strip("\x00")
|
||||||
|
@@ -322,7 +322,7 @@ class HyperVKvpReportingHandler(Reportin
|
||||||
|
def _break_down(self, key, meta_data, description):
|
||||||
|
del meta_data[self.MSG_KEY]
|
||||||
|
des_in_json = json.dumps(description)
|
||||||
|
- des_in_json = des_in_json[1 : (len(des_in_json) - 1)]
|
||||||
|
+ des_in_json = des_in_json[1:(len(des_in_json) - 1)]
|
||||||
|
i = 0
|
||||||
|
result_array = []
|
||||||
|
message_place_holder = '"' + self.MSG_KEY + '":""'
|
||||||
|
@@ -355,7 +355,7 @@ class HyperVKvpReportingHandler(Reportin
|
||||||
|
Values will be truncated as needed.
|
||||||
|
"""
|
||||||
|
if len(value) >= self.HV_KVP_AZURE_MAX_VALUE_SIZE:
|
||||||
|
- value = value[0 : self.HV_KVP_AZURE_MAX_VALUE_SIZE - 1]
|
||||||
|
+ value = value[0:self.HV_KVP_AZURE_MAX_VALUE_SIZE - 1]
|
||||||
|
|
||||||
|
data = [self._encode_kvp_item(key, value)]
|
||||||
|
|
||||||
|
--- cloudinit/sources/__init__.py.orig
|
||||||
|
+++ cloudinit/sources/__init__.py
|
||||||
|
@@ -789,7 +789,7 @@ class DataSource(CloudInitPickleMixin, m
|
||||||
|
if not short_name.startswith(nfrom):
|
||||||
|
continue
|
||||||
|
for nto in tlist:
|
||||||
|
- cand = "/dev/%s%s" % (nto, short_name[len(nfrom) :])
|
||||||
|
+ cand = "/dev/%s%s" % (nto, short_name[len(nfrom):])
|
||||||
|
if os.path.exists(cand):
|
||||||
|
return cand
|
||||||
|
return None
|
||||||
|
--- cloudinit/sources/helpers/azure.py.orig
|
||||||
|
+++ cloudinit/sources/helpers/azure.py
|
||||||
|
@@ -492,7 +492,7 @@ class OpenSSLManager:
|
||||||
|
"""
|
||||||
|
raw_fp = self._run_x509_action("-fingerprint", certificate)
|
||||||
|
eq = raw_fp.find("=")
|
||||||
|
- octets = raw_fp[eq + 1 : -1].split(":")
|
||||||
|
+ octets = raw_fp[eq + 1:-1].split(":")
|
||||||
|
return "".join(octets)
|
||||||
|
|
||||||
|
@azure_ds_telemetry_reporter
|
||||||
|
--- cloudinit/sources/helpers/netlink.py.orig
|
||||||
|
+++ cloudinit/sources/helpers/netlink.py
|
||||||
|
@@ -146,7 +146,7 @@ def unpack_rta_attr(data, offset):
|
||||||
|
return None # Should mean our offset is >= remaining data
|
||||||
|
|
||||||
|
# Unpack just the attribute's data. Offset by 4 to skip length/type header
|
||||||
|
- attr_data = data[offset + RTA_DATA_START_OFFSET : offset + length]
|
||||||
|
+ attr_data = data[offset + RTA_DATA_START_OFFSET:offset + length]
|
||||||
|
return RTAAttr(length, rta_type, attr_data)
|
||||||
|
|
||||||
|
|
||||||
|
--- cloudinit/ssh_util.py.orig
|
||||||
|
+++ cloudinit/ssh_util.py
|
||||||
|
@@ -659,7 +659,7 @@ def get_opensshd_version():
|
||||||
|
prefix = "OpenSSH_"
|
||||||
|
for line in err.split("\n"):
|
||||||
|
if line.startswith(prefix):
|
||||||
|
- return line[len(prefix) : line.find(",")]
|
||||||
|
+ return line[len(prefix):line.find(",")]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
--- cloudinit/user_data.py.orig
|
||||||
|
+++ cloudinit/user_data.py
|
||||||
|
@@ -210,13 +210,13 @@ class UserDataProcessor:
|
||||||
|
for line in content.splitlines():
|
||||||
|
lc_line = line.lower()
|
||||||
|
if lc_line.startswith("#include-once"):
|
||||||
|
- line = line[len("#include-once") :].lstrip()
|
||||||
|
+ line = line[len("#include-once"):].lstrip()
|
||||||
|
# Every following include will now
|
||||||
|
# not be refetched.... but will be
|
||||||
|
# re-read from a local urlcache (if it worked)
|
||||||
|
include_once_on = True
|
||||||
|
elif lc_line.startswith("#include"):
|
||||||
|
- line = line[len("#include") :].lstrip()
|
||||||
|
+ line = line[len("#include"):].lstrip()
|
||||||
|
# Disable the include once if it was on
|
||||||
|
# if it wasn't, then this has no effect.
|
||||||
|
include_once_on = False
|
||||||
|
--- cloudinit/util.py.orig
|
||||||
|
+++ cloudinit/util.py
|
||||||
|
@@ -585,7 +585,7 @@ def get_linux_distro():
|
||||||
|
dist = ("", "", "")
|
||||||
|
try:
|
||||||
|
# Was removed in 3.8
|
||||||
|
- dist = platform.dist() # type: ignore # pylint: disable=W1505,E1101
|
||||||
|
+ dist = platform.dist() # type: ignore pylint: disable=W1505,E1101
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
@@ -1172,7 +1172,7 @@ def read_cc_from_cmdline(cmdline=None):
|
||||||
|
if end < 0:
|
||||||
|
end = clen
|
||||||
|
tokens.append(
|
||||||
|
- parse.unquote(cmdline[begin + begin_l : end].lstrip()).replace(
|
||||||
|
+ parse.unquote(cmdline[begin + begin_l:end].lstrip()).replace(
|
||||||
|
"\\n", "\n"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@@ -1744,7 +1744,7 @@ def get_output_cfg(
|
||||||
|
found = False
|
||||||
|
for s in swlist:
|
||||||
|
if val.startswith(s):
|
||||||
|
- val = "%s %s" % (s, val[len(s) :].strip())
|
||||||
|
+ val = "%s %s" % (s, val[len(s):].strip())
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
@@ -2360,7 +2360,7 @@ def shellify(cmdlist, add_header=True):
|
||||||
|
|
||||||
|
def strip_prefix_suffix(line, prefix=None, suffix=None):
|
||||||
|
if prefix and line.startswith(prefix):
|
||||||
|
- line = line[len(prefix) :]
|
||||||
|
+ line = line[len(prefix):]
|
||||||
|
if suffix and line.endswith(suffix):
|
||||||
|
line = line[: -len(suffix)]
|
||||||
|
return line
|
||||||
|
@@ -2869,7 +2869,7 @@ def human2bytes(size):
|
||||||
|
for m in mpliers:
|
||||||
|
if size.endswith(m):
|
||||||
|
mplier = m
|
||||||
|
- num = size[0 : -len(m)]
|
||||||
|
+ num = size[0:-len(m)]
|
||||||
|
|
||||||
|
try:
|
||||||
|
num = float(num)
|
||||||
|
@@ -2947,12 +2947,12 @@ def rootdev_from_cmdline(cmdline):
|
||||||
|
if found.startswith("/dev/"):
|
||||||
|
return found
|
||||||
|
if found.startswith("LABEL="):
|
||||||
|
- return "/dev/disk/by-label/" + found[len("LABEL=") :]
|
||||||
|
+ return "/dev/disk/by-label/" + found[len("LABEL="):]
|
||||||
|
if found.startswith("UUID="):
|
||||||
|
- return "/dev/disk/by-uuid/" + found[len("UUID=") :].lower()
|
||||||
|
+ return "/dev/disk/by-uuid/" + found[len("UUID="):].lower()
|
||||||
|
if found.startswith("PARTUUID="):
|
||||||
|
disks_path = (
|
||||||
|
- "/dev/disk/by-partuuid/" + found[len("PARTUUID=") :].lower()
|
||||||
|
+ "/dev/disk/by-partuuid/" + found[len("PARTUUID="):].lower()
|
||||||
|
)
|
||||||
|
if os.path.exists(disks_path):
|
||||||
|
return disks_path
|
||||||
|
--- setup.py.orig
|
||||||
|
+++ setup.py
|
||||||
|
@@ -194,7 +194,7 @@ elif os.path.isfile("/etc/system-release
|
||||||
|
else:
|
||||||
|
# String formatted CPE
|
||||||
|
inc = 1
|
||||||
|
- (cpe_vendor, cpe_product, cpe_version) = cpe_data[2 + inc : 5 + inc]
|
||||||
|
+ (cpe_vendor, cpe_product, cpe_version) = cpe_data[2 + inc:5 + inc]
|
||||||
|
if cpe_vendor == "amazon":
|
||||||
|
USR_LIB_EXEC = "usr/libexec"
|
||||||
|
|
||||||
|
--- tests/integration_tests/conftest.py.orig
|
||||||
|
+++ tests/integration_tests/conftest.py
|
||||||
|
@@ -501,6 +501,7 @@ def pytest_sessionstart(session) -> None
|
||||||
|
|
||||||
|
def pytest_sessionfinish(session, exitstatus) -> None:
|
||||||
|
"""do session teardown"""
|
||||||
|
+ global _SESSION_CLOUD
|
||||||
|
global REAPER
|
||||||
|
log.info("finishing session")
|
||||||
|
try:
|
||||||
|
--- tests/integration_tests/dropins/test_custom_modules.py.orig
|
||||||
|
+++ tests/integration_tests/dropins/test_custom_modules.py
|
||||||
|
@@ -20,7 +20,7 @@ def test_custom_module_24_1(client: Inte
|
||||||
|
"""
|
||||||
|
client.push_file(
|
||||||
|
ASSETS_DIR / "dropins/cc_custom_module_24_1.py",
|
||||||
|
- "/usr/lib/python3/dist-packages/cloudinit/config/cc_custom_module_24_1.py",
|
||||||
|
+ "/usr/lib/python3/dist-packages/cloudinit/config/cc_custom_module_24_1.py", # noqa: E501
|
||||||
|
)
|
||||||
|
output = client.execute("cloud-init single --name cc_custom_module_24_1")
|
||||||
|
if releases.CURRENT_RELEASE >= releases.PLUCKY:
|
||||||
|
--- tests/unittests/config/test_apt_source_v3.py.orig
|
||||||
|
+++ tests/unittests/config/test_apt_source_v3.py
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
# This file is part of cloud-init. See LICENSE file for license information.
|
||||||
|
+# flake8: noqa
|
||||||
|
# pylint: disable=attribute-defined-outside-init
|
||||||
|
|
||||||
|
"""test_handler_apt_source_v3
|
||||||
|
@@ -1429,7 +1430,6 @@ Suites: mantic-backports
|
||||||
|
Components: main
|
||||||
|
"""
|
||||||
|
|
||||||
|
-
|
||||||
|
DEB822_DISABLED_SINGLE_SUITE = """\
|
||||||
|
## Entry disabled by cloud-init, due to disable_suites
|
||||||
|
# disabled by cloud-init: Types: deb
|
||||||
|
@@ -1446,7 +1446,6 @@ DEB822_DISABLED_MULTIPLE_SUITES = """\
|
||||||
|
# disabled by cloud-init: Components: main
|
||||||
|
"""
|
||||||
|
|
||||||
|
-
|
||||||
|
class TestDisableSuitesDeb822:
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"disabled_suites,src,expected",
|
||||||
|
--- tests/unittests/config/test_cc_apt_configure.py.orig
|
||||||
|
+++ tests/unittests/config/test_cc_apt_configure.py
|
||||||
|
@@ -293,7 +293,7 @@ class TestAptConfigure:
|
||||||
|
cc_apt.UBUNTU_DEFAULT_APT_SOURCES_LIST,
|
||||||
|
"ubuntu",
|
||||||
|
cc_apt.UBUNTU_DEFAULT_APT_SOURCES_LIST,
|
||||||
|
- id="ubuntu_no_warning_when_existig_sources_list_content_allowed",
|
||||||
|
+ id="ubuntu_no_warning_when_existig_sources_list_content_allowed", # noqa: E501
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
--- tests/unittests/config/test_cc_yum_add_repo.py.orig
|
||||||
|
+++ tests/unittests/config/test_cc_yum_add_repo.py
|
||||||
|
@@ -90,7 +90,7 @@ class TestConfig(helpers.FilesystemMocki
|
||||||
|
"yum_repos": {
|
||||||
|
"epel-testing": {
|
||||||
|
"name": "Extra Packages for Enterprise Linux 5 - Testing",
|
||||||
|
- "mirrorlist": "http://mirrors.blah.org/metalink?repo=rhel-$releasever",
|
||||||
|
+ "mirrorlist": "http://mirrors.blah.org/metalink?repo=rhel-$releasever", # noqa: E501
|
||||||
|
"enabled": False,
|
||||||
|
"gpgcheck": True,
|
||||||
|
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL",
|
||||||
|
@@ -110,7 +110,7 @@ class TestConfig(helpers.FilesystemMocki
|
||||||
|
"failovermethod": "priority",
|
||||||
|
"gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL",
|
||||||
|
"enabled": "0",
|
||||||
|
- "mirrorlist": "http://mirrors.blah.org/metalink?repo=rhel-$releasever",
|
||||||
|
+ "mirrorlist": "http://mirrors.blah.org/metalink?repo=rhel-$releasever", # noqa: E501
|
||||||
|
"gpgcheck": "1",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--- tests/unittests/config/test_schema.py.orig
|
||||||
|
+++ tests/unittests/config/test_schema.py
|
||||||
|
@@ -1293,7 +1293,7 @@ class TestMain:
|
||||||
|
"vd2_key": "vendor2_cloud_config",
|
||||||
|
"net_key": "network_config",
|
||||||
|
},
|
||||||
|
- id="prefer_processed_vd_file_path_when_raw_and_processed_empty",
|
||||||
|
+ id="prefer_processed_vd_file_path_when_raw_and_processed_empty", # noqa: E501
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@@ -2047,7 +2047,7 @@ apt_reboot_if_required: Deprecated in ve
|
||||||
|
Valid schema {cfg_file}
|
||||||
|
""" # noqa: E501
|
||||||
|
),
|
||||||
|
- id="test_deprecation_info_boundary_does_unannotated_unredacted",
|
||||||
|
+ id="test_deprecation_info_boundary_does_unannotated_unredacted", # noqa: E501
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
--- tests/unittests/distros/test_create_users.py.orig
|
||||||
|
+++ tests/unittests/distros/test_create_users.py
|
||||||
|
@@ -260,7 +260,7 @@ class TestCreateUser:
|
||||||
|
"ubuntu",
|
||||||
|
True,
|
||||||
|
["Not unlocking blank password for existing user foo_user."],
|
||||||
|
- id="no_unlock_in_snappy_on_locked_empty_user_passwd_in_extrausers",
|
||||||
|
+ id="no_unlock_in_snappy_on_locked_empty_user_passwd_in_extrausers", # noqa: E501
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
{"/etc/shadow": f"dnsmasq::\n{USER}::"},
|
||||||
|
@@ -281,14 +281,14 @@ class TestCreateUser:
|
||||||
|
"dragonflybsd",
|
||||||
|
False,
|
||||||
|
["Not unlocking blank password for existing user foo_user."],
|
||||||
|
- id="no_unlock_on_locked_format1_empty_user_passwd_dragonflybsd",
|
||||||
|
+ id="no_unlock_on_locked_format1_empty_user_passwd_dragonflybsd", # noqa: E501
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
{"/etc/master.passwd": f"dnsmasq::\n{USER}:*LOCKED*:"},
|
||||||
|
"dragonflybsd",
|
||||||
|
False,
|
||||||
|
["Not unlocking blank password for existing user foo_user."],
|
||||||
|
- id="no_unlock_on_locked_format2_empty_user_passwd_dragonflybsd",
|
||||||
|
+ id="no_unlock_on_locked_format2_empty_user_passwd_dragonflybsd", # noqa: E501
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
{"/etc/master.passwd": f"dnsmasq::\n{USER}::"},
|
||||||
|
--- tests/unittests/helpers.py.orig
|
||||||
|
+++ tests/unittests/helpers.py
|
||||||
|
@@ -315,7 +315,7 @@ class FilesystemMockingTestCase(Resource
|
||||||
|
real_root = os.path.join(real_root, "roots", example_root)
|
||||||
|
for dir_path, _dirnames, filenames in os.walk(real_root):
|
||||||
|
real_path = dir_path
|
||||||
|
- make_path = rebase_path(real_path[len(real_root) :], target_root)
|
||||||
|
+ make_path = rebase_path(real_path[len(real_root):], target_root)
|
||||||
|
util.ensure_dir(make_path)
|
||||||
|
for f in filenames:
|
||||||
|
real_path = os.path.abspath(os.path.join(real_path, f))
|
||||||
|
@@ -541,7 +541,7 @@ def dir2dict(startdir, prefix=None):
|
||||||
|
for root, _dirs, files in os.walk(startdir):
|
||||||
|
for fname in files:
|
||||||
|
fpath = os.path.join(root, fname)
|
||||||
|
- key = fpath[len(prefix) :]
|
||||||
|
+ key = fpath[len(prefix):]
|
||||||
|
flist[key] = util.load_text_file(fpath)
|
||||||
|
return flist
|
||||||
|
|
||||||
|
--- tests/unittests/sources/test_akamai.py.orig
|
||||||
|
+++ tests/unittests/sources/test_akamai.py
|
||||||
|
@@ -278,7 +278,7 @@ class TestDataSourceAkamai:
|
||||||
|
(
|
||||||
|
False,
|
||||||
|
"H4sIAAAAAAACAytJLS7hAgDGNbk7BQAAAA==",
|
||||||
|
- b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\x03+I-.\xe1\x02\x00\xc65\xb9;\x05\x00\x00\x00",
|
||||||
|
+ b"\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\x03+I-.\xe1\x02\x00\xc65\xb9;\x05\x00\x00\x00", # noqa: E501
|
||||||
|
"base64-encoded gzipped data",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
--- tests/unittests/sources/test_configdrive.py.orig
|
||||||
|
+++ tests/unittests/sources/test_configdrive.py
|
||||||
|
@@ -412,7 +412,7 @@ class TestConfigDriveDataSource(CiTestCa
|
||||||
|
}
|
||||||
|
for name, dev_name in name_tests.items():
|
||||||
|
with ExitStack() as mocks:
|
||||||
|
- provided_name = dev_name[len("/dev/") :]
|
||||||
|
+ provided_name = dev_name[len("/dev/"):]
|
||||||
|
provided_name = "s" + provided_name[1:]
|
||||||
|
find_mock = mocks.enter_context(
|
||||||
|
mock.patch.object(
|
||||||
|
--- tests/unittests/sources/test_hetzner.py.orig
|
||||||
|
+++ tests/unittests/sources/test_hetzner.py
|
||||||
|
@@ -109,7 +109,8 @@ class TestDataSourceHetzner(CiTestCase):
|
||||||
|
iface="eth0",
|
||||||
|
connectivity_urls_data=[
|
||||||
|
{
|
||||||
|
- "url": "http://169.254.169.254/hetzner/v1/metadata/instance-id"
|
||||||
|
+ "url":
|
||||||
|
+ "http://169.254.169.254/hetzner/v1/metadata/instance-id"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
--- tests/unittests/sources/test_maas.py.orig
|
||||||
|
+++ tests/unittests/sources/test_maas.py
|
||||||
|
@@ -113,7 +113,7 @@ class TestMAASDataSource:
|
||||||
|
if not url.startswith(prefix):
|
||||||
|
raise ValueError("unexpected call %s" % url)
|
||||||
|
|
||||||
|
- short = url[len(prefix) :]
|
||||||
|
+ short = url[len(prefix):]
|
||||||
|
if short not in data:
|
||||||
|
raise url_helper.UrlError("not found", code=404, url=url)
|
||||||
|
return url_helper.StringResponse(data[short], url)
|
||||||
|
--- tests/unittests/sources/test_smartos.py.orig
|
||||||
|
+++ tests/unittests/sources/test_smartos.py
|
||||||
|
@@ -792,7 +792,7 @@ class ShortReader:
|
||||||
|
rsize = next_null - self.index + 1
|
||||||
|
i = self.index
|
||||||
|
self.index += rsize
|
||||||
|
- ret = self.data[i : i + rsize]
|
||||||
|
+ ret = self.data[i:i + rsize]
|
||||||
|
if len(ret) and ret[-1:] == self.endbyte:
|
||||||
|
ret = ret[:-1]
|
||||||
|
return ret
|
||||||
|
--- tests/unittests/test_url_helper.py.orig
|
||||||
|
+++ tests/unittests/test_url_helper.py
|
||||||
|
@@ -324,7 +324,7 @@ class TestReadUrl:
|
||||||
|
expected_headers["User-Agent"] = "Cloud-Init/%s" % (
|
||||||
|
version.version_string()
|
||||||
|
)
|
||||||
|
- headers_cb = lambda _: headers
|
||||||
|
+ headers_cb = lambda _: headers # noqa: E731
|
||||||
|
|
||||||
|
class FakeSession(requests.Session):
|
||||||
|
@classmethod
|
||||||
|
--- tests/unittests/test_util.py.orig
|
||||||
|
+++ tests/unittests/test_util.py
|
||||||
|
@@ -3334,7 +3334,7 @@ class TestLogExc:
|
||||||
|
def test_logexc(self, caplog):
|
||||||
|
try:
|
||||||
|
_ = 1 / 0
|
||||||
|
- except Exception as _:
|
||||||
|
+ except Exception as _: # noqa: F841
|
||||||
|
util.logexc(LOG, "an error occurred")
|
||||||
|
|
||||||
|
assert caplog.record_tuples == [
|
||||||
|
@@ -3353,7 +3353,7 @@ class TestLogExc:
|
||||||
|
def test_logexc_with_log_level(self, caplog, log_level):
|
||||||
|
try:
|
||||||
|
_ = 1 / 0
|
||||||
|
- except Exception as _:
|
||||||
|
+ except Exception as _: # noqa: F841
|
||||||
|
util.logexc(LOG, "an error occurred", log_level=log_level)
|
||||||
|
|
||||||
|
assert caplog.record_tuples == [
|
@@ -1,412 +0,0 @@
|
|||||||
--- cloudinit/cmd/main.py.orig
|
|
||||||
+++ cloudinit/cmd/main.py
|
|
||||||
@@ -28,26 +28,27 @@ from cloudinit.config.modules import Mod
|
|
||||||
|
|
||||||
patcher.patch_logging()
|
|
||||||
|
|
||||||
-from cloudinit.config.schema import validate_cloudconfig_schema
|
|
||||||
-from cloudinit import log as logging
|
|
||||||
-from cloudinit import netinfo
|
|
||||||
-from cloudinit import signal_handler
|
|
||||||
-from cloudinit import sources
|
|
||||||
-from cloudinit import stages
|
|
||||||
-from cloudinit import url_helper
|
|
||||||
-from cloudinit import util
|
|
||||||
-from cloudinit import version
|
|
||||||
-from cloudinit import warnings
|
|
||||||
-
|
|
||||||
-from cloudinit import reporting
|
|
||||||
-from cloudinit.reporting import events
|
|
||||||
+from cloudinit.config.schema import validate_cloudconfig_schema # noqa: E402
|
|
||||||
+from cloudinit import log as logging # noqa: E402
|
|
||||||
+from cloudinit import netinfo # noqa: E402
|
|
||||||
+from cloudinit import signal_handler # noqa: E402
|
|
||||||
+from cloudinit import sources # noqa: E402
|
|
||||||
+from cloudinit import stages # noqa: E402
|
|
||||||
+from cloudinit import url_helper # noqa: E402
|
|
||||||
+from cloudinit import util # noqa: E402
|
|
||||||
+from cloudinit import version # noqa: E402
|
|
||||||
+from cloudinit import warnings # noqa: E402
|
|
||||||
+
|
|
||||||
+from cloudinit import reporting # noqa: E402
|
|
||||||
+from cloudinit.reporting import events # noqa: E402
|
|
||||||
|
|
||||||
-from cloudinit.settings import PER_INSTANCE, PER_ALWAYS, PER_ONCE, CLOUD_CONFIG
|
|
||||||
+from cloudinit.settings import ( # noqa: E402
|
|
||||||
+ PER_INSTANCE, PER_ALWAYS, PER_ONCE, CLOUD_CONFIG) # noqa: E402
|
|
||||||
|
|
||||||
-from cloudinit import atomic_helper
|
|
||||||
+from cloudinit import atomic_helper # noqa: E402
|
|
||||||
|
|
||||||
-from cloudinit.config import cc_set_hostname
|
|
||||||
-from cloudinit.cmd.devel import read_cfg_paths
|
|
||||||
+from cloudinit.config import cc_set_hostname # noqa: E402
|
|
||||||
+from cloudinit.cmd.devel import read_cfg_paths # noqa: E402
|
|
||||||
|
|
||||||
|
|
||||||
# Welcome message template
|
|
||||||
@@ -538,7 +539,7 @@ def di_report_warn(datasource, cfg):
|
|
||||||
# where Name is the thing that shows up in datasource_list.
|
|
||||||
modname = datasource.__module__.rpartition(".")[2]
|
|
||||||
if modname.startswith(sources.DS_PREFIX):
|
|
||||||
- modname = modname[len(sources.DS_PREFIX) :]
|
|
||||||
+ modname = modname[len(sources.DS_PREFIX):]
|
|
||||||
else:
|
|
||||||
LOG.warning(
|
|
||||||
"Datasource '%s' came from unexpected module '%s'.",
|
|
||||||
--- cloudinit/config/cc_apt_configure.py.orig
|
|
||||||
+++ cloudinit/config/cc_apt_configure.py
|
|
||||||
@@ -354,7 +354,7 @@ def mirrorurl_to_apt_fileprefix(mirror):
|
|
||||||
string = string[0:-1]
|
|
||||||
pos = string.find("://")
|
|
||||||
if pos >= 0:
|
|
||||||
- string = string[pos + 3 :]
|
|
||||||
+ string = string[pos + 3:]
|
|
||||||
string = string.replace("/", "_")
|
|
||||||
return string
|
|
||||||
|
|
||||||
--- cloudinit/config/cc_ssh_authkey_fingerprints.py.orig
|
|
||||||
+++ cloudinit/config/cc_ssh_authkey_fingerprints.py
|
|
||||||
@@ -44,7 +44,7 @@ LOG = logging.getLogger(__name__)
|
|
||||||
def _split_hash(bin_hash):
|
|
||||||
split_up = []
|
|
||||||
for i in range(0, len(bin_hash), 2):
|
|
||||||
- split_up.append(bin_hash[i : i + 2])
|
|
||||||
+ split_up.append(bin_hash[i: i + 2])
|
|
||||||
return split_up
|
|
||||||
|
|
||||||
|
|
||||||
--- cloudinit/config/modules.py.orig
|
|
||||||
+++ cloudinit/config/modules.py
|
|
||||||
@@ -39,7 +39,7 @@ class ModuleDetails(NamedTuple):
|
|
||||||
def form_module_name(name):
|
|
||||||
canon_name = name.replace("-", "_")
|
|
||||||
if canon_name.lower().endswith(".py"):
|
|
||||||
- canon_name = canon_name[0 : (len(canon_name) - 3)]
|
|
||||||
+ canon_name = canon_name[0: (len(canon_name) - 3)]
|
|
||||||
canon_name = canon_name.strip()
|
|
||||||
if not canon_name:
|
|
||||||
return None
|
|
||||||
--- cloudinit/distros/parsers/ifconfig.py.orig
|
|
||||||
+++ cloudinit/distros/parsers/ifconfig.py
|
|
||||||
@@ -140,7 +140,7 @@ class Ifconfig:
|
|
||||||
dev.index = int(toks[1])
|
|
||||||
|
|
||||||
if toks[0] == "description:":
|
|
||||||
- dev.description = line[line.index(":") + 2 :]
|
|
||||||
+ dev.description = line[line.index(":") + 2:]
|
|
||||||
|
|
||||||
if (
|
|
||||||
toks[0].startswith("options=")
|
|
||||||
@@ -165,7 +165,7 @@ class Ifconfig:
|
|
||||||
dev.groups += toks[1:]
|
|
||||||
|
|
||||||
if toks[0] == "media:":
|
|
||||||
- dev.media = line[line.index(": ") + 2 :]
|
|
||||||
+ dev.media = line[line.index(": ") + 2:]
|
|
||||||
|
|
||||||
if toks[0] == "nd6":
|
|
||||||
nd6_opts = re.split(r"<|>", toks[0])
|
|
||||||
--- cloudinit/net/dhcp.py.orig
|
|
||||||
+++ cloudinit/net/dhcp.py
|
|
||||||
@@ -415,24 +415,24 @@ class IscDhclient(DhcpClient):
|
|
||||||
if len(tokens[idx:]) < req_toks:
|
|
||||||
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
|
||||||
return static_routes
|
|
||||||
- net_address = ".".join(tokens[idx + 1 : idx + 5])
|
|
||||||
- gateway = ".".join(tokens[idx + 5 : idx + req_toks])
|
|
||||||
+ net_address = ".".join(tokens[idx + 1: idx + 5])
|
|
||||||
+ gateway = ".".join(tokens[idx + 5: idx + req_toks])
|
|
||||||
current_idx = idx + req_toks
|
|
||||||
elif net_length in range(17, 25):
|
|
||||||
req_toks = 8
|
|
||||||
if len(tokens[idx:]) < req_toks:
|
|
||||||
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
|
||||||
return static_routes
|
|
||||||
- net_address = ".".join(tokens[idx + 1 : idx + 4] + ["0"])
|
|
||||||
- gateway = ".".join(tokens[idx + 4 : idx + req_toks])
|
|
||||||
+ net_address = ".".join(tokens[idx + 1: idx + 4] + ["0"])
|
|
||||||
+ gateway = ".".join(tokens[idx + 4: idx + req_toks])
|
|
||||||
current_idx = idx + req_toks
|
|
||||||
elif net_length in range(9, 17):
|
|
||||||
req_toks = 7
|
|
||||||
if len(tokens[idx:]) < req_toks:
|
|
||||||
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
|
||||||
return static_routes
|
|
||||||
- net_address = ".".join(tokens[idx + 1 : idx + 3] + ["0", "0"])
|
|
||||||
- gateway = ".".join(tokens[idx + 3 : idx + req_toks])
|
|
||||||
+ net_address = ".".join(tokens[idx + 1: idx + 3] + ["0", "0"])
|
|
||||||
+ gateway = ".".join(tokens[idx + 3: idx + req_toks])
|
|
||||||
current_idx = idx + req_toks
|
|
||||||
elif net_length in range(1, 9):
|
|
||||||
req_toks = 6
|
|
||||||
@@ -440,9 +440,9 @@ class IscDhclient(DhcpClient):
|
|
||||||
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
|
||||||
return static_routes
|
|
||||||
net_address = ".".join(
|
|
||||||
- tokens[idx + 1 : idx + 2] + ["0", "0", "0"]
|
|
||||||
+ tokens[idx + 1: idx + 2] + ["0", "0", "0"]
|
|
||||||
)
|
|
||||||
- gateway = ".".join(tokens[idx + 2 : idx + req_toks])
|
|
||||||
+ gateway = ".".join(tokens[idx + 2: idx + req_toks])
|
|
||||||
current_idx = idx + req_toks
|
|
||||||
elif net_length == 0:
|
|
||||||
req_toks = 5
|
|
||||||
@@ -450,7 +450,7 @@ class IscDhclient(DhcpClient):
|
|
||||||
_trunc_error(net_length, req_toks, len(tokens[idx:]))
|
|
||||||
return static_routes
|
|
||||||
net_address = "0.0.0.0"
|
|
||||||
- gateway = ".".join(tokens[idx + 1 : idx + req_toks])
|
|
||||||
+ gateway = ".".join(tokens[idx + 1: idx + req_toks])
|
|
||||||
current_idx = idx + req_toks
|
|
||||||
else:
|
|
||||||
LOG.error(
|
|
||||||
--- cloudinit/net/network_state.py.orig
|
|
||||||
+++ cloudinit/net/network_state.py
|
|
||||||
@@ -135,7 +135,7 @@ class CommandHandlerMeta(type):
|
|
||||||
command_handlers = {}
|
|
||||||
for attr_name, attr in dct.items():
|
|
||||||
if callable(attr) and attr_name.startswith("handle_"):
|
|
||||||
- handles_what = attr_name[len("handle_") :]
|
|
||||||
+ handles_what = attr_name[len("handle_"):]
|
|
||||||
if handles_what:
|
|
||||||
command_handlers[handles_what] = attr
|
|
||||||
dct["command_handlers"] = command_handlers
|
|
||||||
--- cloudinit/reporting/handlers.py.orig
|
|
||||||
+++ cloudinit/reporting/handlers.py
|
|
||||||
@@ -295,13 +295,13 @@ class HyperVKvpReportingHandler(Reportin
|
|
||||||
)
|
|
||||||
)
|
|
||||||
k = (
|
|
||||||
- record_data[0 : self.HV_KVP_EXCHANGE_MAX_KEY_SIZE]
|
|
||||||
+ record_data[0: self.HV_KVP_EXCHANGE_MAX_KEY_SIZE]
|
|
||||||
.decode("utf-8")
|
|
||||||
.strip("\x00")
|
|
||||||
)
|
|
||||||
v = (
|
|
||||||
record_data[
|
|
||||||
- self.HV_KVP_EXCHANGE_MAX_KEY_SIZE : self.HV_KVP_RECORD_SIZE
|
|
||||||
+ self.HV_KVP_EXCHANGE_MAX_KEY_SIZE: self.HV_KVP_RECORD_SIZE
|
|
||||||
]
|
|
||||||
.decode("utf-8")
|
|
||||||
.strip("\x00")
|
|
||||||
@@ -320,7 +320,7 @@ class HyperVKvpReportingHandler(Reportin
|
|
||||||
def _break_down(self, key, meta_data, description):
|
|
||||||
del meta_data[self.MSG_KEY]
|
|
||||||
des_in_json = json.dumps(description)
|
|
||||||
- des_in_json = des_in_json[1 : (len(des_in_json) - 1)]
|
|
||||||
+ des_in_json = des_in_json[1: (len(des_in_json) - 1)]
|
|
||||||
i = 0
|
|
||||||
result_array = []
|
|
||||||
message_place_holder = '"' + self.MSG_KEY + '":""'
|
|
||||||
@@ -353,7 +353,7 @@ class HyperVKvpReportingHandler(Reportin
|
|
||||||
Values will be truncated as needed.
|
|
||||||
"""
|
|
||||||
if len(value) >= self.HV_KVP_AZURE_MAX_VALUE_SIZE:
|
|
||||||
- value = value[0 : self.HV_KVP_AZURE_MAX_VALUE_SIZE - 1]
|
|
||||||
+ value = value[0: self.HV_KVP_AZURE_MAX_VALUE_SIZE - 1]
|
|
||||||
|
|
||||||
data = [self._encode_kvp_item(key, value)]
|
|
||||||
|
|
||||||
--- cloudinit/sources/__init__.py.orig
|
|
||||||
+++ cloudinit/sources/__init__.py
|
|
||||||
@@ -747,7 +747,7 @@ class DataSource(CloudInitPickleMixin, m
|
|
||||||
if not short_name.startswith(nfrom):
|
|
||||||
continue
|
|
||||||
for nto in tlist:
|
|
||||||
- cand = "/dev/%s%s" % (nto, short_name[len(nfrom) :])
|
|
||||||
+ cand = "/dev/%s%s" % (nto, short_name[len(nfrom):])
|
|
||||||
if os.path.exists(cand):
|
|
||||||
return cand
|
|
||||||
return None
|
|
||||||
--- cloudinit/sources/helpers/azure.py.orig
|
|
||||||
+++ cloudinit/sources/helpers/azure.py
|
|
||||||
@@ -566,7 +566,7 @@ class OpenSSLManager:
|
|
||||||
"""
|
|
||||||
raw_fp = self._run_x509_action("-fingerprint", certificate)
|
|
||||||
eq = raw_fp.find("=")
|
|
||||||
- octets = raw_fp[eq + 1 : -1].split(":")
|
|
||||||
+ octets = raw_fp[eq + 1: -1].split(":")
|
|
||||||
return "".join(octets)
|
|
||||||
|
|
||||||
@azure_ds_telemetry_reporter
|
|
||||||
--- cloudinit/sources/helpers/netlink.py.orig
|
|
||||||
+++ cloudinit/sources/helpers/netlink.py
|
|
||||||
@@ -150,7 +150,7 @@ def unpack_rta_attr(data, offset):
|
|
||||||
return None # Should mean our offset is >= remaining data
|
|
||||||
|
|
||||||
# Unpack just the attribute's data. Offset by 4 to skip length/type header
|
|
||||||
- attr_data = data[offset + RTA_DATA_START_OFFSET : offset + length]
|
|
||||||
+ attr_data = data[offset + RTA_DATA_START_OFFSET: offset + length]
|
|
||||||
return RTAAttr(length, rta_type, attr_data)
|
|
||||||
|
|
||||||
|
|
||||||
--- cloudinit/ssh_util.py.orig
|
|
||||||
+++ cloudinit/ssh_util.py
|
|
||||||
@@ -659,7 +659,7 @@ def get_opensshd_version():
|
|
||||||
prefix = "OpenSSH_"
|
|
||||||
for line in err.split("\n"):
|
|
||||||
if line.startswith(prefix):
|
|
||||||
- return line[len(prefix) : line.find(",")]
|
|
||||||
+ return line[len(prefix): line.find(",")]
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
--- cloudinit/url_helper.py.orig
|
|
||||||
+++ cloudinit/url_helper.py
|
|
||||||
@@ -73,7 +73,7 @@ def read_file_or_url(url, **kwargs) -> U
|
|
||||||
if url.lower().startswith("file://"):
|
|
||||||
if kwargs.get("data"):
|
|
||||||
LOG.warning("Unable to post data to file resource %s", url)
|
|
||||||
- file_path = url[len("file://") :]
|
|
||||||
+ file_path = url[len("file://"):]
|
|
||||||
try:
|
|
||||||
with open(file_path, "rb") as fp:
|
|
||||||
contents = fp.read()
|
|
||||||
--- cloudinit/user_data.py.orig
|
|
||||||
+++ cloudinit/user_data.py
|
|
||||||
@@ -211,13 +211,13 @@ class UserDataProcessor:
|
|
||||||
for line in content.splitlines():
|
|
||||||
lc_line = line.lower()
|
|
||||||
if lc_line.startswith("#include-once"):
|
|
||||||
- line = line[len("#include-once") :].lstrip()
|
|
||||||
+ line = line[len("#include-once"):].lstrip()
|
|
||||||
# Every following include will now
|
|
||||||
# not be refetched.... but will be
|
|
||||||
# re-read from a local urlcache (if it worked)
|
|
||||||
include_once_on = True
|
|
||||||
elif lc_line.startswith("#include"):
|
|
||||||
- line = line[len("#include") :].lstrip()
|
|
||||||
+ line = line[len("#include"):].lstrip()
|
|
||||||
# Disable the include once if it was on
|
|
||||||
# if it wasn't, then this has no effect.
|
|
||||||
include_once_on = False
|
|
||||||
--- cloudinit/util.py.orig
|
|
||||||
+++ cloudinit/util.py
|
|
||||||
@@ -1177,7 +1177,7 @@ def read_cc_from_cmdline(cmdline=None):
|
|
||||||
if end < 0:
|
|
||||||
end = clen
|
|
||||||
tokens.append(
|
|
||||||
- parse.unquote(cmdline[begin + begin_l : end].lstrip()).replace(
|
|
||||||
+ parse.unquote(cmdline[begin + begin_l: end].lstrip()).replace(
|
|
||||||
"\\n", "\n"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -1724,7 +1724,7 @@ def get_output_cfg(cfg, mode):
|
|
||||||
found = False
|
|
||||||
for s in swlist:
|
|
||||||
if val.startswith(s):
|
|
||||||
- val = "%s %s" % (s, val[len(s) :].strip())
|
|
||||||
+ val = "%s %s" % (s, val[len(s):].strip())
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
if not found:
|
|
||||||
@@ -2362,7 +2362,7 @@ def shellify(cmdlist, add_header=True):
|
|
||||||
|
|
||||||
def strip_prefix_suffix(line, prefix=None, suffix=None):
|
|
||||||
if prefix and line.startswith(prefix):
|
|
||||||
- line = line[len(prefix) :]
|
|
||||||
+ line = line[len(prefix):]
|
|
||||||
if suffix and line.endswith(suffix):
|
|
||||||
line = line[: -len(suffix)]
|
|
||||||
return line
|
|
||||||
@@ -2942,7 +2942,7 @@ def human2bytes(size):
|
|
||||||
for m in mpliers:
|
|
||||||
if size.endswith(m):
|
|
||||||
mplier = m
|
|
||||||
- num = size[0 : -len(m)]
|
|
||||||
+ num = size[0: -len(m)]
|
|
||||||
|
|
||||||
try:
|
|
||||||
num = float(num)
|
|
||||||
@@ -3022,12 +3022,12 @@ def rootdev_from_cmdline(cmdline):
|
|
||||||
if found.startswith("/dev/"):
|
|
||||||
return found
|
|
||||||
if found.startswith("LABEL="):
|
|
||||||
- return "/dev/disk/by-label/" + found[len("LABEL=") :]
|
|
||||||
+ return "/dev/disk/by-label/" + found[len("LABEL="):]
|
|
||||||
if found.startswith("UUID="):
|
|
||||||
- return "/dev/disk/by-uuid/" + found[len("UUID=") :].lower()
|
|
||||||
+ return "/dev/disk/by-uuid/" + found[len("UUID="):].lower()
|
|
||||||
if found.startswith("PARTUUID="):
|
|
||||||
disks_path = (
|
|
||||||
- "/dev/disk/by-partuuid/" + found[len("PARTUUID=") :].lower()
|
|
||||||
+ "/dev/disk/by-partuuid/" + found[len("PARTUUID="):].lower()
|
|
||||||
)
|
|
||||||
if os.path.exists(disks_path):
|
|
||||||
return disks_path
|
|
||||||
--- setup.py.orig
|
|
||||||
+++ setup.py
|
|
||||||
@@ -187,7 +187,7 @@ elif os.path.isfile("/etc/system-release
|
|
||||||
else:
|
|
||||||
# String formatted CPE
|
|
||||||
inc = 1
|
|
||||||
- (cpe_vendor, cpe_product, cpe_version) = cpe_data[2 + inc : 5 + inc]
|
|
||||||
+ (cpe_vendor, cpe_product, cpe_version) = cpe_data[2 + inc: 5 + inc]
|
|
||||||
if cpe_vendor == "amazon":
|
|
||||||
USR_LIB_EXEC = "usr/libexec"
|
|
||||||
|
|
||||||
--- tests/unittests/helpers.py.orig
|
|
||||||
+++ tests/unittests/helpers.py
|
|
||||||
@@ -265,7 +265,7 @@ class FilesystemMockingTestCase(Resource
|
|
||||||
real_root = os.path.join(real_root, "roots", example_root)
|
|
||||||
for (dir_path, _dirnames, filenames) in os.walk(real_root):
|
|
||||||
real_path = dir_path
|
|
||||||
- make_path = rebase_path(real_path[len(real_root) :], target_root)
|
|
||||||
+ make_path = rebase_path(real_path[len(real_root):], target_root)
|
|
||||||
util.ensure_dir(make_path)
|
|
||||||
for f in filenames:
|
|
||||||
real_path = util.abs_join(real_path, f)
|
|
||||||
@@ -469,7 +469,7 @@ def dir2dict(startdir, prefix=None):
|
|
||||||
for root, _dirs, files in os.walk(startdir):
|
|
||||||
for fname in files:
|
|
||||||
fpath = os.path.join(root, fname)
|
|
||||||
- key = fpath[len(prefix) :]
|
|
||||||
+ key = fpath[len(prefix):]
|
|
||||||
flist[key] = util.load_file(fpath)
|
|
||||||
return flist
|
|
||||||
|
|
||||||
--- tests/unittests/reporting/test_reporting_hyperv.py.orig
|
|
||||||
+++ tests/unittests/reporting/test_reporting_hyperv.py
|
|
||||||
@@ -293,7 +293,7 @@ class TextKvpReporter(CiTestCase):
|
|
||||||
reporter,
|
|
||||||
2,
|
|
||||||
[
|
|
||||||
- log_content[-azure.MAX_LOG_TO_KVP_LENGTH :].encode(),
|
|
||||||
+ log_content[-azure.MAX_LOG_TO_KVP_LENGTH:].encode(),
|
|
||||||
extra_content.encode(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
--- tests/unittests/sources/test_configdrive.py.orig
|
|
||||||
+++ tests/unittests/sources/test_configdrive.py
|
|
||||||
@@ -412,7 +412,7 @@ class TestConfigDriveDataSource(CiTestCa
|
|
||||||
}
|
|
||||||
for name, dev_name in name_tests.items():
|
|
||||||
with ExitStack() as mocks:
|
|
||||||
- provided_name = dev_name[len("/dev/") :]
|
|
||||||
+ provided_name = dev_name[len("/dev/"):]
|
|
||||||
provided_name = "s" + provided_name[1:]
|
|
||||||
find_mock = mocks.enter_context(
|
|
||||||
mock.patch.object(
|
|
||||||
--- tests/unittests/sources/test_maas.py.orig
|
|
||||||
+++ tests/unittests/sources/test_maas.py
|
|
||||||
@@ -131,7 +131,7 @@ class TestMAASDataSource(CiTestCase):
|
|
||||||
if not url.startswith(prefix):
|
|
||||||
raise ValueError("unexpected call %s" % url)
|
|
||||||
|
|
||||||
- short = url[len(prefix) :]
|
|
||||||
+ short = url[len(prefix):]
|
|
||||||
if short not in data:
|
|
||||||
raise url_helper.UrlError("not found", code=404, url=url)
|
|
||||||
return url_helper.StringResponse(data[short])
|
|
||||||
--- tests/unittests/sources/test_smartos.py.orig
|
|
||||||
+++ tests/unittests/sources/test_smartos.py
|
|
||||||
@@ -766,7 +766,7 @@ class ShortReader:
|
|
||||||
rsize = next_null - self.index + 1
|
|
||||||
i = self.index
|
|
||||||
self.index += rsize
|
|
||||||
- ret = self.data[i : i + rsize]
|
|
||||||
+ ret = self.data[i: i + rsize]
|
|
||||||
if len(ret) and ret[-1:] == self.endbyte:
|
|
||||||
ret = ret[:-1]
|
|
||||||
return ret
|
|
14
cloud-init-lint-set-interpreter.patch
Normal file
14
cloud-init-lint-set-interpreter.patch
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
--- tools/run-lint.orig
|
||||||
|
+++ tools/run-lint
|
||||||
|
@@ -13,7 +13,10 @@ else
|
||||||
|
files=( "$@" )
|
||||||
|
fi
|
||||||
|
|
||||||
|
-cmd=( "python3" -m "flake8" "${files[@]}" )
|
||||||
|
+if [ -z "$PYTHON" ]; then
|
||||||
|
+ PYTHON="python3"
|
||||||
|
+fi
|
||||||
|
+cmd=( "$PYTHON" -m "flake8" "${files[@]}" )
|
||||||
|
|
||||||
|
echo "Running: " "${cmd[@]}" 1>&2
|
||||||
|
exec "${cmd[@]}"
|
19
cloud-init-needs-action.patch
Normal file
19
cloud-init-needs-action.patch
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
--- cloudinit/cmd/main.py.orig
|
||||||
|
+++ cloudinit/cmd/main.py
|
||||||
|
@@ -1334,8 +1334,14 @@ def all_stages(parser):
|
||||||
|
|
||||||
|
def sub_main(args):
|
||||||
|
|
||||||
|
- # Subparsers.required = True and each subparser sets action=(name, functor)
|
||||||
|
- (name, functor) = args.action
|
||||||
|
+ try:
|
||||||
|
+ # Subparsers.required = True
|
||||||
|
+ # and each subparser sets action=(name, functor)
|
||||||
|
+ (name, functor) = args.action
|
||||||
|
+ except AttributeError:
|
||||||
|
+ print('No Subcommand specified. Please specify a subcommand '
|
||||||
|
+ 'in addition to the option')
|
||||||
|
+ sys.exit(1)
|
||||||
|
|
||||||
|
# Setup basic logging for cloud-init:
|
||||||
|
# - for cloud-init stages if --debug
|
@@ -1,27 +0,0 @@
|
|||||||
--- cloudinit/net/network_manager.py.orig
|
|
||||||
+++ cloudinit/net/network_manager.py
|
|
||||||
@@ -9,7 +9,6 @@
|
|
||||||
import configparser
|
|
||||||
import io
|
|
||||||
import itertools
|
|
||||||
-import os
|
|
||||||
import uuid
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
@@ -401,7 +400,6 @@ def available(target=None):
|
|
||||||
# It is imported here to avoid circular import
|
|
||||||
from cloudinit.distros import uses_systemd
|
|
||||||
|
|
||||||
- config_present = os.path.isfile(subp.target_path(target, path=NM_CFG_FILE))
|
|
||||||
nmcli_present = subp.which("nmcli", target=target)
|
|
||||||
service_active = True
|
|
||||||
if uses_systemd():
|
|
||||||
@@ -410,7 +408,7 @@ def available(target=None):
|
|
||||||
except subp.ProcessExecutionError:
|
|
||||||
service_active = False
|
|
||||||
|
|
||||||
- return config_present and bool(nmcli_present) and service_active
|
|
||||||
+ return bool(nmcli_present) and service_active
|
|
||||||
|
|
||||||
|
|
||||||
# vi: ts=4 expandtab
|
|
@@ -1,15 +1,26 @@
|
|||||||
|
--- tests/unittests/test_ds_identify.py.orig
|
||||||
|
+++ tests/unittests/test_ds_identify.py
|
||||||
|
@@ -951,7 +951,7 @@ class TestDsIdentify(DsIdentifyBase):
|
||||||
|
|
||||||
|
nova does not identify itself on platforms other than intel.
|
||||||
|
https://bugs.launchpad.net/cloud-init/+bugs?field.tag=dsid-nova"""
|
||||||
|
-
|
||||||
|
+ return
|
||||||
|
data = copy.deepcopy(VALID_CFG["OpenStack"])
|
||||||
|
del data["files"][P_PRODUCT_NAME]
|
||||||
|
data.update(
|
||||||
--- tools/ds-identify.orig
|
--- tools/ds-identify.orig
|
||||||
+++ tools/ds-identify
|
+++ tools/ds-identify
|
||||||
@@ -95,7 +95,7 @@ DI_MAIN=${DI_MAIN:-main}
|
@@ -101,7 +101,7 @@ DI_MAIN=${DI_MAIN:-main}
|
||||||
DI_BLKID_EXPORT_OUT=""
|
DI_BLKID_EXPORT_OUT=""
|
||||||
DI_GEOM_LABEL_STATUS_OUT=""
|
DI_GEOM_LABEL_STATUS_OUT=""
|
||||||
DI_DEFAULT_POLICY="search,found=all,maybe=all,notfound=${DI_DISABLED}"
|
DI_DEFAULT_POLICY="search,found=all,maybe=none,notfound=${DI_DISABLED}"
|
||||||
-DI_DEFAULT_POLICY_NO_DMI="search,found=all,maybe=all,notfound=${DI_ENABLED}"
|
-DI_DEFAULT_POLICY_NO_DMI="search,found=all,maybe=none,notfound=${DI_ENABLED}"
|
||||||
+DI_DEFAULT_POLICY_NO_DMI="search,found=all,maybe=all,notfound=${DI_DISABLED}"
|
+DI_DEFAULT_POLICY_NO_DMI="search,found=all,maybe=none,notfound=${DI_DISABLED}"
|
||||||
DI_DMI_BOARD_NAME=""
|
DI_DMI_BOARD_NAME=""
|
||||||
DI_DMI_CHASSIS_ASSET_TAG=""
|
DI_DMI_CHASSIS_ASSET_TAG=""
|
||||||
DI_DMI_PRODUCT_NAME=""
|
DI_DMI_PRODUCT_NAME=""
|
||||||
@@ -1261,12 +1261,6 @@ dscheck_OpenStack() {
|
@@ -1474,11 +1474,6 @@ dscheck_OpenStack() {
|
||||||
return ${DS_FOUND}
|
return ${DS_FOUND}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -18,18 +29,6 @@
|
|||||||
- i?86|x86_64) :;;
|
- i?86|x86_64) :;;
|
||||||
- *) return ${DS_MAYBE};;
|
- *) return ${DS_MAYBE};;
|
||||||
- esac
|
- esac
|
||||||
-
|
|
||||||
return ${DS_NOT_FOUND}
|
return ${DS_NOT_FOUND}
|
||||||
}
|
}
|
||||||
|
|
||||||
--- tests/unittests/test_ds_identify.py.orig
|
|
||||||
+++ tests/unittests/test_ds_identify.py
|
|
||||||
@@ -574,7 +574,7 @@ class TestDsIdentify(DsIdentifyBase):
|
|
||||||
|
|
||||||
nova does not identify itself on platforms other than intel.
|
|
||||||
https://bugs.launchpad.net/cloud-init/+bugs?field.tag=dsid-nova"""
|
|
||||||
-
|
|
||||||
+ return
|
|
||||||
data = copy.deepcopy(VALID_CFG["OpenStack"])
|
|
||||||
del data["files"][P_PRODUCT_NAME]
|
|
||||||
data.update(
|
|
||||||
|
308
cloud-init-no-single-process.patch
Normal file
308
cloud-init-no-single-process.patch
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
--- cloudinit/cmd/status.py.orig
|
||||||
|
+++ cloudinit/cmd/status.py
|
||||||
|
@@ -318,9 +318,8 @@ def systemd_failed(wait: bool) -> bool:
|
||||||
|
for service in [
|
||||||
|
"cloud-final.service",
|
||||||
|
"cloud-config.service",
|
||||||
|
- "cloud-init-network.service",
|
||||||
|
+ "cloud-init.service",
|
||||||
|
"cloud-init-local.service",
|
||||||
|
- "cloud-init-main.service",
|
||||||
|
]:
|
||||||
|
try:
|
||||||
|
stdout = query_systemctl(
|
||||||
|
--- cloudinit/config/cc_mounts.py.orig
|
||||||
|
+++ cloudinit/config/cc_mounts.py
|
||||||
|
@@ -519,7 +519,7 @@ def handle(name: str, cfg: Config, cloud
|
||||||
|
# fs_spec, fs_file, fs_vfstype, fs_mntops, fs-freq, fs_passno
|
||||||
|
uses_systemd = cloud.distro.uses_systemd()
|
||||||
|
default_mount_options = (
|
||||||
|
- "defaults,nofail,x-systemd.after=cloud-init-network.service,_netdev"
|
||||||
|
+ "defaults,nofail,x-systemd.after=cloud-init.service,_netdev"
|
||||||
|
if uses_systemd
|
||||||
|
else "defaults,nobootwait"
|
||||||
|
)
|
||||||
|
--- cloudinit/config/schemas/schema-cloud-config-v1.json.orig
|
||||||
|
+++ cloudinit/config/schemas/schema-cloud-config-v1.json
|
||||||
|
@@ -2034,12 +2034,12 @@
|
||||||
|
},
|
||||||
|
"mount_default_fields": {
|
||||||
|
"type": "array",
|
||||||
|
- "description": "Default mount configuration for any mount entry with less than 6 options provided. When specified, 6 items are required and represent ``/etc/fstab`` entries. Default: ``defaults,nofail,x-systemd.after=cloud-init-network.service,_netdev``.",
|
||||||
|
+ "description": "Default mount configuration for any mount entry with less than 6 options provided. When specified, 6 items are required and represent ``/etc/fstab`` entries. Default: ``defaults,nofail,x-systemd.after=cloud-init.service,_netdev``.",
|
||||||
|
"default": [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"auto",
|
||||||
|
- "defaults,nofail,x-systemd.after=cloud-init-network.service",
|
||||||
|
+ "defaults,nofail,x-systemd.after=cloud-init.service",
|
||||||
|
"0",
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
--- systemd/cloud-config.service.orig
|
||||||
|
+++ systemd/cloud-config.service
|
||||||
|
@@ -9,14 +9,7 @@ ConditionEnvironment=!KERNEL_CMDLINE=clo
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
-# This service is a shim which preserves systemd ordering while allowing a
|
||||||
|
-# single Python process to run cloud-init's logic. This works by communicating
|
||||||
|
-# with the cloud-init process over a unix socket to tell the process that this
|
||||||
|
-# stage can start, and then wait on a return socket until the cloud-init
|
||||||
|
-# process has completed this stage. The output from the return socket is piped
|
||||||
|
-# into a shell so that the process can send a completion message (defaults to
|
||||||
|
-# "done", otherwise includes an error message) and an exit code to systemd.
|
||||||
|
-ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/config.sock -s /run/cloud-init/share/config-return.sock | sh'
|
||||||
|
+ExecStart=/usr/bin/cloud-init modules --mode=config
|
||||||
|
RemainAfterExit=yes
|
||||||
|
TimeoutSec=0
|
||||||
|
|
||||||
|
--- systemd/cloud-config.target.orig
|
||||||
|
+++ systemd/cloud-config.target
|
||||||
|
@@ -14,5 +14,5 @@
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Cloud-config availability
|
||||||
|
-Wants=cloud-init-local.service cloud-init-network.service
|
||||||
|
-After=cloud-init-local.service cloud-init-network.service
|
||||||
|
+Wants=cloud-init-local.service cloud-init.service
|
||||||
|
+After=cloud-init-local.service cloud-init.service
|
||||||
|
--- systemd/cloud-final.service.orig
|
||||||
|
+++ systemd/cloud-final.service
|
||||||
|
@@ -12,16 +12,10 @@ ConditionEnvironment=!KERNEL_CMDLINE=clo
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
-# This service is a shim which preserves systemd ordering while allowing a
|
||||||
|
-# single Python process to run cloud-init's logic. This works by communicating
|
||||||
|
-# with the cloud-init process over a unix socket to tell the process that this
|
||||||
|
-# stage can start, and then wait on a return socket until the cloud-init
|
||||||
|
-# process has completed this stage. The output from the return socket is piped
|
||||||
|
-# into a shell so that the process can send a completion message (defaults to
|
||||||
|
-# "done", otherwise includes an error message) and an exit code to systemd.
|
||||||
|
-ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/final.sock -s /run/cloud-init/share/final-return.sock | sh'
|
||||||
|
+ExecStart=/usr/bin/cloud-init modules --mode=final
|
||||||
|
RemainAfterExit=yes
|
||||||
|
TimeoutSec=0
|
||||||
|
+KillMode=process
|
||||||
|
TasksMax=infinity
|
||||||
|
|
||||||
|
# Output needs to appear in instance console output
|
||||||
|
--- systemd/cloud-init-main.service.tmpl.orig
|
||||||
|
+++ systemd/cloud-init-main.service.tmpl
|
||||||
|
@@ -1,42 +0,0 @@
|
||||||
|
-## template:jinja
|
||||||
|
-# systemd ordering resources
|
||||||
|
-# ==========================
|
||||||
|
-# https://systemd.io/NETWORK_ONLINE/
|
||||||
|
-# https://docs.cloud-init.io/en/latest/explanation/boot.html
|
||||||
|
-# https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
|
||||||
|
-# https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html
|
||||||
|
-# https://www.freedesktop.org/software/systemd/man/latest/systemd-remount-fs.service.html
|
||||||
|
-[Unit]
|
||||||
|
-Description=Cloud-init: Single Process
|
||||||
|
-{% if variant in ["almalinux", "cloudlinux", "ubuntu", "unknown", "debian", "rhel"] %}
|
||||||
|
-DefaultDependencies=no
|
||||||
|
-{% endif %}
|
||||||
|
-{% if variant in ["almalinux", "cloudlinux", "rhel"] %}
|
||||||
|
-Requires=dbus.socket
|
||||||
|
-After=dbus.socket
|
||||||
|
-{% endif %}
|
||||||
|
-
|
||||||
|
-After=systemd-remount-fs.service
|
||||||
|
-Before=cloud-init-local.service
|
||||||
|
-Before=shutdown.target
|
||||||
|
-Conflicts=shutdown.target
|
||||||
|
-RequiresMountsFor=/var/lib/cloud
|
||||||
|
-ConditionPathExists=!/etc/cloud/cloud-init.disabled
|
||||||
|
-ConditionKernelCommandLine=!cloud-init=disabled
|
||||||
|
-ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
|
||||||
|
-
|
||||||
|
-[Service]
|
||||||
|
-Type=notify
|
||||||
|
-ExecStart=/usr/bin/cloud-init --all-stages
|
||||||
|
-KillMode=process
|
||||||
|
-TasksMax=infinity
|
||||||
|
-TimeoutStartSec=infinity
|
||||||
|
-{% if variant in ["almalinux", "cloudlinux", "rhel"] %}
|
||||||
|
-ExecStartPre=/sbin/restorecon /run/cloud-init
|
||||||
|
-{% endif %}
|
||||||
|
-
|
||||||
|
-# Output needs to appear in instance console output
|
||||||
|
-StandardOutput=journal+console
|
||||||
|
-
|
||||||
|
-[Install]
|
||||||
|
-WantedBy=cloud-init.target
|
||||||
|
--- systemd/cloud-init-network.service.tmpl.orig
|
||||||
|
+++ systemd/cloud-init-network.service.tmpl
|
||||||
|
@@ -1,64 +0,0 @@
|
||||||
|
-## template:jinja
|
||||||
|
-[Unit]
|
||||||
|
-# https://docs.cloud-init.io/en/latest/explanation/boot.html
|
||||||
|
-Description=Cloud-init: Network Stage
|
||||||
|
-{% if variant not in ["almalinux", "cloudlinux", "photon", "rhel"] %}
|
||||||
|
-DefaultDependencies=no
|
||||||
|
-{% endif %}
|
||||||
|
-Wants=cloud-init-local.service
|
||||||
|
-Wants=sshd-keygen.service
|
||||||
|
-Wants=sshd.service
|
||||||
|
-After=cloud-init-local.service
|
||||||
|
-{% if variant not in ["ubuntu"] %}
|
||||||
|
-After=systemd-networkd-wait-online.service
|
||||||
|
-{% endif %}
|
||||||
|
-{% if variant in ["ubuntu", "unknown", "debian"] %}
|
||||||
|
-After=networking.service
|
||||||
|
-{% endif %}
|
||||||
|
-{% if variant in ["almalinux", "centos", "cloudlinux", "eurolinux", "fedora",
|
||||||
|
- "miraclelinux", "openeuler", "OpenCloudOS", "openmandriva", "rhel", "rocky",
|
||||||
|
- "suse", "TencentOS", "virtuozzo"] %}
|
||||||
|
-After=NetworkManager.service
|
||||||
|
-After=NetworkManager-wait-online.service
|
||||||
|
-{% endif %}
|
||||||
|
-{% if variant in ["suse"] %}
|
||||||
|
-After=wicked.service
|
||||||
|
-# setting hostname via hostnamectl depends on dbus, which otherwise
|
||||||
|
-# would not be guaranteed at this point.
|
||||||
|
-After=dbus.service
|
||||||
|
-{% endif %}
|
||||||
|
-Before=network-online.target
|
||||||
|
-Before=sshd-keygen.service
|
||||||
|
-Before=sshd.service
|
||||||
|
-Before=systemd-user-sessions.service
|
||||||
|
-{% if variant in ["ubuntu", "unknown", "debian"] %}
|
||||||
|
-Before=sysinit.target
|
||||||
|
-Before=shutdown.target
|
||||||
|
-Conflicts=shutdown.target
|
||||||
|
-{% endif %}
|
||||||
|
-{% if variant in ["suse"] %}
|
||||||
|
-Before=shutdown.target
|
||||||
|
-Conflicts=shutdown.target
|
||||||
|
-{% endif %}
|
||||||
|
-ConditionPathExists=!/etc/cloud/cloud-init.disabled
|
||||||
|
-ConditionKernelCommandLine=!cloud-init=disabled
|
||||||
|
-ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
|
||||||
|
-
|
||||||
|
-[Service]
|
||||||
|
-Type=oneshot
|
||||||
|
-# This service is a shim which preserves systemd ordering while allowing a
|
||||||
|
-# single Python process to run cloud-init's logic. This works by communicating
|
||||||
|
-# with the cloud-init process over a unix socket to tell the process that this
|
||||||
|
-# stage can start, and then wait on a return socket until the cloud-init
|
||||||
|
-# process has completed this stage. The output from the return socket is piped
|
||||||
|
-# into a shell so that the process can send a completion message (defaults to
|
||||||
|
-# "done", otherwise includes an error message) and an exit code to systemd.
|
||||||
|
-ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/network.sock -s /run/cloud-init/share/network-return.sock | sh'
|
||||||
|
-RemainAfterExit=yes
|
||||||
|
-TimeoutSec=0
|
||||||
|
-
|
||||||
|
-# Output needs to appear in instance console output
|
||||||
|
-StandardOutput=journal+console
|
||||||
|
-
|
||||||
|
-[Install]
|
||||||
|
-WantedBy=cloud-init.target
|
||||||
|
--- /dev/null
|
||||||
|
+++ systemd/cloud-init.service.tmpl
|
||||||
|
@@ -0,0 +1,55 @@
|
||||||
|
+## template:jinja
|
||||||
|
+[Unit]
|
||||||
|
+# https://docs.cloud-init.io/en/latest/explanation/boot.html
|
||||||
|
+Description=Cloud-init: Network Stage
|
||||||
|
+{% if variant not in ["almalinux", "cloudlinux", "photon", "rhel"] %}
|
||||||
|
+DefaultDependencies=no
|
||||||
|
+{% endif %}
|
||||||
|
+Wants=cloud-init-local.service
|
||||||
|
+Wants=sshd-keygen.service
|
||||||
|
+Wants=sshd.service
|
||||||
|
+After=cloud-init-local.service
|
||||||
|
+After=systemd-networkd-wait-online.service
|
||||||
|
+{% if variant in ["ubuntu", "unknown", "debian"] %}
|
||||||
|
+After=networking.service
|
||||||
|
+{% endif %}
|
||||||
|
+{% if variant in ["almalinux", "centos", "cloudlinux", "eurolinux", "fedora",
|
||||||
|
+ "miraclelinux", "openeuler", "OpenCloudOS", "openmandriva", "rhel", "rocky",
|
||||||
|
+ "suse", "TencentOS", "virtuozzo"] %}
|
||||||
|
+
|
||||||
|
+After=NetworkManager.service
|
||||||
|
+After=NetworkManager-wait-online.service
|
||||||
|
+{% endif %}
|
||||||
|
+{% if variant in ["suse"] %}
|
||||||
|
+After=wicked.service
|
||||||
|
+# setting hostname via hostnamectl depends on dbus, which otherwise
|
||||||
|
+# would not be guaranteed at this point.
|
||||||
|
+After=dbus.service
|
||||||
|
+{% endif %}
|
||||||
|
+Before=network-online.target
|
||||||
|
+Before=sshd-keygen.service
|
||||||
|
+Before=sshd.service
|
||||||
|
+Before=systemd-user-sessions.service
|
||||||
|
+{% if variant in ["ubuntu", "unknown", "debian"] %}
|
||||||
|
+Before=sysinit.target
|
||||||
|
+Before=shutdown.target
|
||||||
|
+Conflicts=shutdown.target
|
||||||
|
+{% endif %}
|
||||||
|
+{% if variant in ["suse"] %}
|
||||||
|
+Before=shutdown.target
|
||||||
|
+Conflicts=shutdown.target
|
||||||
|
+{% endif %}
|
||||||
|
+ConditionPathExists=!/etc/cloud/cloud-init.disabled
|
||||||
|
+ConditionKernelCommandLine=!cloud-init=disabled
|
||||||
|
+ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
|
||||||
|
+
|
||||||
|
+[Service]
|
||||||
|
+Type=oneshot
|
||||||
|
+ExecStart=/usr/bin/cloud-init init
|
||||||
|
+RemainAfterExit=yes
|
||||||
|
+TimeoutSec=0
|
||||||
|
+
|
||||||
|
+# Output needs to appear in instance console output
|
||||||
|
+StandardOutput=journal+console
|
||||||
|
+
|
||||||
|
+[Install]
|
||||||
|
--- tests/unittests/config/test_cc_mounts.py.orig
|
||||||
|
+++ tests/unittests/config/test_cc_mounts.py
|
||||||
|
@@ -566,9 +566,9 @@ class TestFstabHandling:
|
||||||
|
LABEL=keepme none ext4 defaults 0 0
|
||||||
|
LABEL=UEFI
|
||||||
|
/dev/sda4 /mnt2 auto nofail,comment=cloudconfig 1 2
|
||||||
|
- /dev/sda5 /mnt3 auto defaults,nofail,x-systemd.after=cloud-init-network.service,_netdev,comment=cloudconfig 0 2
|
||||||
|
+ /dev/sda5 /mnt3 auto defaults,nofail,x-systemd.after=cloud-init.service,_netdev,comment=cloudconfig 0 2
|
||||||
|
/dev/sda1 /mnt xfs auto,comment=cloudconfig 0 2
|
||||||
|
- /dev/sda3 /mnt4 btrfs defaults,nofail,x-systemd.after=cloud-init-network.service,_netdev,comment=cloudconfig 0 2
|
||||||
|
+ /dev/sda3 /mnt4 btrfs defaults,nofail,x-systemd.after=cloud-init.service,_netdev,comment=cloudconfig 0 2
|
||||||
|
/dev/sdb1 none swap sw,comment=cloudconfig 0 0
|
||||||
|
""" # noqa: E501
|
||||||
|
).strip()
|
||||||
|
--- systemd/cloud-init-local.service.tmpl.orig
|
||||||
|
+++ systemd/cloud-init-local.service.tmpl
|
||||||
|
@@ -7,6 +7,7 @@ DefaultDependencies=no
|
||||||
|
{% endif %}
|
||||||
|
Wants=network-pre.target
|
||||||
|
After=hv_kvp_daemon.service
|
||||||
|
+After=systemd-remount-fs.service
|
||||||
|
Before=network-pre.target
|
||||||
|
Before=shutdown.target
|
||||||
|
{% if variant in ["almalinux", "cloudlinux", "rhel"] %}
|
||||||
|
@@ -16,6 +17,7 @@ Before=firewalld.target
|
||||||
|
Before=sysinit.target
|
||||||
|
{% endif %}
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
+RequiresMountsFor=/var/lib/cloud
|
||||||
|
ConditionPathExists=!/etc/cloud/cloud-init.disabled
|
||||||
|
ConditionKernelCommandLine=!cloud-init=disabled
|
||||||
|
ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled
|
||||||
|
@@ -25,14 +27,7 @@ Type=oneshot
|
||||||
|
{% if variant in ["almalinux", "cloudlinux", "rhel"] %}
|
||||||
|
ExecStartPre=/sbin/restorecon /run/cloud-init
|
||||||
|
{% endif %}
|
||||||
|
-# This service is a shim which preserves systemd ordering while allowing a
|
||||||
|
-# single Python process to run cloud-init's logic. This works by communicating
|
||||||
|
-# with the cloud-init process over a unix socket to tell the process that this
|
||||||
|
-# stage can start, and then wait on a return socket until the cloud-init
|
||||||
|
-# process has completed this stage. The output from the return socket is piped
|
||||||
|
-# into a shell so that the process can send a completion message (defaults to
|
||||||
|
-# "done", otherwise includes an error message) and an exit code to systemd.
|
||||||
|
-ExecStart=sh -c 'echo "start" | nc -Uu -W1 /run/cloud-init/share/local.sock -s /run/cloud-init/share/local-return.sock | sh'
|
||||||
|
+ExecStart=/usr/bin/cloud-init init --local
|
||||||
|
RemainAfterExit=yes
|
||||||
|
TimeoutSec=0
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
--- cloudinit/sources/DataSourceOracle.py.orig
|
--- cloudinit/sources/DataSourceOracle.py.orig
|
||||||
+++ cloudinit/sources/DataSourceOracle.py
|
+++ cloudinit/sources/DataSourceOracle.py
|
||||||
@@ -204,6 +204,8 @@ class DataSourceOracle(sources.DataSourc
|
@@ -274,6 +274,8 @@ class DataSourceOracle(sources.DataSourc
|
||||||
|
|
||||||
def _is_iscsi_root(self) -> bool:
|
def _is_iscsi_root(self) -> bool:
|
||||||
"""Return whether we are on a iscsi machine."""
|
"""Return whether we are on a iscsi machine."""
|
||||||
@@ -11,10 +11,11 @@
|
|||||||
def _get_iscsi_config(self) -> dict:
|
def _get_iscsi_config(self) -> dict:
|
||||||
--- tests/unittests/sources/test_oracle.py.orig
|
--- tests/unittests/sources/test_oracle.py.orig
|
||||||
+++ tests/unittests/sources/test_oracle.py
|
+++ tests/unittests/sources/test_oracle.py
|
||||||
@@ -996,6 +996,7 @@ class TestNonIscsiRoot_GetDataBehaviour:
|
@@ -1331,7 +1331,7 @@ class TestNonIscsiRoot_GetDataBehaviour:
|
||||||
def test_read_opc_metadata_called_with_ephemeral_dhcp(
|
def test_read_opc_metadata_called_with_ephemeral_dhcp(
|
||||||
self, m_find_fallback_nic, m_EphemeralDHCPv4, oracle_ds
|
self, m_find_fallback_nic, m_ephemeral_network, oracle_ds
|
||||||
):
|
):
|
||||||
|
-
|
||||||
+ return
|
+ return
|
||||||
in_context_manager = False
|
in_context_manager = False
|
||||||
|
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
--- cloudinit/config/cc_package_update_upgrade_install.py.orig
|
|
||||||
+++ cloudinit/config/cc_package_update_upgrade_install.py
|
|
||||||
@@ -18,7 +18,7 @@ from cloudinit.config.schema import Meta
|
|
||||||
from cloudinit.distros import ALL_DISTROS
|
|
||||||
from cloudinit.settings import PER_INSTANCE
|
|
||||||
|
|
||||||
-REBOOT_FILE = "/var/run/reboot-required"
|
|
||||||
+REBOOT_FILES = ("/var/run/reboot-required", "/run/reboot-needed")
|
|
||||||
REBOOT_CMD = ["/sbin/reboot"]
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION = """\
|
|
||||||
@@ -120,11 +120,14 @@ def handle(name: str, cfg: Config, cloud
|
|
||||||
# kernel and openssl (possibly some other packages)
|
|
||||||
# write a file /var/run/reboot-required after upgrading.
|
|
||||||
# if that file exists and configured, then just stop right now and reboot
|
|
||||||
- reboot_fn_exists = os.path.isfile(REBOOT_FILE)
|
|
||||||
+ for reboot_marker in REBOOT_FILES:
|
|
||||||
+ reboot_fn_exists = os.path.isfile(reboot_marker)
|
|
||||||
+ if reboot_fn_exists:
|
|
||||||
+ break
|
|
||||||
if (upgrade or pkglist) and reboot_if_required and reboot_fn_exists:
|
|
||||||
try:
|
|
||||||
LOG.warning(
|
|
||||||
- "Rebooting after upgrade or install per %s", REBOOT_FILE
|
|
||||||
+ "Rebooting after upgrade or install per %s", reboot_marker
|
|
||||||
)
|
|
||||||
# Flush the above warning + anything else out...
|
|
||||||
logging.flushLoggers(LOG)
|
|
@@ -1,374 +0,0 @@
|
|||||||
--- tests/unittests/config/test_cc_yum_add_repo.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_yum_add_repo.py
|
|
||||||
@@ -2,7 +2,7 @@
|
|
||||||
|
|
||||||
import configparser
|
|
||||||
import logging
|
|
||||||
-import re
|
|
||||||
+# import re
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
@@ -137,10 +137,10 @@ class TestAddYumRepoSchema:
|
|
||||||
{"yum_repo_dir": True},
|
|
||||||
"yum_repo_dir: True is not of type 'string'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"yum_repos": {}},
|
|
||||||
- re.escape("yum_repos: {} does not have enough properties"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"yum_repos": {}},
|
|
||||||
+ # re.escape("yum_repos: {} does not have enough properties"),
|
|
||||||
+ # ),
|
|
||||||
# baseurl required
|
|
||||||
(
|
|
||||||
{"yum_repos": {"My-Repo": {}}},
|
|
||||||
--- tests/unittests/config/test_cc_apk_configure.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_apk_configure.py
|
|
||||||
@@ -352,11 +352,11 @@ class TestApkConfigureSchema:
|
|
||||||
" allowed ('bogus' was unexpected)"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apk_repos": {"alpine_repo": {}}},
|
|
||||||
- "apk_repos.alpine_repo: 'version' is a required property,"
|
|
||||||
- " apk_repos.alpine_repo: {} does not have enough properties",
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apk_repos": {"alpine_repo": {}}},
|
|
||||||
+ # "apk_repos.alpine_repo: 'version' is a required property,"
|
|
||||||
+ # " apk_repos.alpine_repo: {} does not have enough properties",
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apk_repos": {"alpine_repo": True}},
|
|
||||||
"apk_repos.alpine_repo: True is not of type 'object', 'null'",
|
|
||||||
@@ -366,10 +366,10 @@ class TestApkConfigureSchema:
|
|
||||||
"apk_repos.preserve_repositories: 'wrongtype' is not of type"
|
|
||||||
" 'boolean'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apk_repos": {}},
|
|
||||||
- "apk_repos: {} does not have enough properties",
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apk_repos": {}},
|
|
||||||
+ # "apk_repos: {} does not have enough properties",
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apk_repos": {"local_repo_base_url": None}},
|
|
||||||
"apk_repos.local_repo_base_url: None is not of type 'string'",
|
|
||||||
--- tests/unittests/config/test_cc_apt_configure.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_apt_configure.py
|
|
||||||
@@ -32,7 +32,7 @@ class TestAPTConfigureSchema:
|
|
||||||
" ('boguskey' was unexpected)"
|
|
||||||
),
|
|
||||||
),
|
|
||||||
- ({"apt": {}}, "apt: {} does not have enough properties"),
|
|
||||||
+ # ({"apt": {}}, "apt: {} does not have enough properties"),
|
|
||||||
(
|
|
||||||
{"apt": {"preserve_sources_list": 1}},
|
|
||||||
"apt.preserve_sources_list: 1 is not of type 'boolean'",
|
|
||||||
@@ -41,10 +41,10 @@ class TestAPTConfigureSchema:
|
|
||||||
{"apt": {"disable_suites": 1}},
|
|
||||||
"apt.disable_suites: 1 is not of type 'array'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apt": {"disable_suites": []}},
|
|
||||||
- re.escape("apt.disable_suites: [] is too short"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apt": {"disable_suites": []}},
|
|
||||||
+ # re.escape("apt.disable_suites: [] is too short"),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apt": {"disable_suites": [1]}},
|
|
||||||
"apt.disable_suites.0: 1 is not of type 'string'",
|
|
||||||
@@ -61,18 +61,18 @@ class TestAPTConfigureSchema:
|
|
||||||
{"apt": {"primary": "nonlist"}},
|
|
||||||
"apt.primary: 'nonlist' is not of type 'array'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apt": {"primary": []}},
|
|
||||||
- re.escape("apt.primary: [] is too short"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apt": {"primary": []}},
|
|
||||||
+ # re.escape("apt.primary: [] is too short"),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apt": {"primary": ["nonobj"]}},
|
|
||||||
"apt.primary.0: 'nonobj' is not of type 'object'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apt": {"primary": [{}]}},
|
|
||||||
- "apt.primary.0: 'arches' is a required property",
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apt": {"primary": [{}]}},
|
|
||||||
+ # "apt.primary.0: 'arches' is a required property",
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apt": {"primary": [{"boguskey": True}]}},
|
|
||||||
re.escape(
|
|
||||||
@@ -98,10 +98,10 @@ class TestAPTConfigureSchema:
|
|
||||||
},
|
|
||||||
"apt.primary.0.search: 'non-array' is not of type 'array'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apt": {"primary": [{"arches": ["amd64"], "search": []}]}},
|
|
||||||
- re.escape("apt.primary.0.search: [] is too short"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apt": {"primary": [{"arches": ["amd64"], "search": []}]}},
|
|
||||||
+ # re.escape("apt.primary.0.search: [] is too short"),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{
|
|
||||||
"apt": {
|
|
||||||
@@ -130,10 +130,10 @@ class TestAPTConfigureSchema:
|
|
||||||
{"apt": {"debconf_selections": True}},
|
|
||||||
"apt.debconf_selections: True is not of type 'object'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apt": {"debconf_selections": {}}},
|
|
||||||
- "apt.debconf_selections: {} does not have enough properties",
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apt": {"debconf_selections": {}}},
|
|
||||||
+ # "apt.debconf_selections: {} does not have enough properties",
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apt": {"sources_list": True}},
|
|
||||||
"apt.sources_list: True is not of type 'string'",
|
|
||||||
@@ -166,10 +166,10 @@ class TestAPTConfigureSchema:
|
|
||||||
{"apt": {"sources": {"opaquekey": True}}},
|
|
||||||
"apt.sources.opaquekey: True is not of type 'object'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"apt": {"sources": {"opaquekey": {}}}},
|
|
||||||
- "apt.sources.opaquekey: {} does not have enough properties",
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"apt": {"sources": {"opaquekey": {}}}},
|
|
||||||
+ # "apt.sources.opaquekey: {} does not have enough properties",
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"apt": {"sources": {"opaquekey": {"boguskey": True}}}},
|
|
||||||
re.escape(
|
|
||||||
--- tests/unittests/config/test_cc_bootcmd.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_bootcmd.py
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
# This file is part of cloud-init. See LICENSE file for license information.
|
|
||||||
-import re
|
|
||||||
+# import re
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
@@ -128,13 +128,13 @@ class TestBootCMDSchema:
|
|
||||||
"Cloud config schema errors: bootcmd: 1 is not of type"
|
|
||||||
" 'array'",
|
|
||||||
),
|
|
||||||
- ({"bootcmd": []}, re.escape("bootcmd: [] is too short")),
|
|
||||||
- (
|
|
||||||
- {"bootcmd": []},
|
|
||||||
- re.escape(
|
|
||||||
- "Cloud config schema errors: bootcmd: [] is too short"
|
|
||||||
- ),
|
|
||||||
- ),
|
|
||||||
+ # ({"bootcmd": []}, re.escape("bootcmd: [] is too short")),
|
|
||||||
+ # (
|
|
||||||
+ # {"bootcmd": []},
|
|
||||||
+ # re.escape(
|
|
||||||
+ # "Cloud config schema errors: bootcmd: [] is too short"
|
|
||||||
+ # ),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{
|
|
||||||
"bootcmd": [
|
|
||||||
--- tests/unittests/config/test_cc_ca_certs.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_ca_certs.py
|
|
||||||
@@ -394,10 +394,10 @@ class TestCACertsSchema:
|
|
||||||
{"ca_certs": 1},
|
|
||||||
"ca_certs: 1 is not of type 'object'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"ca_certs": {}},
|
|
||||||
- re.escape("ca_certs: {} does not have enough properties"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"ca_certs": {}},
|
|
||||||
+ # re.escape("ca_certs: {} does not have enough properties"),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"ca_certs": {"boguskey": 1}},
|
|
||||||
re.escape(
|
|
||||||
@@ -413,10 +413,10 @@ class TestCACertsSchema:
|
|
||||||
{"ca_certs": {"trusted": [1]}},
|
|
||||||
"ca_certs.trusted.0: 1 is not of type 'string'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"ca_certs": {"trusted": []}},
|
|
||||||
- re.escape("ca_certs.trusted: [] is too short"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"ca_certs": {"trusted": []}},
|
|
||||||
+ # re.escape("ca_certs.trusted: [] is too short"),
|
|
||||||
+ # ),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
@skipUnlessJsonSchema()
|
|
||||||
--- tests/unittests/config/test_cc_chef.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_chef.py
|
|
||||||
@@ -304,10 +304,10 @@ class TestBootCMDSchema:
|
|
||||||
{"chef": 1},
|
|
||||||
"chef: 1 is not of type 'object'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"chef": {}},
|
|
||||||
- re.escape(" chef: {} does not have enough properties"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"chef": {}},
|
|
||||||
+ # re.escape(" chef: {} does not have enough properties"),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"chef": {"boguskey": True}},
|
|
||||||
re.escape(
|
|
||||||
@@ -319,10 +319,10 @@ class TestBootCMDSchema:
|
|
||||||
{"chef": {"directories": 1}},
|
|
||||||
"chef.directories: 1 is not of type 'array'",
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"chef": {"directories": []}},
|
|
||||||
- re.escape("chef.directories: [] is too short"),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"chef": {"directories": []}},
|
|
||||||
+ # re.escape("chef.directories: [] is too short"),
|
|
||||||
+ # ),
|
|
||||||
(
|
|
||||||
{"chef": {"directories": [1]}},
|
|
||||||
"chef.directories.0: 1 is not of type 'string'",
|
|
||||||
--- tests/unittests/config/test_cc_lxd.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_lxd.py
|
|
||||||
@@ -385,7 +385,7 @@ class TestLXDSchema:
|
|
||||||
# Require bridge.mode
|
|
||||||
({"lxd": {"bridge": {}}}, "bridge: 'mode' is a required property"),
|
|
||||||
# Require init or bridge keys
|
|
||||||
- ({"lxd": {}}, "lxd: {} does not have enough properties"),
|
|
||||||
+ # ({"lxd": {}}, "lxd: {} does not have enough properties"),
|
|
||||||
# Require some non-empty preseed config of type string
|
|
||||||
({"lxd": {"preseed": {}}}, "not of type 'string'"),
|
|
||||||
({"lxd": {"preseed": ""}}, None),
|
|
||||||
--- tests/unittests/config/test_cc_mounts.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_mounts.py
|
|
||||||
@@ -583,9 +583,9 @@ class TestMountsSchema:
|
|
||||||
"config, error_msg",
|
|
||||||
[
|
|
||||||
# We expect to see one mount if provided in user-data.
|
|
||||||
- ({"mounts": []}, re.escape("mounts: [] is too short")),
|
|
||||||
+ # ({"mounts": []}, re.escape("mounts: [] is too short")),
|
|
||||||
# Disallow less than 1 item per mount entry
|
|
||||||
- ({"mounts": [[]]}, re.escape("mounts.0: [] is too short")),
|
|
||||||
+ # ({"mounts": [[]]}, re.escape("mounts.0: [] is too short")),
|
|
||||||
# Disallow more than 6 items per mount entry
|
|
||||||
({"mounts": [["1"] * 7]}, "mounts.0:.* is too long"),
|
|
||||||
# Disallow mount_default_fields will anything other than 6 items
|
|
||||||
--- tests/unittests/config/test_cc_package_update_upgrade_install.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_package_update_upgrade_install.py
|
|
||||||
@@ -17,7 +17,7 @@ class TestPackageUpdateUpgradeSchema:
|
|
||||||
# packages list with three entries (2 required)
|
|
||||||
({"packages": ["p1", ["p2", "p3", "p4"]]}, ""),
|
|
||||||
# empty packages list
|
|
||||||
- ({"packages": []}, "is too short"),
|
|
||||||
+ # ({"packages": []}, "is too short"),
|
|
||||||
(
|
|
||||||
{"apt_update": False},
|
|
||||||
(
|
|
||||||
--- tests/unittests/config/test_cc_runcmd.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_runcmd.py
|
|
||||||
@@ -90,7 +90,7 @@ class TestRunCmdSchema:
|
|
||||||
({"runcmd": ["echo bye", "echo bye"]}, None),
|
|
||||||
# Invalid schemas
|
|
||||||
({"runcmd": 1}, "1 is not of type 'array'"),
|
|
||||||
- ({"runcmd": []}, r"runcmd: \[\] is too short"),
|
|
||||||
+ # ({"runcmd": []}, r"runcmd: \[\] is too short"),
|
|
||||||
(
|
|
||||||
{
|
|
||||||
"runcmd": [
|
|
||||||
--- tests/unittests/config/test_cc_set_passwords.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_set_passwords.py
|
|
||||||
@@ -715,12 +715,12 @@ class TestSetPasswordsSchema:
|
|
||||||
{"chpasswd": {"list": ["user"]}},
|
|
||||||
pytest.raises(SchemaValidationError),
|
|
||||||
),
|
|
||||||
- (
|
|
||||||
- {"chpasswd": {"list": []}},
|
|
||||||
- pytest.raises(
|
|
||||||
- SchemaValidationError, match=r"\[\] is too short"
|
|
||||||
- ),
|
|
||||||
- ),
|
|
||||||
+ # (
|
|
||||||
+ # {"chpasswd": {"list": []}},
|
|
||||||
+ # pytest.raises(
|
|
||||||
+ # SchemaValidationError, match=r"\[\] is too short"
|
|
||||||
+ # ),
|
|
||||||
+ # ),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
@skipUnlessJsonSchema()
|
|
||||||
--- tests/unittests/config/test_cc_snap.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_snap.py
|
|
||||||
@@ -279,16 +279,17 @@ class TestSnapSchema:
|
|
||||||
{"snap": {"commands": ["ls"], "invalid-key": ""}},
|
|
||||||
"Additional properties are not allowed",
|
|
||||||
),
|
|
||||||
- ({"snap": {}}, "{} does not have enough properties"),
|
|
||||||
+ # ({"snap": {}}, "{} does not have enough properties"),
|
|
||||||
(
|
|
||||||
{"snap": {"commands": "broken"}},
|
|
||||||
"'broken' is not of type 'object', 'array'",
|
|
||||||
),
|
|
||||||
- ({"snap": {"commands": []}}, r"snap.commands: \[\] is too short"),
|
|
||||||
- (
|
|
||||||
- {"snap": {"commands": {}}},
|
|
||||||
- r"snap.commands: {} does not have enough properties",
|
|
||||||
- ),
|
|
||||||
+ # ({"snap": {
|
|
||||||
+ # "commands": []}}, r"snap.commands: \[\] is too short"),
|
|
||||||
+ # (
|
|
||||||
+ # {"snap": {"commands": {}}},
|
|
||||||
+ # r"snap.commands: {} does not have enough properties",
|
|
||||||
+ # ),
|
|
||||||
({"snap": {"commands": [123]}}, ""),
|
|
||||||
({"snap": {"commands": {"01": 123}}}, ""),
|
|
||||||
({"snap": {"commands": [["snap", "install", 123]]}}, ""),
|
|
||||||
@@ -302,11 +303,11 @@ class TestSnapSchema:
|
|
||||||
{"snap": {"assertions": "broken"}},
|
|
||||||
"'broken' is not of type 'object', 'array'",
|
|
||||||
),
|
|
||||||
- ({"snap": {"assertions": []}}, r"\[\] is too short"),
|
|
||||||
- (
|
|
||||||
- {"snap": {"assertions": {}}},
|
|
||||||
- r"\{} does not have enough properties",
|
|
||||||
- ),
|
|
||||||
+ # ({"snap": {"assertions": []}}, r"\[\] is too short"),
|
|
||||||
+ # (
|
|
||||||
+ # {"snap": {"assertions": {}}},
|
|
||||||
+ # r"\{} does not have enough properties",
|
|
||||||
+ # ),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
@skipUnlessJsonSchema()
|
|
||||||
--- tests/unittests/config/test_cc_write_files.py.orig
|
|
||||||
+++ tests/unittests/config/test_cc_write_files.py
|
|
||||||
@@ -222,7 +222,7 @@ class TestWriteFilesSchema:
|
|
||||||
[
|
|
||||||
# Top-level write_files type validation
|
|
||||||
({"write_files": 1}, "write_files: 1 is not of type 'array'"),
|
|
||||||
- ({"write_files": []}, re.escape("write_files: [] is too short")),
|
|
||||||
+ # ({"write_files": []}, re.escape("write_files: [] is too short")),
|
|
||||||
(
|
|
||||||
{"write_files": [{}]},
|
|
||||||
"write_files.0: 'path' is a required property",
|
|
34
cloud-init-ssh-usrmerge.patch
Normal file
34
cloud-init-ssh-usrmerge.patch
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
--- cloudinit/ssh_util.py.orig
|
||||||
|
+++ cloudinit/ssh_util.py
|
||||||
|
@@ -544,6 +544,10 @@ def parse_ssh_config_map(fname):
|
||||||
|
|
||||||
|
|
||||||
|
def _includes_dconf(fname: str) -> bool:
|
||||||
|
+ # Handle cases where sshd_config is handled in /usr/etc/ssh/sshd_config
|
||||||
|
+ # so /etc/ssh/sshd_config.d/ exists but /etc/ssh/sshd_config doesn't
|
||||||
|
+ if not os.path.exists(fname) and os.path.exists(f"{fname}.d"):
|
||||||
|
+ return True
|
||||||
|
if not os.path.isfile(fname):
|
||||||
|
return False
|
||||||
|
for line in util.load_text_file(fname).splitlines():
|
||||||
|
--- tests/unittests/test_ssh_util.py.orig
|
||||||
|
+++ tests/unittests/test_ssh_util.py
|
||||||
|
@@ -561,6 +561,18 @@ class TestUpdateSshConfig:
|
||||||
|
expected_conf_file = f"{mycfg}.d/50-cloud-init.conf"
|
||||||
|
assert not os.path.isfile(expected_conf_file)
|
||||||
|
|
||||||
|
+ def test_without_sshd_config(self, tmpdir):
|
||||||
|
+ """In some cases /etc/ssh/sshd_config.d exists but /etc/ssh/sshd_config
|
||||||
|
+ doesn't. In this case we shouldn't create /etc/ssh/sshd_config but make
|
||||||
|
+ /etc/ssh/sshd_config.d/50-cloud-init.conf."""
|
||||||
|
+ mycfg = tmpdir.join("sshd_config")
|
||||||
|
+ os.mkdir(os.path.join(tmpdir, "sshd_config.d"))
|
||||||
|
+ assert ssh_util.update_ssh_config({"key": "value"}, mycfg)
|
||||||
|
+ expected_conf_file = f"{mycfg}.d/50-cloud-init.conf"
|
||||||
|
+ assert os.path.isfile(expected_conf_file)
|
||||||
|
+ assert not os.path.isfile(mycfg)
|
||||||
|
+ assert "key value\n" == util.load_text_file(expected_conf_file)
|
||||||
|
+
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"cfg",
|
||||||
|
["Include {mycfg}.d/*.conf", "Include {mycfg}.d/*.conf # comment"],
|
@@ -1,68 +0,0 @@
|
|||||||
--- cloudinit/distros/__init__.py.orig
|
|
||||||
+++ cloudinit/distros/__init__.py
|
|
||||||
@@ -880,9 +880,12 @@ class Distro(persistence.CloudInitPickle
|
|
||||||
# it actually exists as a directory
|
|
||||||
sudoers_contents = ""
|
|
||||||
base_exists = False
|
|
||||||
+ system_sudo_base = "/usr/etc/sudoers"
|
|
||||||
if os.path.exists(sudo_base):
|
|
||||||
sudoers_contents = util.load_file(sudo_base)
|
|
||||||
base_exists = True
|
|
||||||
+ elif os.path.exists(system_sudo_base):
|
|
||||||
+ sudoers_contents = util.load_file(system_sudo_base)
|
|
||||||
found_include = False
|
|
||||||
for line in sudoers_contents.splitlines():
|
|
||||||
line = line.strip()
|
|
||||||
@@ -907,7 +910,7 @@ class Distro(persistence.CloudInitPickle
|
|
||||||
"#includedir %s" % (path),
|
|
||||||
"",
|
|
||||||
]
|
|
||||||
- sudoers_contents = "\n".join(lines)
|
|
||||||
+ sudoers_contents += "\n".join(lines)
|
|
||||||
util.write_file(sudo_base, sudoers_contents, 0o440)
|
|
||||||
else:
|
|
||||||
lines = [
|
|
||||||
--- tests/unittests/distros/test__init__.py.orig
|
|
||||||
+++ tests/unittests/distros/test__init__.py
|
|
||||||
@@ -230,6 +230,41 @@ class TestGenericDistro(helpers.Filesyst
|
|
||||||
self.assertIn("josh", contents)
|
|
||||||
self.assertEqual(2, contents.count("josh"))
|
|
||||||
|
|
||||||
+ def test_sudoers_ensure_append_sudoer_file(self):
|
|
||||||
+ cls = distros.fetch("ubuntu")
|
|
||||||
+ d = cls("ubuntu", {}, None)
|
|
||||||
+ self.patchOS(self.tmp)
|
|
||||||
+ self.patchUtils(self.tmp)
|
|
||||||
+ util.write_file("/etc/sudoers", "josh, josh\n")
|
|
||||||
+ d.ensure_sudo_dir("/b", "/etc/sudoers")
|
|
||||||
+ contents = util.load_file("/etc/sudoers")
|
|
||||||
+ self.assertIn("includedir /b", contents)
|
|
||||||
+ self.assertTrue(os.path.isdir("/b"))
|
|
||||||
+ self.assertIn("josh", contents)
|
|
||||||
+ self.assertEqual(2, contents.count("josh"))
|
|
||||||
+
|
|
||||||
+ def test_usr_sudoers_ensure_new(self):
|
|
||||||
+ cls = distros.fetch("ubuntu")
|
|
||||||
+ d = cls("ubuntu", {}, None)
|
|
||||||
+ self.patchOS(self.tmp)
|
|
||||||
+ self.patchUtils(self.tmp)
|
|
||||||
+ util.write_file("/usr/etc/sudoers", "josh, josh\n")
|
|
||||||
+ d.ensure_sudo_dir("/b")
|
|
||||||
+ contents = util.load_file("/etc/sudoers")
|
|
||||||
+ self.assertIn("josh", contents)
|
|
||||||
+ self.assertEqual(2, contents.count("josh"))
|
|
||||||
+ self.assertIn("includedir /b", contents)
|
|
||||||
+ self.assertTrue(os.path.isdir("/b"))
|
|
||||||
+
|
|
||||||
+ def test_usr_sudoers_ensure_no_etc_creat(self):
|
|
||||||
+ cls = distros.fetch("ubuntu")
|
|
||||||
+ d = cls("ubuntu", {}, None)
|
|
||||||
+ self.patchOS(self.tmp)
|
|
||||||
+ self.patchUtils(self.tmp)
|
|
||||||
+ util.write_file("/usr/etc/sudoers", "#includedir /b")
|
|
||||||
+ d.ensure_sudo_dir("/b")
|
|
||||||
+ self.assertTrue(not os.path.exists("/etc/sudoers"))
|
|
||||||
+
|
|
||||||
def test_sudoers_ensure_only_one_includedir(self):
|
|
||||||
cls = distros.fetch("ubuntu")
|
|
||||||
d = cls("ubuntu", {}, None)
|
|
@@ -1,177 +0,0 @@
|
|||||||
--- cloudinit/distros/__init__.py.orig
|
|
||||||
+++ cloudinit/distros/__init__.py
|
|
||||||
@@ -287,6 +287,15 @@ class Distro(persistence.CloudInitPickle
|
|
||||||
|
|
||||||
network_state = parse_net_config_data(netconfig, renderer=renderer)
|
|
||||||
self._write_network_state(network_state, renderer)
|
|
||||||
+ # The sysconfig renderer has no route writing implementation
|
|
||||||
+ # for SUSE yet use the old code for now that depends on the
|
|
||||||
+ # raw config.
|
|
||||||
+ try:
|
|
||||||
+ # Only exists for SUSE distro via this patch all other
|
|
||||||
+ # implementations throw which breaks testing
|
|
||||||
+ self._write_routes(netconfig)
|
|
||||||
+ except AttributeError:
|
|
||||||
+ pass
|
|
||||||
|
|
||||||
# Now try to bring them up
|
|
||||||
if bring_up:
|
|
||||||
--- cloudinit/distros/opensuse.py.orig
|
|
||||||
+++ cloudinit/distros/opensuse.py
|
|
||||||
@@ -10,7 +10,7 @@
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
-from cloudinit import distros, helpers
|
|
||||||
+from cloudinit import distros, helpers, net
|
|
||||||
from cloudinit import log as logging
|
|
||||||
from cloudinit import subp, util
|
|
||||||
from cloudinit.distros import rhel_util as rhutil
|
|
||||||
@@ -238,6 +238,147 @@ class Distro(distros.Distro):
|
|
||||||
conf.set_hostname(hostname)
|
|
||||||
util.write_file(filename, str(conf), 0o644)
|
|
||||||
|
|
||||||
+ def _write_routes_v1(self, netconfig):
|
|
||||||
+ """Write route files, not part of the standard distro interface"""
|
|
||||||
+ # Due to the implementation of the sysconfig renderer default routes
|
|
||||||
+ # are setup in ifcfg-* files. But this does not work on SLES or
|
|
||||||
+ # openSUSE https://bugs.launchpad.net/cloud-init/+bug/1812117
|
|
||||||
+ # this is a very hacky way to get around the problem until a real
|
|
||||||
+ # solution is found in the sysconfig renderer
|
|
||||||
+ device_configs = netconfig.get('config', [])
|
|
||||||
+ default_nets = ('::', '0.0.0.0')
|
|
||||||
+ for config in device_configs:
|
|
||||||
+ if_name = config.get('name')
|
|
||||||
+ subnets = config.get('subnets', [])
|
|
||||||
+ config_routes = ''
|
|
||||||
+ has_default_route = False
|
|
||||||
+ seen_default_gateway = None
|
|
||||||
+ for subnet in subnets:
|
|
||||||
+ # Render the default gateway if it is present
|
|
||||||
+ gateway = subnet.get('gateway')
|
|
||||||
+ if gateway:
|
|
||||||
+ config_routes += ' '.join(
|
|
||||||
+ ['default', gateway, '-', '-\n']
|
|
||||||
+ )
|
|
||||||
+ has_default_route = True
|
|
||||||
+ if not seen_default_gateway:
|
|
||||||
+ seen_default_gateway = gateway
|
|
||||||
+ # Render subnet routes
|
|
||||||
+ routes = subnet.get('routes', [])
|
|
||||||
+ for route in routes:
|
|
||||||
+ dest = route.get('destination') or route.get('network')
|
|
||||||
+ if not dest or dest in default_nets:
|
|
||||||
+ dest = 'default'
|
|
||||||
+ if not has_default_route:
|
|
||||||
+ has_default_route = True
|
|
||||||
+ if dest != 'default':
|
|
||||||
+ netmask = route.get('netmask')
|
|
||||||
+ if netmask:
|
|
||||||
+ if net.is_ipv4_network(netmask):
|
|
||||||
+ prefix = net.ipv4_mask_to_net_prefix(netmask)
|
|
||||||
+ if net.is_ipv6_network(netmask):
|
|
||||||
+ prefix = net.ipv6_mask_to_net_prefix(netmask)
|
|
||||||
+ dest += '/' + str(prefix)
|
|
||||||
+ if '/' not in dest:
|
|
||||||
+ LOG.warning(
|
|
||||||
+ 'Skipping route; has no prefix "%s"', dest
|
|
||||||
+ )
|
|
||||||
+ continue
|
|
||||||
+ gateway = route.get('gateway')
|
|
||||||
+ if not gateway:
|
|
||||||
+ LOG.warning(
|
|
||||||
+ 'Missing gateway for "%s", skipping', dest
|
|
||||||
+ )
|
|
||||||
+ continue
|
|
||||||
+ if (
|
|
||||||
+ dest == 'default'
|
|
||||||
+ and has_default_route
|
|
||||||
+ and gateway == seen_default_gateway
|
|
||||||
+ ):
|
|
||||||
+ dest_info = dest
|
|
||||||
+ if gateway:
|
|
||||||
+ dest_info = ' '.join([dest, gateway, '-', '-'])
|
|
||||||
+ LOG.warning(
|
|
||||||
+ '%s already has default route, skipping "%s"',
|
|
||||||
+ if_name, dest_info
|
|
||||||
+ )
|
|
||||||
+ continue
|
|
||||||
+ config_routes += ' '.join(
|
|
||||||
+ [dest, gateway, '-', '-\n']
|
|
||||||
+ )
|
|
||||||
+ if config_routes:
|
|
||||||
+ route_file = '/etc/sysconfig/network/ifroute-%s' % if_name
|
|
||||||
+ util.write_file(route_file, config_routes)
|
|
||||||
+
|
|
||||||
+ def _render_route_string(self, netconfig_route):
|
|
||||||
+ route_to = netconfig_route.get('to', None)
|
|
||||||
+ route_via = netconfig_route.get('via', None)
|
|
||||||
+ route_metric = netconfig_route.get('metric', None)
|
|
||||||
+ route_string = ''
|
|
||||||
+
|
|
||||||
+ if route_to and route_via:
|
|
||||||
+ route_string = ' '.join([route_to, route_via, '-', '-'])
|
|
||||||
+ if route_metric:
|
|
||||||
+ route_string += ' metric {}\n'.format(route_metric)
|
|
||||||
+ else:
|
|
||||||
+ route_string += '\n'
|
|
||||||
+ else:
|
|
||||||
+ LOG.warning('invalid route definition, skipping route')
|
|
||||||
+
|
|
||||||
+ return route_string
|
|
||||||
+
|
|
||||||
+ def _write_routes_v2(self, netconfig):
|
|
||||||
+ for device_type in netconfig:
|
|
||||||
+ if device_type == 'version':
|
|
||||||
+ continue
|
|
||||||
+
|
|
||||||
+ if device_type == 'routes':
|
|
||||||
+ # global static routes
|
|
||||||
+ config_routes = ''
|
|
||||||
+ for route in netconfig['routes']:
|
|
||||||
+ config_routes += self._render_route_string(route)
|
|
||||||
+ if config_routes:
|
|
||||||
+ route_file = '/etc/sysconfig/network/routes'
|
|
||||||
+ util.write_file(route_file, config_routes)
|
|
||||||
+ else:
|
|
||||||
+ devices = netconfig[device_type]
|
|
||||||
+ for device_name in devices:
|
|
||||||
+ config_routes = ''
|
|
||||||
+ device_config = devices[device_name]
|
|
||||||
+ try:
|
|
||||||
+ gateways = [
|
|
||||||
+ v for k, v in device_config.items()
|
|
||||||
+ if 'gateway' in k
|
|
||||||
+ ]
|
|
||||||
+ for gateway in gateways:
|
|
||||||
+ config_routes += ' '.join(
|
|
||||||
+ ['default', gateway, '-', '-\n']
|
|
||||||
+ )
|
|
||||||
+ for route in device_config.get('routes', []):
|
|
||||||
+ config_routes += self._render_route_string(route)
|
|
||||||
+ if config_routes:
|
|
||||||
+ route_file = \
|
|
||||||
+ '/etc/sysconfig/network/ifroute-{}'.format(
|
|
||||||
+ device_name
|
|
||||||
+ )
|
|
||||||
+ util.write_file(route_file, config_routes)
|
|
||||||
+ except Exception:
|
|
||||||
+ # the parser above epxects another level of nesting
|
|
||||||
+ # which should be there in case it's properly
|
|
||||||
+ # formatted; if not we may get an exception on items()
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ def _write_routes(self, netconfig):
|
|
||||||
+ netconfig_ver = netconfig.get('version')
|
|
||||||
+ if netconfig_ver == 1:
|
|
||||||
+ self._write_routes_v1(netconfig)
|
|
||||||
+ elif netconfig_ver == 2:
|
|
||||||
+ self._write_routes_v2(netconfig)
|
|
||||||
+ else:
|
|
||||||
+ LOG.warning(
|
|
||||||
+ 'unsupported or missing netconfig version, not writing routes'
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
@property
|
|
||||||
def preferred_ntp_clients(self):
|
|
||||||
"""The preferred ntp client is dependent on the version."""
|
|
1436
cloud-init.changes
1436
cloud-init.changes
File diff suppressed because it is too large
Load Diff
166
cloud-init.spec
166
cloud-init.spec
@@ -17,8 +17,16 @@
|
|||||||
# change this whenever config changes incompatible
|
# change this whenever config changes incompatible
|
||||||
%global configver 0.7
|
%global configver 0.7
|
||||||
|
|
||||||
|
%if 0%{?suse_version} >= 1600
|
||||||
|
%define pythons %{primary_python}
|
||||||
|
%else
|
||||||
|
%define pythons python311
|
||||||
|
%endif
|
||||||
|
%global _sitelibdir %{%{pythons}_sitelib}
|
||||||
|
|
||||||
|
|
||||||
Name: cloud-init
|
Name: cloud-init
|
||||||
Version: 23.3
|
Version: 25.1.3
|
||||||
Release: 0
|
Release: 0
|
||||||
License: GPL-3.0
|
License: GPL-3.0
|
||||||
Summary: Cloud node initialization tool
|
Summary: Cloud node initialization tool
|
||||||
@@ -34,25 +42,24 @@ Patch2: cloud-init-break-resolv-symlink.patch
|
|||||||
Patch3: cloud-init-sysconf-path.patch
|
Patch3: cloud-init-sysconf-path.patch
|
||||||
# FIXME (lp#1860164)
|
# FIXME (lp#1860164)
|
||||||
Patch4: cloud-init-no-tempnet-oci.patch
|
Patch4: cloud-init-no-tempnet-oci.patch
|
||||||
# FIXME (lp#1812117)
|
# FIXME https://github.com/canonical/cloud-init/issues/5152 and LP#1715241
|
||||||
Patch6: cloud-init-write-routes.patch
|
Patch5: cloud-init-no-openstack-guess.patch
|
||||||
# FIXME (https://github.com/canonical/cloud-init/issues/4339)
|
|
||||||
Patch7: cloud-init-keep-flake.patch
|
|
||||||
Patch8: cloud-init-lint-fixes.patch
|
|
||||||
# FIXME (https://github.com/canonical/cloud-init/pull/4788)
|
|
||||||
Patch9: cloud-init-pckg-reboot.patch
|
|
||||||
# FIXME
|
|
||||||
Patch10: cloud-init-skip-empty-conf.patch
|
|
||||||
# FIXME (https://github.com/canonical/cloud-init/commit/d0f00bd54649e527d69ad597cbcad6efa8548e58)
|
|
||||||
Patch11: cloud-init-ds-deterministic.patch
|
|
||||||
# FIXME https://github.com/canonical/cloud-init/issues/5152 adn LP#1715241
|
|
||||||
Patch12: cloud-init-no-openstack-guess.patch
|
|
||||||
# FIXME upstream comit 812df5038
|
|
||||||
Patch13: cloud-init-no-nmcfg-needed.patch
|
|
||||||
# FIXME https://github.com/canonical/cloud-init/pull/5161
|
|
||||||
Patch14: cloud-init-usr-sudoers.patch
|
|
||||||
# FIXME https://github.com/canonical/cloud-init/issues/5075
|
# FIXME https://github.com/canonical/cloud-init/issues/5075
|
||||||
Patch15: cloud-init-skip-rename.patch
|
Patch6: cloud-init-skip-rename.patch
|
||||||
|
# FIXME https://github.com/canonical/cloud-init/pull/6105
|
||||||
|
Patch7: cloud-init-ssh-usrmerge.patch
|
||||||
|
# FIXME https://github.com/canonical/cloud-init/pull/6121
|
||||||
|
Patch8: cloud-init-lint-set-interpreter.patch
|
||||||
|
Patch9: cloud-init-lint-fix.patch
|
||||||
|
# FIXME https://github.com/canonical/cloud-init/blob/ubuntu/noble/debian/patches/no-single-process.patch
|
||||||
|
# We have an old version of netcat that does not support the necessary
|
||||||
|
# feature to support a single process for cloud-init. Once we have netcat
|
||||||
|
# 1.226 or later available we can get rid of this patch
|
||||||
|
# Maybe there is hope for 16 https://jira.suse.com/browse/PED-12810
|
||||||
|
Patch11: cloud-init-no-single-process.patch
|
||||||
|
# FIXME https://github.com/canonical/cloud-init/pull/6214
|
||||||
|
Patch12: cloud-init-needs-action.patch
|
||||||
|
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
BuildRequires: filesystem
|
BuildRequires: filesystem
|
||||||
# pkg-config is needed to find correct systemd unit dir
|
# pkg-config is needed to find correct systemd unit dir
|
||||||
@@ -61,49 +68,50 @@ BuildRequires: pkg-config
|
|||||||
BuildRequires: pkgconfig(udev)
|
BuildRequires: pkgconfig(udev)
|
||||||
BuildRequires: procps
|
BuildRequires: procps
|
||||||
BuildRequires: python-rpm-macros
|
BuildRequires: python-rpm-macros
|
||||||
BuildRequires: python3-devel
|
BuildRequires: %{pythons}-devel
|
||||||
BuildRequires: python3-setuptools
|
BuildRequires: %{pythons}-setuptools
|
||||||
# Test requirements
|
# Test requirements
|
||||||
BuildRequires: python3-Jinja2
|
BuildRequires: %{pythons}-Jinja2
|
||||||
BuildRequires: python3-PyYAML
|
BuildRequires: %{pythons}-PyYAML
|
||||||
BuildRequires: python3-configobj >= 5.0.2
|
BuildRequires: %{pythons}-configobj >= 5.0.2
|
||||||
BuildRequires: python3-flake8
|
BuildRequires: %{pythons}-flake8
|
||||||
BuildRequires: python3-httpretty
|
BuildRequires: %{pythons}-httpretty
|
||||||
BuildRequires: python3-jsonpatch
|
BuildRequires: %{pythons}-jsonpatch
|
||||||
BuildRequires: python3-jsonschema
|
BuildRequires: %{pythons}-jsonschema
|
||||||
BuildRequires: python3-netifaces
|
BuildRequires: %{pythons}-oauthlib
|
||||||
BuildRequires: python3-oauthlib
|
BuildRequires: %{pythons}-passlib
|
||||||
BuildRequires: python3-passlib
|
BuildRequires: %{pythons}-pytest
|
||||||
BuildRequires: python3-pytest
|
BuildRequires: %{pythons}-pytest-cov
|
||||||
BuildRequires: python3-pytest-cov
|
BuildRequires: %{pythons}-pytest-mock
|
||||||
BuildRequires: python3-pytest-mock
|
BuildRequires: %{pythons}-requests
|
||||||
BuildRequires: python3-requests
|
BuildRequires: %{pythons}-responses
|
||||||
BuildRequires: python3-responses
|
BuildRequires: %{pythons}-serial
|
||||||
BuildRequires: python3-serial
|
|
||||||
BuildRequires: system-user-nobody
|
BuildRequires: system-user-nobody
|
||||||
BuildRequires: distribution-release
|
BuildRequires: distribution-release
|
||||||
BuildRequires: util-linux
|
BuildRequires: util-linux
|
||||||
Requires: bash
|
Requires: bash
|
||||||
|
%if 0%{?suse_version} >= 1600
|
||||||
|
Requires: dhcpcd
|
||||||
|
%else
|
||||||
Requires: dhcp-client
|
Requires: dhcp-client
|
||||||
|
%endif
|
||||||
Requires: file
|
Requires: file
|
||||||
Requires: growpart
|
Requires: growpart
|
||||||
Requires: e2fsprogs
|
Requires: e2fsprogs
|
||||||
Requires: net-tools
|
Requires: net-tools
|
||||||
Requires: openssh
|
Requires: openssh
|
||||||
Requires: procps
|
Requires: procps
|
||||||
Requires: python3-configobj >= 5.0.2
|
Requires: %{pythons}-configobj >= 5.0.2
|
||||||
Requires: python3-Jinja2
|
Requires: %{pythons}-Jinja2
|
||||||
Requires: python3-jsonpatch
|
Requires: %{pythons}-jsonpatch
|
||||||
Requires: python3-jsonschema
|
Requires: %{pythons}-jsonschema
|
||||||
Requires: python3-netifaces
|
Requires: %{pythons}-oauthlib
|
||||||
Requires: python3-oauthlib
|
Requires: %{pythons}-passlib
|
||||||
Requires: python3-passlib
|
Requires: %{pythons}-PyYAML
|
||||||
Requires: python3-pyserial
|
Requires: %{pythons}-requests
|
||||||
Requires: python3-PyYAML
|
Requires: %{pythons}-serial
|
||||||
Requires: python3-requests
|
Requires: %{pythons}-setuptools
|
||||||
Requires: python3-serial
|
Requires: %{pythons}-xml
|
||||||
Requires: python3-setuptools
|
|
||||||
Requires: python3-xml
|
|
||||||
Requires: sudo
|
Requires: sudo
|
||||||
Requires: util-linux
|
Requires: util-linux
|
||||||
Requires: wget
|
Requires: wget
|
||||||
@@ -156,16 +164,13 @@ Documentation and examples for cloud-init tools
|
|||||||
%patch -P 2
|
%patch -P 2
|
||||||
%patch -P 3
|
%patch -P 3
|
||||||
%patch -P 4
|
%patch -P 4
|
||||||
|
%patch -P 5
|
||||||
%patch -P 6
|
%patch -P 6
|
||||||
%patch -P 7
|
%patch -P 7
|
||||||
%patch -P 8
|
%patch -P 8
|
||||||
%patch -P 9
|
%patch -P 9
|
||||||
%patch -P 10
|
|
||||||
%patch -P 11
|
%patch -P 11
|
||||||
%patch -P 12
|
%patch -P 12
|
||||||
%patch -P 13
|
|
||||||
%patch -P 14
|
|
||||||
%patch -P 15
|
|
||||||
|
|
||||||
# patch in the full version to version.py
|
# patch in the full version to version.py
|
||||||
version_pys=$(find . -name version.py -type f)
|
version_pys=$(find . -name version.py -type f)
|
||||||
@@ -174,14 +179,26 @@ version_pys=$(find . -name version.py -type f)
|
|||||||
sed -i "s,@@PACKAGED_VERSION@@,%{version}-%{release}," $version_pys
|
sed -i "s,@@PACKAGED_VERSION@@,%{version}-%{release}," $version_pys
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%python3_build
|
%python_build
|
||||||
|
|
||||||
|
|
||||||
%check
|
%check
|
||||||
|
# Total HACK, we have no macro that expands the proper Python interpreter
|
||||||
|
# in a way that it can be used to set en environment variable
|
||||||
|
if [ -e /usr/bin/python3.13 ]; then
|
||||||
|
export PYTHON=/usr/bin/python3.13
|
||||||
|
else
|
||||||
|
export PYTHON=/usr/bin/python3.11
|
||||||
|
fi
|
||||||
make unittest
|
make unittest
|
||||||
make lint
|
# Disable the flake checks and accept the bugs we may introduce with the
|
||||||
|
# patches. On SLE 15 SP5 flake dies with some weird internal error
|
||||||
|
#make lint
|
||||||
|
|
||||||
%install
|
%install
|
||||||
%python3_install --init-system=%{initsys} --distro=suse
|
%python_exec setup.py install --prefix=%{_prefix} --init-system=%{initsys} --distro=suse --root=%{buildroot}
|
||||||
|
|
||||||
|
|
||||||
find %{buildroot} \( -name .gitignore -o -name .placeholder \) -delete
|
find %{buildroot} \( -name .gitignore -o -name .placeholder \) -delete
|
||||||
# from debian install script
|
# from debian install script
|
||||||
for x in "%{buildroot}%{_bindir}/"*.py; do
|
for x in "%{buildroot}%{_bindir}/"*.py; do
|
||||||
@@ -206,12 +223,15 @@ sed -i s/suse/opensuse/ %{buildroot}/%{_sysconfdir}/cloud/cloud.cfg
|
|||||||
sed -i s/suse/sles/ %{buildroot}/%{_sysconfdir}/cloud/cloud.cfg
|
sed -i s/suse/sles/ %{buildroot}/%{_sysconfdir}/cloud/cloud.cfg
|
||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
mkdir -p %{buildroot}/%{systemd_prefix}/systemd/system/sshd-keygen@.service.d
|
||||||
mkdir -p %{buildroot}/%{_sysconfdir}/rsyslog.d
|
mkdir -p %{buildroot}/%{_sysconfdir}/rsyslog.d
|
||||||
mkdir -p %{buildroot}/usr/lib/udev/rules.d/
|
mkdir -p %{buildroot}/usr/lib/udev/rules.d/
|
||||||
cp -a %{SOURCE1} %{buildroot}/%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
|
cp -a %{SOURCE1} %{buildroot}/%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
|
||||||
mkdir -p %{buildroot}%{_sbindir}
|
mkdir -p %{buildroot}%{_sbindir}
|
||||||
|
%if 0%{?suse_version} < 1600
|
||||||
install -m 755 %{SOURCE2} %{buildroot}%{_sbindir}
|
install -m 755 %{SOURCE2} %{buildroot}%{_sbindir}
|
||||||
|
sed -i "s/python3/python3.11/" %{buildroot}%{_sbindir}/hidesensitivedata
|
||||||
|
%endif
|
||||||
# remove debian/ubuntu specific profile.d file (bnc#779553)
|
# remove debian/ubuntu specific profile.d file (bnc#779553)
|
||||||
rm -f %{buildroot}%{_sysconfdir}/profile.d/Z99-cloud-locale-test.sh
|
rm -f %{buildroot}%{_sysconfdir}/profile.d/Z99-cloud-locale-test.sh
|
||||||
|
|
||||||
@@ -222,50 +242,56 @@ rm %{buildroot}/%{_sysconfdir}/cloud/templates/*.ubuntu.*
|
|||||||
|
|
||||||
# remove duplicate files
|
# remove duplicate files
|
||||||
%if 0%{?suse_version}
|
%if 0%{?suse_version}
|
||||||
%fdupes %{buildroot}%{python3_sitelib}
|
%fdupes %{buildroot}%{_sitelibdir}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?suse_version} < 1600
|
||||||
%post
|
%post
|
||||||
/usr/sbin/hidesensitivedata
|
/usr/sbin/hidesensitivedata
|
||||||
|
%endif
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
|
%dir %attr(0755, root, root) %{_localstatedir}/lib/cloud
|
||||||
|
%dir %{_sysconfdir}/cloud
|
||||||
|
%dir %{docdir}
|
||||||
|
%dir %{_sysconfdir}/rsyslog.d
|
||||||
|
%dir %{systemd_prefix}/systemd/system/sshd-keygen@.service.d
|
||||||
%license LICENSE LICENSE-GPLv3
|
%license LICENSE LICENSE-GPLv3
|
||||||
%{_bindir}/cloud-id
|
%{_bindir}/cloud-id
|
||||||
%{_bindir}/cloud-init
|
%{_bindir}/cloud-init
|
||||||
%{_bindir}/cloud-init-per
|
%{_bindir}/cloud-init-per
|
||||||
|
%if 0%{?suse_version} < 1600
|
||||||
%{_sbindir}/hidesensitivedata
|
%{_sbindir}/hidesensitivedata
|
||||||
%dir %{_sysconfdir}/cloud
|
%endif
|
||||||
%dir %{_sysconfdir}/cloud/clean.d
|
|
||||||
%{_sysconfdir}/cloud/clean.d/README
|
|
||||||
%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d
|
%config(noreplace) %{_sysconfdir}/cloud/cloud.cfg.d
|
||||||
%config(noreplace) %{_sysconfdir}/cloud/templates
|
%config(noreplace) %{_sysconfdir}/cloud/templates
|
||||||
%{_sysconfdir}/systemd/system/sshd-keygen@.service.d/disable-sshd-keygen-if-cloud-init-active.conf
|
%{systemd_prefix}/systemd/system/sshd-keygen@.service.d/disable-sshd-keygen-if-cloud-init-active.conf
|
||||||
%{_mandir}/man*/*
|
%{_mandir}/man*/*
|
||||||
%if 0%{?suse_version} && 0%{?suse_version} < 1500
|
%if 0%{?suse_version} && 0%{?suse_version} < 1500
|
||||||
%dir %{_datadir}/bash-completion
|
%dir %{_datadir}/bash-completion
|
||||||
%dir %{_datadir}/bash-completion/completions
|
%dir %{_datadir}/bash-completion/completions
|
||||||
%endif
|
%endif
|
||||||
%{_datadir}/bash-completion/completions/cloud-init
|
%{_datadir}/bash-completion/completions/cloud-init
|
||||||
%{python3_sitelib}/cloudinit
|
%{_sitelibdir}/cloudinit
|
||||||
%{python3_sitelib}/cloud_init-%{version}*.egg-info
|
%{_sitelibdir}/cloud_init-%{version}*.egg-info
|
||||||
%{_prefix}/lib/cloud-init
|
%{_prefix}/lib/cloud-init
|
||||||
%{systemd_prefix}/systemd/system-generators/cloud-init-generator
|
%{systemd_prefix}/systemd/system-generators/cloud-init-generator
|
||||||
%{systemd_prefix}/systemd/system/cloud-config.service
|
%{systemd_prefix}/systemd/system/cloud-config.service
|
||||||
%{systemd_prefix}/systemd/system/cloud-config.target
|
%{systemd_prefix}/systemd/system/cloud-config.target
|
||||||
%{systemd_prefix}/systemd/system/cloud-init-local.service
|
%{systemd_prefix}/systemd/system/cloud-init-local.service
|
||||||
%{systemd_prefix}/systemd/system/cloud-init.service
|
%{systemd_prefix}/systemd/system/cloud-init.service
|
||||||
|
%{systemd_prefix}/systemd/system/cloud-init-main.service
|
||||||
|
%{systemd_prefix}/systemd/system/cloud-init-network.service
|
||||||
%{systemd_prefix}/systemd/system/cloud-init.target
|
%{systemd_prefix}/systemd/system/cloud-init.target
|
||||||
%{systemd_prefix}/systemd/system/cloud-final.service
|
%{systemd_prefix}/systemd/system/cloud-final.service
|
||||||
%dir %{_sysconfdir}/rsyslog.d
|
|
||||||
%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
|
%{_sysconfdir}/rsyslog.d/21-cloudinit.conf
|
||||||
/usr/lib/udev/rules.d/66-azure-ephemeral.rules
|
%{_prefix}/lib/udev/rules.d/66-azure-ephemeral.rules
|
||||||
# We use cloud-netconfig to handle new interfaces added to the instance
|
# We use cloud-netconfig to handle new interfaces added to the instance
|
||||||
%exclude %{systemd_prefix}/systemd/system/cloud-init-hotplugd.service
|
%exclude %{systemd_prefix}/systemd/system/cloud-init-hotplugd.service
|
||||||
%exclude %{systemd_prefix}/systemd/system/cloud-init-hotplugd.socket
|
%exclude %{systemd_prefix}/systemd/system/cloud-init-hotplugd.socket
|
||||||
%dir %attr(0755, root, root) %{_localstatedir}/lib/cloud
|
|
||||||
%dir %{docdir}
|
|
||||||
%dir /etc/systemd/system/sshd-keygen@.service.d
|
|
||||||
|
|
||||||
|
|
||||||
%files config-suse
|
%files config-suse
|
||||||
|
Reference in New Issue
Block a user