Skip to content

Commit d14a798

Browse files
monrog2takishida
authored andcommitted
PUV updates (#254)
* feat: synth class + write back each function as json result * fix: Clean up get_vpc_nodes() and its pytest * feat: Split the main script execution code into each func and add pytest * feat: Retire json_log and adopt json per rule for both PUV and regular use + linting * feat: Support QA version and AciVersion instance as input in AciVersion (#259) * feat: Support QA version and AciVersion instance as input in AciVersion * fix: Use supported version format in older_than * fix: Use ValueError in AciVersion * feat: -c (cversion) / -d (debug_function) args into puv (#265) * feat: Update synthMaintP with the latest schema with ruleId * feat: Add decorator `@check_wrapper` for all check functions A new decorator `@check_wrapper` is to move most of the I/O functionalities, such as printing and writing the result into a file, outside of each check function so that each check can focus on the validation logic itself by minimizing the impact from a requirement change in the output format and so on. To support this, a new class `Result` is also introduced to make it clear what a check function is expected to return. As long as `Result` class is returned, the decorator `@check_wrapper` handles the printing them to stdout and files. * feat: rename synth class to AciResult + breakdown --puv into --api-only and --no-cleanup * feat: Add --version and --total-checks input args * feat: Do not touch log folders with some options like --version * fix: ValueError when col and row len do not match + pytest * fix: correct checks with mismatched col row length * fix: cimc logic update for QA --------- Co-authored-by: takishida <38262981+takishida@users.noreply.github.com> Co-authored-by: tkishida <tkishida@cisco.com>
1 parent 3f0cf6c commit d14a798

11 files changed

Lines changed: 2096 additions & 1127 deletions

aci-preupgrade-validation-script.py

Lines changed: 1157 additions & 1080 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

tests/cimc_compatibilty_check/test_cimc_compatibilty_check.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
# icurl queries
14-
eqptCh_api = 'eqptCh.json?query-target-filter=wcard(eqptCh.descr,"APIC")'
14+
eqptCh_api = 'eqptCh.json?query-target-filter=wcard(eqptCh.descr,"APIC")'
1515

1616
compatRsSuppHwL2_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicl2].json'
1717
compatRsSuppHwM1_api = 'uni/fabric/compcat-default/ctlrfw-apic-6.0(5)/rssuppHw-[uni/fabric/compcat-default/ctlrhw-apicm1].json'
@@ -40,6 +40,14 @@
4040
"6.0(5a)",
4141
script.PASS,
4242
),
43+
# Seen in QA testing where version + model does not have catalog entry
44+
(
45+
{eqptCh_api: read_data(dir, "eqptCh_newver.json"),
46+
compatRsSuppHwL2_api: read_data(dir, "compatRsSuppHw_605_L2.json"),
47+
compatRsSuppHwM1_api: read_data(dir, "compatRsSuppHw_empty.json")},
48+
"6.0(5a)",
49+
script.MANUAL,
50+
),
4351
],
4452
)
4553
def test_logic(mock_icurl, tversion, expected_result):

tests/conftest.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010

1111
script = importlib.import_module("aci-preupgrade-validation-script")
1212

13-
log = logging.getLogger(__name__)
13+
log = logging.getLogger()
14+
15+
16+
@pytest.fixture(scope="session", autouse=True)
17+
def init():
18+
script.initialize()
1419

1520

1621
@pytest.fixture

tests/test_AciResult.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import pytest
2+
import importlib
3+
import json
4+
5+
script = importlib.import_module("aci-preupgrade-validation-script")
6+
7+
8+
@pytest.mark.parametrize(
9+
"func_name, name, description, result, recommended_action, reason, doc_url, column, row, unformatted_column, unformatted_rows, expected_show, expected_criticality, expected_passed",
10+
[
11+
# Check 1: NA
12+
(
13+
"fake_func_name_NA_test",
14+
"NA",
15+
"",
16+
script.NA,
17+
"",
18+
"",
19+
"",
20+
["col1", "col2"],
21+
[["row1", "row2"], ["row3", "row4"]],
22+
["col1", "col2"],
23+
[["row1", "row2"], ["row3", "row4"]],
24+
False,
25+
"informational",
26+
"passed"
27+
),
28+
# Check 2: PASS
29+
(
30+
"fake_func_name_PASS_test",
31+
"PASS",
32+
"",
33+
script.PASS,
34+
"",
35+
"",
36+
"",
37+
[],
38+
[],
39+
[],
40+
[],
41+
True,
42+
"informational",
43+
"passed"
44+
),
45+
# Check 3: POST
46+
(
47+
"fake_func_name_POST_test",
48+
"POST",
49+
"",
50+
script.POST,
51+
"reboot",
52+
"test reason",
53+
"https://test_doc_url.html",
54+
["col1", "col2"],
55+
[["row1", "row2"], ["row3", "row4"]],
56+
["col1", "col2"],
57+
[["row1", "row2"], ["row3", "row4"]],
58+
False,
59+
"informational",
60+
"failed"
61+
),
62+
# Check 4: MANUAL
63+
(
64+
"fake_func_name_MANUAL_test",
65+
"MANUAL",
66+
"",
67+
script.MANUAL,
68+
"reboot",
69+
"test reason",
70+
"https://test_doc_url.html",
71+
["col1", "col2"],
72+
[["row1", "row2"], ["row3", "row4"]],
73+
["col1", "col2"],
74+
[["row1", "row2"], ["row3", "row4"]],
75+
True,
76+
"warning",
77+
"failed"
78+
),
79+
# Check 5: ERROR
80+
(
81+
"fake_func_name_ERROR_test",
82+
"ERROR",
83+
"",
84+
script.ERROR,
85+
"reboot",
86+
"test reason",
87+
"https://test_doc_url.html",
88+
["col1", "col2"],
89+
[["row1", "row2"], ["row3", "row4"]],
90+
["col1", "col2"],
91+
[["row1", "row2"], ["row3", "row4"]],
92+
True,
93+
"major",
94+
"failed"
95+
),
96+
# Check 6: FAIL_UF
97+
(
98+
"fake_func_name_FAIL_UF_test",
99+
"FAIL_UF",
100+
"",
101+
script.FAIL_UF,
102+
"reboot",
103+
"test reason",
104+
"https://test_doc_url.html",
105+
["col1", "col2"],
106+
[["row1", "row2"], ["row3", "row4"]],
107+
["col1", "col2"],
108+
[["row1", "row2"], ["row3", "row4"]],
109+
True,
110+
"critical",
111+
"failed"
112+
),
113+
# Check 7: FAIL_O
114+
(
115+
"fake_func_name_FAIL_O_test",
116+
"FAIL_O",
117+
"",
118+
script.FAIL_O,
119+
"reboot",
120+
"test reason",
121+
"https://test_doc_url.html",
122+
["col1", "col2", "col3"],
123+
[["row1", "row2", "row3"], ["row4", "row5", "row6"]],
124+
["col4", "col5"],
125+
[["row1", "row2"], ["row3", "row4"]],
126+
True,
127+
"critical",
128+
"failed"
129+
),
130+
# Check 8: FAIL_O Formatted only
131+
(
132+
"fake_func_name_FAIL_O_formatted_only_test",
133+
"FAIL_O Formatted only",
134+
"",
135+
script.FAIL_O,
136+
"reboot",
137+
"test reason",
138+
"https://test_doc_url.html",
139+
["col1", "col2", "col3"],
140+
[["row1", "row2", "row3"], ["row4", "row5", "row6"]],
141+
[],
142+
[],
143+
True,
144+
"critical",
145+
"failed"
146+
),
147+
# Check 9: FAIL_O unformatted only
148+
(
149+
"fake_func_name_FAIL_O_unformatted_only_test",
150+
"FAIL_O Unformatted only",
151+
"",
152+
script.FAIL_O,
153+
"reboot",
154+
"test reason",
155+
"https://test_doc_url.html",
156+
[],
157+
[],
158+
["col1", "col2", "col3"],
159+
[["row1", "row2", "row3"], ["row4", "row5", "row6"]],
160+
True,
161+
"critical",
162+
"failed"
163+
),
164+
],
165+
)
166+
def test_AciResult(
167+
func_name,
168+
name,
169+
description,
170+
result,
171+
recommended_action,
172+
reason,
173+
doc_url,
174+
column,
175+
row,
176+
unformatted_column,
177+
unformatted_rows,
178+
expected_show,
179+
expected_criticality,
180+
expected_passed,
181+
):
182+
synth = script.AciResult(func_name, name, description)
183+
synth.updateWithResults(result, recommended_action, reason, doc_url, column, row, unformatted_column, unformatted_rows)
184+
file = synth.writeResult()
185+
with open(file, "r") as f:
186+
data = json.load(f)
187+
assert data["ruleId"] == func_name
188+
assert data["showValidation"] == expected_show
189+
assert data["severity"] == expected_criticality
190+
assert data["ruleStatus"] == expected_passed
191+
192+
193+
@pytest.mark.parametrize(
194+
"headers, data",
195+
[
196+
("", []), # invalid headers (columns)
197+
([], {}), # invalid data (rows)
198+
("", {}), # invalid headers and data
199+
]
200+
)
201+
def test_invalid_headers_or_data(headers, data):
202+
with pytest.raises(TypeError):
203+
synth = script.AciResult("func_name", "Check Title", "A Description")
204+
synth.craftData(
205+
column=headers,
206+
rows=data,
207+
)
208+
209+
@pytest.mark.parametrize(
210+
"headers, data",
211+
[
212+
(["col1", "col2"], [["row1"], ["row2"]]), # Rows are shorter
213+
(["col1"], [["row1", "row2"], ["row3", "row4"]]), # columns are shorter
214+
]
215+
)
216+
def test_mismatched_lengths(headers, data):
217+
with pytest.raises(ValueError):
218+
synth = script.AciResult("func_name", "Check Title", "A Description")
219+
synth.craftData(
220+
column=headers,
221+
rows=data,
222+
)

0 commit comments

Comments
 (0)