feat: Update to OPA v1.2.0 (#373)

Regorus now defaults to rego v1. `import rego.v1` is no longer needed.
Additionally, `future` keywords are automatically imported.

See
https://www.openpolicyagent.org/docs/latest/v0-upgrade/#changes-to-rego-in-opa-v10
to understand the differences between rego v1 and v0.

BREAKING CHANGE:

v0 style policies will error out by default. To enable v0 behavior, call engine.set_rego_v0(true) before
loading policies.

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2025-03-10 11:56:01 -07:00
committed by GitHub
parent cbd772623a
commit c963e477a3
36 changed files with 244 additions and 91 deletions
+2
View File
@@ -27,6 +27,7 @@ struct YamlTest {
fn eval_test_case(dir: &Path, case: &TestCase) -> Result<Value> {
let mut engine = Engine::new();
engine.set_rego_v0(true);
engine.add_data(case.data.clone())?;
engine.set_input(case.input.clone());
@@ -116,6 +117,7 @@ fn run_aci_tests(dir: &Path) -> Result<()> {
#[cfg(feature = "coverage")]
fn run_aci_tests_coverage(dir: &Path) -> Result<()> {
let mut engine = Engine::new();
engine.set_rego_v0(true);
engine.set_enable_coverage(true);
let mut added = std::collections::BTreeSet::new();
+1
View File
@@ -45,6 +45,7 @@ fn yaml_test_impl(file: &str) -> Result<()> {
let mut engine = Engine::new();
engine.set_enable_coverage(true);
engine.set_rego_v0(true);
for (idx, rego) in case.modules.iter().enumerate() {
engine.add_policy(format!("rego_{idx}"), rego.clone())?;
+15 -5
View File
@@ -9,6 +9,16 @@ use anyhow::{bail, Result};
use clap::Parser;
use walkdir::WalkDir;
fn normalize_printed_paths(mut prints: Vec<String>) -> Vec<String> {
prints.iter_mut().for_each(|p| {
*p = p
.replace("\\", "/")
.replace("//", "/")
.replace("\r\n", "\n");
});
prints
}
fn run_kata_tests(
tests_dir: &Path,
name: &Option<String>,
@@ -43,6 +53,7 @@ fn run_kata_tests(
let prints_file = path.join("prints.json");
let mut engine = Engine::new();
engine.set_rego_v0(true);
engine.add_policy_from_file(&policy_file)?;
engine.set_gather_prints(true);
engine.set_strict_builtin_errors(false);
@@ -110,14 +121,14 @@ fn run_kata_tests(
if generate {
results.push(r);
prints.push(engine.take_prints()?);
prints.push(normalize_printed_paths(engine.take_prints()?));
} else {
let expected = results.pop().unwrap();
assert_eq!(r, expected, "{lineno} failed in {}", inputs_file.display());
let p = engine.take_prints()?;
assert_eq!(p, new_engine.take_prints()?);
assert_eq!(p, prints.pop().unwrap());
let p = normalize_printed_paths(engine.take_prints()?);
assert_eq!(p, normalize_printed_paths(new_engine.take_prints()?));
assert_eq!(p, normalize_printed_paths(prints.pop().unwrap()));
}
num_queries += 2;
@@ -179,7 +190,6 @@ fn stateful_policy_test() -> Result<()> {
let policy = String::from(
r#"
package example
import rego.v1
default allow := false
+10 -6
View File
@@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
use walkdir::WalkDir;
const OPA_REPO: &str = "https://github.com/open-policy-agent/opa";
const OPA_BRANCH: &str = "v0.70.0";
const OPA_BRANCH: &str = "v1.2.0";
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[serde(deny_unknown_fields)]
@@ -51,13 +51,13 @@ struct YamlTest {
cases: Vec<TestCase>,
}
fn eval_test_case(case: &TestCase, is_rego_v1_test: bool) -> Result<Value> {
fn eval_test_case(case: &TestCase, is_rego_v0_test: bool) -> Result<Value> {
let mut engine = Engine::new();
#[cfg(feature = "coverage")]
engine.set_enable_coverage(true);
engine.set_rego_v1(is_rego_v1_test);
engine.set_rego_v0(is_rego_v0_test);
if let Some(data) = &case.data {
engine.add_data(data.clone())?;
@@ -174,7 +174,7 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
continue;
}
let is_rego_v1_test = path_dir_str.starts_with("v1/") || path_dir.starts_with("v1\\");
let is_rego_v0_test = path_dir_str.starts_with("v0/") || path_dir.starts_with("v0\\");
let entry = status.entry(path_dir_str).or_insert((0, 0, 0));
let yaml_str = std::fs::read_to_string(&path_str)?;
@@ -219,7 +219,7 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
print!("{:4}: {:90}", entry.2, case.note);
entry.2 += 1;
match (eval_test_case(&case, is_rego_v1_test), &case.want_result) {
match (eval_test_case(&case, is_rego_v0_test), &case.want_result) {
(Ok(actual), Some(expected))
if is_json_schema_test && json_schema_tests_check(&actual, &expected) =>
{
@@ -294,6 +294,10 @@ fn run_opa_tests(opa_tests_dir: String, folders: &[String]) -> Result<()> {
}
}
if is_rego_v0_test {
cmd += " -v0";
}
std::fs::write(path.join(format!("query{n}.text")), case.query.as_bytes())?;
cmd += format!(" \"{}\"", &case.query).as_str();
@@ -394,7 +398,7 @@ fn main() -> Result<()> {
bail!("failed to clone OPA repository");
}
}
format!("{branch_dir}/test/cases/testdata")
format!("{branch_dir}/v1/test/cases/testdata")
}
};