Implement schema patching (RFC 7386) #573
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.



Implements Schema patching
This PR introduces schema patching, allowing fine-grained modifications to JSON schemas
via a new
patchSchemaWithkey underonyxia-api, similar to overwriting.Schema resolution now supports JSON Merge Patch (RFC 7386)
in addition to the existing
overwriteSchemaWithand$refsubstitution mechanisms.Motivation
The existing overwriting mechanism completely replaces the JSON structure, which has several drawbacks:
By introducing a targeted JSON patching mechanism, users can specify only the values that need updating,
improving both readability and maintainability.
Corner cases
$ref,rewriteSchemaWith,patchSchemaWith) are present,only the first available, in that order, is applied.
rewriteSchemaWithnested within a patched object is processed first, followed by patching on the resolved JSONpatchSchemaWithentries are applied from the innermost to the outermost level."key": null(only valid in patches, not in schema files)Does not fail if the
"key"is missing from the patched objectImplementation Notes
deepCopy()by reconstructing a freshJsonNoderewriteSchemaWith,patchSchemaWith) are removed from the final resolved schemaExample
The
input.jsonschema below is resolved asoutput.jsonwhenthe
ingress.json,enabled.json,hostname.json, andignored.jsonfilescan be retrieved from the
JsonSchemaRegistryService.input.json
{ "title": "Original Ingress title", "type": "Original Ingress type", "x-onyxia": { "patchSchemaWith": "ingress.json" }, "properties": { "enabled": { "description": "Original enabled description", "type": "Original enabled type", "x-onyxia": { "overwriteSchemaWith": "enabled.json", "patchSchemaWith": "ignored.json" } }, "useTlsSecret": { "title" : "Original title not overriden since missing-schema.json doesn't exist", "x-onyxia": { "overwriteSchemaWith": "missing-schema.json" } }, "hostname": { "title": "Original hostname title", "type": "Original hostname type", "x-onyxia": { "patchSchemaWith": "hostname.json" } }, "useCertManager": { "$ref": "#/definitions/useCertManagerRef" } }, "definitions": { "useCertManagerRef": { "type": "Use Cert Manager type from ref", "description": "Use Cert Manager description from ref" } } }ingress.json
{ "title": "Title edited by by ingress.json", "description": "Description added by ingress.json", "properties": { "ingressClassName": { "default": "New ingressClassName object created by ingress.json" }, "enabled": { "title": "Title created by enabled.json and then overriden by ingress.json" }, "hostname": { "title": "Title overriden by ingress.json", "description": null, "type": "Type deleted by hostname.json, recreated by ingress.json", "nonexistent-field-deleted-without-error": null }, "useCertManager": { "description": "Use Cert Manager description edited by ingress.json" } } }enabled.json
{ "title": "Title created by enabled.json", "description": "Description overwritten by enabled.json", "type": "type overwritten by enabled.json", "new_field": "New field created by enabled.json" }hostname.json
{ "title": "Title edited by hostname.json", "description": "New description created by hostname.json", "type": null }ignored.json
"I replace stuff with this string if I'm used anywhere"output.json
{ "title": "Title edited by by ingress.json", "type": "Original Ingress type", "properties": { "enabled": { "title": "Title created by enabled.json and then overriden by ingress.json", "description": "Description overwritten by enabled.json", "type": "type overwritten by enabled.json", "new_field": "New field created by enabled.json" }, "useTlsSecret": { "title": "Original title not overriden since missing-schema.json doesn't exist" }, "hostname": { "title": "Title overriden by ingress.json", "type": "Type deleted by hostname.json, recreated by ingress.json" }, "useCertManager": { "type": "Use Cert Manager type from ref", "description": "Use Cert Manager description edited by ingress.json" }, "ingressClassName": { "default": "New ingressClassName object created by ingress.json" } }, "definitions": { "useCertManagerRef": { "type": "Use Cert Manager type from ref", "description": "Use Cert Manager description from ref" } }, "description": "Description added by ingress.json" }