#![allow(clippy::unwrap_used)]
use std::collections::VecDeque;
use std::path::Path;
use std::sync::Mutex;
use async_trait::async_trait;
use serde_json::{Value, json};
use crate::error::ProjectsError;
use crate::stripe::{CommandOutput, CommandRunner};
#[derive(Debug, Default)]
pub struct ScriptedRunner {
outputs: Mutex<VecDeque<CommandOutput>>,
calls: Mutex<Vec<Vec<String>>>,
}
impl ScriptedRunner {
pub fn new(outputs: Vec<CommandOutput>) -> Self {
Self {
outputs: Mutex::new(outputs.into()),
calls: Mutex::new(Vec::new()),
}
}
pub fn calls(&self) -> Vec<Vec<String>> {
self.calls.lock().unwrap().clone()
}
}
#[async_trait]
impl CommandRunner for ScriptedRunner {
async fn run(&self, args: &[String], _cwd: &Path) -> Result<CommandOutput, ProjectsError> {
self.calls.lock().unwrap().push(args.to_vec());
self.outputs
.lock()
.unwrap()
.pop_front()
.ok_or_else(|| ProjectsError::Unavailable {
detail: format!("ScriptedRunner exhausted at call {args:?}"),
})
}
}
pub fn ok(data: Value) -> CommandOutput {
CommandOutput {
status: 0,
stdout: json!({ "ok": true, "data": data }).to_string(),
stderr: String::new(),
}
}
pub fn ok_empty() -> CommandOutput {
ok(json!({}))
}
pub fn status(project_id: Option<&str>) -> CommandOutput {
match project_id {
Some(id) => ok(json!({ "project": { "id": id } })),
None => ok(json!({})),
}
}
pub fn services(names: &[&str]) -> CommandOutput {
let list: Vec<Value> = names.iter().map(|n| json!({ "name": n })).collect();
ok(json!({ "services": list }))
}
pub fn env_list(names: &[&str]) -> CommandOutput {
let list: Vec<Value> = names.iter().map(|n| json!({ "name": n })).collect();
ok(json!({ "environments": list }))
}
pub fn raw(stdout: &str) -> CommandOutput {
CommandOutput {
status: 0,
stdout: stdout.to_owned(),
stderr: String::new(),
}
}
pub fn parent_plan_steps() -> Vec<CommandOutput> {
vec![services(&[]), ok(json!({})), ok_empty()]
}
pub fn provision_script(
catalog_envelope: &str,
add_variables: Value,
parent_plans: usize,
) -> ScriptedRunner {
let mut steps = vec![
raw(catalog_envelope), status(Some("project_1")), env_list(&["demo"]), ok_empty(), ];
for _ in 0..parent_plans {
steps.extend(parent_plan_steps());
}
steps.extend([
services(&[]), ok(json!({ "variables": add_variables })), ok_empty(), ok_empty(), ]);
ScriptedRunner::new(steps)
}