quarkiverse / quarkus-helm

Quarkus Extension to generate the Helm artifacts
Apache License 2.0
10 stars 8 forks source link

Helm values.schema.json validation not working with boolean and numeric env vars types #261

Closed ThoSap closed 1 year ago

ThoSap commented 1 year ago

Hi,

first of all I'm using Quarkus 3.1.2.Final and Quarkiverse Helm 1.0.8. For the configuration file, I'm not using application.properties, but application.yml (https://quarkus.io/guides/config-yaml).

Today I wanted to make a clean configuration for the new values.schema.json file, for example for the Quarkus runtime property QUARKUS_MAILER_PORT. As this is a port number, the type must be an integer and must be between 0 (or 1 as 0 is a reserved port) and 65535.

As boolean and numeric types must be quoted for K8s Pod environment variables, I added the following workaround with an expression

# Specifiy the env var for the Deployment
quarkus.kubernetes.env.vars.QUARKUS_MAILER_PORT=${quarkus.mailer.port}

# Fix the quoting (https://helm.sh/docs/chart_template_guide/functions_and_pipelines/#pipelines), else we get the error message below
quarkus.helm.expressions.QUARKUS_MAILER_PORT.path=(kind == Deployment).spec.template.spec.containers.(name == my-container).env.(name == QUARKUS_MAILER_PORT).value
quarkus.helm.expressions.QUARKUS_MAILER_PORT.expression={{ .Values.app.envs.MAIL_FOLDER_MAIL | quote }}

If we do not add this workaround, the Helm deploy or the K8s Deployment fails with

Deployment in version "v1" cannot be handled as a Deployment:
  json: cannot unmarshal number into Go struct field EnvVar.spec.template.spec.containers.env.value of type string

// OR

Deployment in version "v1" cannot be handled as a Deployment:
  json: cannot unmarshal bool into Go struct field EnvVar.spec.template.spec.containers.env.value of type string

For the Helm values.schema.json validation, I added the following properties

quarkus.helm.values-schema.properties.QUARKUS_MAILER_PORT.name=app.envs.QUARKUS_MAILER_PORT
quarkus.helm.values-schema.properties.QUARKUS_MAILER_PORT.type=integer
quarkus.helm.values-schema.properties.QUARKUS_MAILER_PORT.minimum=1
quarkus.helm.values-schema.properties.QUARKUS_MAILER_PORT.maximum=65535

but no matter what I try, the value in the values.yaml is always generated as a string

---
app:
  envs:
    QUARKUS_MAILER_PORT: "25"
# The rest of the YAML was removed for brevity

therefore, the schema Helm values.schema.json validation fails with image when I want to deploy the Helm instance.

In my YAML application.yml instead of application.properties the K8s/Helm configuration is configured as follows (many unrelated properties are missing in this example for brevity):

quarkus:
  kubernetes:
    env:
      vars:
        # Quarkus Mailer
        QUARKUS_MAILER_HOST: ${quarkus.mailer.host}
        QUARKUS_MAILER_PORT: ${quarkus.mailer.port}
        QUARKUS_MAILER_FROM: ${quarkus.mailer.from}
  helm:
    values-schema:
      properties:
        QUARKUS_MAILER_PORT:
          name: app.envs.QUARKUS_MAILER_PORT
          type: integer
          minimum: 1
          maximum: 65535
    expressions:
      QUARKUS_MAILER_PORT:
        path: (kind == Deployment).spec.template.spec.containers.(name == my-container).env.(name == QUARKUS_MAILER_PORT).value
        expression: "{{ .Values.app.envs.QUARKUS_MAILER_PORT | quote }}"
Sgitario commented 1 year ago

Unfortunately, the mapping of env var types only works for string types because system properties are String based properties. Alternatively, what you can do is:

quarkus.mailer.port=${app.mailerPort}
quarkus.helm.values.mailerPort.value-as-int=1000
quarkus.helm.values-schema.properties.mailerPort.minimum=1
quarkus.helm.values-schema.properties.mailerPort.maximum=65535
quarkus.helm.values-schema.properties.mailerPort.type=integer

Quarkus Helm will bind the Quarkus property with the Helm values automatically by you, so you don't need to provide the path. Can you give it a try? I hope it helps!

ThoSap commented 1 year ago

Got it, but why do other env var strings not end up being quoted, but boolean and numeric types are quoted?

The issue would be fixed, if the boolean and numeric values are not quoted in file values.yaml. See the following example: image

This is due to historic reasons, as I'm an OG Quarkiverse Helm user since 0.1.2 😉 I will remove the manual path mapping,

Sgitario commented 1 year ago

Got it, but why do other env var strings not end up being quoted, but boolean and numeric types are quoted?

This indeed works as you stated from https://github.com/quarkiverse/quarkus-helm/pull/230. For String values, it's not quoted. However, having a deeper look, perhaps this was a bad idea from my side. I will fix it asap.

Sgitario commented 1 year ago

It seems the quoted is indeed necessary, otherwise we got:

Error: INSTALLATION FAILED: Deployment in version "v1" cannot be handled as a Deployment: json: cannot unmarshal bool into Go struct field EnvVar.spec.template.spec.initContainers.env.value of type string

So, the env var values only accept string values.

Sgitario commented 1 year ago

Since using env-var won't work with String values, I recommend you to use https://quarkus.io/guides/kubernetes-config to provide configuration from a configMap. Then, you can map the values within the configMap with the generated Helm chart.

Sgitario commented 1 year ago

I've created a new example to better explain how to map properties that are not a string. Feel free to have a look into this.