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
26#[derive(Clone)]
27pub struct DatabricksCli {
28 profile: Option<String>,
29}
30
31impl DatabricksCli {
32 pub fn new(profile: Option<String>) -> Self {
33 Self { profile }
34 }
35
36 pub async fn run(&self, args: &[&str]) -> Result<Value> {
37 let mut cmd = Command::new("databricks");
38 cmd.current_dir("/");
43 cmd.arg("--output").arg("json");
44 if let Some(p) = &self.profile {
45 cmd.arg("--profile").arg(p);
46 }
47 cmd.args(args);
48
49 let out = cmd
50 .output()
51 .await
52 .context("failed to run databricks CLI — is it installed?")?;
53
54 if !out.status.success() {
55 let stderr = String::from_utf8_lossy(&out.stderr);
56 anyhow::bail!("databricks CLI error: {}", stderr.trim());
57 }
58
59 let stdout = String::from_utf8_lossy(&out.stdout);
60 serde_json::from_str(&stdout).context("failed to parse CLI JSON output")
61 }
62
63 pub async fn run_raw(&self, args: &[&str]) -> Result<String> {
66 let mut cmd = Command::new("databricks");
67 cmd.current_dir("/");
68 if let Some(p) = &self.profile {
69 cmd.arg("--profile").arg(p);
70 }
71 cmd.args(args);
72
73 let out = cmd
74 .output()
75 .await
76 .context("failed to run databricks CLI — is it installed?")?;
77
78 if !out.status.success() {
79 let stderr = String::from_utf8_lossy(&out.stderr);
80 anyhow::bail!("databricks CLI error: {}", stderr.trim());
81 }
82 Ok(String::from_utf8_lossy(&out.stdout).to_string())
83 }
84
85 pub async fn run_action(&self, args: &[&str]) -> Result<()> {
88 let mut cmd = Command::new("databricks");
89 cmd.current_dir("/");
90 if let Some(p) = &self.profile {
91 cmd.arg("--profile").arg(p);
92 }
93 cmd.args(args);
94
95 let out = cmd
96 .output()
97 .await
98 .context("failed to run databricks CLI — is it installed?")?;
99
100 if !out.status.success() {
101 let stderr = String::from_utf8_lossy(&out.stderr);
102 anyhow::bail!("databricks CLI error: {}", stderr.trim());
103 }
104 Ok(())
105 }
106}