Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests(lxd): avoid failure on multiple calls to --show-log #5811

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions tests/integration_tests/modules/test_combined.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
get_inactive_modules,
lxd_has_nocloud,
verify_clean_boot,
verify_clean_log,
verify_ordered_items_in_text,
)

Expand Down Expand Up @@ -150,17 +149,16 @@ def test_deprecated_message(self, class_client: IntegrationInstance):
# user-data. Pass 22.2 in against the client's version_boundary.
if lifecycle.should_log_deprecation("22.2", version_boundary):
deprecated_messages.append(boundary_message)
verify_clean_boot(
class_client, require_deprecations=deprecated_messages
)
else:
# Expect the distros deprecated call to be redacted.
# jsonschema still emits deprecation log due to changed_version
# instead of deprecated_version
verify_clean_boot(
class_client, require_deprecations=deprecated_messages
)
assert f"[INFO]: {boundary_message}" in log
verify_clean_boot(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing that needs to change here, but it does seem a little odd calling verify_clean_boot multiple times in multiple tests in the class given that they're all operating on the same instance and the log won't be any different between tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I had wondered about just consolidating the deprecation test and the no_problems test. I have though consolidated the rsyslog verify_clean_boot call with testy_no_problems case as they are both testing and asserting the same log warning condition based on presence of rsyslogd.

class_client,
require_deprecations=deprecated_messages,
ignore_warnings=True,
)

def test_ntp_with_apt(self, class_client: IntegrationInstance):
"""LP #1628337.
Expand Down Expand Up @@ -212,11 +210,11 @@ def test_random_seed_data(self, class_client: IntegrationInstance):
assert result.startswith("MYUb34023nD:LFDK10913jk;dfnk:Df")

def test_rsyslog(self, class_client: IntegrationInstance):
"""Test rsyslog is configured correctly."""
client = class_client
assert "My test log" in client.read_from_file(
"/var/spool/rsyslog/cloudinit.log"
)
"""Test rsyslog is configured correctly when applicable."""
if class_client.execute("command -v rsyslogd").ok:
assert "My test log" in class_client.read_from_file(
"/var/spool/rsyslog/cloudinit.log"
)

def test_runcmd(self, class_client: IntegrationInstance):
"""Test runcmd works as expected"""
Expand Down Expand Up @@ -247,9 +245,7 @@ def test_timezone(self, class_client: IntegrationInstance):
assert timezone_output.strip() == "CET"

def test_no_problems(self, class_client: IntegrationInstance):
"""Test no errors, warnings, deprecations, tracebacks or
inactive modules.
"""
"""Test no errors, warnings, tracebacks or inactive modules."""
client = class_client
status_file = client.read_from_file("/run/cloud-init/status.json")
status_json = json.loads(status_file)["v1"]
Expand All @@ -260,7 +256,19 @@ def test_no_problems(self, class_client: IntegrationInstance):
assert result_json["errors"] == []

log = client.read_from_file("/var/log/cloud-init.log")
verify_clean_log(log, ignore_deprecations=False)
require_warnings = []
if class_client.execute("command -v rsyslogd").failed:
# Some minimal images may not have an installed rsyslog package
# Test user-data doesn't provide install_rsyslog: true so expect
# warnings when not installed.
require_warnings.append(
"Failed to reload-or-try-restart rsyslog.service:"
" Unit rsyslog.service not found."
)
# Set ignore_deprecations=True as test_deprecated_message covers this
verify_clean_boot(
client, ignore_deprecations=True, require_warnings=require_warnings
)
requested_modules = {
"apt_configure",
"byobu",
Expand Down
27 changes: 20 additions & 7 deletions tests/integration_tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ def append_or_create_list(
maybe_list = [value]
return maybe_list

traceback_texts = []
if ignore_tracebacks is None:
ignore_tracebacks = []
# Define exceptions by matrix of platform and Ubuntu release
if "azure" == PLATFORM:
# Consistently on all Azure launches:
Expand All @@ -147,17 +148,19 @@ def append_or_create_list(
ignore_errors = append_or_create_list(
ignore_warnings, "Stderr: RTNETLINK answers: File exists"
)
traceback_texts.append("Stderr: RTNETLINK answers: File exists")
if isinstance(ignore_tracebacks, list):
ignore_tracebacks.append("Stderr: RTNETLINK answers: File exists")
# LP: #1833446
ignore_warnings = append_or_create_list(
ignore_warnings,
"UrlError: 404 Client Error: Not Found for url: "
"http://169.254.169.254/latest/meta-data/",
)
traceback_texts.append(
"UrlError: 404 Client Error: Not Found for url: "
"http://169.254.169.254/latest/meta-data/"
)
if isinstance(ignore_tracebacks, list):
ignore_tracebacks.append(
"UrlError: 404 Client Error: Not Found for url: "
"http://169.254.169.254/latest/meta-data/"
)
# Oracle has a file in /etc/cloud/cloud.cfg.d that contains
# users:
# - default
Expand All @@ -168,7 +171,7 @@ def append_or_create_list(
ignore_warnings,
"Unable to disable SSH logins for opc given ssh_redirect_user",
)

# Preserve platform-specific tracebacks expected
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So was traceback_texts just not being used before when it was supposed to? If None or a list is passed as ignore_tracebacks, should we just use that use and append to that rather than keeping a separate list here?

Copy link
Collaborator Author

@blackboxsw blackboxsw Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes traceback_texts was defined and left unused. If False is provided, we want to report any tracebacks. If None is provided, that's the default and in default case I think we want to ignore expected tracebacks per platform. If a list is passed then we should append to that list instead of keeping the separate list here.

_verify_clean_boot(
instance,
ignore_deprecations=ignore_deprecations,
Expand Down Expand Up @@ -538,10 +541,20 @@ def get_console_log(client: "IntegrationInstance"):
console_log = client.instance.console_log()
except NotImplementedError:
pytest.skip("NotImplementedError when requesting console log")
except RuntimeError as e:
if "open : no such file or directory" in str(e):
if hasattr(client, "lxc_log"):
return client.lxc_log
raise e
if console_log is None:
pytest.skip("Console log has not been setup")
if console_log.lower().startswith("no console output"):
pytest.fail("no console output")
if PLATFORM in ("lxd_vm", "lxd_container"):
# Preserve non empty console log on lxc platforms because
# lxc console --show-log can be called once and the log is flushed.
# Multiple calls to --show-log error on "no such file or directory".
client.lxc_log = console_log # type: ignore[attr-defined]
return console_log


Expand Down