-
Notifications
You must be signed in to change notification settings - Fork 667
/
Copy pathmeta_runtime.py
151 lines (127 loc) · 5 KB
/
meta_runtime.py
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
"""Implementation of meta-runtime rule."""
from __future__ import annotations
import sys
from typing import TYPE_CHECKING
from packaging.specifiers import SpecifierSet
from ansiblelint.rules import AnsibleLintRule
# Copyright (c) 2018, Ansible Project
if TYPE_CHECKING:
from ansiblelint.errors import MatchError
from ansiblelint.file_utils import Lintable
class CheckRequiresAnsibleVersion(AnsibleLintRule):
"""Required ansible version in meta/runtime.yml must be a supported version."""
id = "meta-runtime"
description = (
"The ``requires_ansible`` key in runtime.yml must specify "
"a supported platform version of ansible-core and be a valid version value "
"in x.y.z format."
)
severity = "VERY_HIGH"
tags = ["metadata"]
version_changed = "6.11.0"
_ids = {
"meta-runtime[unsupported-version]": "'requires_ansible' key must refer to a currently supported version",
"meta-runtime[invalid-version]": "'requires_ansible' is not a valid requirement specification",
}
def matchyaml(self, file: Lintable) -> list[MatchError]:
"""Find violations inside meta files.
:param file: Input lintable file that is a match for `meta-runtime`
:returns: List of errors matched to the input file
"""
results = []
if file.kind != "meta-runtime":
return []
requires_ansible = file.data.get("requires_ansible", None)
if requires_ansible:
if self.options and not any(
version in requires_ansible
for version in self.options.supported_ansible
):
supported_ansible = [f">={x}0" for x in self.options.supported_ansible]
msg = f"'requires_ansible' key must refer to a currently supported version such as: {', '.join(supported_ansible)}"
results.append(
self.create_matcherror(
message=msg,
tag="meta-runtime[unsupported-version]",
filename=file,
),
)
try:
SpecifierSet(requires_ansible)
except ValueError:
results.append(
self.create_matcherror(
message="'requires_ansible' is not a valid requirement specification",
tag="meta-runtime[invalid-version]",
filename=file,
),
)
return results
# testing code to be loaded only with pytest or when executed the rule file
if "pytest" in sys.modules:
import pytest
# pylint: disable=ungrouped-imports
from ansiblelint.rules import RulesCollection
from ansiblelint.runner import Runner
@pytest.mark.parametrize(
("test_file", "failures", "tags"),
(
pytest.param(
"examples/meta_runtime_version_checks/pass_0/meta/runtime.yml",
0,
"meta-runtime[unsupported-version]",
id="pass0",
),
pytest.param(
"examples/meta_runtime_version_checks/fail_0/meta/runtime.yml",
1,
"meta-runtime[unsupported-version]",
id="fail0",
),
pytest.param(
"examples/meta_runtime_version_checks/fail_1/meta/runtime.yml",
1,
"meta-runtime[unsupported-version]",
id="fail1",
),
pytest.param(
"examples/meta_runtime_version_checks/fail_2/meta/runtime.yml",
1,
"meta-runtime[invalid-version]",
id="fail2",
),
),
)
def test_default_meta_supported_version(
default_rules_collection: RulesCollection,
test_file: str,
failures: int,
tags: str,
) -> None:
"""Test for default supported ansible versions."""
default_rules_collection.register(CheckRequiresAnsibleVersion())
results = Runner(test_file, rules=default_rules_collection).run()
for result in results:
assert result.rule.id == CheckRequiresAnsibleVersion().id
assert result.tag == tags
assert len(results) == failures
@pytest.mark.parametrize(
("test_file", "failures"),
(
pytest.param(
"examples/meta_runtime_version_checks/pass_1/meta/runtime.yml",
0,
id="pass1",
),
),
)
def test_added_meta_supported_version(
default_rules_collection: RulesCollection,
test_file: str,
failures: int,
) -> None:
"""Test for added supported ansible versions in the config."""
default_rules_collection.register(CheckRequiresAnsibleVersion())
default_rules_collection.options.supported_ansible_also = ["2.9"]
results = Runner(test_file, rules=default_rules_collection).run()
assert len(results) == failures