Skip to content

Commit 18e9339

Browse files
Refactor import statements to separate TestStatus enum for improved c… (#135)
1 parent 8c8c0f4 commit 18e9339

File tree

3 files changed

+89
-37
lines changed

3 files changed

+89
-37
lines changed

src/module_utils/enums.py

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from enum import Enum
66
from typing import Dict, Any, List, Optional
7-
from dataclasses import dataclass, field
87
from datetime import datetime
98

109

@@ -154,7 +153,6 @@ def to_dict(self) -> Dict[str, Any]:
154153
}
155154

156155

157-
@dataclass
158156
class ApplicabilityRule:
159157
"""
160158
Represents a rule to determine if a check is applicable based on context properties
@@ -165,8 +163,9 @@ class ApplicabilityRule:
165163
:type value: Any
166164
"""
167165

168-
property: str
169-
value: Any
166+
def __init__(self, property: str, value: Any):
167+
self.property = property
168+
self.value = value
170169

171170
def is_applicable(self, context_value: Any) -> bool:
172171
"""
@@ -202,7 +201,6 @@ def is_applicable(self, context_value: Any) -> bool:
202201
return context_value == self.value
203202

204203

205-
@dataclass
206204
class Check:
207205
"""
208206
Represents a configuration check
@@ -217,8 +215,8 @@ class Check:
217215
:type category: str
218216
:param workload: Workload type (e.g., SAP, Non-SAP)
219217
:type workload: str
220-
:param TestSeverity: TestSeverity level of the check
221-
:type TestSeverity: TestSeverity
218+
:param severity: Severity level of the check
219+
:type severity: TestSeverity
222220
:param collector_type: Type of collector to use (e.g., command, azure)
223221
:type collector_type: str
224222
:param collector_args: Arguments for the collector
@@ -237,20 +235,37 @@ class Check:
237235
:type report: Optional[str]
238236
"""
239237

240-
id: str
241-
name: str
242-
description: str
243-
category: str
244-
workload: str
245-
severity: TestSeverity = TestSeverity.WARNING
246-
collector_type: str = "command"
247-
collector_args: Dict[str, Any] = field(default_factory=dict)
248-
validator_type: str = "string"
249-
validator_args: Dict[str, Any] = field(default_factory=dict)
250-
tags: List[str] = field(default_factory=list)
251-
applicability: List[ApplicabilityRule] = field(default_factory=list)
252-
references: Dict[str, str] = field(default_factory=dict)
253-
report: Optional[str] = "check"
238+
def __init__(
239+
self,
240+
id: str,
241+
name: str,
242+
description: str,
243+
category: str,
244+
workload: str,
245+
severity: TestSeverity = TestSeverity.WARNING,
246+
collector_type: str = "command",
247+
collector_args: Optional[Dict[str, Any]] = None,
248+
validator_type: str = "string",
249+
validator_args: Optional[Dict[str, Any]] = None,
250+
tags: Optional[List[str]] = None,
251+
applicability: Optional[List[ApplicabilityRule]] = None,
252+
references: Optional[Dict[str, str]] = None,
253+
report: Optional[str] = "check",
254+
):
255+
self.id = id
256+
self.name = name
257+
self.description = description
258+
self.category = category
259+
self.workload = workload
260+
self.severity = severity
261+
self.collector_type = collector_type
262+
self.collector_args = collector_args if collector_args is not None else {}
263+
self.validator_type = validator_type
264+
self.validator_args = validator_args if validator_args is not None else {}
265+
self.tags = tags if tags is not None else []
266+
self.applicability = applicability if applicability is not None else []
267+
self.references = references if references is not None else {}
268+
self.report = report
254269

255270
def is_applicable(self, context: Dict[str, Any]) -> bool:
256271
"""
@@ -270,7 +285,6 @@ def is_applicable(self, context: Dict[str, Any]) -> bool:
270285
return True
271286

272287

273-
@dataclass
274288
class CheckResult:
275289
"""
276290
Represents the result of a check execution
@@ -293,11 +307,22 @@ class CheckResult:
293307
:type details: Optional[str]
294308
"""
295309

296-
check: Check
297-
status: TestStatus
298-
hostname: str
299-
expected_value: Any
300-
actual_value: Any
301-
execution_time: float
302-
timestamp: datetime = field(default_factory=datetime.now)
303-
details: Optional[str] = None
310+
def __init__(
311+
self,
312+
check: Check,
313+
status: TestStatus,
314+
hostname: str,
315+
expected_value: Any,
316+
actual_value: Any,
317+
execution_time: float,
318+
timestamp: Optional[datetime] = None,
319+
details: Optional[str] = None,
320+
):
321+
self.check = check
322+
self.status = status
323+
self.hostname = hostname
324+
self.expected_value = expected_value
325+
self.actual_value = actual_value
326+
self.execution_time = execution_time
327+
self.timestamp = timestamp if timestamp is not None else datetime.now()
328+
self.details = details

src/modules/configuration_check_module.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -438,8 +438,8 @@ def validate_string(self, check: Check, collected_data: str) -> Dict[str, Any]:
438438

439439
if check.validator_args.get("strip_whitespace", True):
440440
expected = str(expected).strip()
441-
expected = re.sub(r'\s+', ' ', expected)
442-
collected = re.sub(r'\s+', ' ', collected)
441+
expected = re.sub(r"\s+", " ", expected)
442+
collected = re.sub(r"\s+", " ", collected)
443443

444444
if check.validator_args.get("case_insensitive", False):
445445
expected = expected.lower()
@@ -794,8 +794,33 @@ def get_results_summary(self) -> Dict[str, int]:
794794

795795
def format_results_for_html_report(self):
796796
"""
797-
Reformat results for HTML report
797+
Reformat results for HTML report.
798+
Removes CONTEXT template placeholders to prevent Ansible template evaluation errors.
798799
"""
800+
801+
def remove_context_templates(value):
802+
"""
803+
Recursively remove or neutralize CONTEXT template placeholders.
804+
Replaces {{ CONTEXT.* }} with a safe placeholder to prevent Ansible templating issues.
805+
806+
:param value: Value to process (str, dict, list, or other)
807+
:type value: Any
808+
:return: Value with CONTEXT templates removed
809+
:rtype: Any
810+
"""
811+
if isinstance(value, str):
812+
# Replace {{ CONTEXT.property }} with <CONTEXT.property> to neutralize templates
813+
return re.sub(
814+
r"\{\{\s*CONTEXT\.[^}]+\s*\}\}",
815+
lambda m: m.group(0).replace("{{", "<").replace("}}", ">"),
816+
value,
817+
)
818+
if isinstance(value, dict):
819+
return {k: remove_context_templates(v) for k, v in value.items()}
820+
if isinstance(value, list):
821+
return [remove_context_templates(item) for item in value]
822+
return value
823+
799824
serialized_results = []
800825
for check_result in self.result["check_results"]:
801826
result_dict = {
@@ -811,9 +836,9 @@ def format_results_for_html_report(self):
811836
else str(check_result.check.severity)
812837
),
813838
"collector_type": check_result.check.collector_type,
814-
"collector_args": check_result.check.collector_args,
839+
"collector_args": remove_context_templates(check_result.check.collector_args),
815840
"validator_type": check_result.check.validator_type,
816-
"validator_args": check_result.check.validator_args,
841+
"validator_args": remove_context_templates(check_result.check.validator_args),
817842
"tags": check_result.check.tags,
818843
"references": check_result.check.references,
819844
"report": check_result.check.report,

src/modules/get_package_list.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
from ansible.module_utils.basic import AnsibleModule
1010

1111
try:
12-
from ansible.module_utils.sap_automation_qa import SapAutomationQA, TestStatus
12+
from ansible.module_utils.sap_automation_qa import SapAutomationQA
13+
from ansible.module_utils.enums import TestStatus
1314
except ImportError:
14-
from src.module_utils.sap_automation_qa import SapAutomationQA, TestStatus
15+
from src.module_utils.sap_automation_qa import SapAutomationQA
16+
from src.module_utils.enums import TestStatus
1517

1618
DOCUMENTATION = r"""
1719
---

0 commit comments

Comments
 (0)