Skip to content

Commit

Permalink
Use anyhow, use docstrings for modules (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
vrmiguel committed Nov 30, 2023
1 parent 1a3ef4e commit 1c57b14
Show file tree
Hide file tree
Showing 30 changed files with 167 additions and 249 deletions.
28 changes: 15 additions & 13 deletions src/cli/auth_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ extern crate rpassword;

use crate::cli::cloud_account::CloudAccount;
use crate::cli::config::Config;
use crate::Result;
use anyhow::{bail, Context};
use chrono::prelude::*;
use clap::ArgMatches;
use reqwest::cookie::Jar;
Expand All @@ -12,7 +14,6 @@ use rpassword::read_password;
use serde_json::Value;
use simplelog::*;
use std::collections::HashMap;
use std::error::Error;
use std::io;
use std::io::Write;
use std::sync::Arc;
Expand All @@ -24,7 +25,7 @@ const CLERK_SIGN_IN_SLUG: &str = "/v1/client/sign_ins?_clerk_js_version=4.53.0";
pub struct AuthClient {}

impl AuthClient {
pub fn authenticate(args: &ArgMatches) -> Result<String, Box<dyn Error>> {
pub fn authenticate(args: &ArgMatches) -> Result<String> {
println!("Please enter the email address for a service user (https://tembo.io/docs/tembo-cloud/api):");
let user = Self::get_input();

Expand Down Expand Up @@ -91,7 +92,7 @@ impl AuthClient {
url: &str,
user: &str,
_pw: &str,
) -> Result<String, Box<dyn Error>> {
) -> Result<String> {
let request_url = format!("{}/{}", url, CLERK_SIGN_IN_SLUG);

let mut map = HashMap::new();
Expand All @@ -109,9 +110,9 @@ impl AuthClient {
}
status_code if status_code.is_client_error() => {
info!("{}", res.text()?);
Err(From::from("Client error"))
bail!("Client error")
}
_ => Err(From::from("Client error")),
_ => bail!("Client error"),
}
}

Expand All @@ -121,7 +122,7 @@ impl AuthClient {
id: &str,
pw: &str,
args: &ArgMatches,
) -> Result<String, Box<dyn Error>> {
) -> Result<String> {
let request_url = format!(
"{}/v1/client/sign_ins/{}/attempt_first_factor?_clerk_js_version=4.53.0",
url, id
Expand All @@ -137,17 +138,18 @@ impl AuthClient {
match res.status() {
StatusCode::OK => (),
status_code if status_code.is_client_error() => {
let error = res.text()?;
error!("client error:");
error!("{}", &res.text()?);
return Err(From::from("Client error"));
error!("{error}");
bail!("Client error: {error}");
}
_ => (),
};

let json: &Value = &res.json()?;
let session_id = json["client"]["sessions"][0]["id"]
.as_str()
.ok_or("Failed to parse jwt")?
.with_context(|| "Failed to parse jwt")?
.to_string();

// set or update the user's org ids
Expand All @@ -160,7 +162,7 @@ impl AuthClient {
client: &reqwest::blocking::Client,
url: &str,
session_id: &str,
) -> Result<String, Box<dyn Error>> {
) -> Result<String> {
println!(
"Please enter the number of days you would like this token to valid for [1, 30, 365]:"
);
Expand All @@ -179,22 +181,22 @@ impl AuthClient {
status_code if status_code.is_client_error() => {
error!("- client error:");
error!("- {}", &res.text()?);
return Err(From::from("Client error"));
bail!("Client error");
}
_ => (),
};

let json: &Value = &res.json()?;
let jwt = json["jwt"]
.as_str()
.ok_or("Failed to parse jwt")?
.with_context(|| "Failed to parse jwt")?
.to_string();

Ok(jwt)
}

// stores the user's organization id(s) in the config
fn set_org_ids(json: Value, args: &ArgMatches) -> Result<(), Box<dyn Error>> {
fn set_org_ids(json: Value, args: &ArgMatches) -> Result<()> {
let mut config = Config::new(args, &Config::full_path(args));
let mut org_ids = vec![];

Expand Down
12 changes: 6 additions & 6 deletions src/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

use crate::cli::cloud_account::CloudAccount;
use crate::cli::instance::Instance;
use crate::Result;
use chrono::prelude::*;
use clap::ArgMatches;
use serde::Deserialize;
use serde::Serialize;
use simplelog::*;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::fs::File;
Expand Down Expand Up @@ -63,7 +63,7 @@ impl Config {
}

// Reads the contents of an existing config file and returns contents as a string
pub fn read_to_string(file_path: &PathBuf) -> Result<String, Box<dyn Error>> {
pub fn read_to_string(file_path: &PathBuf) -> Result<String> {
let mut file = File::open(file_path)?;
let mut contents = String::new();

Expand All @@ -81,7 +81,7 @@ impl Config {
}

// Writes the current Config to the config file, overwriting anything else that was there
pub fn write(&self, file_path: &PathBuf) -> Result<(), Box<dyn Error>> {
pub fn write(&self, file_path: &PathBuf) -> Result<()> {
let mut file = File::create(file_path)?;
let _delete = file.set_len(0); // this deletes all contents from the file

Expand All @@ -108,21 +108,21 @@ impl Config {
}

// Creates the config directory
fn create_config_dir(dir_path: &str) -> Result<(), Box<dyn Error>> {
fn create_config_dir(dir_path: &str) -> Result<()> {
fs::create_dir_all(dir_path)?;

Ok(())
}

// Creates the config file in the config directory
fn create_config_file(path: &str) -> Result<(), Box<dyn Error>> {
fn create_config_file(path: &str) -> Result<()> {
File::create_new(path)?; // don't overwrite existing file at path

Ok(())
}

// Initializes the config file, creating the directories and files as needed
fn init(&self, file_path: &Path) -> Result<(), Box<dyn Error>> {
fn init(&self, file_path: &Path) -> Result<()> {
let mut dir_path = file_path.to_path_buf();
dir_path.pop(); // removes any filename and extension

Expand Down
62 changes: 14 additions & 48 deletions src/cli/docker.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::cli::instance::Instance;
use crate::Result;
use anyhow::bail;
use simplelog::*;
use spinners::{Spinner, Spinners};
use std::error::Error;
use std::fmt;
use std::process::Command as ShellCommand;
use std::process::Output;

Expand All @@ -17,7 +17,7 @@ impl Docker {
.expect("failed to execute process")
}

pub fn installed_and_running() -> Result<(), Box<dyn Error>> {
pub fn installed_and_running() -> Result {
info!("Checking requirements: [Docker]");

let output = Self::info();
Expand All @@ -26,18 +26,14 @@ impl Docker {

// determine if docker is installed
if stdout.is_empty() && !stderr.is_empty() {
return Err(Box::new(DockerError::new(
"- Docker is not installed, please visit docker.com to install",
)));
bail!("- Docker is not installed, please visit docker.com to install")
} else {
// determine if docker is running
if !stdout.is_empty() && !stderr.is_empty() {
let connection_err = stderr.find("Cannot connect to the Docker daemon");

if connection_err.is_some() {
return Err(Box::new(DockerError::new(
"- Docker is not running, please start it and try again",
)));
bail!("- Docker is not running, please start it and try again")
}
}
}
Expand All @@ -46,7 +42,7 @@ impl Docker {
}

// Build & run docker image
pub fn build_run() -> Result<(), Box<dyn Error>> {
pub fn build_run() -> Result {
let container_name = "tembo-pg";

if Self::container_list_filtered(container_name)
Expand All @@ -66,15 +62,15 @@ impl Docker {
}

// run sqlx migrate
pub fn run_sqlx_migrate() -> Result<(), Box<dyn Error>> {
pub fn run_sqlx_migrate() -> Result {
let command = "DATABASE_URL=postgres://postgres:postgres@localhost:5432 sqlx migrate run";
run_command(&command)?;

Ok(())
}

// start container if exists for name otherwise build container and start
pub fn start(name: &str, instance: &Instance) -> Result<(), Box<dyn Error>> {
pub fn start(name: &str, instance: &Instance) -> Result {
if Self::container_list_filtered(name)
.unwrap()
.contains("tembo-pg")
Expand All @@ -92,7 +88,7 @@ impl Docker {
}

// stop container for given name
pub fn stop(name: &str) -> Result<(), Box<dyn Error>> {
pub fn stop(name: &str) -> Result {
let mut sp = Spinner::new(Spinners::Line, "Stopping instance".into());
let mut command = String::from("cd tembo ");
command.push_str("&& docker stop ");
Expand All @@ -110,16 +106,14 @@ impl Docker {
let stderr = String::from_utf8(output.stderr).unwrap();

if !stderr.is_empty() {
return Err(Box::new(DockerError::new(
format!("There was an issue stopping the instance: {}", stderr).as_str(),
)));
bail!("There was an issue stopping the instance: {}", stderr)
}

Ok(())
}

#[allow(dead_code)]
pub fn container_list() -> Result<String, Box<dyn Error>> {
pub fn container_list() -> Result<String> {
let mut ls_command = String::from("cd tembo "); // TODO: does this work for installed crates?
ls_command.push_str("&& docker ls --all");

Expand All @@ -133,7 +127,7 @@ impl Docker {
Ok(stdout.unwrap())
}

pub fn container_list_filtered(name: &str) -> Result<String, Box<dyn Error>> {
pub fn container_list_filtered(name: &str) -> Result<String> {
let ls_command = format!("docker container ls --all -f name={}", name);

let output = ShellCommand::new("sh")
Expand All @@ -147,7 +141,7 @@ impl Docker {
}
}

pub fn run_command(command: &str) -> Result<(), Box<dyn Error>> {
pub fn run_command(command: &str) -> Result<()> {
let mut sp = Spinner::new(Spinners::Line, "Running Docker Build & Run".into());

let output = ShellCommand::new("sh")
Expand All @@ -159,40 +153,12 @@ pub fn run_command(command: &str) -> Result<(), Box<dyn Error>> {
let stderr = String::from_utf8(output.stderr).unwrap();

if !stderr.is_empty() {
return Err(Box::new(DockerError::new(
format!("There was an issue building & running docker: {}", stderr).as_str(),
)));
bail!("There was an issue building & running docker: {}", stderr)
}

Ok(())
}

// Define Docker not installed Error
#[derive(Debug)]
pub struct DockerError {
details: String,
}

impl DockerError {
pub fn new(msg: &str) -> DockerError {
DockerError {
details: msg.to_string(),
}
}
}

impl fmt::Display for DockerError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.details)
}
}

impl Error for DockerError {
fn description(&self) -> &str {
&self.details
}
}

#[cfg(test)]
mod tests {
#[test]
Expand Down
6 changes: 3 additions & 3 deletions src/cli/file_utils.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use crate::Result;
use curl::easy::Easy;
use simplelog::*;
use std::env;
use std::error::Error;
use std::fs::{self, File};
use std::io::Write;
use std::path::Path;

pub struct FileUtils {}

impl FileUtils {
pub fn create_dir(dir_name: String, dir_path: String) -> Result<(), Box<dyn Error>> {
pub fn create_dir(dir_name: String, dir_path: String) -> Result<()> {
if Path::new(&dir_path).exists() {
info!("Tembo {} path exists", dir_name);
return Ok(());
Expand All @@ -28,7 +28,7 @@ impl FileUtils {
file_path: String,
file_content: String,
recreate: bool,
) -> Result<(), Box<dyn Error>> {
) -> Result<()> {
let path = Path::new(&file_path);
if !recreate && path.exists() {
info!("Tembo {} file exists", file_name);
Expand Down
Loading

0 comments on commit 1c57b14

Please sign in to comment.