dadav / helm-schema

Generate jsonschemas from helm charts.
MIT License
67 stars 9 forks source link

Root-level `oneOf`? #62

Open mircea-pavel-anton opened 1 month ago

mircea-pavel-anton commented 1 month ago

Say I have a helm chart with this values.yaml:

---
# @schema
# required: true
# type: string
# @schema
valueA: ""

# @schema
# required: false
# type: string
# @schema
valueB: ""

# @schema
# required: false
# type: string
# @schema
valueC: ""

And what I want is to have valueA always required, but then only one of valueB or valueC. They are mutually exclusive.

If I generate the schema, I get this:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "global": {
      "description": "Global values are values that can be accessed from any chart or subchart by exactly the same name.",
      "required": [],
      "title": "global",
      "type": "object"
    },
    "valueA": {
      "default": "",
      "required": [],
      "title": "valueA",
      "type": "string"
    },
    "valueB": {
      "default": "",
      "required": [],
      "title": "valueB",
      "type": "string"
    },
    "valueC": {
      "default": "",
      "required": [],
      "title": "valueC",
      "type": "string"
    }
  },
  "required": [
    "valueA"
  ],
  "type": "object"
}

Which is expected, and what I want essentially is to also include this block:

  "oneOf": [
    {
      "required": [
        "valueB"
      ]
    },
    {
      "required": [
        "valueC"
      ]
    }
  ],

To get this:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false,
  "properties": {
    "global": {
      "description": "Global values are values that can be accessed from any chart or subchart by exactly the same name.",
      "required": [],
      "title": "global",
      "type": "object"
    },
    "valueA": {
      "default": "",
      "required": [],
      "title": "valueA",
      "type": "string"
    },
    "valueB": {
      "default": "",
      "required": [],
      "title": "valueB",
      "type": "string"
    },
    "valueC": {
      "default": "",
      "required": [],
      "title": "valueC",
      "type": "string"
    }
  },
  "required": [
    "valueA"
  ],
  "oneOf": [
    {
      "required": [
        "valueB"
      ]
    },
    {
      "required": [
        "valueC"
      ]
    }
  ],
  "type": "object"
}

It is not clear to me how to do this with the current comment-annotations

dadav commented 1 month ago

Currently not possible

mircea-pavel-anton commented 1 month ago

Leaving it here for others running into the same limitation.

I was able to work around this by adding a validation in my templates:

{{- if .Values.valueB }} 
   {{- if .Values.valueC }} 
     {{- fail "Value B and C are mutually exclusive!" }} 
   {{- end }} 
{{- end }}

Granted, this is not an ideal solution as it will fail at apply-time, but it ultimately achieves the same goal... Mostly