--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: cloud-init FTBFS with Python 3.13
- From: Stefano Rivera <stefanor@debian.org>
- Date: Wed, 18 Sep 2024 19:20:54 +0200
- Message-id: <bj2g5iitc5cwbisitvainotzfqhv4zxe7wlzrr6am4kwo4cvr3@bzdg5ggtrjmw>
Source: cloud-init
Version: 24.3.1-1
Severity: normal
User: debian-python@lists.debian.org
Usertags: python3.13
This package failed build from source when test-built against a version of
python3-defaults that includes 3.13 as a supported version.
To reproduce this issue, build against python3-defaults (python3-all-dev etc.)
from Debian experimental.
What's new in Python 3.13:
https://docs.python.org/3.13/whatsnew/3.13.html
Log snippet:
=================================== FAILURES ===================================
_ TestVersionedSchemas.test_versioned_cloud_config_schema_is_valid_json[schema2-is not one of ['v1']] _
self = <tests.unittests.config.test_schema.TestVersionedSchemas object at 0xffffb4421e00>
schema = {'version': 'v2'}, error_msg = "is not one of ['v1']"
@pytest.mark.parametrize(
"schema,error_msg",
(
({}, None),
({"version": "v1"}, None),
({"version": "v2"}, "is not one of ['v1']"),
(
{"version": "v1", "final_message": -1},
"is not of type 'string'",
),
({"version": "v1", "final_message": "some msg"}, None),
),
)
def test_versioned_cloud_config_schema_is_valid_json(
self, schema, error_msg
):
schema_dir = get_schema_dir()
version_schemafile = os.path.join(
schema_dir, VERSIONED_USERDATA_SCHEMA_FILE
)
# Point to local schema files avoid JSON resolver trying to pull the
# reference from our upstream raw file in github.
version_schema = json.loads(
re.sub(
r"https:\/\/raw.githubusercontent.com\/canonical\/"
r"cloud-init\/main\/cloudinit\/config\/schemas\/",
f"file://{schema_dir}/",
load_text_file(version_schemafile),
)
)
if error_msg:
> with pytest.raises(SchemaValidationError) as context_mgr:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:148: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:16 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/versions.schema.cloud-config.json (quiet=False)
2024-09-18 16:50:16 DEBUG cloudinit.util:util.py:1622 Read 557 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/versions.schema.cloud-config.json
2024-09-18 16:50:16 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestVersionedSchemas.test_versioned_cloud_config_schema_is_valid_json[schema3-is not of type 'string'] _
self = <tests.unittests.config.test_schema.TestVersionedSchemas object at 0xffffb4422ea0>
schema = {'final_message': -1, 'version': 'v1'}
error_msg = "is not of type 'string'"
@pytest.mark.parametrize(
"schema,error_msg",
(
({}, None),
({"version": "v1"}, None),
({"version": "v2"}, "is not one of ['v1']"),
(
{"version": "v1", "final_message": -1},
"is not of type 'string'",
),
({"version": "v1", "final_message": "some msg"}, None),
),
)
def test_versioned_cloud_config_schema_is_valid_json(
self, schema, error_msg
):
schema_dir = get_schema_dir()
version_schemafile = os.path.join(
schema_dir, VERSIONED_USERDATA_SCHEMA_FILE
)
# Point to local schema files avoid JSON resolver trying to pull the
# reference from our upstream raw file in github.
version_schema = json.loads(
re.sub(
r"https:\/\/raw.githubusercontent.com\/canonical\/"
r"cloud-init\/main\/cloudinit\/config\/schemas\/",
f"file://{schema_dir}/",
load_text_file(version_schemafile),
)
)
if error_msg:
> with pytest.raises(SchemaValidationError) as context_mgr:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:148: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:16 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/versions.schema.cloud-config.json (quiet=False)
2024-09-18 16:50:16 DEBUG cloudinit.util:util.py:1622 Read 557 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/versions.schema.cloud-config.json
2024-09-18 16:50:16 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_config_file[None-#cloud-config\nntp:-Valid schema] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3f91130>
_netplan_available = <MagicMock name='available' id='281473671392496'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473671395184'>
schema_type = None, content = b'#cloud-config\nntp:', expected = 'Valid schema'
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil0')
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19d6200>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb19d7000>
@pytest.mark.parametrize(
"schema_type,content,expected",
(
(None, b"#cloud-config\nntp:", "Valid schema"),
("cloud-config", b"#cloud-config\nntp:", "Valid schema"),
(
"network-config",
(
b"network: {'version': 2, 'ethernets':"
b" {'eth0': {'dhcp': true}}}"
),
"Valid schema",
),
(
"network-config",
(
b"network:\n version: 1\n config:\n - type: physical\n"
b" name: eth0\n subnets:\n - type: dhcp\n"
),
"Valid schema",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_config_file(
self,
_netplan_available,
_read_cfg_paths,
schema_type,
content,
expected,
tmpdir,
capsys,
caplog,
):
"""When --config-file parameter is provided, main validates schema."""
myyaml = tmpdir.join("my.yaml")
myargs = ["mycmd", "--config-file", myyaml.strpath]
if schema_type:
myargs += ["--schema-type", schema_type]
myyaml.write(content) # shortest ntp schema
with mock.patch("sys.argv", myargs):
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
> assert expected in out
E AssertionError: assert 'Valid schema' in 'Skipping cloud-config schema validation. Jsonschema dependency missing.\n'
tests/unittests/config/test_schema.py:2010: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil0/my.yaml (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil0/my.yaml
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_config_file[cloud-config-#cloud-config\nntp:-Valid schema] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3f91220>
_netplan_available = <MagicMock name='available' id='281473671688080'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473671689424'>
schema_type = 'cloud-config', content = b'#cloud-config\nntp:'
expected = 'Valid schema'
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil1')
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19d7a10>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb166d710>
@pytest.mark.parametrize(
"schema_type,content,expected",
(
(None, b"#cloud-config\nntp:", "Valid schema"),
("cloud-config", b"#cloud-config\nntp:", "Valid schema"),
(
"network-config",
(
b"network: {'version': 2, 'ethernets':"
b" {'eth0': {'dhcp': true}}}"
),
"Valid schema",
),
(
"network-config",
(
b"network:\n version: 1\n config:\n - type: physical\n"
b" name: eth0\n subnets:\n - type: dhcp\n"
),
"Valid schema",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_config_file(
self,
_netplan_available,
_read_cfg_paths,
schema_type,
content,
expected,
tmpdir,
capsys,
caplog,
):
"""When --config-file parameter is provided, main validates schema."""
myyaml = tmpdir.join("my.yaml")
myargs = ["mycmd", "--config-file", myyaml.strpath]
if schema_type:
myargs += ["--schema-type", schema_type]
myyaml.write(content) # shortest ntp schema
with mock.patch("sys.argv", myargs):
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
> assert expected in out
E AssertionError: assert 'Valid schema' in 'Skipping cloud-config schema validation. Jsonschema dependency missing.\n'
tests/unittests/config/test_schema.py:2010: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil1/my.yaml (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil1/my.yaml
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_config_file[network-config-network: {'version': 2, 'ethernets': {'eth0': {'dhcp': true}}}-Valid schema] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fd1a90>
_netplan_available = <MagicMock name='available' id='281473671689088'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473671682704'>
schema_type = 'network-config'
content = b"network: {'version': 2, 'ethernets': {'eth0': {'dhcp': true}}}"
expected = 'Valid schema'
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil2')
capsys = <_pytest.capture.CaptureFixture object at 0xffffb166edd0>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb166d2b0>
@pytest.mark.parametrize(
"schema_type,content,expected",
(
(None, b"#cloud-config\nntp:", "Valid schema"),
("cloud-config", b"#cloud-config\nntp:", "Valid schema"),
(
"network-config",
(
b"network: {'version': 2, 'ethernets':"
b" {'eth0': {'dhcp': true}}}"
),
"Valid schema",
),
(
"network-config",
(
b"network:\n version: 1\n config:\n - type: physical\n"
b" name: eth0\n subnets:\n - type: dhcp\n"
),
"Valid schema",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_config_file(
self,
_netplan_available,
_read_cfg_paths,
schema_type,
content,
expected,
tmpdir,
capsys,
caplog,
):
"""When --config-file parameter is provided, main validates schema."""
myyaml = tmpdir.join("my.yaml")
myargs = ["mycmd", "--config-file", myyaml.strpath]
if schema_type:
myargs += ["--schema-type", schema_type]
myyaml.write(content) # shortest ntp schema
with mock.patch("sys.argv", myargs):
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
> assert expected in out
E AssertionError: assert 'Valid schema' in 'Skipping network-config-v2 schema validation. Jsonschema dependency missing.\n'
tests/unittests/config/test_schema.py:2010: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil2/my.yaml (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 62 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil2/my.yaml
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:632 Skipping netplan schema validation. No netplan API available
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:632 Skipping netplan schema validation. No netplan API available
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_config_file[network-config-network:\n version: 1\n config:\n - type: physical\n name: eth0\n subnets:\n - type: dhcp\n-Valid schema] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fd26d0>
_netplan_available = <MagicMock name='available' id='281473671684384'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473671689760'>
schema_type = 'network-config'
content = b'network:\n version: 1\n config:\n - type: physical\n name: eth0\n subnets:\n - type: dhcp\n'
expected = 'Valid schema'
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil3')
capsys = <_pytest.capture.CaptureFixture object at 0xffffb166ef90>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb166ef20>
@pytest.mark.parametrize(
"schema_type,content,expected",
(
(None, b"#cloud-config\nntp:", "Valid schema"),
("cloud-config", b"#cloud-config\nntp:", "Valid schema"),
(
"network-config",
(
b"network: {'version': 2, 'ethernets':"
b" {'eth0': {'dhcp': true}}}"
),
"Valid schema",
),
(
"network-config",
(
b"network:\n version: 1\n config:\n - type: physical\n"
b" name: eth0\n subnets:\n - type: dhcp\n"
),
"Valid schema",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_config_file(
self,
_netplan_available,
_read_cfg_paths,
schema_type,
content,
expected,
tmpdir,
capsys,
caplog,
):
"""When --config-file parameter is provided, main validates schema."""
myyaml = tmpdir.join("my.yaml")
myargs = ["mycmd", "--config-file", myyaml.strpath]
if schema_type:
myargs += ["--schema-type", schema_type]
myyaml.write(content) # shortest ntp schema
with mock.patch("sys.argv", myargs):
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
assert 0 == main(), "Expected 0 exit code"
out, _err = capsys.readouterr()
> assert expected in out
E AssertionError: assert 'Valid schema' in 'Skipping network-config-v1 schema validation. Jsonschema dependency missing.\n'
tests/unittests/config/test_schema.py:2010: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil3/my.yaml (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 96 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_config_fil3/my.yaml
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_processed_data_preference_over_raw_data[prefer_processed_data_when_present_and_non_empty] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb4438390>
_read_cfg_paths = <MagicMock name='getuid' id='281473690719904'>
_getuid = <MagicMock name='read_cfg_paths' id='281473690716880'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473690729648'>
update_path_content_by_key = {}
expected_keys = {'net_key': 'network_config', 'ud_key': 'cloud_config', 'vd2_key': 'vendor2_cloud_config', 'vd_key': 'vendor_cloud_config'}
paths = <cloudinit.helpers.Paths object at 0xffffb20a4370>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb166fbd0>
@pytest.mark.parametrize(
"update_path_content_by_key, expected_keys",
(
pytest.param(
{},
{
"ud_key": "cloud_config",
"vd_key": "vendor_cloud_config",
"vd2_key": "vendor2_cloud_config",
"net_key": "network_config",
},
id="prefer_processed_data_when_present_and_non_empty",
),
pytest.param(
{
"cloud_config": "",
"vendor_cloud_config": "",
"vendor2_cloud_config": "",
},
{
"ud_key": "userdata_raw",
"vd_key": "vendordata_raw",
"vd2_key": "vendordata2_raw",
"net_key": "network_config",
},
id="prefer_raw_data_when_processed_is_empty",
),
pytest.param(
{"cloud_config": "", "userdata_raw": ""},
{
"ud_key": "cloud_config",
"vd_key": "vendor_cloud_config",
"vd2_key": "vendor2_cloud_config",
"net_key": "network_config",
},
id="prefer_processed_vd_file_path_when_raw_and_processed_empty",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
def test_main_processed_data_preference_over_raw_data(
self,
_read_cfg_paths,
_getuid,
read_cfg_paths,
update_path_content_by_key,
expected_keys,
paths,
capsys,
):
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
path_content_by_key = {
"cloud_config": "#cloud-config\n{}",
"vendor_cloud_config": "#cloud-config\n{}",
"vendor2_cloud_config": "#cloud-config\n{}",
"vendordata_raw": "#cloud-config\n{}",
"vendordata2_raw": "#cloud-config\n{}",
"network_config": "{version: 1, config: []}",
"userdata_raw": "#cloud-config\n{}",
}
expected_paths = dict(
(key, paths.get_ipath_cur(expected_keys[key]))
for key in expected_keys
)
path_content_by_key.update(update_path_content_by_key)
for path_key, path_content in path_content_by_key.items():
write_file(paths.get_ipath_cur(path_key), path_content)
data_types = "user-data, vendor-data, vendor2-data, network-config"
ud_msg = " Valid schema user-data"
if (
not path_content_by_key["cloud_config"]
and not path_content_by_key["userdata_raw"]
):
ud_msg = (
f"Empty 'cloud-config' found at {expected_paths['ud_key']}."
" Nothing to validate."
)
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {expected_paths["ud_key"]}:
{ud_msg}
2. vendor-data at {expected_paths['vd_key']}:
Valid schema vendor-data
3. vendor2-data at {expected_paths['vd2_key']}:
Valid schema vendor2-data
4. network-config at {expected_paths['net_key']}:
Valid schema network-config
"""
)
myargs = ["mycmd", "--system"]
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
> assert expected == out
E AssertionError: assert 'Found cloud-...work-config\n' == 'Found cloud-...cy missing.\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/cloud-config.txt:
E - Skipping cloud-config schema validation. Jsonschema dependency missing.
E + Valid schema user-data
E ...
E
E ...Full output truncated (11 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2113: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/cloud-config.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor-data.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor-data2.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/network-config.json - wb: [644] 24 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/user-data.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 24 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe0/cloud_dir/instance/network-config.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_processed_data_preference_over_raw_data[prefer_raw_data_when_processed_is_empty] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fd8f50>
_read_cfg_paths = <MagicMock name='getuid' id='281473670634128'>
_getuid = <MagicMock name='read_cfg_paths' id='281473670633792'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670627744'>
update_path_content_by_key = {'cloud_config': '', 'vendor2_cloud_config': '', 'vendor_cloud_config': ''}
expected_keys = {'net_key': 'network_config', 'ud_key': 'userdata_raw', 'vd2_key': 'vendordata2_raw', 'vd_key': 'vendordata_raw'}
paths = <cloudinit.helpers.Paths object at 0xffffb1c5b750>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb166db00>
@pytest.mark.parametrize(
"update_path_content_by_key, expected_keys",
(
pytest.param(
{},
{
"ud_key": "cloud_config",
"vd_key": "vendor_cloud_config",
"vd2_key": "vendor2_cloud_config",
"net_key": "network_config",
},
id="prefer_processed_data_when_present_and_non_empty",
),
pytest.param(
{
"cloud_config": "",
"vendor_cloud_config": "",
"vendor2_cloud_config": "",
},
{
"ud_key": "userdata_raw",
"vd_key": "vendordata_raw",
"vd2_key": "vendordata2_raw",
"net_key": "network_config",
},
id="prefer_raw_data_when_processed_is_empty",
),
pytest.param(
{"cloud_config": "", "userdata_raw": ""},
{
"ud_key": "cloud_config",
"vd_key": "vendor_cloud_config",
"vd2_key": "vendor2_cloud_config",
"net_key": "network_config",
},
id="prefer_processed_vd_file_path_when_raw_and_processed_empty",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
def test_main_processed_data_preference_over_raw_data(
self,
_read_cfg_paths,
_getuid,
read_cfg_paths,
update_path_content_by_key,
expected_keys,
paths,
capsys,
):
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
path_content_by_key = {
"cloud_config": "#cloud-config\n{}",
"vendor_cloud_config": "#cloud-config\n{}",
"vendor2_cloud_config": "#cloud-config\n{}",
"vendordata_raw": "#cloud-config\n{}",
"vendordata2_raw": "#cloud-config\n{}",
"network_config": "{version: 1, config: []}",
"userdata_raw": "#cloud-config\n{}",
}
expected_paths = dict(
(key, paths.get_ipath_cur(expected_keys[key]))
for key in expected_keys
)
path_content_by_key.update(update_path_content_by_key)
for path_key, path_content in path_content_by_key.items():
write_file(paths.get_ipath_cur(path_key), path_content)
data_types = "user-data, vendor-data, vendor2-data, network-config"
ud_msg = " Valid schema user-data"
if (
not path_content_by_key["cloud_config"]
and not path_content_by_key["userdata_raw"]
):
ud_msg = (
f"Empty 'cloud-config' found at {expected_paths['ud_key']}."
" Nothing to validate."
)
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {expected_paths["ud_key"]}:
{ud_msg}
2. vendor-data at {expected_paths['vd_key']}:
Valid schema vendor-data
3. vendor2-data at {expected_paths['vd2_key']}:
Valid schema vendor2-data
4. network-config at {expected_paths['net_key']}:
Valid schema network-config
"""
)
myargs = ["mycmd", "--system"]
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
> assert expected == out
E AssertionError: assert 'Found cloud-...work-config\n' == 'Found cloud-...cy missing.\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/user-data.txt:
E - Skipping cloud-config schema validation. Jsonschema dependency missing.
E + Valid schema user-data
E ...
E
E ...Full output truncated (11 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2113: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/cloud-config.txt - wb: [644] 0 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 0 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 0 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-data.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-data2.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/network-config.json - wb: [644] 24 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/user-data.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/user-data.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/user-data.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-data.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-data.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-data2.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/vendor-data2.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 24 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe1/cloud_dir/instance/network-config.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_processed_data_preference_over_raw_data[prefer_processed_vd_file_path_when_raw_and_processed_empty] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fd9010>
_read_cfg_paths = <MagicMock name='getuid' id='281473670631104'>
_getuid = <MagicMock name='read_cfg_paths' id='281473670637152'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670642192'>
update_path_content_by_key = {'cloud_config': '', 'userdata_raw': ''}
expected_keys = {'net_key': 'network_config', 'ud_key': 'cloud_config', 'vd2_key': 'vendor2_cloud_config', 'vd_key': 'vendor_cloud_config'}
paths = <cloudinit.helpers.Paths object at 0xffffb1ca04b0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb166def0>
@pytest.mark.parametrize(
"update_path_content_by_key, expected_keys",
(
pytest.param(
{},
{
"ud_key": "cloud_config",
"vd_key": "vendor_cloud_config",
"vd2_key": "vendor2_cloud_config",
"net_key": "network_config",
},
id="prefer_processed_data_when_present_and_non_empty",
),
pytest.param(
{
"cloud_config": "",
"vendor_cloud_config": "",
"vendor2_cloud_config": "",
},
{
"ud_key": "userdata_raw",
"vd_key": "vendordata_raw",
"vd2_key": "vendordata2_raw",
"net_key": "network_config",
},
id="prefer_raw_data_when_processed_is_empty",
),
pytest.param(
{"cloud_config": "", "userdata_raw": ""},
{
"ud_key": "cloud_config",
"vd_key": "vendor_cloud_config",
"vd2_key": "vendor2_cloud_config",
"net_key": "network_config",
},
id="prefer_processed_vd_file_path_when_raw_and_processed_empty",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
def test_main_processed_data_preference_over_raw_data(
self,
_read_cfg_paths,
_getuid,
read_cfg_paths,
update_path_content_by_key,
expected_keys,
paths,
capsys,
):
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
path_content_by_key = {
"cloud_config": "#cloud-config\n{}",
"vendor_cloud_config": "#cloud-config\n{}",
"vendor2_cloud_config": "#cloud-config\n{}",
"vendordata_raw": "#cloud-config\n{}",
"vendordata2_raw": "#cloud-config\n{}",
"network_config": "{version: 1, config: []}",
"userdata_raw": "#cloud-config\n{}",
}
expected_paths = dict(
(key, paths.get_ipath_cur(expected_keys[key]))
for key in expected_keys
)
path_content_by_key.update(update_path_content_by_key)
for path_key, path_content in path_content_by_key.items():
write_file(paths.get_ipath_cur(path_key), path_content)
data_types = "user-data, vendor-data, vendor2-data, network-config"
ud_msg = " Valid schema user-data"
if (
not path_content_by_key["cloud_config"]
and not path_content_by_key["userdata_raw"]
):
ud_msg = (
f"Empty 'cloud-config' found at {expected_paths['ud_key']}."
" Nothing to validate."
)
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {expected_paths["ud_key"]}:
{ud_msg}
2. vendor-data at {expected_paths['vd_key']}:
Valid schema vendor-data
3. vendor2-data at {expected_paths['vd2_key']}:
Valid schema vendor2-data
4. network-config at {expected_paths['net_key']}:
Valid schema network-config
"""
)
myargs = ["mycmd", "--system"]
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
> assert expected == out
E AssertionError: assert 'Found cloud-...work-config\n' == 'Found cloud-...cy missing.\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/cloud-config.txt:
E Empty 'cloud-config' found at /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/cloud-config.txt. Nothing to validate.
E
E 2. vendor-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor-cloud-config.txt:...
E
E ...Full output truncated (10 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2113: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/cloud-config.txt - wb: [644] 0 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor-data.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor-data2.txt - wb: [644] 16 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/network-config.json - wb: [644] 24 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/user-data.txt - wb: [644] 0 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 0 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 16 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 24 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_processed_data_prefe2/cloud_dir/instance/network-config.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_system_userdata_vendordata_and_network_config[netv1_schema_validated] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fd5e90>
_netplan_available = <MagicMock name='available' id='281473670639168'>
_getuid = <MagicMock name='getuid' id='281473670636480'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670636816'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670641856'>
net_config = 'network:\n version: 1\n config:\n - type: physical\n name: eth0\n subnets:\n - type: dhcp\n'
net_output = ' Valid schema network-config'
error_raised = <contextlib._GeneratorContextManager object at 0xffffb4643b60>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb166da90>
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb16de340>
paths = <cloudinit.helpers.Paths object at 0xffffb197d6d0>
@pytest.mark.parametrize(
"net_config,net_output,error_raised",
(
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Valid schema network-config",
does_not_raise(),
id="netv1_schema_validated",
),
pytest.param(
"network:\n version: 2\n ethernets:\n eth0:\n"
" dhcp4: true\n",
" Valid schema network-config",
does_not_raise(),
id="netv2_schema_validated_non_netplan",
),
pytest.param(
"network: {}\n",
"Skipping network-config schema validation on empty config.",
does_not_raise(),
id="empty_net_validation_is_skipped",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_errors_handled",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth01234567890123\n subnets:\n"
" - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_error_on_nic_name_length",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_system_userdata_vendordata_and_network_config(
self,
_netplan_available,
_getuid,
_read_cfg_paths,
read_cfg_paths,
net_config,
net_output,
error_raised,
capsys,
mocker,
paths,
):
"""When --system is provided, main validates all config userdata."""
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
cloud_config_file = paths.get_ipath_cur("cloud_config")
write_file(cloud_config_file, b"#cloud-config\nntp:")
vd_file = paths.get_ipath_cur("vendor_cloud_config")
write_file(vd_file, b"#cloud-config\nssh_import_id: [me]")
vd2_file = paths.get_ipath_cur("vendor2_cloud_config")
write_file(vd2_file, b"#cloud-config\nssh_pwauth: true")
network_file = paths.get_ipath_cur("network_config")
write_file(network_file, net_config)
myargs = ["mycmd", "--system"]
with error_raised:
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
net_output = net_output.format(network_file=network_file)
data_types = "user-data, vendor-data, vendor2-data, network-config"
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {cloud_config_file}:
Valid schema user-data
2. vendor-data at {vd_file}:
Valid schema vendor-data
3. vendor2-data at {vd2_file}:
Valid schema vendor2-data
4. network-config at {network_file}:
{net_output}
"""
)
> assert expected == out
E AssertionError: assert 'Found cloud-...work-config\n' == 'Found cloud-...cy missing.\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/cloud-config.txt:
E - Skipping cloud-config schema validation. Jsonschema dependency missing.
E + Valid schema user-data
E ...
E
E ...Full output truncated (11 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2211: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/cloud-config.txt - wb: [644] 18 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 33 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 30 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/network-config.json - wb: [644] 96 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 33 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 30 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 96 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use0/cloud_dir/instance/network-config.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_system_userdata_vendordata_and_network_config[netv2_schema_validated_non_netplan] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fd4310>
_netplan_available = <MagicMock name='available' id='281473670631440'>
_getuid = <MagicMock name='getuid' id='281473670636144'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670629088'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670628416'>
net_config = 'network:\n version: 2\n ethernets:\n eth0:\n dhcp4: true\n'
net_output = ' Valid schema network-config'
error_raised = <contextlib._GeneratorContextManager object at 0xffffb46438c0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19d74d0>
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb1629570>
paths = <cloudinit.helpers.Paths object at 0xffffb197d450>
@pytest.mark.parametrize(
"net_config,net_output,error_raised",
(
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Valid schema network-config",
does_not_raise(),
id="netv1_schema_validated",
),
pytest.param(
"network:\n version: 2\n ethernets:\n eth0:\n"
" dhcp4: true\n",
" Valid schema network-config",
does_not_raise(),
id="netv2_schema_validated_non_netplan",
),
pytest.param(
"network: {}\n",
"Skipping network-config schema validation on empty config.",
does_not_raise(),
id="empty_net_validation_is_skipped",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_errors_handled",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth01234567890123\n subnets:\n"
" - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_error_on_nic_name_length",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_system_userdata_vendordata_and_network_config(
self,
_netplan_available,
_getuid,
_read_cfg_paths,
read_cfg_paths,
net_config,
net_output,
error_raised,
capsys,
mocker,
paths,
):
"""When --system is provided, main validates all config userdata."""
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
cloud_config_file = paths.get_ipath_cur("cloud_config")
write_file(cloud_config_file, b"#cloud-config\nntp:")
vd_file = paths.get_ipath_cur("vendor_cloud_config")
write_file(vd_file, b"#cloud-config\nssh_import_id: [me]")
vd2_file = paths.get_ipath_cur("vendor2_cloud_config")
write_file(vd2_file, b"#cloud-config\nssh_pwauth: true")
network_file = paths.get_ipath_cur("network_config")
write_file(network_file, net_config)
myargs = ["mycmd", "--system"]
with error_raised:
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
net_output = net_output.format(network_file=network_file)
data_types = "user-data, vendor-data, vendor2-data, network-config"
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {cloud_config_file}:
Valid schema user-data
2. vendor-data at {vd_file}:
Valid schema vendor-data
3. vendor2-data at {vd2_file}:
Valid schema vendor2-data
4. network-config at {network_file}:
{net_output}
"""
)
> assert expected == out
E AssertionError: assert 'Found cloud-...work-config\n' == 'Found cloud-...cy missing.\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/cloud-config.txt:
E - Skipping cloud-config schema validation. Jsonschema dependency missing.
E + Valid schema user-data
E ...
E
E ...Full output truncated (11 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2211: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/cloud-config.txt - wb: [644] 18 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 33 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 30 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/network-config.json - wb: [644] 56 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 33 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 30 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 56 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use1/cloud_dir/instance/network-config.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:632 Skipping netplan schema validation. No netplan API available
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:632 Skipping netplan schema validation. No netplan API available
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestMain.test_main_validates_system_userdata_vendordata_and_network_config[empty_net_validation_is_skipped] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fee0d0>
_netplan_available = <MagicMock name='available' id='281473670638832'>
_getuid = <MagicMock name='getuid' id='281473670630768'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670629424'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670629760'>
net_config = 'network: {}\n'
net_output = 'Skipping network-config schema validation on empty config.'
error_raised = <contextlib._GeneratorContextManager object at 0xffffb4643a10>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb18932a0>
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb1629090>
paths = <cloudinit.helpers.Paths object at 0xffffb206c5f0>
@pytest.mark.parametrize(
"net_config,net_output,error_raised",
(
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Valid schema network-config",
does_not_raise(),
id="netv1_schema_validated",
),
pytest.param(
"network:\n version: 2\n ethernets:\n eth0:\n"
" dhcp4: true\n",
" Valid schema network-config",
does_not_raise(),
id="netv2_schema_validated_non_netplan",
),
pytest.param(
"network: {}\n",
"Skipping network-config schema validation on empty config.",
does_not_raise(),
id="empty_net_validation_is_skipped",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_errors_handled",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth01234567890123\n subnets:\n"
" - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_error_on_nic_name_length",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_system_userdata_vendordata_and_network_config(
self,
_netplan_available,
_getuid,
_read_cfg_paths,
read_cfg_paths,
net_config,
net_output,
error_raised,
capsys,
mocker,
paths,
):
"""When --system is provided, main validates all config userdata."""
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
cloud_config_file = paths.get_ipath_cur("cloud_config")
write_file(cloud_config_file, b"#cloud-config\nntp:")
vd_file = paths.get_ipath_cur("vendor_cloud_config")
write_file(vd_file, b"#cloud-config\nssh_import_id: [me]")
vd2_file = paths.get_ipath_cur("vendor2_cloud_config")
write_file(vd2_file, b"#cloud-config\nssh_pwauth: true")
network_file = paths.get_ipath_cur("network_config")
write_file(network_file, net_config)
myargs = ["mycmd", "--system"]
with error_raised:
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
net_output = net_output.format(network_file=network_file)
data_types = "user-data, vendor-data, vendor2-data, network-config"
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {cloud_config_file}:
Valid schema user-data
2. vendor-data at {vd_file}:
Valid schema vendor-data
3. vendor2-data at {vd2_file}:
Valid schema vendor2-data
4. network-config at {network_file}:
{net_output}
"""
)
> assert expected == out
E AssertionError: assert 'Found cloud-...pty config.\n' == 'Found cloud-...pty config.\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/cloud-config.txt:
E - Skipping cloud-config schema validation. Jsonschema dependency missing.
E + Valid schema user-data
E ...
E
E ...Full output truncated (10 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2211: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/cloud-config.txt - wb: [644] 18 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 33 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 30 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/network-config.json - wb: [644] 12 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 33 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 30 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 12 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use2/cloud_dir/instance/network-config.json
_ TestMain.test_main_validates_system_userdata_vendordata_and_network_config[netv1_schema_errors_handled] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb3fee530>
_netplan_available = <MagicMock name='available' id='281473670638496'>
_getuid = <MagicMock name='getuid' id='281473670633456'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473670631776'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473672413264'>
net_config = 'network:\n version: 1\n config:\n - type: physical\n name: eth0\n subnets:\n - type: dhcp\n'
net_output = ' Invalid network-config /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/network-config.json'
error_raised = <_pytest.python_api.RaisesContext object at 0xffffb4643bd0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb1890670>
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb18f8600>
paths = <cloudinit.helpers.Paths object at 0xffffb2481810>
@pytest.mark.parametrize(
"net_config,net_output,error_raised",
(
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Valid schema network-config",
does_not_raise(),
id="netv1_schema_validated",
),
pytest.param(
"network:\n version: 2\n ethernets:\n eth0:\n"
" dhcp4: true\n",
" Valid schema network-config",
does_not_raise(),
id="netv2_schema_validated_non_netplan",
),
pytest.param(
"network: {}\n",
"Skipping network-config schema validation on empty config.",
does_not_raise(),
id="empty_net_validation_is_skipped",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_errors_handled",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth01234567890123\n subnets:\n"
" - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_error_on_nic_name_length",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_system_userdata_vendordata_and_network_config(
self,
_netplan_available,
_getuid,
_read_cfg_paths,
read_cfg_paths,
net_config,
net_output,
error_raised,
capsys,
mocker,
paths,
):
"""When --system is provided, main validates all config userdata."""
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
cloud_config_file = paths.get_ipath_cur("cloud_config")
write_file(cloud_config_file, b"#cloud-config\nntp:")
vd_file = paths.get_ipath_cur("vendor_cloud_config")
write_file(vd_file, b"#cloud-config\nssh_import_id: [me]")
vd2_file = paths.get_ipath_cur("vendor2_cloud_config")
write_file(vd2_file, b"#cloud-config\nssh_pwauth: true")
network_file = paths.get_ipath_cur("network_config")
write_file(network_file, net_config)
myargs = ["mycmd", "--system"]
with error_raised:
# Always assert we have no netplan module which triggers
# schema skip of network-config version: 2 until cloud-init
# grows internal schema-network-config-v2.json.
with mock.patch.dict("sys.modules", netplan=ImportError()):
with mock.patch("sys.argv", myargs):
main()
out, _err = capsys.readouterr()
net_output = net_output.format(network_file=network_file)
data_types = "user-data, vendor-data, vendor2-data, network-config"
expected = dedent(
f"""\
Found cloud-config data types: {data_types}
1. user-data at {cloud_config_file}:
Valid schema user-data
2. vendor-data at {vd_file}:
Valid schema vendor-data
3. vendor2-data at {vd2_file}:
Valid schema vendor2-data
4. network-config at {network_file}:
{net_output}
"""
)
> assert expected == out
E AssertionError: assert 'Found cloud-...config.json\n' == 'Found cloud-...config.json\n'
E
E Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
E
E 1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/cloud-config.txt:
E - Skipping cloud-config schema validation. Jsonschema dependency missing.
E + Valid schema user-data
E ...
E
E ...Full output truncated (10 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2211: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/cloud-config.txt - wb: [644] 18 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 33 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 30 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/network-config.json - wb: [644] 95 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 33 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 30 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 95 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use3/cloud_dir/instance/network-config.json
_ TestMain.test_main_validates_system_userdata_vendordata_and_network_config[netv1_schema_error_on_nic_name_length] _
self = <tests.unittests.config.test_schema.TestMain object at 0xffffb44fe840>
_netplan_available = <MagicMock name='available' id='281473672425696'>
_getuid = <MagicMock name='getuid' id='281473672935616'>
_read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473672933264'>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473672925872'>
net_config = 'network:\n version: 1\n config:\n - type: physical\n name: eth01234567890123\n subnets:\n - type: dhcp\n'
net_output = ' Invalid network-config {network_file}'
error_raised = <_pytest.python_api.RaisesContext object at 0xffffb46ec050>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb18906e0>
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb1629a50>
paths = <cloudinit.helpers.Paths object at 0xffffb24df930>
@pytest.mark.parametrize(
"net_config,net_output,error_raised",
(
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Valid schema network-config",
does_not_raise(),
id="netv1_schema_validated",
),
pytest.param(
"network:\n version: 2\n ethernets:\n eth0:\n"
" dhcp4: true\n",
" Valid schema network-config",
does_not_raise(),
id="netv2_schema_validated_non_netplan",
),
pytest.param(
"network: {}\n",
"Skipping network-config schema validation on empty config.",
does_not_raise(),
id="empty_net_validation_is_skipped",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth0\n subnets:\n - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_errors_handled",
),
pytest.param(
"network:\n version: 1\n config:\n - type: physical\n"
" name: eth01234567890123\n subnets:\n"
" - type: dhcp\n",
" Invalid network-config {network_file}",
pytest.raises(SystemExit),
id="netv1_schema_error_on_nic_name_length",
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
@mock.patch(M_PATH + "os.getuid", return_value=0)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_main_validates_system_userdata_vendordata_and_network_config(
self,
_netplan_available,
_getuid,
_read_cfg_paths,
read_cfg_paths,
net_config,
net_output,
error_raised,
capsys,
mocker,
paths,
):
"""When --system is provided, main validates all config userdata."""
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
cloud_config_file = paths.get_ipath_cur("cloud_config")
write_file(cloud_config_file, b"#cloud-config\nntp:")
vd_file = paths.get_ipath_cur("vendor_cloud_config")
write_file(vd_file, b"#cloud-config\nssh_import_id: [me]")
vd2_file = paths.get_ipath_cur("vendor2_cloud_config")
write_file(vd2_file, b"#cloud-config\nssh_pwauth: true")
network_file = paths.get_ipath_cur("network_config")
write_file(network_file, net_config)
myargs = ["mycmd", "--system"]
> with error_raised:
E Failed: DID NOT RAISE <class 'SystemExit'>
tests/unittests/config/test_schema.py:2183: Failed
----------------------------- Captured stdout call -----------------------------
Found cloud-config data types: user-data, vendor-data, vendor2-data, network-config
1. user-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/cloud-config.txt:
Skipping cloud-config schema validation. Jsonschema dependency missing.
2. vendor-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor-cloud-config.txt:
Skipping cloud-config schema validation. Jsonschema dependency missing.
3. vendor2-data at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor2-cloud-config.txt:
Skipping cloud-config schema validation. Jsonschema dependency missing.
4. network-config at /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/network-config.json:
Skipping network-config-v1 schema validation. Jsonschema dependency missing.
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/cloud-config.txt - wb: [644] 18 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor-cloud-config.txt - wb: [644] 33 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor2-cloud-config.txt - wb: [644] 30 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:2345 Writing to /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/network-config.json - wb: [644] 109 bytes
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 18 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 33 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor2-cloud-config.txt (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 30 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/vendor2-cloud-config.txt
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/network-config.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 109 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_main_validates_system_use4/cloud_dir/instance/network-config.json
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_________ TestNetworkSchema.test_network_schema[net_v2_invalid_config] _________
self = <tests.unittests.config.test_schema.TestNetworkSchema object at 0xffffb46e74d0>
_netplan_available = <MagicMock name='available' id='281473693803792'>
src_config = {'network': {'config': [], 'version': 2}}
schema_type_version = <SchemaType.NETWORK_CONFIG_V2: 'network-config-v2'>
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46ee200>
log = '', caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb2ab64a0>
@pytest.mark.parametrize(
"src_config, schema_type_version, expectation, log",
(
pytest.param(
{"network": {"config": [], "version": 2}},
SchemaType.NETWORK_CONFIG_V2,
pytest.raises(
SchemaValidationError,
match=re.escape(
"Additional properties are not allowed ('config' was "
"unexpected)"
),
),
"",
id="net_v2_invalid_config",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_simple_example",
),
pytest.param(
{
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_no_top_level",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {
"id0": {
"match": {
"macaddress": "00:11:22:33:44:55",
},
"wakeonlan": True,
"dhcp4": True,
"addresses": [
"192.168.14.2/24",
"2001:1::1/64",
],
"gateway4": "192.168.14.1",
"gateway6": "2001:1::2",
"nameservers": {
"search": ["foo.local", "bar.local"],
"addresses": ["8.8.8.8"],
},
"routes": [
{
"to": "192.0.2.0/24",
"via": "11.0.0.1",
"metric": 3,
},
],
},
"lom": {
"match": {"driver": "ixgbe"},
"set-name": "lom1",
"dhcp6": True,
},
"switchports": {
"match": {"name": "enp2*"},
"mtu": 1280,
},
},
"bonds": {
"bond0": {"interfaces": ["id0", "lom"]},
},
"bridges": {
"br0": {
"interfaces": ["wlp1s0", "switchports"],
"dhcp4": True,
},
},
"vlans": {
"en-intra": {
"id": 1,
"link": "id0",
"dhcp4": "yes",
},
},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_complex_example",
),
pytest.param(
{"network": {"version": 1}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=re.escape("'config' is a required property"),
),
"",
id="config_key_required",
),
pytest.param(
{"network": {"version": 1, "config": []}},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="config_key_required",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"name": "me", "type": "typo"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=(
r"network.config.0: {'name': 'me', 'type': 'typo'} is"
" not valid under any of the given schemas"
),
),
"",
id="unknown_config_type_item",
),
pytest.param(
{"network": {"version": 1, "config": [{"type": "physical"}]}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"network.config.0: 'name' is a required property.*",
),
"",
id="physical_requires_name_property",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"type": "physical", "name": "a"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_name_succeeds",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "a", "asdf": 1}
],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"Additional properties are not allowed.*",
),
"",
id="physical_no_additional_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_PHYSICAL_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_BOND_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="bond_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "eth0", "mtu": None},
{"type": "nameserver", "address": "8.8.8.8"},
],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="GH-4710_mtu_none_and_str_address",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_network_schema(
self,
_netplan_available,
src_config,
schema_type_version,
expectation,
log,
caplog,
):
net_schema = get_schema(schema_type=schema_type_version)
> with expectation:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:2564: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 17775 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v2.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:632 Skipping netplan schema validation. No netplan API available
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_________ TestNetworkSchema.test_network_schema[config_key_required0] __________
self = <tests.unittests.config.test_schema.TestNetworkSchema object at 0xffffb453fe30>
_netplan_available = <MagicMock name='available' id='281473674745840'>
src_config = {'network': {'version': 1}}
schema_type_version = <SchemaType.NETWORK_CONFIG_V1: 'network-config-v1'>
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46ee430>
log = '', caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb2232820>
@pytest.mark.parametrize(
"src_config, schema_type_version, expectation, log",
(
pytest.param(
{"network": {"config": [], "version": 2}},
SchemaType.NETWORK_CONFIG_V2,
pytest.raises(
SchemaValidationError,
match=re.escape(
"Additional properties are not allowed ('config' was "
"unexpected)"
),
),
"",
id="net_v2_invalid_config",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_simple_example",
),
pytest.param(
{
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_no_top_level",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {
"id0": {
"match": {
"macaddress": "00:11:22:33:44:55",
},
"wakeonlan": True,
"dhcp4": True,
"addresses": [
"192.168.14.2/24",
"2001:1::1/64",
],
"gateway4": "192.168.14.1",
"gateway6": "2001:1::2",
"nameservers": {
"search": ["foo.local", "bar.local"],
"addresses": ["8.8.8.8"],
},
"routes": [
{
"to": "192.0.2.0/24",
"via": "11.0.0.1",
"metric": 3,
},
],
},
"lom": {
"match": {"driver": "ixgbe"},
"set-name": "lom1",
"dhcp6": True,
},
"switchports": {
"match": {"name": "enp2*"},
"mtu": 1280,
},
},
"bonds": {
"bond0": {"interfaces": ["id0", "lom"]},
},
"bridges": {
"br0": {
"interfaces": ["wlp1s0", "switchports"],
"dhcp4": True,
},
},
"vlans": {
"en-intra": {
"id": 1,
"link": "id0",
"dhcp4": "yes",
},
},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_complex_example",
),
pytest.param(
{"network": {"version": 1}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=re.escape("'config' is a required property"),
),
"",
id="config_key_required",
),
pytest.param(
{"network": {"version": 1, "config": []}},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="config_key_required",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"name": "me", "type": "typo"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=(
r"network.config.0: {'name': 'me', 'type': 'typo'} is"
" not valid under any of the given schemas"
),
),
"",
id="unknown_config_type_item",
),
pytest.param(
{"network": {"version": 1, "config": [{"type": "physical"}]}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"network.config.0: 'name' is a required property.*",
),
"",
id="physical_requires_name_property",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"type": "physical", "name": "a"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_name_succeeds",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "a", "asdf": 1}
],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"Additional properties are not allowed.*",
),
"",
id="physical_no_additional_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_PHYSICAL_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_BOND_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="bond_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "eth0", "mtu": None},
{"type": "nameserver", "address": "8.8.8.8"},
],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="GH-4710_mtu_none_and_str_address",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_network_schema(
self,
_netplan_available,
src_config,
schema_type_version,
expectation,
log,
caplog,
):
net_schema = get_schema(schema_type=schema_type_version)
> with expectation:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:2564: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_______ TestNetworkSchema.test_network_schema[unknown_config_type_item] ________
self = <tests.unittests.config.test_schema.TestNetworkSchema object at 0xffffb3fa47c0>
_netplan_available = <MagicMock name='available' id='281473671385440'>
src_config = {'network': {'config': [{'name': 'me', 'type': 'typo'}], 'version': 1}}
schema_type_version = <SchemaType.NETWORK_CONFIG_V1: 'network-config-v1'>
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46ee580>
log = '', caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb18133f0>
@pytest.mark.parametrize(
"src_config, schema_type_version, expectation, log",
(
pytest.param(
{"network": {"config": [], "version": 2}},
SchemaType.NETWORK_CONFIG_V2,
pytest.raises(
SchemaValidationError,
match=re.escape(
"Additional properties are not allowed ('config' was "
"unexpected)"
),
),
"",
id="net_v2_invalid_config",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_simple_example",
),
pytest.param(
{
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_no_top_level",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {
"id0": {
"match": {
"macaddress": "00:11:22:33:44:55",
},
"wakeonlan": True,
"dhcp4": True,
"addresses": [
"192.168.14.2/24",
"2001:1::1/64",
],
"gateway4": "192.168.14.1",
"gateway6": "2001:1::2",
"nameservers": {
"search": ["foo.local", "bar.local"],
"addresses": ["8.8.8.8"],
},
"routes": [
{
"to": "192.0.2.0/24",
"via": "11.0.0.1",
"metric": 3,
},
],
},
"lom": {
"match": {"driver": "ixgbe"},
"set-name": "lom1",
"dhcp6": True,
},
"switchports": {
"match": {"name": "enp2*"},
"mtu": 1280,
},
},
"bonds": {
"bond0": {"interfaces": ["id0", "lom"]},
},
"bridges": {
"br0": {
"interfaces": ["wlp1s0", "switchports"],
"dhcp4": True,
},
},
"vlans": {
"en-intra": {
"id": 1,
"link": "id0",
"dhcp4": "yes",
},
},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_complex_example",
),
pytest.param(
{"network": {"version": 1}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=re.escape("'config' is a required property"),
),
"",
id="config_key_required",
),
pytest.param(
{"network": {"version": 1, "config": []}},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="config_key_required",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"name": "me", "type": "typo"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=(
r"network.config.0: {'name': 'me', 'type': 'typo'} is"
" not valid under any of the given schemas"
),
),
"",
id="unknown_config_type_item",
),
pytest.param(
{"network": {"version": 1, "config": [{"type": "physical"}]}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"network.config.0: 'name' is a required property.*",
),
"",
id="physical_requires_name_property",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"type": "physical", "name": "a"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_name_succeeds",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "a", "asdf": 1}
],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"Additional properties are not allowed.*",
),
"",
id="physical_no_additional_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_PHYSICAL_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_BOND_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="bond_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "eth0", "mtu": None},
{"type": "nameserver", "address": "8.8.8.8"},
],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="GH-4710_mtu_none_and_str_address",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_network_schema(
self,
_netplan_available,
src_config,
schema_type_version,
expectation,
log,
caplog,
):
net_schema = get_schema(schema_type=schema_type_version)
> with expectation:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:2564: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
____ TestNetworkSchema.test_network_schema[physical_requires_name_property] ____
self = <tests.unittests.config.test_schema.TestNetworkSchema object at 0xffffb46fef50>
_netplan_available = <MagicMock name='available' id='281473694073248'>
src_config = {'network': {'config': [{'type': 'physical'}], 'version': 1}}
schema_type_version = <SchemaType.NETWORK_CONFIG_V1: 'network-config-v1'>
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46ee660>
log = '', caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb18cb460>
@pytest.mark.parametrize(
"src_config, schema_type_version, expectation, log",
(
pytest.param(
{"network": {"config": [], "version": 2}},
SchemaType.NETWORK_CONFIG_V2,
pytest.raises(
SchemaValidationError,
match=re.escape(
"Additional properties are not allowed ('config' was "
"unexpected)"
),
),
"",
id="net_v2_invalid_config",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_simple_example",
),
pytest.param(
{
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_no_top_level",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {
"id0": {
"match": {
"macaddress": "00:11:22:33:44:55",
},
"wakeonlan": True,
"dhcp4": True,
"addresses": [
"192.168.14.2/24",
"2001:1::1/64",
],
"gateway4": "192.168.14.1",
"gateway6": "2001:1::2",
"nameservers": {
"search": ["foo.local", "bar.local"],
"addresses": ["8.8.8.8"],
},
"routes": [
{
"to": "192.0.2.0/24",
"via": "11.0.0.1",
"metric": 3,
},
],
},
"lom": {
"match": {"driver": "ixgbe"},
"set-name": "lom1",
"dhcp6": True,
},
"switchports": {
"match": {"name": "enp2*"},
"mtu": 1280,
},
},
"bonds": {
"bond0": {"interfaces": ["id0", "lom"]},
},
"bridges": {
"br0": {
"interfaces": ["wlp1s0", "switchports"],
"dhcp4": True,
},
},
"vlans": {
"en-intra": {
"id": 1,
"link": "id0",
"dhcp4": "yes",
},
},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_complex_example",
),
pytest.param(
{"network": {"version": 1}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=re.escape("'config' is a required property"),
),
"",
id="config_key_required",
),
pytest.param(
{"network": {"version": 1, "config": []}},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="config_key_required",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"name": "me", "type": "typo"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=(
r"network.config.0: {'name': 'me', 'type': 'typo'} is"
" not valid under any of the given schemas"
),
),
"",
id="unknown_config_type_item",
),
pytest.param(
{"network": {"version": 1, "config": [{"type": "physical"}]}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"network.config.0: 'name' is a required property.*",
),
"",
id="physical_requires_name_property",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"type": "physical", "name": "a"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_name_succeeds",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "a", "asdf": 1}
],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"Additional properties are not allowed.*",
),
"",
id="physical_no_additional_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_PHYSICAL_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_BOND_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="bond_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "eth0", "mtu": None},
{"type": "nameserver", "address": "8.8.8.8"},
],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="GH-4710_mtu_none_and_str_address",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_network_schema(
self,
_netplan_available,
src_config,
schema_type_version,
expectation,
log,
caplog,
):
net_schema = get_schema(schema_type=schema_type_version)
> with expectation:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:2564: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
___ TestNetworkSchema.test_network_schema[physical_no_additional_properties] ___
self = <tests.unittests.config.test_schema.TestNetworkSchema object at 0xffffb3f92c60>
_netplan_available = <MagicMock name='available' id='281473694076944'>
src_config = {'network': {'config': [{'asdf': 1, 'name': 'a', 'type': 'physical'}], 'version': 1}}
schema_type_version = <SchemaType.NETWORK_CONFIG_V1: 'network-config-v1'>
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46ee7b0>
log = '', caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb18ca3c0>
@pytest.mark.parametrize(
"src_config, schema_type_version, expectation, log",
(
pytest.param(
{"network": {"config": [], "version": 2}},
SchemaType.NETWORK_CONFIG_V2,
pytest.raises(
SchemaValidationError,
match=re.escape(
"Additional properties are not allowed ('config' was "
"unexpected)"
),
),
"",
id="net_v2_invalid_config",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_simple_example",
),
pytest.param(
{
"version": 2,
"ethernets": {"eno1": {"dhcp4": True}},
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_no_top_level",
),
pytest.param(
{
"network": {
"version": 2,
"ethernets": {
"id0": {
"match": {
"macaddress": "00:11:22:33:44:55",
},
"wakeonlan": True,
"dhcp4": True,
"addresses": [
"192.168.14.2/24",
"2001:1::1/64",
],
"gateway4": "192.168.14.1",
"gateway6": "2001:1::2",
"nameservers": {
"search": ["foo.local", "bar.local"],
"addresses": ["8.8.8.8"],
},
"routes": [
{
"to": "192.0.2.0/24",
"via": "11.0.0.1",
"metric": 3,
},
],
},
"lom": {
"match": {"driver": "ixgbe"},
"set-name": "lom1",
"dhcp6": True,
},
"switchports": {
"match": {"name": "enp2*"},
"mtu": 1280,
},
},
"bonds": {
"bond0": {"interfaces": ["id0", "lom"]},
},
"bridges": {
"br0": {
"interfaces": ["wlp1s0", "switchports"],
"dhcp4": True,
},
},
"vlans": {
"en-intra": {
"id": 1,
"link": "id0",
"dhcp4": "yes",
},
},
}
},
SchemaType.NETWORK_CONFIG_V2,
does_not_raise(),
"",
id="net_v2_complex_example",
),
pytest.param(
{"network": {"version": 1}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=re.escape("'config' is a required property"),
),
"",
id="config_key_required",
),
pytest.param(
{"network": {"version": 1, "config": []}},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="config_key_required",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"name": "me", "type": "typo"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=(
r"network.config.0: {'name': 'me', 'type': 'typo'} is"
" not valid under any of the given schemas"
),
),
"",
id="unknown_config_type_item",
),
pytest.param(
{"network": {"version": 1, "config": [{"type": "physical"}]}},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"network.config.0: 'name' is a required property.*",
),
"",
id="physical_requires_name_property",
),
pytest.param(
{
"network": {
"version": 1,
"config": [{"type": "physical", "name": "a"}],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_name_succeeds",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "a", "asdf": 1}
],
}
},
SchemaType.NETWORK_CONFIG_V1,
pytest.raises(
SchemaValidationError,
match=r"Additional properties are not allowed.*",
),
"",
id="physical_no_additional_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_PHYSICAL_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="physical_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [VALID_BOND_CONFIG],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="bond_with_all_known_properties",
),
pytest.param(
{
"network": {
"version": 1,
"config": [
{"type": "physical", "name": "eth0", "mtu": None},
{"type": "nameserver", "address": "8.8.8.8"},
],
}
},
SchemaType.NETWORK_CONFIG_V1,
does_not_raise(),
"",
id="GH-4710_mtu_none_and_str_address",
),
),
)
@mock.patch("cloudinit.net.netplan.available", return_value=False)
def test_network_schema(
self,
_netplan_available,
src_config,
schema_type_version,
expectation,
log,
caplog,
):
net_schema = get_schema(schema_type=schema_type_version)
> with expectation:
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/config/test_schema.py:2564: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 21068 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-network-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_unable_to_read_cfg_paths[failure0-expected_logs0] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb46e7c50>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473694082320'>
failure = OSError('No permissions on /var/lib/cloud/instance')
expected_logs = ['Using default instance-data/user-data paths for non-root']
paths = <cloudinit.helpers.Paths object at 0xffffb20a7bb0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb18c94e0>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb1933d90>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_unable_to_r0')
@pytest.mark.parametrize(
"failure, expected_logs",
(
(
IOError("No permissions on /var/lib/cloud/instance"),
["Using default instance-data/user-data paths for non-root"],
),
(
DataSourceNotFoundException("No cached datasource found yet"),
["datasource not detected"],
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_unable_to_read_cfg_paths(
self,
read_cfg_paths,
failure,
expected_logs,
paths,
capsys,
caplog,
tmpdir,
):
if isinstance(failure, IOError):
failure.errno = EACCES
read_cfg_paths.side_effect = [failure, paths]
user_data_fn = tmpdir.join("user-data")
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
#cloud-config
packages: [sl]
"""
)
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=False,
docs=None,
system=None,
instance_data=None,
)
handle_schema_args("unused", args)
> assert "Valid schema" in capsys.readouterr().out
E AssertionError: assert 'Valid schema' in 'Skipping cloud-config schema validation. Jsonschema dependency missing.\n'
E + where 'Skipping cloud-config schema validation. Jsonschema dependency missing.\n' = CaptureResult(out='Skipping cloud-config schema validation. Jsonschema dependency missing.\n', err='').out
E + where CaptureResult(out='Skipping cloud-config schema validation. Jsonschema dependency missing.\n', err='') = readouterr()
E + where readouterr = <_pytest.capture.CaptureFixture object at 0xffffb18c94e0>.readouterr
tests/unittests/config/test_schema.py:2734: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:1782 Using default instance-data/user-data paths for non-root user
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_unable_to_r0/user-data (quiet=False)
2024-09-18 16:50:17 DEBUG cloudinit.util:util.py:1622 Read 29 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_unable_to_r0/user-data
2024-09-18 16:50:17 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_unable_to_read_cfg_paths[failure1-expected_logs1] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb46e7d90>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473671073136'>
failure = DataSourceNotFoundException('No cached datasource found yet')
expected_logs = ['datasource not detected']
paths = <cloudinit.helpers.Paths object at 0xffffb1b9eb70>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19aee40>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb19ac210>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_unable_to_r1')
@pytest.mark.parametrize(
"failure, expected_logs",
(
(
IOError("No permissions on /var/lib/cloud/instance"),
["Using default instance-data/user-data paths for non-root"],
),
(
DataSourceNotFoundException("No cached datasource found yet"),
["datasource not detected"],
),
),
)
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_unable_to_read_cfg_paths(
self,
read_cfg_paths,
failure,
expected_logs,
paths,
capsys,
caplog,
tmpdir,
):
if isinstance(failure, IOError):
failure.errno = EACCES
read_cfg_paths.side_effect = [failure, paths]
user_data_fn = tmpdir.join("user-data")
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
#cloud-config
packages: [sl]
"""
)
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=False,
docs=None,
system=None,
instance_data=None,
)
handle_schema_args("unused", args)
> assert "Valid schema" in capsys.readouterr().out
E AssertionError: assert 'Valid schema' in 'Skipping cloud-config schema validation. Jsonschema dependency missing.\n'
E + where 'Skipping cloud-config schema validation. Jsonschema dependency missing.\n' = CaptureResult(out='Skipping cloud-config schema validation. Jsonschema dependency missing.\n', err='').out
E + where CaptureResult(out='Skipping cloud-config schema validation. Jsonschema dependency missing.\n', err='') = readouterr()
E + where readouterr = <_pytest.capture.CaptureFixture object at 0xffffb19aee40>.readouterr
tests/unittests/config/test_schema.py:2734: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:18 WARNING cloudinit.config.schema:schema.py:1790 datasource not detected, using default instance-data/user-data paths.
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_unable_to_r1/user-data (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 29 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_unable_to_r1/user-data
2024-09-18 16:50:18 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_args_annotate_deprecated_config[test_annotated_deprecation_info_boundary_devel_shows] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb3ff4b00>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473669246528'>
annotate = True, deprecation_info_boundary = 'devel'
expected_output = '#cloud-config\npackages:\n- htop\napt_update: true # D1\napt_upgrade: true # D2\napt_reb...* instead.\n# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.\n\nValid schema {cfg_file}\n'
paths = <cloudinit.helpers.Paths object at 0xffffb1b79770>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb19ad400>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19adfd0>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota0')
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb1b765b0>
@pytest.mark.parametrize(
"annotate, deprecation_info_boundary, expected_output",
[
pytest.param(
True,
"devel",
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true # D1
apt_upgrade: true # D2
apt_reboot_if_required: true # D3
# Deprecations: -------------
# D1: Deprecated in version 22.2. Use **package_update** instead.
# D2: Deprecated in version 22.2. Use **package_upgrade** instead.
# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_annotated_deprecation_info_boundary_devel_shows",
),
pytest.param(
True,
"22.1",
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true # D1
apt_upgrade: true # D2
apt_reboot_if_required: true # D3
# Deprecations: -------------
# D1: Deprecated in version 22.2. Use **package_update** instead.
# D2: Deprecated in version 22.2. Use **package_upgrade** instead.
# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_annotated_deprecation_info_boundary_below_unredacted",
),
pytest.param(
False,
"18.2",
dedent(
"""\
Cloud config schema deprecations: \
apt_reboot_if_required: Deprecated in version 22.2. Use\
**package_reboot_if_required** instead., apt_update: Deprecated in version\
22.2. Use **package_update** instead., apt_upgrade: Deprecated in version\
22.2. Use **package_upgrade** instead.\
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_deprecation_info_boundary_does_unannotated_unredacted",
),
],
)
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_args_annotate_deprecated_config(
self,
read_cfg_paths,
annotate,
deprecation_info_boundary,
expected_output,
paths,
caplog,
capsys,
tmpdir,
mocker,
):
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
user_data_fn = tmpdir.join("user-data")
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true
apt_upgrade: true
apt_reboot_if_required: true
"""
)
)
mocker.patch.object(
features, "DEPRECATION_INFO_BOUNDARY", deprecation_info_boundary
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=annotate,
docs=None,
system=None,
instance_data=None,
)
handle_schema_args("unused", args)
out, err = capsys.readouterr()
> assert (
expected_output.format(cfg_file=user_data_fn).split()
== out.split()
)
E AssertionError: assert ['#cloud-conf..., 'true', ...] == ['Skipping', ...endency', ...]
E
E At index 0 diff: '#cloud-config' != 'Skipping'
E Left contains 42 more items, first extra item: 'D1'
E
E Full diff:
E [
E - 'Skipping',...
E
E ...Full output truncated (56 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2844: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota0/user-data (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 95 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota0/user-data
2024-09-18 16:50:18 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_args_annotate_deprecated_config[test_annotated_deprecation_info_boundary_below_unredacted] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb3ff4c30>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473672240768'>
annotate = True, deprecation_info_boundary = '22.1'
expected_output = '#cloud-config\npackages:\n- htop\napt_update: true # D1\napt_upgrade: true # D2\napt_reb...* instead.\n# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.\n\nValid schema {cfg_file}\n'
paths = <cloudinit.helpers.Paths object at 0xffffb200dc70>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb19aeac0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19afa80>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota1')
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb18461a0>
@pytest.mark.parametrize(
"annotate, deprecation_info_boundary, expected_output",
[
pytest.param(
True,
"devel",
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true # D1
apt_upgrade: true # D2
apt_reboot_if_required: true # D3
# Deprecations: -------------
# D1: Deprecated in version 22.2. Use **package_update** instead.
# D2: Deprecated in version 22.2. Use **package_upgrade** instead.
# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_annotated_deprecation_info_boundary_devel_shows",
),
pytest.param(
True,
"22.1",
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true # D1
apt_upgrade: true # D2
apt_reboot_if_required: true # D3
# Deprecations: -------------
# D1: Deprecated in version 22.2. Use **package_update** instead.
# D2: Deprecated in version 22.2. Use **package_upgrade** instead.
# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_annotated_deprecation_info_boundary_below_unredacted",
),
pytest.param(
False,
"18.2",
dedent(
"""\
Cloud config schema deprecations: \
apt_reboot_if_required: Deprecated in version 22.2. Use\
**package_reboot_if_required** instead., apt_update: Deprecated in version\
22.2. Use **package_update** instead., apt_upgrade: Deprecated in version\
22.2. Use **package_upgrade** instead.\
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_deprecation_info_boundary_does_unannotated_unredacted",
),
],
)
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_args_annotate_deprecated_config(
self,
read_cfg_paths,
annotate,
deprecation_info_boundary,
expected_output,
paths,
caplog,
capsys,
tmpdir,
mocker,
):
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
user_data_fn = tmpdir.join("user-data")
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true
apt_upgrade: true
apt_reboot_if_required: true
"""
)
)
mocker.patch.object(
features, "DEPRECATION_INFO_BOUNDARY", deprecation_info_boundary
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=annotate,
docs=None,
system=None,
instance_data=None,
)
handle_schema_args("unused", args)
out, err = capsys.readouterr()
> assert (
expected_output.format(cfg_file=user_data_fn).split()
== out.split()
)
E AssertionError: assert ['#cloud-conf..., 'true', ...] == ['Skipping', ...endency', ...]
E
E At index 0 diff: '#cloud-config' != 'Skipping'
E Left contains 42 more items, first extra item: 'D1'
E
E Full diff:
E [
E - 'Skipping',...
E
E ...Full output truncated (56 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2844: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota1/user-data (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 95 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota1/user-data
2024-09-18 16:50:18 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_args_annotate_deprecated_config[test_deprecation_info_boundary_does_unannotated_unredacted] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb3ff9910>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473693810176'>
annotate = False, deprecation_info_boundary = '18.2'
expected_output = 'Cloud config schema deprecations: apt_reboot_if_required: Deprecated in version 22.2. Use **package_reboot_if_require...apt_upgrade: Deprecated in version 22.2. Use **package_upgrade** instead. Valid schema {cfg_file}\n'
paths = <cloudinit.helpers.Paths object at 0xffffb2b2b890>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb19ae0b0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19ae350>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota2')
mocker = <pytest_mock.plugin.MockerFixture object at 0xffffb1847d40>
@pytest.mark.parametrize(
"annotate, deprecation_info_boundary, expected_output",
[
pytest.param(
True,
"devel",
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true # D1
apt_upgrade: true # D2
apt_reboot_if_required: true # D3
# Deprecations: -------------
# D1: Deprecated in version 22.2. Use **package_update** instead.
# D2: Deprecated in version 22.2. Use **package_upgrade** instead.
# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_annotated_deprecation_info_boundary_devel_shows",
),
pytest.param(
True,
"22.1",
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true # D1
apt_upgrade: true # D2
apt_reboot_if_required: true # D3
# Deprecations: -------------
# D1: Deprecated in version 22.2. Use **package_update** instead.
# D2: Deprecated in version 22.2. Use **package_upgrade** instead.
# D3: Deprecated in version 22.2. Use **package_reboot_if_required** instead.
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_annotated_deprecation_info_boundary_below_unredacted",
),
pytest.param(
False,
"18.2",
dedent(
"""\
Cloud config schema deprecations: \
apt_reboot_if_required: Deprecated in version 22.2. Use\
**package_reboot_if_required** instead., apt_update: Deprecated in version\
22.2. Use **package_update** instead., apt_upgrade: Deprecated in version\
22.2. Use **package_upgrade** instead.\
Valid schema {cfg_file}
""" # noqa: E501
),
id="test_deprecation_info_boundary_does_unannotated_unredacted",
),
],
)
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_args_annotate_deprecated_config(
self,
read_cfg_paths,
annotate,
deprecation_info_boundary,
expected_output,
paths,
caplog,
capsys,
tmpdir,
mocker,
):
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
user_data_fn = tmpdir.join("user-data")
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
#cloud-config
packages:
- htop
apt_update: true
apt_upgrade: true
apt_reboot_if_required: true
"""
)
)
mocker.patch.object(
features, "DEPRECATION_INFO_BOUNDARY", deprecation_info_boundary
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=annotate,
docs=None,
system=None,
instance_data=None,
)
handle_schema_args("unused", args)
out, err = capsys.readouterr()
> assert (
expected_output.format(cfg_file=user_data_fn).split()
== out.split()
)
E AssertionError: assert ['Cloud', 'co...recated', ...] == ['Skipping', ...endency', ...]
E
E At index 0 diff: 'Cloud' != 'Skipping'
E Left contains 24 more items, first extra item: 'version'
E
E Full diff:
E [
E - 'Skipping',...
E
E ...Full output truncated (39 lines hidden), use '-vv' to show
tests/unittests/config/test_schema.py:2844: AssertionError
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota2/user-data (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 95 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_annota2/user-data
2024-09-18 16:50:18 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_args_jinja_with_errors[root_annotate_errors_with_exception] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb3fa5bf0>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473674749872'>
getuid = <MagicMock name='getuid' id='281473674754912'>, uid = 0
annotate = True
expected_out = "#cloud-config\nhostname: 123\t\t# E1\n\n# Errors: -------------\n# E1: 123 is not of type 'string'\n\n\n"
expected_err = 'Error: Invalid schema: user-data\n\n'
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46eea50>
paths = <cloudinit.helpers.Paths object at 0xffffb2038870>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb19ae3c0>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb19ae5f0>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_0')
@pytest.mark.parametrize(
"uid, annotate, expected_out, expected_err, expectation",
[
pytest.param(
0,
True,
dedent(
"""\
#cloud-config
hostname: 123 # E1
# Errors: -------------
# E1: 123 is not of type 'string'
""" # noqa: E501
),
"""Error: Invalid schema: user-data\n\n""",
pytest.raises(SystemExit),
id="root_annotate_errors_with_exception",
),
pytest.param(
0,
False,
dedent(
"""\
Invalid user-data {cfg_file}
""" # noqa: E501
),
dedent(
"""\
Error: Cloud config schema errors: hostname: 123 is not of type 'string'
Error: Invalid schema: user-data
""" # noqa: E501
),
pytest.raises(SystemExit),
id="root_no_annotate_exception_with_unique_errors",
),
],
)
@mock.patch(M_PATH + "os.getuid")
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_args_jinja_with_errors(
self,
read_cfg_paths,
getuid,
uid,
annotate,
expected_out,
expected_err,
expectation,
paths,
caplog,
capsys,
tmpdir,
):
getuid.return_value = uid
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
user_data_fn = tmpdir.join("user-data")
if uid == 0:
id_path = paths.get_runpath("instance_data_sensitive")
else:
id_path = paths.get_runpath("instance_data")
with open(id_path, "w") as f:
f.write(json.dumps({"ds": {"asdf": 123}}))
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
## template: jinja
#cloud-config
hostname: {{ ds.asdf }}
"""
)
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=annotate,
docs=None,
system=None,
instance_data=None,
)
> with expectation:
E Failed: DID NOT RAISE <class 'SystemExit'>
tests/unittests/config/test_schema.py:2937: Failed
----------------------------- Captured stdout call -----------------------------
Skipping cloud-config schema validation. Jsonschema dependency missing.
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_0/user-data (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 57 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_0/user-data
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_0/run_dir/instance-data-sensitive.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 21 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_0/run_dir/instance-data-sensitive.json
2024-09-18 16:50:18 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestHandleSchemaArgs.test_handle_schema_args_jinja_with_errors[root_no_annotate_exception_with_unique_errors] _
self = <tests.unittests.config.test_schema.TestHandleSchemaArgs object at 0xffffb3fa5d00>
read_cfg_paths = <MagicMock name='read_cfg_paths' id='281473674750544'>
getuid = <MagicMock name='getuid' id='281473674753232'>, uid = 0
annotate = False, expected_out = 'Invalid user-data {cfg_file}\n'
expected_err = "Error: Cloud config schema errors: hostname: 123 is not of type 'string'\n\nError: Invalid schema: user-data\n\n"
expectation = <_pytest.python_api.RaisesContext object at 0xffffb46efee0>
paths = <cloudinit.helpers.Paths object at 0xffffb2bb1ef0>
caplog = <_pytest.logging.LogCaptureFixture object at 0xffffb1bb9240>
capsys = <_pytest.capture.CaptureFixture object at 0xffffb1bb8e50>
tmpdir = local('/tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_1')
@pytest.mark.parametrize(
"uid, annotate, expected_out, expected_err, expectation",
[
pytest.param(
0,
True,
dedent(
"""\
#cloud-config
hostname: 123 # E1
# Errors: -------------
# E1: 123 is not of type 'string'
""" # noqa: E501
),
"""Error: Invalid schema: user-data\n\n""",
pytest.raises(SystemExit),
id="root_annotate_errors_with_exception",
),
pytest.param(
0,
False,
dedent(
"""\
Invalid user-data {cfg_file}
""" # noqa: E501
),
dedent(
"""\
Error: Cloud config schema errors: hostname: 123 is not of type 'string'
Error: Invalid schema: user-data
""" # noqa: E501
),
pytest.raises(SystemExit),
id="root_no_annotate_exception_with_unique_errors",
),
],
)
@mock.patch(M_PATH + "os.getuid")
@mock.patch(M_PATH + "read_cfg_paths")
def test_handle_schema_args_jinja_with_errors(
self,
read_cfg_paths,
getuid,
uid,
annotate,
expected_out,
expected_err,
expectation,
paths,
caplog,
capsys,
tmpdir,
):
getuid.return_value = uid
paths.get_ipath = paths.get_ipath_cur
read_cfg_paths.return_value = paths
user_data_fn = tmpdir.join("user-data")
if uid == 0:
id_path = paths.get_runpath("instance_data_sensitive")
else:
id_path = paths.get_runpath("instance_data")
with open(id_path, "w") as f:
f.write(json.dumps({"ds": {"asdf": 123}}))
with open(user_data_fn, "w") as f:
f.write(
dedent(
"""\
## template: jinja
#cloud-config
hostname: {{ ds.asdf }}
"""
)
)
args = self.Args(
config_file=str(user_data_fn),
schema_type="cloud-config",
annotate=annotate,
docs=None,
system=None,
instance_data=None,
)
> with expectation:
E Failed: DID NOT RAISE <class 'SystemExit'>
tests/unittests/config/test_schema.py:2937: Failed
----------------------------- Captured stdout call -----------------------------
Skipping cloud-config schema validation. Jsonschema dependency missing.
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_1/user-data (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 57 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_1/user-data
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1613 Reading from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_1/run_dir/instance-data-sensitive.json (quiet=False)
2024-09-18 16:50:18 DEBUG cloudinit.util:util.py:1622 Read 21 bytes from /tmp/pytest-of-debusine-worker/pytest-0/test_handle_schema_args_jinja_1/run_dir/instance-data-sensitive.json
2024-09-18 16:50:18 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestReportingSchema.test_schema_validation[config8-'a' is not of type 'object'] _
self = <test_reporting.TestReportingSchema object at 0xffffb3a2d250>
config = {'reporting': 'a'}, error_msg = "'a' is not of type 'object'"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestReportingSchema.test_schema_validation[config9-'b' is not of type 'object'] _
self = <test_reporting.TestReportingSchema object at 0xffffb409b3e0>
config = {'reporting': {'a': 'b'}}, error_msg = "'b' is not of type 'object'"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestReportingSchema.test_schema_validation[config10-'b'\\ is\\ not\\ one\\ of\\ \\['log'\\]] _
self = <test_reporting.TestReportingSchema object at 0xffffb409b4d0>
config = {'reporting': {'a': {'type': 'b'}}}
error_msg = "'b'\\ is\\ not\\ one\\ of\\ \\['log'\\]"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
___ TestReportingSchema.test_schema_validation[config11-'a' was unexpected] ____
self = <test_reporting.TestReportingSchema object at 0xffffb3e5d0f0>
config = {'reporting': {'a': {'a': 'b', 'type': 'print'}}}
error_msg = "'a' was unexpected"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
___ TestReportingSchema.test_schema_validation[config12-'a' was unexpected] ____
self = <test_reporting.TestReportingSchema object at 0xffffb3e5d2b0>
config = {'reporting': {'a': {'a': 'b', 'type': 'log'}}}
error_msg = "'a' was unexpected"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
___ TestReportingSchema.test_schema_validation[config13-'a' was unexpected] ____
self = <test_reporting.TestReportingSchema object at 0xffffb3e89f30>
config = {'reporting': {'a': {'a': 'b', 'endpoint': 'http://a', 'type': 'webhook'}}}
error_msg = "'a' was unexpected"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
___ TestReportingSchema.test_schema_validation[config14-'a' was unexpected] ____
self = <test_reporting.TestReportingSchema object at 0xffffb42a6e10>
config = {'reporting': {'a': {'a': 'b', 'type': 'hyperv'}}}
error_msg = "'a' was unexpected"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
__ TestReportingSchema.test_schema_validation[config15-'type' is a required] ___
self = <test_reporting.TestReportingSchema object at 0xffffb42a7290>
config = {'reporting': {'a': {'level': 'FATAL'}}}
error_msg = "'type' is a required"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
__ TestReportingSchema.test_schema_validation[config16-'type' is a required] ___
self = <test_reporting.TestReportingSchema object at 0xffffb3b5ad00>
config = {'reporting': {'a': {'endpoint': 'http://a'}}}
error_msg = "'type' is a required"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestReportingSchema.test_schema_validation[config17-'endpoint' is a required] _
self = <test_reporting.TestReportingSchema object at 0xffffb3b5ae60>
config = {'reporting': {'a': {'kvp_file_path': '/a/b'}}}
error_msg = "'endpoint' is a required"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
_ TestReportingSchema.test_schema_validation[config18-'endpoint' is a required] _
self = <test_reporting.TestReportingSchema object at 0xffffb3ec4c30>
config = {'reporting': {'a': {'type': 'webhook'}}}
error_msg = "'endpoint' is a required"
@pytest.mark.parametrize(
"config, error_msg",
[
# GOOD: Minimum valid parameters
({"reporting": {"a": {"type": "print"}}}, None),
({"reporting": {"a": {"type": "log"}}}, None),
(
{
"reporting": {
"a": {"type": "webhook", "endpoint": "http://a"}
}
},
None,
),
({"reporting": {"a": {"type": "hyperv"}}}, None),
# GOOD: All valid parameters
({"reporting": {"a": {"type": "log", "level": "WARN"}}}, None),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
}
}
},
None,
),
(
{
"reporting": {
"a": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
}
}
},
None,
),
# GOOD: All combined together
(
{
"reporting": {
"a": {"type": "print"},
"b": {"type": "log", "level": "WARN"},
"c": {
"type": "webhook",
"endpoint": "http://a",
"timeout": 1,
"retries": 1,
"consumer_key": "somekey",
"token_key": "somekey",
"token_secret": "somesecret",
"consumer_secret": "somesecret",
},
"d": {
"type": "hyperv",
"kvp_file_path": "/some/path",
"event_types": ["a", "b"],
},
}
},
None,
),
# BAD: no top level objects
({"reporting": "a"}, "'a' is not of type 'object'"),
({"reporting": {"a": "b"}}, "'b' is not of type 'object'"),
# BAD: invalid type
(
{"reporting": {"a": {"type": "b"}}},
re.escape("'b' is not one of ['log']"),
),
# BAD: invalid additional properties
(
{"reporting": {"a": {"type": "print", "a": "b"}}},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "log", "a": "b"}}},
"'a' was unexpected",
),
(
{
"reporting": {
"a": {
"type": "webhook",
"endpoint": "http://a",
"a": "b",
}
}
},
"'a' was unexpected",
),
(
{"reporting": {"a": {"type": "hyperv", "a": "b"}}},
"'a' was unexpected",
),
# BAD: missing required properties
({"reporting": {"a": {"level": "FATAL"}}}, "'type' is a required"),
(
{"reporting": {"a": {"endpoint": "http://a"}}},
"'type' is a required",
),
(
{"reporting": {"a": {"kvp_file_path": "/a/b"}}},
"'endpoint' is a required",
),
(
{"reporting": {"a": {"type": "webhook"}}},
"'endpoint' is a required",
),
],
)
def test_schema_validation(self, config, error_msg):
if error_msg is None:
validate_cloudconfig_schema(config, get_schema(), strict=True)
else:
> with pytest.raises(SchemaValidationError, match=error_msg):
E Failed: DID NOT RAISE <class 'cloudinit.config.schema.SchemaValidationError'>
tests/unittests/reporting/test_reporting.py:590: Failed
------------------------------ Captured log call -------------------------------
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1613 Reading from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json (quiet=False)
2024-09-18 16:50:33 DEBUG cloudinit.util:util.py:1622 Read 150110 bytes from /<<PKGBUILDDIR>>/cloudinit/config/schemas/schema-cloud-config-v1.json
2024-09-18 16:50:33 DEBUG cloudinit.config.schema:schema.py:769 Ignoring schema validation. jsonschema is not present
=============================== warnings summary ===============================
tests/unittests/distros/package_management/test_apt.py:122
/<<PKGBUILDDIR>>/tests/unittests/distros/package_management/test_apt.py:122: PytestCollectionWarning: cannot collect test class 'TestUpdatePackageSources' because it has a __init__ constructor (from: tests/unittests/distros/package_management/test_apt.py)
@mock.patch.object(
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_boot_invalid_distro
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_no_ci_log_line
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_ci_log_line
/<<PKGBUILDDIR>>/cloudinit/analyze/__init__.py:131: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
kernel_start_timestamp = datetime.utcfromtimestamp(kernel_start)
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_boot_invalid_distro
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_no_ci_log_line
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_ci_log_line
/<<PKGBUILDDIR>>/cloudinit/analyze/__init__.py:132: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
kernel_end_timestamp = datetime.utcfromtimestamp(kernel_end)
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_boot_invalid_distro
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_no_ci_log_line
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_ci_log_line
/<<PKGBUILDDIR>>/cloudinit/analyze/__init__.py:133: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
ci_sysd_start_timestamp = datetime.utcfromtimestamp(ci_sysd_start)
tests/unittests/analyze/test_boot.py::TestAnalyzeBoot::test_container_ci_log_line
/<<PKGBUILDDIR>>/cloudinit/analyze/__init__.py:141: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
ci_start = datetime.utcfromtimestamp(last_init_local["timestamp"])
tests/unittests/analyze/test_dump.py::TestParseCILogLine::test_parse_logline_returns_event_for_amazon_linux_2_line
/<<PKGBUILDDIR>>/tests/unittests/analyze/test_dump.py:201: DeprecationWarning: Parsing dates involving a day of month without a year specified is ambiguious
and fails to parse leap day. The default behavior will change in Python 3.15
to either always raise an exception or to use a different default year (TBD).
To avoid trouble, add a specific year to the input & format.
See https://github.com/python/cpython/issues/70647.
datetime.strptime("Apr 30 19:39:11", "%b %d %H:%M:%S")
tests/unittests/cmd/devel/test_logs.py::TestCollectLogs::test_collect_logs_end_to_end
/<<PKGBUILDDIR>>/tests/unittests/cmd/devel/test_logs.py:144: DeprecationWarning: Python 3.14 will, by default, filter extracted tar archives and reject files or modify their metadata. Use the filter argument to control this behavior.
tar.extractall(extract_to)
tests/unittests/reporting/test_reporting_hyperv.py: 13 warnings
/<<PKGBUILDDIR>>/cloudinit/reporting/handlers.py:376: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
datetime.utcfromtimestamp(event.timestamp).isoformat() + "Z"
tests/unittests/reporting/test_reporting_hyperv.py::TextKvpReporter::test_get_boot_telemetry
/<<PKGBUILDDIR>>/cloudinit/sources/helpers/azure.py:125: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
datetime.utcfromtimestamp(kernel_start).isoformat() + "Z",
tests/unittests/reporting/test_reporting_hyperv.py::TextKvpReporter::test_get_boot_telemetry
/<<PKGBUILDDIR>>/cloudinit/sources/helpers/azure.py:126: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
datetime.utcfromtimestamp(user_start).isoformat() + "Z",
tests/unittests/reporting/test_reporting_hyperv.py::TextKvpReporter::test_get_boot_telemetry
/<<PKGBUILDDIR>>/cloudinit/sources/helpers/azure.py:127: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
datetime.utcfromtimestamp(cloudinit_activation).isoformat() + "Z",
tests/unittests/sources/azure/test_errors.py: 48 warnings
/<<PKGBUILDDIR>>/tests/unittests/sources/azure/test_errors.py:23: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp = datetime.datetime.utcnow()
tests/unittests/sources/azure/test_errors.py: 13 warnings
tests/unittests/sources/azure/test_kvp.py: 2 warnings
tests/unittests/sources/test_azure.py: 107 warnings
tests/unittests/sources/test_azure_helper.py: 11 warnings
/<<PKGBUILDDIR>>/cloudinit/sources/azure/errors.py:55: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
self.timestamp = datetime.utcnow()
tests/unittests/sources/azure/test_kvp.py::TestReportSuccessToHost::test_report_success_to_host
/<<PKGBUILDDIR>>/tests/unittests/sources/azure/test_kvp.py:14: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp = datetime.utcnow()
tests/unittests/sources/azure/test_kvp.py: 1 warning
tests/unittests/sources/test_azure.py: 49 warnings
/<<PKGBUILDDIR>>/cloudinit/sources/azure/kvp.py:52: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
f"timestamp={datetime.utcnow().isoformat()}",
tests/unittests/sources/test_azure.py: 72 warnings
tests/unittests/sources/test_azure_helper.py: 17 warnings
/<<PKGBUILDDIR>>/cloudinit/sources/helpers/azure.py:1014: DeprecationWarning: Testing an element's truth value will always return True in future versions. Use specific 'len(elem)' or 'elem is not None' test instead.
if not root.find("./wa:ProvisioningSection", cls.NAMESPACES):
tests/unittests/sources/test_azure.py: 24 warnings
/<<PKGBUILDDIR>>/tests/unittests/sources/test_azure.py:318: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
timestamp = datetime.datetime.utcnow()
tests/unittests/sources/test_gce.py::TestDataSourceGCE::test_has_expired
tests/unittests/sources/test_gce.py::TestDataSourceGCE::test_has_expired
/<<PKGBUILDDIR>>/cloudinit/sources/DataSourceGCE.py:236: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
return datetime.datetime.utcnow() > expire_time
tests/unittests/test_cli.py: 16 warnings
/<<PKGBUILDDIR>>/tests/unittests/test_cli.py:36: PytestMockWarning: Mocks returned by pytest-mock do not need to be used as context managers. The mocker fixture automatically undoes mocking at the end of a test. This warning can be ignored if it was triggered by mocking a context manager. https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager
with mocker.patch(
tests/unittests/test_cli.py: 16 warnings
/<<PKGBUILDDIR>>/tests/unittests/test_cli.py:39: PytestMockWarning: Mocks returned by pytest-mock do not need to be used as context managers. The mocker fixture automatically undoes mocking at the end of a test. This warning can be ignored if it was triggered by mocking a context manager. https://pytest-mock.readthedocs.io/en/latest/remarks.html#usage-as-context-manager
), mocker.patch(
tests/unittests/test_ds_identify.py::TestDsIdentify::test_ibmcloud_template_no_userdata_in_provisioning
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestDsIdentify.test_ibmcloud_template_no_userdata_in_provisioning of <tests.unittests.test_ds_identify.TestDsIdentify testMethod=test_ibmcloud_template_no_userdata_in_provisioning>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestDsIdentify::test_ibmcloud_template_userdata_in_provisioning
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestDsIdentify.test_ibmcloud_template_userdata_in_provisioning of <tests.unittests.test_ds_identify.TestDsIdentify testMethod=test_ibmcloud_template_userdata_in_provisioning>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestDsIdentify::test_vmware_on_vmware_open_vm_tools_64
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestDsIdentify.test_vmware_on_vmware_open_vm_tools_64 of <tests.unittests.test_ds_identify.TestDsIdentify testMethod=test_vmware_on_vmware_open_vm_tools_64>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestDsIdentify::test_vmware_on_vmware_open_vm_tools_aarch64_linux_gnu
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestDsIdentify.test_vmware_on_vmware_open_vm_tools_aarch64_linux_gnu of <tests.unittests.test_ds_identify.TestDsIdentify testMethod=test_vmware_on_vmware_open_vm_tools_aarch64_linux_gnu>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestDsIdentify::test_vmware_on_vmware_open_vm_tools_i386_linux_gnu
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestDsIdentify.test_vmware_on_vmware_open_vm_tools_i386_linux_gnu of <tests.unittests.test_ds_identify.TestDsIdentify testMethod=test_vmware_on_vmware_open_vm_tools_i386_linux_gnu>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestDsIdentify::test_vmware_on_vmware_open_vm_tools_x86_64_linux_gnu
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestDsIdentify.test_vmware_on_vmware_open_vm_tools_x86_64_linux_gnu of <tests.unittests.test_ds_identify.TestDsIdentify testMethod=test_vmware_on_vmware_open_vm_tools_x86_64_linux_gnu>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestWSL::test_empty_cloudinitdir
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestWSL.test_empty_cloudinitdir of <tests.unittests.test_ds_identify.TestWSL testMethod=test_empty_cloudinitdir>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestWSL::test_found_via_userdata
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestWSL.test_found_via_userdata of <tests.unittests.test_ds_identify.TestWSL testMethod=test_found_via_userdata>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestWSL::test_no_cloudinitdir_in_userprofile
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestWSL.test_no_cloudinitdir_in_userprofile of <tests.unittests.test_ds_identify.TestWSL testMethod=test_no_cloudinitdir_in_userprofile>>)
return self.run(*args, **kwds)
tests/unittests/test_ds_identify.py::TestWSL::test_no_userprofile
/usr/lib/python3.13/unittest/case.py:707: DeprecationWarning: It is deprecated to return a value that is not None from a test case (<bound method TestWSL.test_no_userprofile of <tests.unittests.test_ds_identify.TestWSL testMethod=test_no_userprofile>>)
return self.run(*args, **kwds)
tests/unittests/test_log.py::TestCloudInitLogger::test_logger_uses_gmtime
/<<PKGBUILDDIR>>/tests/unittests/test_log.py:47: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
utc_before = datetime.datetime.utcnow() - datetime.timedelta(0, 0.5)
tests/unittests/test_log.py::TestCloudInitLogger::test_logger_uses_gmtime
/<<PKGBUILDDIR>>/tests/unittests/test_log.py:49: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
utc_after = datetime.datetime.utcnow() + datetime.timedelta(0, 0.5)
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tests/unittests/config/test_schema.py::TestVersionedSchemas::test_versioned_cloud_config_schema_is_valid_json[schema2-is not one of ['v1']]
FAILED tests/unittests/config/test_schema.py::TestVersionedSchemas::test_versioned_cloud_config_schema_is_valid_json[schema3-is not of type 'string']
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_config_file[None-#cloud-config\nntp:-Valid schema]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_config_file[cloud-config-#cloud-config\nntp:-Valid schema]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_config_file[network-config-network: {'version': 2, 'ethernets': {'eth0': {'dhcp': true}}}-Valid schema]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_config_file[network-config-network:\n version: 1\n config:\n - type: physical\n name: eth0\n subnets:\n - type: dhcp\n-Valid schema]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_processed_data_preference_over_raw_data[prefer_processed_data_when_present_and_non_empty]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_processed_data_preference_over_raw_data[prefer_raw_data_when_processed_is_empty]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_processed_data_preference_over_raw_data[prefer_processed_vd_file_path_when_raw_and_processed_empty]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_system_userdata_vendordata_and_network_config[netv1_schema_validated]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_system_userdata_vendordata_and_network_config[netv2_schema_validated_non_netplan]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_system_userdata_vendordata_and_network_config[empty_net_validation_is_skipped]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_system_userdata_vendordata_and_network_config[netv1_schema_errors_handled]
FAILED tests/unittests/config/test_schema.py::TestMain::test_main_validates_system_userdata_vendordata_and_network_config[netv1_schema_error_on_nic_name_length]
FAILED tests/unittests/config/test_schema.py::TestNetworkSchema::test_network_schema[net_v2_invalid_config]
FAILED tests/unittests/config/test_schema.py::TestNetworkSchema::test_network_schema[config_key_required0]
FAILED tests/unittests/config/test_schema.py::TestNetworkSchema::test_network_schema[unknown_config_type_item]
FAILED tests/unittests/config/test_schema.py::TestNetworkSchema::test_network_schema[physical_requires_name_property]
FAILED tests/unittests/config/test_schema.py::TestNetworkSchema::test_network_schema[physical_no_additional_properties]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_unable_to_read_cfg_paths[failure0-expected_logs0]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_unable_to_read_cfg_paths[failure1-expected_logs1]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_args_annotate_deprecated_config[test_annotated_deprecation_info_boundary_devel_shows]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_args_annotate_deprecated_config[test_annotated_deprecation_info_boundary_below_unredacted]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_args_annotate_deprecated_config[test_deprecation_info_boundary_does_unannotated_unredacted]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_args_jinja_with_errors[root_annotate_errors_with_exception]
FAILED tests/unittests/config/test_schema.py::TestHandleSchemaArgs::test_handle_schema_args_jinja_with_errors[root_no_annotate_exception_with_unique_errors]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config8-'a' is not of type 'object']
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config9-'b' is not of type 'object']
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config10-'b'\\ is\\ not\\ one\\ of\\ \\['log'\\]]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config11-'a' was unexpected]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config12-'a' was unexpected]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config13-'a' was unexpected]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config14-'a' was unexpected]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config15-'type' is a required]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config16-'type' is a required]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config17-'endpoint' is a required]
FAILED tests/unittests/reporting/test_reporting.py::TestReportingSchema::test_schema_validation[config18-'endpoint' is a required]
= 37 failed, 4596 passed, 489 skipped, 18 xfailed, 420 warnings in 83.49s (0:01:23) =
make[1]: *** [debian/rules:10: override_dh_auto_test] Error 1
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
make: *** [debian/rules:7: build] Error 2
dpkg-buildpackage: error: debian/rules build subprocess returned exit status 2
--------------------------------------------------------------------------------
Build finished at 2024-09-18T16:51:29Z
If required, the full build log is available here (for the next 30 days):
https://debusine.debian.net/artifact/776771/
This bug has been filed at "normal" severity, as we haven't started the
transition to add 3.13 as a supported version, yet. This will be raised to RC
as soon as that happens, hopefully well before trixie.
Thanks,
Stefano
--- End Message ---