feat request: local schemas for $ref
Closed this issue · 1 comments
Not sure if this is possible, but we use private repos and I sort of need to create a subschema. Is it possible to add the ability to call a relative path using $ref?
alternatively, is there any way to do something similar to patternProperties
but only covers the key and all properties under that object would still be auto detected?
We have two helm charts which uses an object instead of a list of objects for things and it comes with an example like so:
widgets:
# so users see the full example or takes advantage of global and add their own key
# except this has like 30 keys so I don't really feel like filling out the whole thing in a single annotation
defaultWidget:
enabled: false
foo: value
Another, similar use case where this would be useful:
Defining default values in one dict, while having instances override only specific fields in another dict - merging both together when accessing values.
# -- Default namspace settings for all namespace not setting other values
namespaceDefaults:
rbac:
admin:
# -- Groups to add as admins
groups: ["cluster-admins"]
user:
# - Groups to add as users
groups: []
quotas:
# -- Max allowed storage
storage: 10Gi
# @schema
# childTypePointer: /namespaceDefaults
# @schema
# -- List of namespaces to manage
# see namespaceDefaults for possible values
namespaces:
ns1:
admin:
groups: ["cluster-admins", "app-admins"]
ns2:
storage: 100Gi
ns3: {}
-
# childTypePointer: /namespaceDefaults
could be a JSON Pointer: "a string syntax for identifying a specific value within a JavaScript Object Notation (JSON) document" to select the schema to reuse; -
childTypePointer
could apply the type to all children in the array / dictionary that is annotated by this; -
typePointer
could apply the referenced type to the annotated property itself, instead of its children
Would (should) also work well with something like patternProperties
or if/else
This would also work for a slightly adapted pattern of the example above which we're using:
# @schema
# additionalProperties: true
# @schema
namespaceTypes:
# -- Default config for namspace settings for all namespace not setting other values
default:
rbac:
admin:
# -- Groups to add as admins
groups: ["cluster-admins"]
user:
# - Groups to add as users
groups: []
quotas:
# -- Max allowed storage
storage: 100Gi
# @schema
# childTypePointer: /namespaceDefaults/default
# @schema
# -- System config for development namespace
dev:
rbac:
admin:
# -- Groups to add as admins
groups: ["cluster-admins", "developer"]
user:
# - Groups to add as users
groups: [""]
quotas:
# -- Max allowed storage
storage: 10Gi
# if dev base config wouldn't directly reference default anyways,
# we could use
# @schema
# childTypePointer: /namespaceDefaults/default
# @schema
# -- List of namespaces to manage
# see namespaceDefaults for possible values
namespaces:
ns1:
# -- Use a different type then the default `default` one
type: user
admin:
groups: ["cluster-admins", "app-admins"]
ns2:
storage: 100Gi
ns3: {}
It's basically the same, with a small difference: since namespaces in namespaces
can define type
to choose a different base config than default
, the type of /namespaces/ns1
would extend /namespaceDefaults/default
Obvious difficulties I can imagine with such a solution:
- does the schema itself support such references, or would this require some copying around during rendering the output?
- how to handle cycles in the graph?
- even if it's not cyclic - could a wrong / too deeply nested chain unexpectedly blow up the output size?
- could this work together with
$ref
to select a type defined in another schema? - would
childTypeRelativePointer
andtypeRelativePointer
be beneficial as well? - I thought of pointers because I just saw them being a recognized json schema string format
- we could also think about other methods as well besides pointers. Using more of a query syntax (jsonpath, jq, jmes), we could dynamically generate the type we want to extend from
- definitely sounds a bit too scary and unpredictable for a spec tool, at least on a first glance
- but also fun; maybe there are legitimate use cases here? (can't think of any right now...)