Skip to main content

greentic_operator/
runner_integration.rs

1use std::path::Path;
2use std::process::Command;
3
4use serde_json::Value;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum RunnerFlavor {
8    RunSubcommand,
9    RunnerCli,
10}
11
12pub struct RunFlowOptions<'a> {
13    pub dist_offline: bool,
14    pub tenant: Option<&'a str>,
15    pub team: Option<&'a str>,
16    pub artifacts_dir: Option<&'a Path>,
17    pub runner_flavor: RunnerFlavor,
18}
19
20pub struct RunnerOutput {
21    pub status: std::process::ExitStatus,
22    pub stdout: String,
23    pub stderr: String,
24    pub parsed: Option<Value>,
25}
26
27pub fn run_flow(
28    runner: &Path,
29    pack: &Path,
30    flow: &str,
31    input: &Value,
32) -> anyhow::Result<RunnerOutput> {
33    run_flow_with_options(
34        runner,
35        pack,
36        flow,
37        input,
38        RunFlowOptions {
39            dist_offline: false,
40            tenant: None,
41            team: None,
42            artifacts_dir: None,
43            runner_flavor: RunnerFlavor::RunSubcommand,
44        },
45    )
46}
47
48pub fn run_flow_with_options(
49    runner: &Path,
50    pack: &Path,
51    flow: &str,
52    input: &Value,
53    options: RunFlowOptions<'_>,
54) -> anyhow::Result<RunnerOutput> {
55    let input_str = serde_json::to_string(input)?;
56    let mut command = Command::new(runner);
57    match options.runner_flavor {
58        RunnerFlavor::RunSubcommand => {
59            command
60                .args(["run", "--pack"])
61                .arg(pack)
62                .args(["--flow", flow, "--input"])
63                .arg(&input_str);
64            if options.dist_offline {
65                command.arg("--offline");
66            }
67        }
68        RunnerFlavor::RunnerCli => {
69            command
70                .arg("--pack")
71                .arg(pack)
72                .args(["--flow", flow, "--input"])
73                .arg(&input_str);
74            if let Some(tenant) = options.tenant {
75                command.args(["--tenant", tenant]);
76            }
77            if let Some(team) = options.team {
78                command.args(["--team", team]);
79            }
80            if let Some(artifacts_dir) = options.artifacts_dir {
81                command.arg("--artifacts-dir").arg(artifacts_dir);
82            }
83            if options.dist_offline {
84                command.arg("--offline");
85            }
86        }
87    }
88    let output = command.output()?;
89
90    let stdout = String::from_utf8_lossy(&output.stdout).to_string();
91    let stderr = String::from_utf8_lossy(&output.stderr).to_string();
92    let parsed = serde_json::from_str(&stdout).ok();
93
94    Ok(RunnerOutput {
95        status: output.status,
96        stdout,
97        stderr,
98        parsed,
99    })
100}
101
102pub fn detect_runner_flavor(runner: &Path) -> RunnerFlavor {
103    let name = runner
104        .file_name()
105        .and_then(|value| value.to_str())
106        .unwrap_or_default();
107    if name.contains("runner-cli") {
108        RunnerFlavor::RunnerCli
109    } else {
110        RunnerFlavor::RunSubcommand
111    }
112}