dadav/helm-schema

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 and typeRelativePointer 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...)