newton_cli/commands/
regorus.rs1use anyhow::{anyhow, bail, Result};
7use clap::{Parser, Subcommand};
8
9#[derive(Debug, Parser)]
11pub struct RegorusCommand {
12 #[command(subcommand)]
13 pub subcommand: RegorusSubcommand,
14}
15
16#[derive(Debug, Subcommand)]
18pub enum RegorusSubcommand {
19 Eval {
21 #[arg(long, short, value_name = "bundle")]
23 bundles: Vec<String>,
24
25 #[arg(long, short, value_name = "policy.rego|data.json|data.yaml")]
27 data: Vec<String>,
28
29 #[arg(long, short, value_name = "input.json")]
31 input: Option<String>,
32
33 query: String,
35
36 #[arg(long, short)]
38 trace: bool,
39
40 #[arg(long, short)]
42 non_strict: bool,
43
44 #[arg(long, short)]
46 coverage: bool,
47 },
48
49 Lex {
51 file: String,
53
54 #[arg(long, short)]
56 verbose: bool,
57 },
58
59 Parse {
61 file: String,
63 },
64
65 Ast {
67 file: String,
69 },
70}
71
72impl RegorusCommand {
73 pub fn execute(self) -> Result<()> {
75 match self.subcommand {
76 RegorusSubcommand::Eval {
77 bundles,
78 data,
79 input,
80 query,
81 trace,
82 non_strict,
83 coverage,
84 } => rego_eval(&bundles, &data, input, query, trace, non_strict, coverage),
85 RegorusSubcommand::Lex { file, verbose } => rego_lex(file, verbose),
86 RegorusSubcommand::Parse { file } => rego_parse(file),
87 RegorusSubcommand::Ast { file } => rego_ast(file),
88 }
89 }
90}
91
92fn rego_eval(
93 bundles: &[String],
94 files: &[String],
95 input: Option<String>,
96 query: String,
97 enable_tracing: bool,
98 non_strict: bool,
99 coverage: bool,
100) -> Result<()> {
101 let mut engine = regorus::Engine::new();
102
103 engine.with_newton_crypto_extensions()?;
105
106 engine.set_strict_builtin_errors(!non_strict);
107 engine.set_enable_coverage(coverage);
108
109 for dir in bundles.iter() {
111 let entries = std::fs::read_dir(dir).map_err(|e| anyhow!("failed to read bundle {dir}.\n{e}"))?;
112 for entry in entries {
113 let entry = entry.map_err(|e| anyhow!("failed to unwrap entry. {e}"))?;
114 let path = entry.path();
115
116 match (path.is_file(), path.extension()) {
117 (true, Some(ext)) if ext == "rego" => {}
118 _ => continue,
119 }
120
121 engine.add_policy_from_file(entry.path().display().to_string())?;
122 }
123 }
124
125 for file in files.iter() {
127 if file.ends_with(".rego") {
128 engine.add_policy_from_file(file.clone())?;
129 } else {
130 let data = if file.ends_with(".json") {
131 regorus::Value::from_json_file(file)?
132 } else if file.ends_with(".yaml") {
133 regorus::Value::from_yaml_file(file)?
134 } else {
135 bail!("Unsupported data file `{file}`. Must be rego, json or yaml.");
136 };
137 engine.add_data(data)?;
138 }
139 }
140
141 if let Some(file) = input {
142 let input = if file.ends_with(".json") {
143 regorus::Value::from_json_file(&file)?
144 } else if file.ends_with(".yaml") {
145 regorus::Value::from_yaml_file(&file)?
146 } else {
147 bail!("Unsupported input file `{file}`. Must be json or yaml.")
148 };
149 engine.set_input(input);
150 }
151
152 let results = engine.eval_query(query, enable_tracing)?;
153
154 println!("{}", serde_json::to_string_pretty(&results)?);
155
156 if coverage {
157 let report = engine.get_coverage_report()?;
158 println!("{}", report.to_string_pretty()?);
159 }
160
161 Ok(())
162}
163
164fn rego_lex(file: String, verbose: bool) -> Result<()> {
165 use regorus::unstable::*;
166
167 let source = Source::from_file(file)?;
168 let mut lexer = Lexer::new(&source);
169
170 loop {
171 let token = lexer.next_token()?;
172 if token.0 == TokenKind::Eof {
173 break;
174 }
175
176 if verbose {
177 println!("{}", token.1.message("", ""));
178 }
179
180 println!("{token:?}");
181 }
182 Ok(())
183}
184
185fn rego_parse(file: String) -> Result<()> {
186 use regorus::unstable::*;
187
188 let source = Source::from_file(file)?;
189 let mut parser = Parser::new(&source)?;
190 parser.enable_rego_v1()?;
191
192 let ast = parser.parse()?;
193 println!("{ast:#?}");
194
195 Ok(())
196}
197
198fn rego_ast(file: String) -> Result<()> {
199 let mut engine = regorus::Engine::new();
200 engine.add_policy_from_file(file)?;
201
202 let ast = engine.get_ast_as_json()?;
203 println!("{ast}");
204 Ok(())
205}