From 451111ad1d3ad63a8e0c390065f6e7310d0e807f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20K=C4=99dziak?= Date: Fri, 3 Jan 2025 15:31:26 +0100 Subject: [PATCH] feat(schema): schema changes for custom REST endpoints (#1509) **Issue number:** [ADDON-76812](https://splunk.atlassian.net/browse/ADDON-76812) ### PR Type **What kind of change does this PR introduce?** * [x] Feature * [ ] Bug Fix * [ ] Refactoring (no functional or API changes) * [ ] Documentation Update * [ ] Maintenance (dependency updates, CI, etc.) ## Summary ### Changes Schema changes required for the future feature for adding custom REST endpoints. This change adds new `options` section with `restHandlers`. ```js { "meta": {}, "pages": { "configuration": {}, "inputs": {}, "dashboards": {} }, "alerts": [], "options": { "restHandlers": [] // <--- here } } ``` The array above consists of entries of the following form (example): ```js { "endpoint": "some_endpoint", "handlerType": "EAI", "registerHandler": { "file": "my_handler.py", "actions": ["list", "create", "edit", "remove"] }, "requestParameters": { "create": { "some_param": {"type": "string"}, "other_param": {"type": "number"}, "other_param_nullable": { "type": "number", "nullable": true, } }, "list": { "array_param": { "type": "array", "items": {"type": "string"}, }, "obj_param": { "type": "object", "properties": { "key": {"type": "string"}, } } } }, "responseParams": { // similar to requestParameters } } ``` - `endpoint` - it denotes the URL path that handler is connected to - `handlerType` - currently only `EAI` is specified here, to denote, that only [EAI](https://dev.splunk.com/enterprise/docs/devtools/customrestendpoints/customresteai/) endpoints are supported. This is added in case we would like to support other handlers as well in the future. - `registerHandler` - optional. If specified, it registers the handler in `web.conf` and `restmap.conf`. - `requestParameters` - an object with action name as a key and value being a dictionary containing keys (parameter names) to values (OpenAPI data types). - `responseParameters` - similar to the above one The data types are based on [OpenAPI data types](https://swagger.io/docs/specification/v3_0/data-models/data-types). Example data types: - `{"type": "string"}` - `{"type": "number", "nullable": true}` - `{"type": "boolean"}` - `{"type": "array", "items": {"type": "string"}}` - `{"type": "object", "parameters": {"some_param": {"type": "string"}}}` - `{"anyOf": [...]}` - `{"allOf": [...]}` ### User experience No changes to the current user experience. ## Checklist If an item doesn't apply to your changes, leave it unchecked. * [x] I have performed a self-review of this change according to the [development guidelines](https://splunk.github.io/addonfactory-ucc-generator/contributing/#development-guidelines) * [x] Tests have been added/modified to cover the changes [(testing doc)](https://splunk.github.io/addonfactory-ucc-generator/contributing/#build-and-test) * [ ] Changes are documented * [x] PR title and description follows the [contributing principles](https://splunk.github.io/addonfactory-ucc-generator/contributing/#pull-requests) --------- Co-authored-by: Artem Rys --- .../schema/schema.json | 198 ++++++++++++++++++ tests/unit/test_schema.py | 43 ++++ 2 files changed, 241 insertions(+) diff --git a/splunk_add_on_ucc_framework/schema/schema.json b/splunk_add_on_ucc_framework/schema/schema.json index 5f4e2e444..f25973bf8 100644 --- a/splunk_add_on_ucc_framework/schema/schema.json +++ b/splunk_add_on_ucc_framework/schema/schema.json @@ -2341,6 +2341,201 @@ ] } }, + "OpenApiType": { + "type": "object", + "description": "OpenAPI request or response param type.", + "oneOf": [ + { + "properties": { + "type": { + "type": "string", + "enum": ["string", "number", "integer", "boolean"] + }, + "nullable": { + "type": "boolean", + "default": false + } + }, + "additionalProperties": false, + "required": [ + "type" + ] + }, + { + "properties": { + "type": { + "type": "string", + "const": "array" + }, + "items": { + "$ref": "#/definitions/OpenApiType" + }, + "nullable": { + "type": "boolean", + "default": false + } + }, + "additionalProperties": false, + "required": [ + "type", + "items" + ] + }, + { + "properties": { + "type": { + "type": "string", + "const": "object" + }, + "properties": { + "type": "object", + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/OpenApiType" + } + } + } + }, + "additionalProperties": false, + "required": [ + "type", + "properties" + ] + }, + { + "properties": { + "anyOf": { + "type": "array", + "items": { + "$ref": "#/definitions/OpenApiType" + } + }, + "nullable": { + "type": "boolean", + "default": false + } + }, + "additionalProperties": false, + "required": [ + "anyOf" + ] + }, + { + "properties": { + "oneOf": { + "type": "array", + "items": { + "$ref": "#/definitions/OpenApiType" + } + }, + "nullable": { + "type": "boolean", + "default": false + } + }, + "additionalProperties": false, + "required": [ + "oneOf" + ] + } + ] + }, + "RestHandlerActionParams": { + "type": "object", + "description": "Request or response parameters for a particular action.", + "additionalProperties": false, + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/OpenApiType" + } + } + }, + "RestHandlerParams": { + "type": "object", + "description": "Request or response parameters.", + "additionalProperties": false, + "properties": { + "list": { + "$ref": "#/definitions/RestHandlerActionParams" + }, + "edit": { + "$ref": "#/definitions/RestHandlerActionParams" + }, + "create": { + "$ref": "#/definitions/RestHandlerActionParams" + }, + "remove": { + "$ref": "#/definitions/RestHandlerActionParams" + } + } + }, + "RestHandler": { + "type": "object", + "description": "Rest handlers not automatically generated by UCC.", + "properties": { + "endpoint": { + "type": "string", + "description": "The endpoint for the custom rest handler." + }, + "handlerType": { + "type": "string", + "description": "The type of the handler.", + "enum": ["EAI"] + }, + "registerHandler": { + "type": "object", + "description": "Parameters needed to register the endpoint in web.conf and restmap.conf", + "properties": { + "file": { + "type": "string", + "description": "The file where the custom rest handler is located." + }, + "actions": { + "type": "array", + "description": "The actions that the custom rest handler supports.", + "items": { + "type": "string", + "description": "The action that the custom rest handler supports.", + "enum": ["list", "edit", "create", "remove"] + } + } + }, + "additionalProperties": false, + "required": [ + "file", + "actions" + ] + }, + "requestParameters": { + "type": "object", + "description": "The parameters that the custom rest handler supports.", + "$ref": "#/definitions/RestHandlerParams" + }, + "responseParameters": { + "type": "object", + "description": "The parameters that the custom rest handler returns.", + "$ref": "#/definitions/RestHandlerParams" + } + }, + "additionalProperties": false, + "required": [ + "endpoint", + "handlerType" + ] + }, + "Options": { + "type": "object", + "description": "Additional options for the addon", + "properties": { + "restHandlers": { + "type": "array", + "items": { + "$ref": "#/definitions/RestHandler" + } + } + }, + "additionalProperties": false + }, "Pages": { "type": "object", "description": "Definition of addon pages (configuration, inputs, dashboard)", @@ -3412,6 +3607,9 @@ "$ref": "#/definitions/Alerts" }, "minItems": 1 + }, + "options": { + "$ref": "#/definitions/Options" } }, "required": [ diff --git a/tests/unit/test_schema.py b/tests/unit/test_schema.py index 85c288e08..cba1ca77b 100644 --- a/tests/unit/test_schema.py +++ b/tests/unit/test_schema.py @@ -107,3 +107,46 @@ def test_interval_entity_options(schema_validate, config): } ) ) + + +def test_rest_handler_without_ui(schema_validate, config): + crh = { + "endpoint": "some_endpoint", + "handlerType": "EAI", + "requestParameters": { + "create": { + "some_param": {"type": "string"}, + "other_param": {"type": "number"}, + "other_param_nullable": { + "type": "number", + "nullable": True, + }, + }, + "list": { + "array_param": { + "type": "array", + "items": {"type": "string"}, + }, + "obj_param": { + "type": "object", + "properties": { + "key": {"type": "string"}, + }, + }, + }, + }, + "responseParameters": { + "list": { + "some_param": {"type": "string"}, + }, + }, + } + config.setdefault("options", {})["restHandlers"] = [crh] + schema_validate(config) + + crh["registerHandler"] = { + "file": "my_handler.py", + "actions": ["list", "create", "edit", "remove"], + } + + schema_validate(config)