smbcloud_cli/deploy/
config.rs

1use crate::{
2    deploy::setup::setup_project,
3    ui::{fail_message, fail_symbol, succeed_message, succeed_symbol},
4};
5use git2::{Cred, CredentialType, Error};
6use serde::{Deserialize, Serialize};
7use smbcloud_model::{account::User, project::Project};
8use smbcloud_networking::environment::Environment;
9use smbcloud_networking_project::get_project;
10use spinners::Spinner;
11use std::{fs, path::Path};
12use thiserror::Error;
13
14pub(crate) async fn check_config(env: Environment) -> Result<Config, ConfigError> {
15    let mut spinner: Spinner = Spinner::new(
16        spinners::Spinners::SimpleDotsScrolling,
17        succeed_message("Checking config"),
18    );
19
20    // Check .smb directory
21
22    // Get .smb/config.toml file path in the current directory
23    let config_path = Path::new(".smb/config.toml");
24    if !config_path.exists() {
25        spinner.stop_and_persist(&succeed_symbol(), succeed_message("Setting up deployment"));
26        setup_project(env).await?;
27        spinner = Spinner::new(
28            spinners::Spinners::SimpleDotsScrolling,
29            succeed_message("Checking config"),
30        );
31    }
32
33    // Parse toml file
34    let config_content = fs::read_to_string(config_path).map_err(|_| ConfigError::MissingConfig)?;
35
36    let config: Config = match toml::from_str(&config_content) {
37        Ok(value) => value,
38        Err(e) => {
39            println!("{}", e);
40            spinner.stop_and_persist(&fail_symbol(), fail_message("Config unsync."));
41            handle_config_error()?
42        }
43    };
44    spinner.stop_and_persist(
45        &succeed_symbol(),
46        succeed_message(&format!("Valid config for {}", config.name)),
47    );
48
49    Ok(config)
50}
51
52fn handle_config_error() -> Result<Config, ConfigError> {
53    todo!()
54}
55
56pub(crate) async fn check_project(env: Environment, id: i32) -> Result<(), ConfigError> {
57    let mut spinner: Spinner = Spinner::new(
58        spinners::Spinners::Hamburger,
59        succeed_message("Validate project"),
60    );
61    match get_project(env, id.to_string()).await {
62        Ok(_) => {
63            spinner.stop_and_persist(&succeed_symbol(), succeed_message("Valid project"));
64            Ok(())
65        }
66        Err(_) => {
67            spinner.stop_and_persist(&fail_symbol(), succeed_message("Project is unsynched"));
68            Err(ConfigError::ProjectNotFound)
69        }
70    }
71}
72
73#[derive(Deserialize, Serialize)]
74pub struct Config {
75    pub name: String,
76    pub description: Option<String>,
77    pub project: Project,
78}
79
80impl Config {
81    pub fn credentials(
82        &self,
83        user: User,
84    ) -> impl FnMut(&str, Option<&str>, CredentialType) -> Result<Cred, Error> + '_ {
85        move |_url, _username_from_url, _allowed_types| {
86            Cred::ssh_key("git", None, Path::new(&self.ssh_key_path(user.id)), None)
87        }
88    }
89
90    fn ssh_key_path(&self, user_id: i32) -> String {
91        // Use the dirs crate to get the home directory
92        let home = dirs::home_dir().expect("Could not determine home directory");
93        let key_path = home
94            .join(".ssh")
95            .join(format!("id_{}@smbcloud", user_id));
96        let key_path_str = key_path.to_string_lossy().to_string();
97        println!("Use key path: {}", key_path_str);
98        key_path_str
99    }
100}
101
102#[derive(Error, Debug, PartialEq, Eq)]
103pub enum ConfigError {
104    #[error("Missing config file. Please regenerate with 'smb init'.")]
105    MissingConfig,
106    #[error("Missing id in repository. Please regenerate with 'smb init'.")]
107    MissingId,
108    #[error("Could not find project in your list. Make sure you have access to the project.")]
109    ProjectNotFound,
110    #[error("Cancel operation.")]
111    Cancel,
112    #[error("Input error.")]
113    InputError,
114}