From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DA5F745848; Thu, 22 Aug 2024 18:40:46 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C7FF242F31; Thu, 22 Aug 2024 18:40:11 +0200 (CEST) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mails.dpdk.org (Postfix) with ESMTP id 4800B42F29 for ; Thu, 22 Aug 2024 18:40:08 +0200 (CEST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C5FEE1576; Thu, 22 Aug 2024 09:40:33 -0700 (PDT) Received: from localhost.localdomain (unknown [10.57.86.28]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EE5ED3F66E; Thu, 22 Aug 2024 09:40:06 -0700 (PDT) From: Luca Vizzarro To: dev@dpdk.org Cc: Honnappa Nagarahalli , =?UTF-8?q?Juraj=20Linke=C5=A1?= , Luca Vizzarro , Paul Szczepanek Subject: [PATCH 5/5] dts: add JSON schema generation script Date: Thu, 22 Aug 2024 17:39:41 +0100 Message-Id: <20240822163941.1390326-6-luca.vizzarro@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240822163941.1390326-1-luca.vizzarro@arm.com> References: <20240822163941.1390326-1-luca.vizzarro@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Adds a new script which automatically re-generates the JSON schema file based on the Pydantic configuration models. Moreover, update the JSON schema with this script for the first time. Signed-off-by: Luca Vizzarro Reviewed-by: Paul Szczepanek --- doc/guides/tools/dts.rst | 10 + dts/framework/config/conf_yaml_schema.json | 776 ++++++++++++--------- dts/generate-schema.py | 38 + 3 files changed, 486 insertions(+), 338 deletions(-) create mode 100755 dts/generate-schema.py diff --git a/doc/guides/tools/dts.rst b/doc/guides/tools/dts.rst index 515b15e4d8..317bd0ff99 100644 --- a/doc/guides/tools/dts.rst +++ b/doc/guides/tools/dts.rst @@ -430,6 +430,16 @@ Refer to the script for usage: ``devtools/dts-check-format.sh -h``. Configuration Schema -------------------- +The configuration schema is automatically generated from Pydantic models and can be found +at ``dts/framework/config/conf_yaml_schema.json``. Whenever the models are changed, the schema +should be regenerated using the dedicated script at ``dts/generate-schema.py``, e.g.: + +.. code-block:: console + + $ poetry shell + (dts-py3.10) $ ./generate-schema.py + + Definitions ~~~~~~~~~~~ diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json index f02a310bb5..1cf1bb098a 100644 --- a/dts/framework/config/conf_yaml_schema.json +++ b/dts/framework/config/conf_yaml_schema.json @@ -1,402 +1,502 @@ { - "$schema": "https://json-schema.org/draft-07/schema", - "title": "DTS Config Schema", - "definitions": { - "node_name": { - "type": "string", - "description": "A unique identifier for a node" - }, - "NIC": { - "type": "string", - "enum": [ - "ALL", - "ConnectX3_MT4103", - "ConnectX4_LX_MT4117", - "ConnectX4_MT4115", - "ConnectX5_MT4119", - "ConnectX5_MT4121", - "I40E_10G-10G_BASE_T_BC", - "I40E_10G-10G_BASE_T_X722", - "I40E_10G-SFP_X722", - "I40E_10G-SFP_XL710", - "I40E_10G-X722_A0", - "I40E_1G-1G_BASE_T_X722", - "I40E_25G-25G_SFP28", - "I40E_40G-QSFP_A", - "I40E_40G-QSFP_B", - "IAVF-ADAPTIVE_VF", - "IAVF-VF", - "IAVF_10G-X722_VF", - "ICE_100G-E810C_QSFP", - "ICE_25G-E810C_SFP", - "ICE_25G-E810_XXV_SFP", - "IGB-I350_VF", - "IGB_1G-82540EM", - "IGB_1G-82545EM_COPPER", - "IGB_1G-82571EB_COPPER", - "IGB_1G-82574L", - "IGB_1G-82576", - "IGB_1G-82576_QUAD_COPPER", - "IGB_1G-82576_QUAD_COPPER_ET2", - "IGB_1G-82580_COPPER", - "IGB_1G-I210_COPPER", - "IGB_1G-I350_COPPER", - "IGB_1G-I354_SGMII", - "IGB_1G-PCH_LPTLP_I218_LM", - "IGB_1G-PCH_LPTLP_I218_V", - "IGB_1G-PCH_LPT_I217_LM", - "IGB_1G-PCH_LPT_I217_V", - "IGB_2.5G-I354_BACKPLANE_2_5GBPS", - "IGC-I225_LM", - "IGC-I226_LM", - "IXGBE_10G-82599_SFP", - "IXGBE_10G-82599_SFP_SF_QP", - "IXGBE_10G-82599_T3_LOM", - "IXGBE_10G-82599_VF", - "IXGBE_10G-X540T", - "IXGBE_10G-X540_VF", - "IXGBE_10G-X550EM_A_SFP", - "IXGBE_10G-X550EM_X_10G_T", - "IXGBE_10G-X550EM_X_SFP", - "IXGBE_10G-X550EM_X_VF", - "IXGBE_10G-X550T", - "IXGBE_10G-X550_VF", - "brcm_57414", - "brcm_P2100G", - "cavium_0011", - "cavium_a034", - "cavium_a063", - "cavium_a064", - "fastlinq_ql41000", - "fastlinq_ql41000_vf", - "fastlinq_ql45000", - "fastlinq_ql45000_vf", - "hi1822", - "virtio" - ] - }, - - "ARCH": { - "type": "string", + "$defs": { + "Architecture": { + "description": "The supported architectures of :class:`~framework.testbed_model.node.Node`\\s.", "enum": [ + "i686", "x86_64", + "x86_32", "arm64", "ppc64le" - ] - }, - "OS": { - "type": "string", - "enum": [ - "linux" - ] - }, - "cpu": { - "type": "string", - "description": "Native should be the default on x86", - "enum": [ - "native", - "armv8a", - "dpaa2", - "thunderx", - "xgene1" - ] - }, - "compiler": { - "type": "string", - "enum": [ - "gcc", - "clang", - "icc", - "mscv" - ] + ], + "title": "Architecture", + "type": "string" }, - "build_target": { - "type": "object", - "description": "Targets supported by DTS", + "BuildTargetConfiguration": { + "additionalProperties": false, + "description": "DPDK build configuration.\n\nThe configuration used for building DPDK.\n\nAttributes:\n arch: The target architecture to build for.\n os: The target os to build for.\n cpu: The target CPU to build for.\n compiler: The compiler executable to use.\n compiler_wrapper: This string will be put in front of the compiler when\n executing the build. Useful for adding wrapper commands, such as ``ccache``.", "properties": { "arch": { - "type": "string", - "enum": [ - "ALL", - "x86_64", - "arm64", - "ppc64le", - "other" - ] + "$ref": "#/$defs/Architecture" }, "os": { - "$ref": "#/definitions/OS" + "$ref": "#/$defs/OS" }, "cpu": { - "$ref": "#/definitions/cpu" + "$ref": "#/$defs/CPUType" }, "compiler": { - "$ref": "#/definitions/compiler" + "$ref": "#/$defs/Compiler" }, - "compiler_wrapper": { - "type": "string", - "description": "This will be added before compiler to the CC variable when building DPDK. Optional." + "compiler_wrapper": { + "default": "", + "title": "Compiler Wrapper", + "type": "string" } }, - "additionalProperties": false, "required": [ "arch", "os", "cpu", "compiler" - ] + ], + "title": "BuildTargetConfiguration", + "type": "object" }, - "hugepages_2mb": { - "type": "object", - "description": "Optional hugepage configuration. If not specified, hugepages won't be configured and DTS will use system configuration.", + "CPUType": { + "description": "The supported CPUs of :class:`~framework.testbed_model.node.Node`\\s.", + "enum": [ + "native", + "armv8a", + "dpaa2", + "thunderx", + "xgene1" + ], + "title": "CPUType", + "type": "string" + }, + "Compiler": { + "description": "The supported compilers of :class:`~framework.testbed_model.node.Node`\\s.", + "enum": [ + "gcc", + "clang", + "icc", + "msvc" + ], + "title": "Compiler", + "type": "string" + }, + "HugepageConfiguration": { + "additionalProperties": false, + "description": "The hugepage configuration of :class:`~framework.testbed_model.node.Node`\\s.\n\nAttributes:\n number_of: The number of hugepages to allocate.\n force_first_numa: If :data:`True`, the hugepages will be configured on the first NUMA node.", "properties": { "number_of": { - "type": "integer", - "description": "The number of hugepages to configure. Hugepage size will be the system default." + "title": "Number Of", + "type": "integer" }, "force_first_numa": { - "type": "boolean", - "description": "Set to True to force configuring hugepages on the first NUMA node. Defaults to False." + "title": "Force First Numa", + "type": "boolean" } }, - "additionalProperties": false, "required": [ - "number_of" - ] - }, - "mac_address": { - "type": "string", - "description": "A MAC address", - "pattern": "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$" + "number_of", + "force_first_numa" + ], + "title": "HugepageConfiguration", + "type": "object" }, - "pci_address": { - "type": "string", - "pattern": "^[\\da-fA-F]{4}:[\\da-fA-F]{2}:[\\da-fA-F]{2}.\\d:?\\w*$" + "OS": { + "description": "The supported operating systems of :class:`~framework.testbed_model.node.Node`\\s.", + "enum": [ + "linux", + "freebsd", + "windows" + ], + "title": "OS", + "type": "string" }, - "port_peer_address": { - "description": "Peer is a TRex port, and IXIA port or a PCI address", - "oneOf": [ - { - "description": "PCI peer port", - "$ref": "#/definitions/pci_address" + "PortConfig": { + "additionalProperties": false, + "description": "The port configuration of :class:`~framework.testbed_model.node.Node`\\s.\n\nAttributes:\n pci: The PCI address of the port.\n os_driver_for_dpdk: The operating system driver name for use with DPDK.\n os_driver: The operating system driver name when the operating system controls the port.\n peer_node: The :class:`~framework.testbed_model.node.Node` of the port\n connected to this port.\n peer_pci: The PCI address of the port connected to this port.", + "properties": { + "pci": { + "description": "The local PCI address of the port.", + "pattern": "^[\\da-fA-F]{4}:[\\da-fA-F]{2}:[\\da-fA-F]{2}.\\d:?\\w*$", + "title": "Pci", + "type": "string" + }, + "os_driver_for_dpdk": { + "description": "The driver that the kernel should bind this device to for DPDK to use it.", + "examples": [ + "vfio-pci", + "mlx5_core" + ], + "title": "Os Driver For Dpdk", + "type": "string" + }, + "os_driver": { + "description": "The driver normally used by this port", + "examples": [ + "i40e", + "ice", + "mlx5_core" + ], + "title": "Os Driver", + "type": "string" + }, + "peer_node": { + "description": "The name of the peer node this port is connected to.", + "title": "Peer Node", + "type": "string" + }, + "peer_pci": { + "description": "The PCI address of the peer port this port is connected to.", + "pattern": "^[\\da-fA-F]{4}:[\\da-fA-F]{2}:[\\da-fA-F]{2}.\\d:?\\w*$", + "title": "Peer Pci", + "type": "string" } - ] + }, + "required": [ + "pci", + "os_driver_for_dpdk", + "os_driver", + "peer_node", + "peer_pci" + ], + "title": "PortConfig", + "type": "object" }, - "test_suite": { - "type": "string", - "enum": [ - "hello_world", - "os_udp", - "pmd_buffer_scatter" - ] + "ScapyTrafficGeneratorConfig": { + "additionalProperties": false, + "description": "Scapy traffic generator specific configuration.", + "properties": { + "type": { + "const": "SCAPY", + "enum": [ + "SCAPY" + ], + "title": "Type", + "type": "string" + } + }, + "required": [ + "type" + ], + "title": "ScapyTrafficGeneratorConfig", + "type": "object" }, - "test_target": { - "type": "object", + "SutNodeConfiguration": { + "additionalProperties": false, + "description": ":class:`~framework.testbed_model.sut_node.SutNode` specific configuration.\n\nAttributes:\n memory_channels: The number of memory channels to use when running DPDK.", "properties": { - "suite": { - "$ref": "#/definitions/test_suite" + "name": { + "description": "A unique identifier for this node.", + "title": "Name", + "type": "string" + }, + "hostname": { + "description": "The hostname or IP address of the node.", + "title": "Hostname", + "type": "string" + }, + "user": { + "description": "The login user to use to connect to this node.", + "title": "User", + "type": "string" }, - "cases": { - "type": "array", - "description": "If specified, only this subset of test suite's test cases will be run.", + "password": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The login password to use to connect to this node. SSH keys are STRONGLY preferred, use only as last resort.", + "title": "Password" + }, + "use_first_core": { + "default": false, + "description": "DPDK won't use the first physical core if set to False.", + "title": "Use First Core", + "type": "boolean" + }, + "hugepages_2mb": { + "anyOf": [ + { + "$ref": "#/$defs/HugepageConfiguration" + }, + { + "type": "null" + } + ], + "default": null + }, + "ports": { "items": { - "type": "string" + "$ref": "#/$defs/PortConfig" }, - "minimum": 1 + "minItems": 1, + "title": "Ports", + "type": "array" + }, + "memory_channels": { + "default": 1, + "description": "Number of memory channels to use when running DPDK.", + "title": "Memory Channels", + "type": "integer" + }, + "arch": { + "$ref": "#/$defs/Architecture" + }, + "os": { + "$ref": "#/$defs/OS" + }, + "lcores": { + "default": "1", + "description": "Comma-separated list of logical cores to use. An empty string means use all lcores.", + "examples": [ + "1,2,3,4,5,18-22", + "10-15" + ], + "pattern": "^(([0-9]+|([0-9]+-[0-9]+))(,([0-9]+|([0-9]+-[0-9]+)))*)?$", + "title": "Lcores", + "type": "string" } }, "required": [ - "suite" + "name", + "hostname", + "user", + "ports", + "arch", + "os" ], - "additionalProperties": false - } - }, - "type": "object", - "properties": { - "nodes": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "A unique identifier for this node" - }, - "hostname": { - "type": "string", - "description": "A hostname from which the node running DTS can access this node. This can also be an IP address." - }, - "user": { - "type": "string", - "description": "The user to access this node with." - }, - "password": { - "type": "string", - "description": "The password to use on this node. Use only as a last resort. SSH keys are STRONGLY preferred." - }, - "arch": { - "$ref": "#/definitions/ARCH" - }, - "os": { - "$ref": "#/definitions/OS" - }, - "lcores": { - "type": "string", - "pattern": "^(([0-9]+|([0-9]+-[0-9]+))(,([0-9]+|([0-9]+-[0-9]+)))*)?$", - "description": "Optional comma-separated list of logical cores to use, e.g.: 1,2,3,4,5,18-22. Defaults to 1. An empty string means use all lcores." + "title": "SutNodeConfiguration", + "type": "object" + }, + "TGNodeConfiguration": { + "additionalProperties": false, + "description": ":class:`~framework.testbed_model.tg_node.TGNode` specific configuration.\n\nAttributes:\n traffic_generator: The configuration of the traffic generator present on the TG node.", + "properties": { + "name": { + "description": "A unique identifier for this node.", + "title": "Name", + "type": "string" + }, + "hostname": { + "description": "The hostname or IP address of the node.", + "title": "Hostname", + "type": "string" + }, + "user": { + "description": "The login user to use to connect to this node.", + "title": "User", + "type": "string" + }, + "password": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "The login password to use to connect to this node. SSH keys are STRONGLY preferred, use only as last resort.", + "title": "Password" + }, + "use_first_core": { + "default": false, + "description": "DPDK won't use the first physical core if set to False.", + "title": "Use First Core", + "type": "boolean" + }, + "hugepages_2mb": { + "anyOf": [ + { + "$ref": "#/$defs/HugepageConfiguration" + }, + { + "type": "null" + } + ], + "default": null + }, + "ports": { + "items": { + "$ref": "#/$defs/PortConfig" }, - "use_first_core": { - "type": "boolean", - "description": "Indicate whether DPDK should use the first physical core. It won't be used by default." + "minItems": 1, + "title": "Ports", + "type": "array" + }, + "arch": { + "$ref": "#/$defs/Architecture" + }, + "os": { + "$ref": "#/$defs/OS" + }, + "lcores": { + "default": "1", + "description": "Comma-separated list of logical cores to use. An empty string means use all lcores.", + "examples": [ + "1,2,3,4,5,18-22", + "10-15" + ], + "pattern": "^(([0-9]+|([0-9]+-[0-9]+))(,([0-9]+|([0-9]+-[0-9]+)))*)?$", + "title": "Lcores", + "type": "string" + }, + "traffic_generator": { + "discriminator": { + "mapping": { + "SCAPY": "#/$defs/ScapyTrafficGeneratorConfig" + }, + "propertyName": "type" }, - "memory_channels": { - "type": "integer", - "description": "How many memory channels to use. Optional, defaults to 1." + "oneOf": [ + { + "$ref": "#/$defs/ScapyTrafficGeneratorConfig" + } + ], + "title": "Traffic Generator" + } + }, + "required": [ + "name", + "hostname", + "user", + "ports", + "arch", + "os", + "traffic_generator" + ], + "title": "TGNodeConfiguration", + "type": "object" + }, + "TestRunConfiguration": { + "additionalProperties": false, + "description": "The configuration of a test run.\n\nThe configuration contains testbed information, what tests to execute\nand with what DPDK build.\n\nAttributes:\n build_targets: A list of DPDK builds to test.\n perf: Whether to run performance tests.\n func: Whether to run functional tests.\n skip_smoke_tests: Whether to skip smoke tests.\n test_suites: The names of test suites and/or test cases to execute.\n system_under_test_node: The SUT node configuration to use in this test run.\n traffic_generator_node: The TG node name to use in this test run.", + "properties": { + "perf": { + "description": "Enable performance testing.", + "title": "Perf", + "type": "boolean" + }, + "func": { + "description": "Enable functional testing.", + "title": "Func", + "type": "boolean" + }, + "test_suites": { + "items": { + "$ref": "#/$defs/TestSuiteConfig" }, - "hugepages_2mb": { - "$ref": "#/definitions/hugepages_2mb" + "minItems": 1, + "title": "Test Suites", + "type": "array" + }, + "build_targets": { + "items": { + "$ref": "#/$defs/BuildTargetConfiguration" }, - "ports": { - "type": "array", - "items": { - "type": "object", - "description": "Each port should be described on both sides of the connection. This makes configuration slightly more verbose but greatly simplifies implementation. If there are inconsistencies, then DTS will not run until that issue is fixed. An example inconsistency would be port 1, node 1 says it is connected to port 1, node 2, but port 1, node 2 says it is connected to port 2, node 1.", - "properties": { - "pci": { - "$ref": "#/definitions/pci_address", - "description": "The local PCI address of the port" - }, - "os_driver_for_dpdk": { - "type": "string", - "description": "The driver that the kernel should bind this device to for DPDK to use it. (ex: vfio-pci)" - }, - "os_driver": { - "type": "string", - "description": "The driver normally used by this port (ex: i40e)" - }, - "peer_node": { - "type": "string", - "description": "The name of the node the peer port is on" - }, - "peer_pci": { - "$ref": "#/definitions/pci_address", - "description": "The PCI address of the peer port" - } - }, - "additionalProperties": false, - "required": [ - "pci", - "os_driver_for_dpdk", - "os_driver", - "peer_node", - "peer_pci" - ] - }, - "minimum": 1 + "title": "Build Targets", + "type": "array" + }, + "skip_smoke_tests": { + "default": false, + "title": "Skip Smoke Tests", + "type": "boolean" + }, + "system_under_test_node": { + "$ref": "#/$defs/TestRunSUTNodeConfiguration" + }, + "traffic_generator_node": { + "title": "Traffic Generator Node", + "type": "string" + } + }, + "required": [ + "perf", + "func", + "test_suites", + "build_targets", + "system_under_test_node", + "traffic_generator_node" + ], + "title": "TestRunConfiguration", + "type": "object" + }, + "TestRunSUTNodeConfiguration": { + "additionalProperties": false, + "description": "The SUT node configuration of a test run.\n\nAttributes:\n node_name: The SUT node to use in this test run.\n vdevs: The names of virtual devices to test.", + "properties": { + "vdevs": { + "items": { + "type": "string" }, - "traffic_generator": { - "oneOf": [ - { - "type": "object", - "description": "Scapy traffic generator. Used for functional testing.", - "properties": { - "type": { - "type": "string", - "enum": [ - "SCAPY" - ] - } - } - } - ] - } + "title": "Vdevs", + "type": "array" }, - "additionalProperties": false, - "required": [ - "name", - "hostname", - "user", - "arch", - "os" - ] + "node_name": { + "title": "Node Name", + "type": "string" + } }, - "minimum": 1 + "required": [ + "node_name" + ], + "title": "TestRunSUTNodeConfiguration", + "type": "object" }, - "test_runs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "build_targets": { - "type": "array", - "items": { - "$ref": "#/definitions/build_target" + "TestSuiteConfig": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "test_suite": { + "description": "The identifying name of the test suite.", + "title": "Test suite name", + "type": "string" }, - "minimum": 1 - }, - "perf": { - "type": "boolean", - "description": "Enable performance testing." - }, - "func": { - "type": "boolean", - "description": "Enable functional testing." - }, - "test_suites": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/definitions/test_suite" - }, - { - "$ref": "#/definitions/test_target" - } - ] + "test_cases": { + "description": "The identifying name of the test cases of the test suite.", + "items": { + "type": "string" + }, + "title": "Test cases by name", + "type": "array" } }, - "skip_smoke_tests": { - "description": "Optional field that allows you to skip smoke testing", - "type": "boolean" - }, - "system_under_test_node": { - "type":"object", - "properties": { - "node_name": { - "$ref": "#/definitions/node_name" - }, - "vdevs": { - "description": "Optional list of names of vdevs to be used in the test run", - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "node_name" - ] + "required": [ + "test_suite" + ], + "type": "object" + }, + { + "type": "string" + } + ], + "description": "Test suite configuration.\n\nInformation about a single test suite to be executed. It can be represented and validated as a\nstring type in the form of: ``TEST_SUITE [TEST_CASE, ...]``, in the configuration file.\n\nAttributes:\n test_suite: The name of the test suite module without the starting ``TestSuite_``.\n test_cases: The names of test cases from this test suite to execute.\n If empty, all test cases will be executed.", + "title": "TestSuiteConfig" + } + }, + "description": "DTS testbed and test configuration.\n\nAttributes:\n test_runs: Test run configurations.\n nodes: Node configurations.", + "properties": { + "test_runs": { + "items": { + "$ref": "#/$defs/TestRunConfiguration" + }, + "minItems": 1, + "title": "Test Runs", + "type": "array" + }, + "nodes": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/TGNodeConfiguration" }, - "traffic_generator_node": { - "$ref": "#/definitions/node_name" + { + "$ref": "#/$defs/SutNodeConfiguration" } - }, - "additionalProperties": false, - "required": [ - "build_targets", - "perf", - "func", - "test_suites", - "system_under_test_node", - "traffic_generator_node" ] }, - "minimum": 1 + "minItems": 1, + "title": "Nodes", + "type": "array" } }, "required": [ "test_runs", "nodes" ], - "additionalProperties": false -} + "title": "Configuration", + "type": "object", + "$schema": "https://json-schema.org/draft/2020-12/schema" +} \ No newline at end of file diff --git a/dts/generate-schema.py b/dts/generate-schema.py new file mode 100755 index 0000000000..b41d28492f --- /dev/null +++ b/dts/generate-schema.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Arm Limited + +"""JSON schema generation script.""" + +import json +import os + +from pydantic.json_schema import GenerateJsonSchema + +from framework.config import ConfigurationType + +DTS_DIR = os.path.dirname(os.path.realpath(__file__)) +RELATIVE_PATH_TO_SCHEMA = "framework/config/conf_yaml_schema.json" + + +class GenerateSchemaWithDialect(GenerateJsonSchema): + """Custom schema generator which adds the schema dialect.""" + + def generate(self, schema, mode="validation"): + """Generate JSON schema.""" + json_schema = super().generate(schema, mode=mode) + json_schema["$schema"] = self.schema_dialect + return json_schema + + +try: + path = os.path.join(DTS_DIR, RELATIVE_PATH_TO_SCHEMA) + + with open(path, "w") as schema_file: + schema_dict = ConfigurationType.json_schema(schema_generator=GenerateSchemaWithDialect) + schema_json = json.dumps(schema_dict, indent=2) + schema_file.write(schema_json) + + print("Schema generated successfully!") +except Exception as e: + raise Exception("failed to generate schema") from e -- 2.34.1