use crate::client::DatalabClient;
use crate::error::{DatalabError, Result};
use crate::output::Progress;
use clap::{Args, Subcommand};
use serde_json::json;
use std::fs;
use std::path::PathBuf;
#[derive(Subcommand, Debug)]
pub enum WorkflowsCommand {
Create(CreateArgs),
List(ListArgs),
Get(GetArgs),
Execute(ExecuteArgs),
Execution(ExecutionArgs),
Delete(DeleteArgs),
StepTypes(StepTypesArgs),
}
#[derive(Args, Debug)]
pub struct CreateArgs {
#[arg(long, value_name = "NAME")]
pub name: String,
#[arg(long, value_name = "FILE")]
pub steps: PathBuf,
#[arg(long, value_name = "ID")]
pub team_id: Option<i64>,
#[arg(long, default_value = "60", value_name = "SECS")]
pub timeout: u64,
}
#[derive(Args, Debug)]
pub struct ListArgs {
#[arg(long, default_value = "60", value_name = "SECS")]
pub timeout: u64,
}
#[derive(Args, Debug)]
pub struct GetArgs {
#[arg(value_name = "WORKFLOW_ID")]
pub workflow_id: String,
#[arg(long, default_value = "60", value_name = "SECS")]
pub timeout: u64,
}
#[derive(Args, Debug)]
pub struct ExecuteArgs {
#[arg(value_name = "WORKFLOW_ID")]
pub workflow_id: String,
#[arg(long, value_name = "FILE")]
pub input: PathBuf,
#[arg(long, default_value = "300", value_name = "SECS")]
pub timeout: u64,
}
#[derive(Args, Debug)]
pub struct ExecutionArgs {
#[arg(value_name = "EXECUTION_ID")]
pub execution_id: String,
#[arg(long, default_value = "60", value_name = "SECS")]
pub timeout: u64,
}
#[derive(Args, Debug)]
pub struct DeleteArgs {
#[arg(value_name = "WORKFLOW_ID")]
pub workflow_id: String,
#[arg(long, default_value = "60", value_name = "SECS")]
pub timeout: u64,
}
#[derive(Args, Debug)]
pub struct StepTypesArgs {
#[arg(long, default_value = "60", value_name = "SECS")]
pub timeout: u64,
}
pub async fn execute(cmd: WorkflowsCommand, progress: &Progress) -> Result<()> {
match cmd {
WorkflowsCommand::Create(args) => create(args, progress).await,
WorkflowsCommand::List(args) => list(args, progress).await,
WorkflowsCommand::Get(args) => get(args, progress).await,
WorkflowsCommand::Execute(args) => execute_workflow(args, progress).await,
WorkflowsCommand::Execution(args) => execution(args, progress).await,
WorkflowsCommand::Delete(args) => delete(args, progress).await,
WorkflowsCommand::StepTypes(args) => step_types(args, progress).await,
}
}
async fn create(args: CreateArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
if !args.steps.exists() {
return Err(DatalabError::FileNotFound(args.steps.clone()));
}
progress.start("create-workflow", Some(&args.name));
let steps_content = fs::read_to_string(&args.steps)?;
let steps: serde_json::Value = serde_json::from_str(&steps_content)
.map_err(|e| DatalabError::InvalidInput(format!("Invalid JSON in steps file: {}", e)))?;
let mut body = json!({
"name": args.name,
"steps": steps,
});
if let Some(team_id) = args.team_id {
body["team_id"] = json!(team_id);
}
let response = client.post_json("workflows/workflows", &body).await?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}
async fn list(args: ListArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
progress.start("list-workflows", None);
let response = client.get("workflows/workflows").await?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}
async fn get(args: GetArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
progress.start("get-workflow", Some(&args.workflow_id));
let path = format!("workflows/workflows/{}", args.workflow_id);
let response = client.get(&path).await?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}
async fn execute_workflow(args: ExecuteArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
if !args.input.exists() {
return Err(DatalabError::FileNotFound(args.input.clone()));
}
progress.start("execute-workflow", Some(&args.workflow_id));
let input_content = fs::read_to_string(&args.input)?;
let input_config: serde_json::Value = serde_json::from_str(&input_content)
.map_err(|e| DatalabError::InvalidInput(format!("Invalid JSON in input file: {}", e)))?;
let body = json!({
"input_config": input_config,
});
let path = format!("workflows/workflows/{}/execute", args.workflow_id);
let response = client.post_json(&path, &body).await?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}
async fn execution(args: ExecutionArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
progress.start("get-execution", Some(&args.execution_id));
let path = format!("workflows/executions/{}", args.execution_id);
let response = client.get(&path).await?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}
async fn delete(args: DeleteArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
progress.start("delete-workflow", Some(&args.workflow_id));
let path = format!("workflows/workflows/{}", args.workflow_id);
client.delete(&path).await?;
println!(
"{}",
serde_json::to_string_pretty(&json!({
"deleted": true,
"workflow_id": args.workflow_id,
}))?
);
Ok(())
}
async fn step_types(args: StepTypesArgs, progress: &Progress) -> Result<()> {
let client = DatalabClient::new(Some(args.timeout))?;
progress.start("list-step-types", None);
let response = client.get("workflows/step-types").await?;
println!("{}", serde_json::to_string_pretty(&response)?);
Ok(())
}