File: test_invalid_configs.py

package info (click to toggle)
incant 0.4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,996 kB
  • sloc: python: 1,482; sh: 35; makefile: 10; ruby: 1
file content (160 lines) | stat: -rw-r--r-- 4,755 bytes parent folder | download
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.",
    )