Skip to content

Commit

Permalink
refactor, temporary regression in features, run and auth work
Browse files Browse the repository at this point in the history
  • Loading branch information
tiptenbrink committed Dec 15, 2023
1 parent 28c535b commit e121f4d
Show file tree
Hide file tree
Showing 12 changed files with 676 additions and 270 deletions.
82 changes: 82 additions & 0 deletions src/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use crate::commands::{DEFAULT, TIDPLOY_DEFAULT};
use crate::secret_store::{get_password, set_password};

use crate::state::State;

use keyring::Error as KeyringError;

use rpassword::prompt_password;

use std::io::Error as IOError;

use thiserror::Error as ThisError;

#[derive(ThisError, Debug)]
#[error("{msg} {source}")]
pub(crate) struct AuthError {
pub(crate) msg: String,
pub(crate) source: AuthErrorKind,
}

#[derive(ThisError, Debug)]
pub(crate) enum AuthErrorKind {
#[error("Failed to get password from prompt! {0}")]
Prompt(#[from] IOError),
#[error("No password saved.")]
NoPassword,
#[error("Internal keyring failure. {0}")]
Keyring(#[from] KeyringError),
}

pub(crate) fn auth_command(state: &State, key: String) -> Result<(), AuthError> {
let password = prompt_password("Enter password:\n").map_err(|e| AuthError {
msg: "Failed to create password prompt!".to_owned(),
source: e.into(),
})?;
let path_str = state.deploy_path.as_str().replace('/', "\\\\");
let store_key: String = format!(
"{}:{}/{}/{}",
key, state.repo.name, path_str, state.commit_sha
);
println!("{}", key);
set_password(&password, &store_key).map_err(|e| {
let msg = format!(
"Could not set password in auth command with store_key {}!",
store_key
);
AuthError {
msg,
source: e.into(),
}
})?;
Ok(println!("Set password with store_key {}!", &store_key))
}

pub(crate) fn auth_get_password(state: &State, key: &str) -> Result<String, AuthErrorKind> {
let path_str = state.deploy_path.as_str().replace('/', "\\\\");
let store_key: String = format!(
"{}:{}/{}/{}",
key, state.repo.name, path_str, state.commit_sha
);
if let Some(password) = get_password(&store_key)? {
return Ok(password);
}
let store_key_default_commit = format!(
"{}:{}/{}/{}",
key, state.repo.name, path_str, TIDPLOY_DEFAULT
);
if let Some(password) = get_password(&store_key_default_commit)? {
return Ok(password);
}

let store_key_default_commit_deploy =
format!("{}:{}/{}/{}", key, state.repo.name, "", TIDPLOY_DEFAULT);
if let Some(password) = get_password(&store_key_default_commit_deploy)? {
return Ok(password);
}
let store_key_default = format!("{}:{}/{}/{}", key, DEFAULT, "", TIDPLOY_DEFAULT);
match get_password(&store_key_default)? {
Some(password) => Ok(password),
None => Err(AuthErrorKind::NoPassword),
}
}
117 changes: 62 additions & 55 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
use crate::auth::{auth_command, AuthError};
use crate::errors::ProcessError;
use crate::process::run_entrypoint;

use crate::config::{load_dploy_config, DployConfig, traverse_configs, ConfigError};
use crate::errors::{GitError, ProcessError, RelPathError};
use crate::filesystem::{FileError, get_current_dir};
use crate::git::{git_root_origin_url, relative_to_git_root};
use crate::secret_store::{get_password, set_password};
use crate::secrets::SecretOutput;
use crate::state::{StateContext, LoadError};
use clap::{Parser, Subcommand, ValueEnum};
use keyring::Error as KeyringError;
use rpassword::prompt_password;
use spinoff::{spinners, Spinner};
use std::env::VarError;
use std::ffi::OsString;
use std::fs::{self};
use std::path::PathBuf;
use std::process::Output;
use std::{
collections::HashMap,
env,
io::BufRead,
io::BufReader,
io::Error as IOError,
path::Path,
process::{Command as Cmd, Stdio},
};
use crate::state::{create_state_pre, create_state_run, CliEnvState, LoadError, StateContext};
use clap::{Parser, Subcommand};

// use std::time::Instant;
use thiserror::Error as ThisError;
use relative_path::RelativePathBuf;

pub(crate) const DEFAULT_INFER: &str = "default_infer";
pub(crate) const TIDPLOY_DEFAULT: &str = "_tidploy_default";
Expand All @@ -37,31 +18,29 @@ struct Cli {
#[command(subcommand)]
command: Commands,

#[arg(long, value_enum)]
#[arg(long, value_enum, global = true)]
context: Option<StateContext>,

#[arg(long)]
no_network: Option<bool>,
#[arg(long, global = true)]
network: Option<bool>,

#[arg(short, long)]
/// Set the repository URL, defaults to 'default_infer', in which case it is inferred from the current repository. Set to 'default' to not set it.
/// Falls back to environment variable using TIDPLOY_REPO and then to config with key 'repo_url'
/// For infering, it looks at the URL set to the 'origin' remote
#[arg(short, long, global = true)]
repo: Option<String>,

#[arg(short, long)]
#[arg(short, long, global = true)]
tag: Option<String>,

#[arg(short, long)]
#[arg(short, long, global = true)]
deploy_pth: Option<String>,


}

#[derive(Subcommand, Debug)]
enum Commands {
/// Save authentication details for specific stage until reboot
Auth {
key: String
},

Auth { key: String },
// /// Download tag or version with specific env, run automatically if using deploy
// Download,

Expand All @@ -73,16 +52,14 @@ enum Commands {
// #[arg(short)]
// variables: Vec<String>
// },
/// Run an entrypoint using the password set for a specific repo and stage 'deploy', can be used after download
Run {
#[arg(short = 'x', long = "exe", default_value = "_tidploy_default")]
executable: String,


// /// Run an entrypoint using the password set for a specific repo and stage 'deploy', can be used after download
// Run {
// #[arg(long = "exe", default_value = "_tidploy_default")]
// executable: String,

// #[arg(short)]
// variables: Vec<String>
// },
#[arg(short, num_args = 2)]
variables: Vec<String>,
},
}

#[derive(ThisError, Debug)]
Expand All @@ -92,19 +69,49 @@ pub struct Error(#[from] ErrorRepr);
#[derive(ThisError, Debug)]
enum ErrorRepr {
#[error("Load error failure! {0}")]
Load(#[from] LoadError)
Load(#[from] LoadError),
#[error("Auth failure! {0}")]
Auth(#[from] AuthError),
#[error("Error unning executable! {0}")]
Exe(#[from] ProcessError),
}





pub(crate) fn run_cli() -> Result<(), Error> {
//let now = Instant::now();

let args = Cli::parse();

let state = create_state(args.context, args.use_network, args.repo, args.tag, args.deploy_pth);
//println!("{:?}", args);

let cli_state = CliEnvState {
context: args.context,
network: args.network,
repo_url: args.repo,
deploy_path: args.deploy_pth,
tag: args.tag,
};

match args.command {
Commands::Auth { key } => Ok(),
Commands::Auth { key } => {
let state = create_state_pre(cli_state).map_err(ErrorRepr::Load)?;
//println!("{:?}", state);
//println!("time {}", now.elapsed().as_secs_f64());

Ok(auth_command(&state, key).map_err(ErrorRepr::Auth)?)
}
Commands::Run {
executable,
variables,
} => {
let state = create_state_run(cli_state, Some(executable), variables, false)
.map_err(ErrorRepr::Load)?;
//println!("{:?}", state);
//println!("time {}", now.elapsed().as_secs_f64());

run_entrypoint(state.current_dir, &state.exe_name, state.envs)
.map_err(ErrorRepr::Exe)?;

Ok(())
}
}
}
}
Loading

0 comments on commit e121f4d

Please sign in to comment.