fluentci_common/
common.rs

1use std::{
2    fs::canonicalize,
3    path::Path,
4    sync::{mpsc::Receiver, Arc, Mutex},
5};
6
7use anyhow::Error;
8use fluentci_core::deps::{Graph, GraphCommand};
9use fluentci_ext::cache::Cache as CacheExt;
10use fluentci_ext::Extension;
11use fluentci_ext::{archive::tar::czvf::TarCzvf as TarCzvfExt, runner::Runner};
12use fluentci_ext::{archive::zip::Zip as ZipExt, pkgx::Pkgx as PkgxExt};
13use fluentci_secrets::Provider;
14use fluentci_types::{file::File, secret::Secret, service::Service, Output};
15use uuid::Uuid;
16
17pub fn with_exec(
18    graph: Arc<Mutex<Graph>>,
19    args: Vec<String>,
20    ext: Arc<Box<dyn Extension + Send + Sync>>,
21) -> Result<(), Error> {
22    let mut graph = graph.lock().unwrap();
23
24    let id = Uuid::new_v4().to_string();
25    let dep_id = graph.vertices[graph.size() - 1].id.clone();
26    let deps = match graph.size() {
27        1 => vec![],
28        _ => vec![dep_id],
29    };
30    graph.execute(GraphCommand::AddVertex(
31        id.clone(),
32        "exec".into(),
33        args.join(" "),
34        deps,
35        ext,
36    ))?;
37
38    if graph.size() > 2 {
39        let x = graph.size() - 2;
40        let y = graph.size() - 1;
41        graph.execute(GraphCommand::AddEdge(x, y))?;
42    }
43    Ok(())
44}
45
46pub fn with_workdir(
47    graph: Arc<Mutex<Graph>>,
48    path: String,
49    ext: Arc<Box<dyn Extension + Send + Sync>>,
50) -> Result<(), Error> {
51    let mut graph = graph.lock().unwrap();
52
53    if !Path::new(&path).exists() && !path.starts_with("/") {
54        let dir = canonicalize(".").unwrap();
55        let dir = dir.to_str().unwrap();
56        let dir = format!("{}/{}", dir, path);
57        return Err(Error::msg(format!("Path `{}` does not exist", dir)));
58    }
59
60    if !Path::new(&path).exists() {
61        return Err(Error::msg(format!("Path `{}` does not exist", path)));
62    }
63
64    let id = Uuid::new_v4().to_string();
65    let dep_id = graph.vertices[graph.size() - 1].id.clone();
66    let deps = match graph.size() {
67        1 => vec![],
68        _ => vec![dep_id],
69    };
70    graph.execute(GraphCommand::AddVertex(
71        id.clone(),
72        "withWorkdir".into(),
73        path,
74        deps,
75        ext,
76    ))?;
77
78    if graph.size() > 2 {
79        let x = graph.size() - 2;
80        let y = graph.size() - 1;
81        graph.execute(GraphCommand::AddEdge(x, y))?;
82    }
83
84    graph.execute_vertex(&id)?;
85
86    Ok(())
87}
88
89pub fn with_cache(graph: Arc<Mutex<Graph>>, cache_id: String, path: String) -> Result<(), Error> {
90    let mut graph = graph.lock().unwrap();
91    let runner = graph.runner.clone();
92    graph.runner = Arc::new(Box::new(CacheExt::default()));
93    graph.runner.setup()?;
94
95    if let Some(cache) = graph.volumes.iter().find(|v| v.id.clone() == cache_id) {
96        let id = Uuid::new_v4().to_string();
97        let dep_id = graph.vertices[graph.size() - 1].id.clone();
98        let deps = match graph.size() {
99            1 => vec![],
100            _ => vec![dep_id],
101        };
102        let cache_key_path = format!("{}:{}", cache.path, path);
103        graph.execute(GraphCommand::AddVertex(
104            id.clone(),
105            "withCache".into(),
106            cache_key_path,
107            deps,
108            Arc::new(Box::new(CacheExt::default())),
109        ))?;
110
111        let x = graph.size() - 2;
112        let y = graph.size() - 1;
113        graph.execute(GraphCommand::AddEdge(x, y))?;
114
115        graph.execute_vertex(&id)?;
116        graph.runner = runner;
117        return Ok(());
118    }
119
120    return Err(Error::msg("Cache not found"));
121}
122
123pub fn with_file(graph: Arc<Mutex<Graph>>, file_id: String, path: String) -> Result<(), Error> {
124    let mut graph = graph.lock().unwrap();
125    let runner = graph.runner.clone();
126    graph.runner = Arc::new(Box::new(Runner::default()));
127    graph.runner.setup()?;
128
129    if let Some(file) = graph.volumes.iter().find(|v| v.id.clone() == file_id) {
130        let id = Uuid::new_v4().to_string();
131        let dep_id = graph.vertices[graph.size() - 1].id.clone();
132        let deps = match graph.size() {
133            1 => vec![],
134            _ => vec![dep_id],
135        };
136        let copy_file = format!("cp {} {}", file.path, path);
137        graph.execute(GraphCommand::AddVertex(
138            id.clone(),
139            "withFile".into(),
140            copy_file,
141            deps,
142            Arc::new(Box::new(Runner::default())),
143        ))?;
144
145        let x = graph.size() - 2;
146        let y = graph.size() - 1;
147        graph.execute(GraphCommand::AddEdge(x, y))?;
148
149        graph.execute_vertex(&id)?;
150
151        graph.runner = runner;
152        return Ok(());
153    }
154
155    return Err(Error::msg("File not found"));
156}
157
158pub fn stdout(
159    graph: Arc<Mutex<Graph>>,
160    rx: Arc<Mutex<Receiver<(String, usize)>>>,
161) -> Result<String, Error> {
162    let mut graph = graph.lock().unwrap();
163    graph.execute(GraphCommand::Execute(Output::Stdout))?;
164    let rx = rx.lock().unwrap();
165    let (stdout, code) = rx.recv().unwrap();
166
167    if code != 0 {
168        return Err(Error::msg(format!(
169            "Failed to execute command `{}`",
170            stdout
171        )));
172    }
173    Ok(stdout)
174}
175
176pub fn stderr(
177    graph: Arc<Mutex<Graph>>,
178    rx: Arc<Mutex<Receiver<(String, usize)>>>,
179) -> Result<String, Error> {
180    let mut graph = graph.lock().unwrap();
181    graph.execute(GraphCommand::Execute(Output::Stderr))?;
182    let rx = rx.lock().unwrap();
183    let (stderr, code) = rx.recv().unwrap();
184
185    if code != 0 {
186        return Err(Error::msg(format!(
187            "Failed to execute command `{}`",
188            stderr
189        )));
190    }
191
192    Ok(stderr)
193}
194
195pub fn zip(graph: Arc<Mutex<Graph>>, path: String) -> Result<File, Error> {
196    let mut graph = graph.lock().unwrap();
197    graph.runner = Arc::new(Box::new(ZipExt::default()));
198    graph.runner.setup()?;
199
200    let id = Uuid::new_v4().to_string();
201    let dep_id = graph.vertices[graph.size() - 1].id.clone();
202
203    graph.execute(GraphCommand::AddVertex(
204        id.clone(),
205        "zip".into(),
206        path.clone(),
207        vec![dep_id],
208        Arc::new(Box::new(ZipExt::default())),
209    ))?;
210
211    let x = graph.size() - 2;
212    let y = graph.size() - 1;
213    graph.execute(GraphCommand::AddEdge(x, y))?;
214
215    graph.execute_vertex(&id)?;
216
217    let output_file = match path.split('/').last() {
218        Some(file) => format!("{}.zip", file),
219        None => format!("{}.zip", path),
220    };
221
222    let parent_dir = path.split('/').collect::<Vec<&str>>();
223    let parent_dir = parent_dir[..parent_dir.len() - 1].join("/");
224
225    let id = Uuid::new_v4().to_string();
226    let file = File {
227        id: id.clone(),
228        path: format!("{}/{}", parent_dir, output_file),
229    };
230
231    graph.execute(GraphCommand::AddVolume(
232        id,
233        "file".into(),
234        file.path.clone(),
235    ))?;
236
237    Ok(file)
238}
239
240pub fn tar_czvf(graph: Arc<Mutex<Graph>>, path: String) -> Result<File, Error> {
241    let mut graph = graph.lock().unwrap();
242    graph.runner = Arc::new(Box::new(TarCzvfExt::default()));
243    graph.runner.setup()?;
244
245    let id = Uuid::new_v4().to_string();
246    let dep_id = graph.vertices[graph.size() - 1].id.clone();
247
248    graph.execute(GraphCommand::AddVertex(
249        id.clone(),
250        "tar czvf".into(),
251        path.clone(),
252        vec![dep_id],
253        Arc::new(Box::new(TarCzvfExt::default())),
254    ))?;
255
256    let x = graph.size() - 2;
257    let y = graph.size() - 1;
258    graph.execute(GraphCommand::AddEdge(x, y))?;
259
260    graph.execute_vertex(&id)?;
261
262    let output_file = match path.split('/').last() {
263        Some(file) => format!("{}.tar.gz", file),
264        None => format!("{}.tar.gz", path),
265    };
266
267    let parent_dir = path.split('/').collect::<Vec<&str>>();
268    let parent_dir = parent_dir[..parent_dir.len() - 1].join("/");
269
270    let id = Uuid::new_v4().to_string();
271    let file = File {
272        id: id.clone(),
273        path: format!("{}/{}", parent_dir, output_file),
274    };
275
276    graph.execute(GraphCommand::AddVolume(
277        id,
278        "file".into(),
279        file.path.clone(),
280    ))?;
281
282    Ok(file)
283}
284
285pub fn as_service(graph: Arc<Mutex<Graph>>, name: String) -> Result<Service, Error> {
286    let mut graph = graph.lock().unwrap();
287    let runner = graph.runner.clone();
288    graph.runner = Arc::new(Box::new(Runner::default()));
289    graph.runner.setup()?;
290
291    let id = Uuid::new_v4().to_string();
292    let dep_id = graph.vertices[graph.size() - 1].id.clone();
293    let deps = match graph.size() {
294        1 => vec![],
295        _ => vec![dep_id],
296    };
297    graph.execute(GraphCommand::AddVertex(
298        id.clone(),
299        "asService".into(),
300        name,
301        deps,
302        Arc::new(Box::new(Runner::default())),
303    ))?;
304
305    if graph.size() > 2 {
306        let x = graph.size() - 2;
307        let y = graph.size() - 1;
308        graph.execute(GraphCommand::AddEdge(x, y))?;
309
310        graph.register_service(&id);
311    }
312
313    let service = Service { id: id.clone() };
314
315    graph.runner = runner;
316    Ok(service)
317}
318
319pub fn with_service(graph: Arc<Mutex<Graph>>, service_id: String) -> Result<(), Error> {
320    let mut graph = graph.lock().unwrap();
321    match graph.services.iter().find(|s| s.id == service_id) {
322        Some(_) => {
323            graph.execute(GraphCommand::EnableService(service_id.clone()))?;
324            Ok(())
325        }
326        None => Err(Error::msg("Service not found")),
327    }
328}
329
330pub fn with_env_variable(graph: Arc<Mutex<Graph>>, key: &str, value: &str) -> Result<(), Error> {
331    let mut graph = graph.lock().unwrap();
332    graph.execute(GraphCommand::AddEnvVariable(key.into(), value.into()))?;
333    Ok(())
334}
335
336pub fn wait_on(graph: Arc<Mutex<Graph>>, port: u32, timeout: Option<u32>) -> Result<(), Error> {
337    let mut graph = graph.lock().unwrap();
338    let runner = graph.runner.clone();
339    graph.runner = Arc::new(Box::new(PkgxExt::default()));
340    graph.runner.setup()?;
341
342    let id = Uuid::new_v4().to_string();
343    let dep_id = graph.vertices[graph.size() - 1].id.clone();
344    let deps = match graph.size() {
345        1 => vec![],
346        _ => vec![dep_id],
347    };
348    let cmd = format!(
349        "pkgx deno run -A npm:wait-port localhost:{} -t {}",
350        port,
351        timeout.unwrap_or(60) * 1000
352    );
353    graph.execute(GraphCommand::AddVertex(
354        id.clone(),
355        "waitOn".into(),
356        cmd,
357        deps,
358        Arc::new(Box::new(PkgxExt::default())),
359    ))?;
360
361    if graph.size() > 2 {
362        let x = graph.size() - 2;
363        let y = graph.size() - 1;
364        graph.execute(GraphCommand::AddEdge(x, y))?;
365    }
366
367    graph.runner = runner;
368    return Ok(());
369}
370
371pub fn add_secretmanager(graph: Arc<Mutex<Graph>>, provider: Provider) -> Result<String, Error> {
372    let mut graph = graph.lock().unwrap();
373    let id = Uuid::new_v4().to_string();
374    graph.execute(GraphCommand::AddSecretManager(id.clone(), provider))?;
375    Ok(id)
376}
377
378pub fn get_secret(
379    graph: Arc<Mutex<Graph>>,
380    secret_manager_id: &str,
381    name: &str,
382) -> Result<Vec<Secret>, Error> {
383    let mut graph = graph.lock().unwrap();
384    let secret = graph.get_secret(secret_manager_id, name.to_string())?;
385    Ok(secret)
386}
387
388pub fn with_secret_variable(
389    graph: Arc<Mutex<Graph>>,
390    env_name: &str,
391    secret_id: &str,
392    secret_name: &str,
393) -> Result<(), Error> {
394    let mut graph = graph.lock().unwrap();
395    graph.execute(GraphCommand::AddSecretVariable(
396        env_name.into(),
397        secret_id.into(),
398        secret_name.into(),
399    ))?;
400    Ok(())
401}
402
403pub fn set_secret(graph: Arc<Mutex<Graph>>, name: &str, value: &str) -> Result<String, Error> {
404    let mut graph = graph.lock().unwrap();
405    let id = graph.set_secret(name.into(), value.into())?;
406    Ok(id)
407}
408
409pub fn get_secret_plaintext(
410    graph: Arc<Mutex<Graph>>,
411    secret_id: &str,
412    name: &str,
413) -> Result<String, Error> {
414    let graph = graph.lock().unwrap();
415    let secret = graph.get_secret_plaintext(secret_id.into(), name.into())?;
416    Ok(secret)
417}