1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
import pytest
import yaml
from incant.config_manager import ConfigManager
from incant.exceptions import ConfigurationError
class MockReporter:
def __init__(self):
self.messages = []
def info(self, message: str):
self.messages.append(("info", message))
def error(self, message: str):
self.messages.append(("error", message))
def success(self, message: str):
self.messages.append(("success", message))
def warning(self, message: str):
self.messages.append(("warning", message))
def header(self, message: str):
self.messages.append(("header", message))
def echo(self, message: str):
self.messages.append(("echo", message))
@pytest.fixture
def mock_reporter():
return MockReporter()
def run_test_with_config(tmp_path, mock_reporter, config, error_msg):
config_file = tmp_path / "incant.yaml"
config_file.write_text(yaml.dump(config))
with pytest.raises(ConfigurationError, match=error_msg):
ConfigManager(mock_reporter, config_path=str(config_file))
def test_missing_image(tmp_path, mock_reporter):
config = {"instances": {"test": {}}}
run_test_with_config(
tmp_path, mock_reporter, config, "Instance 'test' is missing required 'image' field."
)
def test_invalid_provision_type(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": 123}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"Provisioning for instance 'test' must be a string or a list of steps.",
)
def test_invalid_provision_step_type(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": [123]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"Provisioning step 0 in instance 'test' must be a string or a dictionary.",
)
def test_provision_step_multiple_keys(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": [{"copy": "a", "ssh": "b"}]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"Provisioning step 0 in instance 'test' must have exactly one key",
)
def test_provision_step_unknown_key(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": [{"unknown": "a"}]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"Unknown provisioning step type 'unknown' in instance 'test'",
)
def test_copy_step_missing_fields(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": [{"copy": {"source": "a"}}]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"is missing required field\\(s\\): target",
)
def test_copy_step_invalid_field_types(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": [{"copy": {"source": 1, "target": 2}}]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"must have string 'source' and 'target'",
)
@pytest.mark.parametrize(
"field,value,err",
[
("uid", "a", "invalid 'uid'"),
("gid", "a", "invalid 'gid'"),
("mode", 123, "invalid 'mode'"),
("mode", "abc", "invalid 'mode'"),
("recursive", "a", "invalid 'recursive'"),
("create_dirs", "a", "invalid 'create_dirs'"),
],
)
def test_copy_step_invalid_values(tmp_path, mock_reporter, field, value, err):
config = {
"instances": {
"test": {
"image": "ubuntu",
"provision": [{"copy": {"source": "a", "target": "b", field: value}}],
}
}
}
run_test_with_config(tmp_path, mock_reporter, config, err)
def test_invalid_ssh_step_type(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "provision": [{"ssh": 123}]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"must have a boolean or dictionary value",
)
def test_invalid_pre_launch_type(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "pre-launch": 123}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"Pre-launch commands for instance 'test' must be a list of strings.",
)
def test_invalid_pre_launch_item_type(tmp_path, mock_reporter):
config = {"instances": {"test": {"image": "ubuntu", "pre-launch": [123]}}}
run_test_with_config(
tmp_path,
mock_reporter,
config,
"Pre-launch command 0 in instance 'test' must be a string.",
)
|