summaryrefslogtreecommitdiff
path: root/tests/integration_tests/test_paths.py
blob: 14513c82ba689adaab38d1fb96f3c409e032f65f (plain)
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
import os
import re
from datetime import datetime
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.util import 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)
        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):
        help_result = custom_client.execute("cloud-init collect-logs -h")
        assert help_result.ok, help_result.stderr
        assert f"{NEW_CLOUD_DIR}/instance/user-data.txt" in re.sub(
            r"\s+", "", help_result.stdout
        ), "user-data file not correctly render in collect-logs -h"

        # 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.utcnow().date().strftime("cloud-init-logs-%Y-%m-%d")
        expected_logs = [
            f"{dirname}/",
            f"{dirname}/cloud-init.log",
            f"{dirname}/cloud-init-output.log",
            f"{dirname}/dmesg.txt",
            f"{dirname}/user-data.txt",
            f"{dirname}/version",
            f"{dirname}/dpkg-version",
            f"{dirname}/journal.txt",
            f"{dirname}/run/",
            f"{dirname}/run/cloud-init/",
            f"{dirname}/run/cloud-init/result.json",
            f"{dirname}/run/cloud-init/.instance-id",
            f"{dirname}/run/cloud-init/cloud-init-generator.log",
            f"{dirname}/run/cloud-init/enabled",
            f"{dirname}/run/cloud-init/cloud-id",
            f"{dirname}/run/cloud-init/instance-data.json",
            f"{dirname}/run/cloud-init/instance-data-sensitive.json",
            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.utcnow().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.not_bionic
    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)