From 3d243f622a0d8bd557f1541f5edb243114a70983 Mon Sep 17 00:00:00 2001 From: Aayush Tiwari Date: Sat, 11 Jul 2026 20:15:26 +0530 Subject: [PATCH] Add yaml.is_valid builtin Signed-off-by: Aayush Tiwari --- .../opa-builtins-json/build.gradle.kts | 7 ++++ .../opa/ast/builtin/impls/JsonBuiltins.java | 23 ++++++++++++- .../ast/builtin/impls/JsonBuiltinsTest.java | 33 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 opa-builtins/opa-builtins-json/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltinsTest.java diff --git a/opa-builtins/opa-builtins-json/build.gradle.kts b/opa-builtins/opa-builtins-json/build.gradle.kts index e23c02f6..1a2890e0 100644 --- a/opa-builtins/opa-builtins-json/build.gradle.kts +++ b/opa-builtins/opa-builtins-json/build.gradle.kts @@ -18,6 +18,9 @@ dependencies { // RegoValueModule (auto-registered via Jackson SPI) provides (de)serializers for the AST // types so they don't need to carry annotations. runtimeOnly(project(":opa-jackson")) + + testImplementation("org.junit.jupiter:junit-jupiter:6.1.1") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.1.1") } java { @@ -25,3 +28,7 @@ java { languageVersion = JavaLanguageVersion.of(17) } } + +tasks.test { + useJUnitPlatform() +} diff --git a/opa-builtins/opa-builtins-json/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltins.java b/opa-builtins/opa-builtins-json/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltins.java index 2cc6a725..7b2da5c8 100644 --- a/opa-builtins/opa-builtins-json/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltins.java +++ b/opa-builtins/opa-builtins-json/src/main/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltins.java @@ -123,6 +123,7 @@ public Map> builti result.put("json.remove", instance::remove); result.put("json.unmarshal", instance::unmarshal); result.put("json.verify_schema", instance::verify_schema); + result.put("yaml.is_valid", instance::yamlIsValid); result.put("yaml.marshal", instance::yamlMarshal); result.put("yaml.unmarshal", instance::yamlUnmarshal); return result; @@ -706,6 +707,26 @@ public RegoString yamlMarshal(EvaluationContext ctx, RegoValue[] args) { } } + @OpaBuiltin( + name = "yaml.is_valid", + description = "Verifies the input string is a valid YAML document.", + categories = {"encoding"}, + args = {@OpaType(type = "string", name = "x", description = "a YAML string")}, + result = + @OpaType( + name = "result", + description = "`true` if `x` is valid YAML, `false` otherwise")) + public RegoBoolean yamlIsValid(EvaluationContext ctx, RegoValue[] args) { + String yamlInput = getArg(args, 0, RegoString.class).getValue(); + + try { + YAML_MAPPER.readTree(yamlInput); + return RegoBoolean.TRUE; + } catch (JsonProcessingException e) { + return RegoBoolean.FALSE; + } + } + @OpaBuiltin( name = "yaml.unmarshal", description = "Deserializes the input YAML string.", @@ -1071,4 +1092,4 @@ private JsonNode removeNodes(JsonNode node, Set paths) { return result; } -} \ No newline at end of file +} diff --git a/opa-builtins/opa-builtins-json/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltinsTest.java b/opa-builtins/opa-builtins-json/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltinsTest.java new file mode 100644 index 00000000..1bdc7cd9 --- /dev/null +++ b/opa-builtins/opa-builtins-json/src/test/java/io/github/open_policy_agent/opa/ast/builtin/impls/JsonBuiltinsTest.java @@ -0,0 +1,33 @@ +package io.github.open_policy_agent.opa.ast.builtin.impls; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import io.github.open_policy_agent.opa.ast.types.RegoBoolean; +import io.github.open_policy_agent.opa.ast.types.RegoString; +import io.github.open_policy_agent.opa.ast.types.RegoValue; +import org.junit.jupiter.api.Test; + +class JsonBuiltinsTest { + + private final JsonBuiltins builtins = new JsonBuiltins(); + + @Test + void registersYamlIsValidBuiltin() { + assertTrue(builtins.builtins().containsKey("yaml.is_valid")); + } + + @Test + void yamlIsValidReturnsTrueForValidYaml() { + RegoValue[] args = {new RegoString("name: opa\nvalues:\n - sdk\n - java\n")}; + + assertEquals(RegoBoolean.TRUE, builtins.yamlIsValid(null, args)); + } + + @Test + void yamlIsValidReturnsFalseForInvalidYaml() { + RegoValue[] args = {new RegoString("name: [unterminated")}; + + assertEquals(RegoBoolean.FALSE, builtins.yamlIsValid(null, args)); + } +}