Skip to content

Full JSON Schema validation for values.schema.json (replace hand-rolled validator with NetworkNT) #816

Description

@alexmond

Summary

SchemaValidator (jhelm-core) is a hand-rolled partial JSON Schema validator that recognizes only ~10 keywords. Real Helm validates values.schema.json with a full-spec library, so charts whose schema uses anything outside jhelm's subset pass jhelm but behave differently under Helm — a silent compatibility gap.

Current state

jhelm-core/src/main/java/org/alexmond/jhelm/core/service/SchemaValidator.java implements by hand:

  • type, required, properties (recursive), enum
  • minimum, maximum, minLength, maxLength, pattern

Everything else in the schema is silently ignored, notably: $ref/$defs/definitions, additionalProperties, items / array-element validation, oneOf/anyOf/allOf/not, if/then/else, const, patternProperties, dependencies/dependentSchemas, format, multipleOf, exclusiveMinimum/exclusiveMaximum.

Enforced in two places (both call SchemaValidator.validate(chartName, schemaJson, values) and catch SchemaValidationException):

  • Engine.java:810-819 — on render (throws TemplateRenderException)
  • LintAction.java:125-137 — on lint (adds each error as a lint finding)

What upstream Helm uses

Library Draft
Helm 3 (release-3.x) github.com/xeipuuv/gojsonschema Draft-07 (full spec)
Helm 4 (main) github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 draft 2020-12 default (full spec)

So jhelm doesn't even cover full Draft-07 (Helm 3's baseline), let alone Helm 4's 2020-12.

Concrete divergences (chart passes jhelm, Helm differs):

  • additionalProperties: false with an unknown key — Helm rejects, jhelm passes.
  • $ref to #/$defs/... — Helm resolves and validates, jhelm ignores.
  • oneOf / if-then-else conditional validation — enforced by Helm, ignored by jhelm.
  • Array items constraints — enforced by Helm, ignored by jhelm.

Proposed fix

Replace the hand-rolled validator with com.networknt:json-schema-validator (v3 API), configured for draft 2020-12 by default and $schema-aware (a chart declaring "$schema": ".../draft-07/schema#" validates as Draft-07, matching Helm 3 charts; absent $schema defaults to 2020-12, matching Helm 4).

The sibling repo yj-schema-validator already uses this exact library (json-schema-validator 3.0.5) on Jackson 3 (tools.jackson, same as jhelm) — it is the reference implementation. Core pattern (YamlSchemaValidator.getSchemaByPath / validateJsonNode):

SchemaRegistryConfig cfg = SchemaRegistryConfig.builder().build();
SchemaRegistry registry = SchemaRegistry.withDefaultDialect(
        SpecificationVersion.DRAFT_2020_12, b -> b.schemaRegistryConfig(cfg));
Schema schema = registry.getSchema(schemaNode);
OutputUnit result = schema.validate(valuesJson, InputFormat.JSON, OutputFormat.LIST);

Porting requirements / caveats

  1. Preserve the public contract. Keep validate(String chartName, String schemaJson, Map<String,Object> values) throwing SchemaValidationException(chartName, List<String>) so Engine and LintAction are untouched.
  2. Map OutputUnitList<String>. Walk getDetails() → each detail's getInstanceLocation() + getErrors() (keyword→message) into the existing error-string list.
  3. Helm float64 semantics. Helm loads values as float64, so a whole-valued double (8080.0, 3.0) must satisfy type: integer. JSON-Schema spec says integer matches a number with zero fractional part; NetworkNT honors this — lock it with a test (jhelm renders values as boxed Doubles).
  4. Malformed schema → treated as absent (warn + skip), matching current behavior and real Helm.
  5. Cache the compiled Schema keyed by schema content — the current code re-parses on every validate() call (SchemaValidator.java:44).
  6. Use the NetworkNT v3 API (SchemaRegistry/Schema), not the older 1.x JsonSchemaFactory/ValidationMessage API most online examples show — follow yj.
  7. Input: serialize the Map values via tools.jackson JsonMapper and validate with InputFormat.JSON.

Done when

  • SchemaValidator backed by NetworkNT, full-spec 2019-09/2020-12 (+ Draft-07 via $schema).
  • Existing SchemaValidatorTest cases stay green; new cases cover additionalProperties, $ref/$defs, oneOf/anyOf/allOf, if/then/else, items, const, the float64-integer parity case, and $schema-driven draft selection.
  • Malformed-schema-as-absent preserved; Engine/LintAction unchanged.
  • Build gates green (PMD, checkstyle, tests).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions