1use anyhow::{Context, Result};
2use serde_json::Value;
3use tokio::process::Command;
4
5pub fn list_profiles() -> Vec<String> {
7 let Some(home) = std::env::var_os("HOME") else {
8 return Vec::new();
9 };
10 let path = std::path::Path::new(&home).join(".databrickscfg");
11 let Ok(content) = std::fs::read_to_string(path) else {
12 return Vec::new();
13 };
14 content
15 .lines()
16 .filter_map(|line| {
17 let line = line.trim();
18 line.strip_prefix('[')
19 .and_then(|rest| rest.strip_suffix(']'))
20 .map(str::to_string)
21 })
22 .filter(|name| !name.starts_with("__"))
23 .collect()
24}
25
26pub struct DatabricksCli {
27 profile: Option<String>,
28}
29
30impl DatabricksCli {
31 pub fn new(profile: Option<String>) -> Self {
32 Self { profile }
33 }
34
35 pub async fn run(&self, args: &[&str]) -> Result<Value> {
36 let mut cmd = Command::new("databricks");
37 cmd.current_dir("/");
42 cmd.arg("--output").arg("json");
43 if let Some(p) = &self.profile {
44 cmd.arg("--profile").arg(p);
45 }
46 cmd.args(args);
47
48 let out = cmd
49 .output()
50 .await
51 .context("failed to run databricks CLI — is it installed?")?;
52
53 if !out.status.success() {
54 let stderr = String::from_utf8_lossy(&out.stderr);
55 anyhow::bail!("databricks CLI error: {}", stderr.trim());
56 }
57
58 let stdout = String::from_utf8_lossy(&out.stdout);
59 serde_json::from_str(&stdout).context("failed to parse CLI JSON output")
60 }
61
62 pub async fn run_raw(&self, args: &[&str]) -> Result<String> {
65 let mut cmd = Command::new("databricks");
66 cmd.current_dir("/");
67 if let Some(p) = &self.profile {
68 cmd.arg("--profile").arg(p);
69 }
70 cmd.args(args);
71
72 let out = cmd
73 .output()
74 .await
75 .context("failed to run databricks CLI — is it installed?")?;
76
77 if !out.status.success() {
78 let stderr = String::from_utf8_lossy(&out.stderr);
79 anyhow::bail!("databricks CLI error: {}", stderr.trim());
80 }
81 Ok(String::from_utf8_lossy(&out.stdout).to_string())
82 }
83
84 pub async fn run_action(&self, args: &[&str]) -> Result<()> {
87 let mut cmd = Command::new("databricks");
88 cmd.current_dir("/");
89 if let Some(p) = &self.profile {
90 cmd.arg("--profile").arg(p);
91 }
92 cmd.args(args);
93
94 let out = cmd
95 .output()
96 .await
97 .context("failed to run databricks CLI — is it installed?")?;
98
99 if !out.status.success() {
100 let stderr = String::from_utf8_lossy(&out.stderr);
101 anyhow::bail!("databricks CLI error: {}", stderr.trim());
102 }
103 Ok(())
104 }
105}