icepick workflow: detach simulator from normal flow
This commit is contained in:
parent
57ab484995
commit
f09fb4dd59
|
@ -107,8 +107,9 @@ pub fn do_cli_thing() {
|
|||
workflows.push((module.name.clone(), module.workflows.clone()));
|
||||
}
|
||||
let workflows = workflows.leak();
|
||||
let mut workflow_command =
|
||||
clap::Command::new("workflow").about("Run a pre-defined Icepick workflow");
|
||||
let mut workflow_command = clap::Command::new("workflow")
|
||||
.about("Run a pre-defined Icepick workflow")
|
||||
.arg(clap::arg!(--"simulate-workflow").global(true));
|
||||
for module in workflows.iter() {
|
||||
let mut module_subcommand = clap::Command::new(module.0.as_str());
|
||||
for workflow in &module.1 {
|
||||
|
@ -124,12 +125,16 @@ pub fn do_cli_thing() {
|
|||
for command in commands.iter() {
|
||||
let mut subcommand = clap::Command::new(command.0.as_str());
|
||||
for op in &command.2 {
|
||||
let mut op_command = clap::Command::new(op.name.replace('_', "-")).about(&op.description);
|
||||
let mut op_command =
|
||||
clap::Command::new(op.name.replace('_', "-")).about(&op.description);
|
||||
for arg in &op.arguments {
|
||||
let mut op_arg = clap::Arg::new(arg.name.replace('_', "-")).help(arg.description.as_str());
|
||||
let mut op_arg =
|
||||
clap::Arg::new(arg.name.replace('_', "-")).help(arg.description.as_str());
|
||||
op_arg = match arg.r#type {
|
||||
ArgumentType::Required => op_arg.required(true),
|
||||
ArgumentType::Optional => op_arg.required(false).long(arg.name.replace('_', "-")),
|
||||
ArgumentType::Optional => {
|
||||
op_arg.required(false).long(arg.name.replace('_', "-"))
|
||||
}
|
||||
};
|
||||
op_command = op_command.arg(op_arg);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,44 @@ impl Workflow {
|
|||
map
|
||||
}
|
||||
|
||||
pub fn simulate_workflow(&self, mut data: HashSet<String>, operations: &[InvocableOperation]) {
|
||||
// simulate the steps by using a HashSet to traverse the inputs and outputs and ensure
|
||||
// there's no inconsistencies
|
||||
for (i, step) in self.steps.iter().enumerate() {
|
||||
// NOTE: overflow possible but unlikely
|
||||
let step_index = i + 1;
|
||||
|
||||
// Find the relevant Operation
|
||||
let Some(invocable) = operations.iter().find(|op| op.name == step.r#type) else {
|
||||
panic!("Could not find operation: {}", step.r#type);
|
||||
};
|
||||
|
||||
// Check if we have the keys we want to pass into the module.
|
||||
for in_memory_name in step.inputs.values() {
|
||||
if !data.contains(in_memory_name) && !step.values.contains_key(in_memory_name) {
|
||||
panic!("Failed simulation: step #{step_index}: missing value {in_memory_name}");
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the module accepts those keys.
|
||||
for module_input_name in step.inputs.keys() {
|
||||
if !invocable
|
||||
.operation
|
||||
.arguments
|
||||
.iter()
|
||||
.any(|arg| *module_input_name == arg.name)
|
||||
{
|
||||
eprintln!("Simulation: step #{step_index}: input value {module_input_name} will be passed through as JSON input");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the keys we get from the module.
|
||||
for in_memory_name in step.outputs.values() {
|
||||
data.insert(in_memory_name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle(&self, matches: &clap::ArgMatches, modules: Commands) {
|
||||
let inputs = self.load_inputs(matches);
|
||||
let data: HashMap<String, Value> = inputs
|
||||
|
@ -103,43 +141,11 @@ impl Workflow {
|
|||
}
|
||||
}
|
||||
|
||||
// simulate the steps by using a HashSet to traverse the inputs and outputs and ensure
|
||||
// there's no inconsistencies
|
||||
let mut simulated_values = data.keys().collect::<HashSet<_>>();
|
||||
for (i, step) in self.steps.iter().enumerate() {
|
||||
// NOTE: overflow possible but unlikely
|
||||
let step_index = i + 1;
|
||||
|
||||
// Find the relevant Operation
|
||||
let Some(invocable) = operations.iter().find(|op| op.name == step.r#type) else {
|
||||
panic!("Could not find operation: {}", step.r#type);
|
||||
};
|
||||
|
||||
// Check if we have the keys we want to pass into the module.
|
||||
for in_memory_name in step.inputs.values() {
|
||||
if !simulated_values.contains(in_memory_name)
|
||||
&& !step.values.contains_key(in_memory_name)
|
||||
{
|
||||
panic!("Failed simulation: step #{step_index}: missing value {in_memory_name}");
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the module accepts those keys.
|
||||
for module_input_name in step.inputs.keys() {
|
||||
if !invocable
|
||||
.operation
|
||||
.arguments
|
||||
.iter()
|
||||
.any(|arg| *module_input_name == arg.name)
|
||||
{
|
||||
eprintln!("Simulation: step #{step_index}: input value {module_input_name} will be passed through as JSON input");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the keys we get from the module.
|
||||
for in_memory_name in step.outputs.values() {
|
||||
simulated_values.insert(in_memory_name);
|
||||
}
|
||||
if matches.get_flag("simulate-workflow") {
|
||||
self.simulate_workflow(data.into_keys().collect(), &operations);
|
||||
return;
|
||||
}
|
||||
|
||||
todo!("Unsimulated transaction!");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue