1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
import os
from datetime import datetime, timezone
from typing import Iterator
import pytest
from cloudinit.cmd.devel.logs import (
INSTALLER_APPORT_FILES,
INSTALLER_APPORT_SENSITIVE_FILES,
)
from tests.integration_tests.instances import IntegrationInstance
from tests.integration_tests.releases import CURRENT_RELEASE, FOCAL
from tests.integration_tests.util import verify_clean_boot, verify_clean_log
DEFAULT_CLOUD_DIR = "/var/lib/cloud"
NEW_CLOUD_DIR = "/new-cloud-dir"
CUSTOM_CLOUD_DIR = f"""\
system_info:
paths:
cloud_dir: {NEW_CLOUD_DIR}
"""
CUSTOM_CLOUD_DIR_FN = "95-custom-cloud-dir.cfg"
@pytest.fixture
def custom_client(
client: IntegrationInstance, tmpdir
) -> Iterator[IntegrationInstance]:
client.write_to_file(
f"/etc/cloud/cloud.cfg.d/{CUSTOM_CLOUD_DIR_FN}", CUSTOM_CLOUD_DIR
)
client.execute(f"rm -rf {DEFAULT_CLOUD_DIR}") # Remove previous cloud_dir
client.execute("cloud-init clean --logs")
client.restart()
yield client
class TestHonorCloudDir:
def verify_log_and_files(self, custom_client):
log_content = custom_client.read_from_file("/var/log/cloud-init.log")
verify_clean_log(log_content)
verify_clean_boot(custom_client)
assert NEW_CLOUD_DIR in log_content
assert DEFAULT_CLOUD_DIR not in log_content
assert custom_client.execute(f"test ! -d {DEFAULT_CLOUD_DIR}").ok
def collect_logs(self, custom_client: IntegrationInstance):
# Touch a couple of subiquity files to assert collected
installer_files = (
INSTALLER_APPORT_FILES[-1],
INSTALLER_APPORT_SENSITIVE_FILES[-1],
)
for apport_file in installer_files:
custom_client.execute(
f"mkdir -p {os.path.dirname(apport_file.path)}"
)
custom_client.execute(f"touch {apport_file.path}")
collect_logs_result = custom_client.execute(
"cloud-init collect-logs --include-userdata"
)
assert (
collect_logs_result.ok
), f"collect-logs error: {collect_logs_result.stderr}"
found_logs = custom_client.execute(
"tar -tf cloud-init.tar.gz"
).stdout.splitlines()
dirname = (
datetime.now(timezone.utc)
.date()
.strftime("cloud-init-logs-%Y-%m-%d")
)
expected_logs = [
f"{dirname}/",
f"{dirname}/dmesg.txt",
f"{dirname}/dpkg-version",
f"{dirname}/journal.txt",
f"{dirname}/run/",
f"{dirname}/run/cloud-init/",
f"{dirname}/run/cloud-init/.instance-id",
f"{dirname}/run/cloud-init/cloud-id",
f"{dirname}/run/cloud-init/cloud-init-generator.log",
f"{dirname}/run/cloud-init/enabled",
f"{dirname}/run/cloud-init/instance-data-sensitive.json",
f"{dirname}/run/cloud-init/instance-data.json",
f"{dirname}/run/cloud-init/result.json",
f"{dirname}/new-cloud-dir/instance/user-data.txt",
f"{dirname}/var/log/cloud-init-output.log",
f"{dirname}/var/log/cloud-init.log",
f"{dirname}/version",
f"{dirname}{installer_files[0].path}",
f"{dirname}{installer_files[1].path}",
]
for log in expected_logs:
assert log in found_logs
# Assert disabled cloud-init collect-logs grabs /var/lib/cloud/data
custom_client.execute("touch /run/cloud-init/disabled")
assert custom_client.execute(
"cloud-init collect-logs --include-userdata"
).ok
found_logs = custom_client.execute(
"tar -tf cloud-init.tar.gz"
).stdout.splitlines()
dirname = (
datetime.now(timezone.utc)
.date()
.strftime("cloud-init-logs-%Y-%m-%d")
)
assert f"{dirname}/new-cloud-dir/data/result.json" in found_logs
# LXD inserts some agent setup code into VMs on Bionic under
# /var/lib/cloud. The inserted script will cause this test to fail
# because the test ensures nothing is running under /var/lib/cloud.
# Since LXD is doing this and not cloud-init, we should just not run
# on Bionic to avoid it.
@pytest.mark.skipif(
CURRENT_RELEASE < FOCAL,
reason="LXD inserts conflicting setup on releases prior to focal",
)
def test_honor_cloud_dir(self, custom_client: IntegrationInstance):
"""Integration test for LP: #1976564
cloud-init must honor the cloud-dir configured in
/etc/cloud/cloud.cfg.d
"""
self.verify_log_and_files(custom_client)
self.collect_logs(custom_client)
|