diff --git a/.changelog/5160.yml b/.changelog/5160.yml new file mode 100644 index 0000000000..027373204d --- /dev/null +++ b/.changelog/5160.yml @@ -0,0 +1,4 @@ +changes: +- description: Updated the content item structure to adopt standardized id and name fields. + type: internal +pr_number: 5160 diff --git a/TestSuite/layout_rule.py b/TestSuite/layout_rule.py index e81c580ae1..1091e01d67 100644 --- a/TestSuite/layout_rule.py +++ b/TestSuite/layout_rule.py @@ -21,7 +21,9 @@ def __init__( def create_default_layout_rule(self): self.write_json( { + "id": self.rule_id, "rule_id": self.rule_id, + "name": self.name, "rule_name": self.name, "layout_id": "test_layout", "description": "", diff --git a/TestSuite/trigger.py b/TestSuite/trigger.py index 38f23ecdec..16bef1cb47 100644 --- a/TestSuite/trigger.py +++ b/TestSuite/trigger.py @@ -18,11 +18,11 @@ def __init__(self, name: str, trigger_dir_path: Path, json_content: dict = None) def create_default_trigger(self): self.write_json( { - "trigger_id": self.id, + "id": self.id, + "name": self.id, "playbook_id": "mock playbook", "suggestion_reason": "mock reason", "description": "desc", - "trigger_name": self.id, "alerts_filter": { "filter": { "AND": [ diff --git a/TestSuite/xdrc_template.py b/TestSuite/xdrc_template.py index 01e07c0d23..e5113e1135 100644 --- a/TestSuite/xdrc_template.py +++ b/TestSuite/xdrc_template.py @@ -32,7 +32,7 @@ def write_dict(self, yml: dict): def create_default(self): self.write_json( { - "content_global_id": self.id, + "id": self.id, "name": self.id, "os_type": "os_type_test", "profile_type": "profile_type_test", diff --git a/TestSuite/xsiam_dashboard.py b/TestSuite/xsiam_dashboard.py index 6d94b0c5e1..71b476aece 100644 --- a/TestSuite/xsiam_dashboard.py +++ b/TestSuite/xsiam_dashboard.py @@ -17,6 +17,7 @@ def create_default(self): { "dashboards_data": [ { + "id": self.id, "name": self.id, "description": "mock dashboard desc", "status": "ENABLED", diff --git a/TestSuite/xsiam_report.py b/TestSuite/xsiam_report.py index de5f36480c..703bb9178f 100644 --- a/TestSuite/xsiam_report.py +++ b/TestSuite/xsiam_report.py @@ -17,8 +17,8 @@ def create_default(self): { "templates_data": [ { - "global_id": self.id, - "report_name": self.id, + "id": self.id, + "name": self.id, "report_description": None, "default_template_id": None, "time_frame": {"relativeTime": 86400000}, diff --git a/demisto_sdk/commands/common/schemas/layoutrule.yml b/demisto_sdk/commands/common/schemas/layoutrule.yml index 59a2b24d0a..6b02025218 100644 --- a/demisto_sdk/commands/common/schemas/layoutrule.yml +++ b/demisto_sdk/commands/common/schemas/layoutrule.yml @@ -1,11 +1,19 @@ type: map mapping: + id: + type: str + required: true rule_id: + type: str + required: false + # DEPRECATED: Use 'id' field instead. This field is kept for backward compatibility with existing content items. + name: type: str required: true rule_name: type: str - required: true + required: false + # DEPRECATED: Use 'name' field instead. This field is kept for backward compatibility with existing content items. layout_id: type: str required: true diff --git a/demisto_sdk/commands/common/schemas/trigger.yml b/demisto_sdk/commands/common/schemas/trigger.yml index 0fb23992f4..87be3d9ac7 100644 --- a/demisto_sdk/commands/common/schemas/trigger.yml +++ b/demisto_sdk/commands/common/schemas/trigger.yml @@ -4,16 +4,24 @@ mapping: type: str automation_id: type: str - trigger_id: + id: type: str required: true + trigger_id: + type: str + required: false + # DEPRECATED: Use 'id' field instead. This field is kept for backward compatibility with existing content items. fromVersion: type: str toVersion: type: str - trigger_name: + name: type: str required: true + trigger_name: + type: str + required: false + # DEPRECATED: Use 'name' field instead. This field is kept for backward compatibility with existing content items. playbook_id: type: str description: diff --git a/demisto_sdk/commands/common/schemas/xdrctemplate.yml b/demisto_sdk/commands/common/schemas/xdrctemplate.yml index 7b757d5ec3..6a0666a127 100644 --- a/demisto_sdk/commands/common/schemas/xdrctemplate.yml +++ b/demisto_sdk/commands/common/schemas/xdrctemplate.yml @@ -9,9 +9,13 @@ mapping: name: type: str required: true - content_global_id: + id: type: str required: true + content_global_id: + type: str + required: false + # DEPRECATED: Use 'id' field instead. This field is kept for backward compatibility with existing content items. from_xdr_version: type: str required: true diff --git a/demisto_sdk/commands/common/schemas/xsiamdashboard.yml b/demisto_sdk/commands/common/schemas/xsiamdashboard.yml index 99dba0dbf8..0cf6e5e44f 100644 --- a/demisto_sdk/commands/common/schemas/xsiamdashboard.yml +++ b/demisto_sdk/commands/common/schemas/xsiamdashboard.yml @@ -27,9 +27,13 @@ mapping: schema;dashboards_data_schema: type: map mapping: - global_id: + id: type: str required: true + global_id: + type: str + required: false + # DEPRECATED: Use 'id' field instead. This field is kept for backward compatibility with existing content items. status: type: str required: true diff --git a/demisto_sdk/commands/common/schemas/xsiamreport.yml b/demisto_sdk/commands/common/schemas/xsiamreport.yml index d943cd3a1d..94239c5a9a 100644 --- a/demisto_sdk/commands/common/schemas/xsiamreport.yml +++ b/demisto_sdk/commands/common/schemas/xsiamreport.yml @@ -19,12 +19,20 @@ schema;templates_data_schema: mapping: metadata: type: str + id: + type: str + required: true global_id: + type: str + required: false + # DEPRECATED: Use 'id' field instead. This field is kept for backward compatibility with existing content items. + name: type: str required: true report_name: type: str - required: true + required: false + # DEPRECATED: Use 'name' field instead. This field is kept for backward compatibility with existing content items. report_description: type: str required: false diff --git a/demisto_sdk/commands/common/tests/layout_rule_test.py b/demisto_sdk/commands/common/tests/layout_rule_test.py index 22a8b0e616..426a940cbf 100644 --- a/demisto_sdk/commands/common/tests/layout_rule_test.py +++ b/demisto_sdk/commands/common/tests/layout_rule_test.py @@ -14,10 +14,10 @@ def test_is_valid_file(repo): dummy_layout_rule = pack.create_layout_rule( "MyRule", { - "rule_id": "test_rule", + "id": "test_rule", "layout_id": "test_layout_id", "description": "This trigger is test", - "rule_name": "test rule name", + "name": "test rule name", "alerts_filter": { "filter": { "AND": [ @@ -50,10 +50,10 @@ def test_is_valid_file_complicated_schema(repo): dummy_layout_rule = pack.create_layout_rule( "MyRule", { - "rule_id": "test_rule", + "id": "test_rule", "layout_id": "test_layout_id", "description": "This trigger is test", - "rule_name": "test rule name", + "name": "test rule name", "alerts_filter": { "filter": { "OR": [ @@ -109,10 +109,10 @@ def test_is_not_valid_file_complicated_schema(repo): dummy_layout_rule = pack.create_layout_rule( "MyRule", { - "rule_id": "test_rule", + "id": "test_rule", "layout_id": "test_layout_id", "description": "This trigger is test", - "rule_name": "test rule name", + "name": "test rule name", "alerts_filter": { "filter": { "OR": [ diff --git a/demisto_sdk/commands/common/tests/structure_test.py b/demisto_sdk/commands/common/tests/structure_test.py index cf8326b4aa..1e7bd4c121 100644 --- a/demisto_sdk/commands/common/tests/structure_test.py +++ b/demisto_sdk/commands/common/tests/structure_test.py @@ -945,17 +945,17 @@ def test_valid_xsiam_report(self, pack: Pack): validator = StructureValidator(xsiam_report.path) assert validator.is_valid_scheme() - def test_invalid_xsiam_report_missing_global_id(self, pack: Pack): + def test_invalid_xsiam_report_missing_id(self, pack: Pack): """ Given: - An invalid XSIAM report with a missing global_id field + An invalid XSIAM report with a missing id field When: Running schema validation. Then: Make sure the schema is invalid. """ xsiam_report = pack.create_xsiam_report("xsiam_report") - xsiam_report.remove_field_by_path("templates_data.[0].global_id") + xsiam_report.remove_field_by_path("templates_data.[0].id") validator = StructureValidator(xsiam_report.path) assert not validator.is_valid_scheme() diff --git a/demisto_sdk/commands/common/tests/trigger_test.py b/demisto_sdk/commands/common/tests/trigger_test.py index b3bb09926d..b033d960e2 100644 --- a/demisto_sdk/commands/common/tests/trigger_test.py +++ b/demisto_sdk/commands/common/tests/trigger_test.py @@ -13,11 +13,11 @@ def test_is_valid_file(repo): dummy_trigger = pack.create_trigger( "MyTrigger", { - "trigger_id": "trigger_id", + "id": "trigger_id", "playbook_id": "playbook_id", "suggestion_reason": "Reason", "description": "Description", - "trigger_name": "trigger_name", + "name": "trigger_name", "alerts_filter": { "filter": { "AND": [ @@ -48,11 +48,11 @@ def test_is_valid_file_complicated_schema(repo): dummy_trigger = pack.create_trigger( "MyTrigger", { - "trigger_id": "trigger_id", + "id": "trigger_id", "playbook_id": "playbook_id", "suggestion_reason": "Reason", "description": "Description", - "trigger_name": "trigger_name", + "name": "trigger_name", "alerts_filter": { "filter": { "OR": [ @@ -106,11 +106,11 @@ def test_is_not_valid_file_complicated_schema(repo): dummy_trigger = pack.create_trigger( "MyTrigger", { - "trigger_id": "trigger_id", + "id": "trigger_id", "playbook_id": "playbook_id", "suggestion_reason": "Reason", "description": "Description", - "trigger_name": "trigger_name", + "name": "trigger_name", "alerts_filter": { "filter": { "OR": [ diff --git a/demisto_sdk/commands/content_graph/strict_objects/layout_rule.py b/demisto_sdk/commands/content_graph/strict_objects/layout_rule.py index 87c3ca3ba7..dd10bb31f5 100644 --- a/demisto_sdk/commands/content_graph/strict_objects/layout_rule.py +++ b/demisto_sdk/commands/content_graph/strict_objects/layout_rule.py @@ -14,8 +14,10 @@ class _StrictLayoutRule(BaseStrictModel): - rule_id: str - rule_name: str + rule_id: Optional[str] = None + id: str + rule_name: Optional[str] = None + name: str layout_id: str from_version: str = Field( alias="fromVersion" diff --git a/demisto_sdk/commands/content_graph/strict_objects/trigger.py b/demisto_sdk/commands/content_graph/strict_objects/trigger.py index e9777a783d..45cdd6f564 100644 --- a/demisto_sdk/commands/content_graph/strict_objects/trigger.py +++ b/demisto_sdk/commands/content_graph/strict_objects/trigger.py @@ -14,8 +14,10 @@ class _StrictTrigger(BaseStrictModel): - trigger_id: str - trigger_name: str + trigger_id: Optional[str] = None + id: str + trigger_name: Optional[str] = None + name: str playbook_id: Optional[str] description: str suggestion_reason: str diff --git a/demisto_sdk/commands/content_graph/strict_objects/xdrc_template.py b/demisto_sdk/commands/content_graph/strict_objects/xdrc_template.py index b093ecda87..8da3937b45 100644 --- a/demisto_sdk/commands/content_graph/strict_objects/xdrc_template.py +++ b/demisto_sdk/commands/content_graph/strict_objects/xdrc_template.py @@ -16,7 +16,8 @@ class _StrictXDRCTemplate(BaseStrictModel): os_type: str profile_type: str name: str - content_global_id: str + content_global_id: Optional[str] = None + id: str from_xdr_version: str yaml_template: str supportedModules: Optional[List[str]] = Field(None, alias="supportedModules") diff --git a/demisto_sdk/commands/content_graph/strict_objects/xsiam_dashboard.py b/demisto_sdk/commands/content_graph/strict_objects/xsiam_dashboard.py index daff95dac4..0efed23e80 100644 --- a/demisto_sdk/commands/content_graph/strict_objects/xsiam_dashboard.py +++ b/demisto_sdk/commands/content_graph/strict_objects/xsiam_dashboard.py @@ -34,7 +34,8 @@ class _Layout(BaseStrictModel): class _DashboardsData(BaseStrictModel): - global_id: str + global_id: Optional[str] = None + id: str status: str name: str description: Optional[str] = None diff --git a/demisto_sdk/commands/content_graph/strict_objects/xsiam_report.py b/demisto_sdk/commands/content_graph/strict_objects/xsiam_report.py index eea1982c69..f506cce7d0 100644 --- a/demisto_sdk/commands/content_graph/strict_objects/xsiam_report.py +++ b/demisto_sdk/commands/content_graph/strict_objects/xsiam_report.py @@ -38,8 +38,10 @@ class TimeFrame(BaseStrictModel): class TemplatesData(BaseStrictModel): metadata: Optional[str] = None - global_id: str - report_name: str + global_id: Optional[str] = None + id: str + report_name: Optional[str] = None + name: str report_description: Optional[str] = None default_template_id: Optional[int] = None time_frame: Optional[TimeFrame] = None diff --git a/demisto_sdk/commands/validate/tests/ST_validators_test.py b/demisto_sdk/commands/validate/tests/ST_validators_test.py index 43eb5b12f7..35dd8d6857 100644 --- a/demisto_sdk/commands/validate/tests/ST_validators_test.py +++ b/demisto_sdk/commands/validate/tests/ST_validators_test.py @@ -9,7 +9,19 @@ ScriptParser, ) from demisto_sdk.commands.content_graph.parsers.pack import PackParser +from demisto_sdk.commands.content_graph.strict_objects.layout_rule import ( + _StrictLayoutRule, +) from demisto_sdk.commands.content_graph.strict_objects.trigger import _StrictTrigger +from demisto_sdk.commands.content_graph.strict_objects.xdrc_template import ( + _StrictXDRCTemplate, +) +from demisto_sdk.commands.content_graph.strict_objects.xsiam_dashboard import ( + _StrictXSIAMDashboard, +) +from demisto_sdk.commands.content_graph.strict_objects.xsiam_report import ( + _StrictXSIAMReport, +) from demisto_sdk.commands.content_graph.tests.test_tools import load_yaml from demisto_sdk.commands.validate.tests.test_tools import ( REPO, @@ -885,3 +897,237 @@ def test_IsSupportedModulesSubsetOfPack_inherit_pack_when_missing(): [playbook] ) assert len(results) == 0 + + +class TestStandardizedIdAndNameFields: + """ + Test class to validate the existence of standardized 'id' and 'name' fields + in various content items: triggers, xsiam reports, xsiam dashboards, layout rules, and xdrc templates. + """ + + def test_validate_trigger_with_standardized_id_and_name_valid(self): + """ + Given: + - A trigger with standardized 'id' and 'name' fields. + When: + - Instantiating _StrictTrigger. + Then: + - Validation passes (no exception) and fields are set correctly. + """ + trigger = _StrictTrigger( # type: ignore[call-arg] + id="test_trigger", + name="Test Trigger", + description="desc", + suggestion_reason="reason", + playbook_id="Playbook123", + ) + assert trigger.id == "test_trigger" + assert trigger.name == "Test Trigger" + + def test_validate_trigger_missing_required_id_field(self): + """ + Given: + - A trigger missing the required 'id' field (using only old 'trigger_id'). + When: + - Instantiating _StrictTrigger. + Then: + - ValidationError is raised indicating 'id' field is required. + """ + with pytest.raises(ValueError) as exc: + _StrictTrigger( # type: ignore[call-arg] + trigger_id="test_trigger", + trigger_name="Test Trigger", + name="Test Trigger", + description="desc", + suggestion_reason="reason", + playbook_id="Playbook123", + ) + assert "id" in str(exc.value).lower() and "required" in str(exc.value).lower() + + def test_validate_xsiam_report_with_standardized_id_and_name_in_templates_data( + self, + ): + """ + Given: + - An XSIAM report with templates_data containing standardized 'id' and 'name' fields. + When: + - Instantiating _StrictXSIAMReport with valid TemplatesData. + Then: + - Validation passes (no exception) and fields are set correctly. + """ + from demisto_sdk.commands.content_graph.strict_objects.xsiam_report import ( + TemplatesData, + ) + + template_data = TemplatesData( + id="test_template", + global_id="test_template", + name="Test Template", + report_name="Test Template", + time_offset=0, + layout=[], + ) + xsiam_report = _StrictXSIAMReport(templates_data=[template_data]) + assert xsiam_report.templates_data[0].id == "test_template" + assert xsiam_report.templates_data[0].name == "Test Template" + + def test_validate_xsiam_report_missing_required_id_in_templates_data(self): + """ + Given: + - An XSIAM report with templates_data missing the required 'id' field. + When: + - Instantiating TemplatesData without 'id'. + Then: + - ValidationError is raised indicating 'id' field is required. + """ + from demisto_sdk.commands.content_graph.strict_objects.xsiam_report import ( + TemplatesData, + ) + + with pytest.raises(ValueError) as exc: + TemplatesData( # type: ignore[call-arg] + report_name="Test Template", + global_id="test_template", + time_offset=0, + layout=[], + ) + assert ( + "id" in str(exc.value).lower() + and "name" in str(exc.value).lower() + and "required" in str(exc.value).lower() + ) + + def test_validate_xsiam_dashboard_with_standardized_id_and_name_in_dashboards_data( + self, + ): + """ + Given: + - An XSIAM dashboard with dashboards_data containing standardized 'id' and 'name' fields. + When: + - Instantiating _StrictXSIAMDashboard with valid DashboardsData. + Then: + - Validation passes (no exception) and fields are set correctly. + """ + from demisto_sdk.commands.content_graph.strict_objects.xsiam_dashboard import ( + _DashboardsData, + ) + + dashboard_data = _DashboardsData( + id="test_dashboard", + global_id="test_dashboard", + name="Test Dashboard", + status="active", + default_dashboard_id=1, + layout=[], + ) + xsiam_dashboard = _StrictXSIAMDashboard( + dashboards_data=[dashboard_data], widgets_data=[] + ) + assert xsiam_dashboard.dashboards_data[0].id == "test_dashboard" + assert xsiam_dashboard.dashboards_data[0].name == "Test Dashboard" + + def test_validate_xsiam_dashboard_missing_required_id_in_dashboards_data(self): + """ + Given: + - An XSIAM dashboard with dashboards_data missing the required 'id' field. + When: + - Instantiating _DashboardsData without 'id'. + Then: + - ValidationError is raised indicating 'id' field is required. + """ + from demisto_sdk.commands.content_graph.strict_objects.xsiam_dashboard import ( + _DashboardsData, + ) + + with pytest.raises(ValueError) as exc: + _DashboardsData( # type: ignore[call-arg] + name="Test Dashboard", + global_id="test_dashboard", + status="active", + default_dashboard_id=1, + layout=[], + ) + assert "id" in str(exc.value).lower() and "required" in str(exc.value).lower() + + def test_validate_layout_rule_with_standardized_id_and_name_valid(self): + """ + Given: + - A layout rule with standardized 'id' and 'name' fields. + When: + - Instantiating _StrictLayoutRule. + Then: + - Validation passes (no exception) and fields are set correctly. + """ + layout_rule = _StrictLayoutRule( # type: ignore[call-arg] + id="test_layout_rule", + rule_id="test_layout_rule", + name="Test Layout Rule", + rule_name="Test Layout Rule", + layout_id="layout123", + fromVersion="6.0.0", + ) + assert layout_rule.id == "test_layout_rule" + assert layout_rule.name == "Test Layout Rule" + + def test_validate_layout_rule_missing_required_id_field(self): + """ + Given: + - A layout rule missing the required 'id' field (using only old 'rule_id'). + When: + - Instantiating _StrictLayoutRule. + Then: + - ValidationError is raised indicating 'id' field is required. + """ + with pytest.raises(ValueError) as exc: + _StrictLayoutRule( # type: ignore[call-arg] + rule_id="test_layout_rule", + rule_name="Test Layout Rule", + layout_id="layout123", + fromVersion="6.0.0", + ) + assert ( + "id" in str(exc.value).lower() + and "name" in str(exc.value).lower() + and "required" in str(exc.value).lower() + ) + + def test_validate_xdrc_template_with_standardized_id_and_name_valid(self): + """ + Given: + - An XDRC template with standardized 'id' and 'name' fields. + When: + - Instantiating _StrictXDRCTemplate. + Then: + - Validation passes (no exception) and fields are set correctly. + """ + xdrc_template = _StrictXDRCTemplate( + id="test_xdrc_template", + content_global_id="test_xdrc_template", + name="Test XDRC Template", + os_type="Linux", + profile_type="profile1", + from_xdr_version="1.0.0", + yaml_template="template_content", + ) + assert xdrc_template.id == "test_xdrc_template" + assert xdrc_template.name == "Test XDRC Template" + + def test_validate_xdrc_template_missing_required_id_field(self): + """ + Given: + - An XDRC template missing the required 'id' field. + When: + - Instantiating _StrictXDRCTemplate. + Then: + - ValidationError is raised indicating 'id' field is required. + """ + with pytest.raises(ValueError) as exc: + _StrictXDRCTemplate( # type: ignore[call-arg] + name="Test XDRC Template", + content_global_id="test_xdrc_template", + os_type="Linux", + profile_type="profile1", + from_xdr_version="1.0.0", + yaml_template="template_content", + ) + assert "id" in str(exc.value).lower() and "required" in str(exc.value).lower()