diff --git a/CHANGELOG.md b/CHANGELOG.md index 67560868..857d504c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.26.1] - 2024-08-22 +### Fixed +- Fix boot set schema validation bug preventing valid session templates from being created + ## [2.26.0] - 2024-08-20 ### Added - BOS automatically tags IMS images with the 'sbps-project: true' tag when using SBPS as the rootfs provider. diff --git a/api/openapi.yaml.in b/api/openapi.yaml.in index 2587147d..b32c6955 100644 --- a/api/openapi.yaml.in +++ b/api/openapi.yaml.in @@ -497,7 +497,7 @@ components: A null value means the Session has not encountered an error. maxLength: 65536 additionalProperties: false - V2BootSetData: + V2BootSet: description: | A Boot Set is a collection of nodes defined by an explicit list, their functional role, and their logical groupings. This collection of nodes is associated with one @@ -543,13 +543,6 @@ components: $ref: '#/components/schemas/BootSetRootfsProviderPassthrough' additionalProperties: false required: [path, type] - V2BootSet: - allOf: - - $ref: '#/components/schemas/V2BootSetData' - - anyOf: - - required: [node_list] - - required: [node_roles_groups] - - required: [node_groups] V2SessionTemplateArray: description: An array of Session Templates. type: array diff --git a/src/bos/server/controllers/v2/sessiontemplates.py b/src/bos/server/controllers/v2/sessiontemplates.py index 043b5dc0..681c8c61 100644 --- a/src/bos/server/controllers/v2/sessiontemplates.py +++ b/src/bos/server/controllers/v2/sessiontemplates.py @@ -54,6 +54,7 @@ "enable_cfs": True, "name": "name-your-template"} +BOOT_SET_NODE_FIELDS = [ "node_list", "node_roles_groups", "node_groups" ] def _sanitize_xnames(st_json): """ @@ -79,10 +80,10 @@ def _validate_sanitize_session_template(session_template_id, template_data): # The boot_sets field is required. if "boot_sets" not in template_data: raise ParsingException("Missing required 'boot_sets' field") - - # All keys in the boot_sets mapping must match the 'name' fields in the - # boot sets to which they map (if they contain a 'name' field). + for bs_name, bs in template_data["boot_sets"].items(): + # All keys in the boot_sets mapping must match the 'name' fields in the + # boot sets to which they map (if they contain a 'name' field). if "name" not in bs: # Set the field here -- this allows the name to be validated # per the schema later @@ -91,6 +92,11 @@ def _validate_sanitize_session_template(session_template_id, template_data): raise ParsingException(f"boot_sets key ({bs_name}) does not match 'name' " f"field of corresponding boot set ({bs["name"]})") + # Also, validate that each boot set has at least one of the BOOT_SET_NODE_FIELDS + if not any(field_name in bs for field_name in BOOT_SET_NODE_FIELDS): + raise ParsingException(f"Boot set {bs_name} has none of the following " + f"fields: {BOOT_SET_NODE_FIELDS}") + # Convert the JSON request data into a SessionTemplate object. # Any exceptions raised here would be generated from the model # (i.e. bos.server.models.v2_session_template). @@ -130,6 +136,7 @@ def put_v2_sessiontemplate(session_template_id): # noqa: E501 except Exception as err: LOGGER.error("Error creating session template '%s': %s", session_template_id, exc_type_msg(err)) + LOGGER.debug("Full template: %s", template_data) return connexion.problem( status=400, title="The session template could not be created.", detail=str(err))