Skip to content

Commit

Permalink
Provide a way to obtain package names of loaded policies (#239)
Browse files Browse the repository at this point in the history
Engine::
- add_policy and add_policy_from_file return the package name.
- get_packages returns the names of loaded packages.

closes #229

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
  • Loading branch information
anakrish authored May 18, 2024
1 parent 67f65c0 commit 56bd884
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
6 changes: 3 additions & 3 deletions examples/regorus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn read_value_from_json_file(path: &String) -> Result<regorus::Value> {
regorus::Value::from_json_str(&read_file(path)?)
}

fn add_policy_from_file(engine: &mut regorus::Engine, path: String) -> Result<()> {
fn add_policy_from_file(engine: &mut regorus::Engine, path: String) -> Result<String> {
#[cfg(feature = "std")]
return engine.add_policy_from_file(path);

Expand Down Expand Up @@ -65,15 +65,15 @@ fn rego_eval(
_ => continue,
}

add_policy_from_file(&mut engine, entry.path().display().to_string())?;
let _package = add_policy_from_file(&mut engine, entry.path().display().to_string())?;
}
}

// Load given files.
for file in files.iter() {
if file.ends_with(".rego") {
// Read policy file.
add_policy_from_file(&mut engine, file.clone())?;
let _package = add_policy_from_file(&mut engine, file.clone())?;
} else {
// Read data file.
let data = if file.ends_with(".json") {
Expand Down
48 changes: 40 additions & 8 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl Engine {
///
/// The policy file will be parsed and converted to AST representation.
/// Multiple policy files may be added to the engine.
/// Returns the Rego package name declared in the policy.
///
/// * `path`: A filename to be associated with the policy.
/// * `rego`: The rego policy code.
Expand All @@ -52,29 +53,33 @@ impl Engine {
/// # fn main() -> anyhow::Result<()> {
/// let mut engine = Engine::new();
///
/// engine.add_policy(
/// let package = engine.add_policy(
/// "test.rego".to_string(),
/// r#"
/// package test
/// allow = input.user == "root"
/// "#.to_string())?;
///
/// assert_eq!(package, "data.test");
/// # Ok(())
/// # }
/// ```
///
pub fn add_policy(&mut self, path: String, rego: String) -> Result<()> {
pub fn add_policy(&mut self, path: String, rego: String) -> Result<String> {
let source = Source::from_contents(path, rego)?;
let mut parser = Parser::new(&source)?;
self.modules.push(Ref::new(parser.parse()?));
let module = Ref::new(parser.parse()?);
self.modules.push(module.clone());
// if policies change, interpreter needs to be prepared again
self.prepared = false;
Ok(())
Interpreter::get_path_string(&module.package.refr, Some("data"))
}

/// Add a policy from a given file.
///
/// The policy file will be parsed and converted to AST representation.
/// Multiple policy files may be added to the engine.
/// Returns the Rego package name declared in the policy.
///
/// * `path`: Path to the policy file (.rego).
///
Expand All @@ -83,17 +88,44 @@ impl Engine {
/// # fn main() -> anyhow::Result<()> {
/// let mut engine = Engine::new();
///
/// engine.add_policy_from_file("tests/aci/framework.rego")?;
/// let package = engine.add_policy_from_file("tests/aci/framework.rego")?;
///
/// assert_eq!(package, "data.framework");
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "std")]
pub fn add_policy_from_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<()> {
pub fn add_policy_from_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> Result<String> {
let source = Source::from_file(path)?;
let mut parser = Parser::new(&source)?;
self.modules.push(Ref::new(parser.parse()?));
let module = Ref::new(parser.parse()?);
self.modules.push(module.clone());
// if policies change, interpreter needs to be prepared again
self.prepared = false;
Ok(())
Interpreter::get_path_string(&module.package.refr, Some("data"))
}

/// Get the list of packages defined by loaded policies.
///
/// ```
/// # use regorus::*;
/// # fn main() -> anyhow::Result<()> {
/// let mut engine = Engine::new();
///
/// let _ = engine.add_policy_from_file("tests/aci/framework.rego")?;
///
/// // Package names can be different from file names.
/// let _ = engine.add_policy("policy.rego".into(), "package hello.world".into())?;
///
/// assert_eq!(engine.get_packages()?, vec!["data.framework", "data.hello.world"]);
/// # Ok(())
/// # }
/// ```
pub fn get_packages(&self) -> Result<Vec<String>> {
self.modules
.iter()
.map(|m| Interpreter::get_path_string(&m.package.refr, Some("data")))
.collect()
}

/// Set the input document.
Expand Down

0 comments on commit 56bd884

Please sign in to comment.