Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shows better error msg when tembo context or credentials files are invalid #586

Merged
merged 4 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tembo-cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tembo-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
workspace = { members = ["temboclient", "tembodataclient"] }
[package]
name = "tembo-cli"
version = "0.18.1"
version = "0.18.2"
edition = "2021"
authors = ["Tembo.io"]
description = "The CLI for Tembo"
Expand Down
67 changes: 49 additions & 18 deletions tembo-cli/src/cli/context.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::fs;

use anyhow::{anyhow, bail, Ok};
use anyhow::Error;
use anyhow::{anyhow, bail};
use serde::Deserialize;
use serde::Serialize;

use crate::tui;

// TODO: Move this to a template file
pub const CONTEXT_DEFAULT_TEXT: &str = "version = \"1.0\"

Expand Down Expand Up @@ -88,46 +91,74 @@ pub fn tembo_credentials_file_path() -> String {
tembo_home_dir() + "/credentials"
}

pub fn list_context() -> Result<Context, anyhow::Error> {
pub fn list_context() -> Result<Option<Context>, anyhow::Error> {
let filename = tembo_context_file_path();

let contents = fs::read_to_string(&filename)
.map_err(|err| anyhow!("Error reading file {filename}: {err}"))?;

let context: Context =
toml::from_str(&contents).map_err(|err| anyhow!("Error reading file {filename}: {err}"))?;
let maybe_context: Result<Context, toml::de::Error> = toml::from_str(&contents);

match maybe_context {
Ok(context) => Ok(Some(context)),
Err(err) => {
eprintln!("\nInvalid context file {filename}\n");

tui::error(&format!("Error: {}", err.message()));

eprintln!("\nExample context file: \n\n{}", CONTEXT_DEFAULT_TEXT);

Ok(context)
Err(Error::msg("Error listing tembo context!"))
}
}
}

pub fn get_current_context() -> Result<Environment, anyhow::Error> {
let context = list_context()?;
let maybe_context = list_context()?;

let profiles = list_credential_profiles()?;
if let Some(context) = maybe_context {
let maybe_profiles = list_credential_profiles()?;

for mut env in context.environment {
if let Some(_is_set) = env.set {
if let Some(profile) = &env.profile {
let credential = profiles.iter().rev().find(|c| &c.name == profile).unwrap();
if let Some(profiles) = maybe_profiles {
for mut env in context.environment {
if let Some(_is_set) = env.set {
if let Some(profile) = &env.profile {
let credential =
profiles.iter().rev().find(|c| &c.name == profile).unwrap();

env.selected_profile = Some(credential.to_owned());
}
env.selected_profile = Some(credential.to_owned());
}

return Ok(env);
return Ok(env);
}
}
}
}

bail!("Tembo context not set");
}

pub fn list_credential_profiles() -> Result<Vec<Profile>, anyhow::Error> {
pub fn list_credential_profiles() -> Result<Option<Vec<Profile>>, anyhow::Error> {
let filename = tembo_credentials_file_path();

let contents = fs::read_to_string(&filename)
.map_err(|err| anyhow!("Error reading file {filename}: {err}"))?;

let credential: Credential = toml::from_str(&contents)
.map_err(|err| anyhow!("Issue with the format of the TOML file {filename}: {err}"))?;
let maybe_credential: Result<Credential, toml::de::Error> = toml::from_str(&contents);

match maybe_credential {
Ok(credential) => Ok(Some(credential.profile)),
Err(err) => {
eprintln!("\nInvalid credentials file {filename}\n");

tui::error(&format!("Error: {}", err.message()));

Ok(credential.profile)
eprintln!(
"\nExample credentials file: \n\n{}",
CREDENTIALS_DEFAULT_TEXT
);

Err(Error::msg("Error listing tembo credentials profiles!"))
}
}
}
20 changes: 0 additions & 20 deletions tembo-cli/src/cli/extension.rs

This file was deleted.

1 change: 0 additions & 1 deletion tembo-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod context;
pub mod docker;
pub mod extension;
pub mod file_utils;
pub mod sqlx_utils;
pub mod tembo_config;
98 changes: 50 additions & 48 deletions tembo-cli/src/cmd/context/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,63 @@ use cli_table::{Cell, CellStruct, Style, Table};
use colorful::Colorful;

pub fn execute() -> Result<(), anyhow::Error> {
let context = list_context()?;
let maybe_context = list_context()?;

let mut rows: Vec<Vec<CellStruct>> = vec![];
let current_context_profile = context
.environment
.iter()
.find(|e| e.set.is_some())
.unwrap()
.name
.clone();
for e in context.environment {
let mut org_id = String::from(" ");
let mut profile = String::from(" ");
let mut set = false;
if let Some(env_org) = e.org_id {
org_id = env_org;
}
if let Some(context) = maybe_context {
let mut rows: Vec<Vec<CellStruct>> = vec![];
let current_context_profile = context
.environment
.iter()
.find(|e| e.set.is_some())
.unwrap()
.name
.clone();
for e in context.environment {
let mut org_id = String::from(" ");
let mut profile = String::from(" ");
let mut set = false;
if let Some(env_org) = e.org_id {
org_id = env_org;
}

if e.target == *"docker" {
profile = String::from("local")
} else if let Some(env_profile) = e.profile {
profile = env_profile;
}
if e.target == *"docker" {
profile = String::from("local")
} else if let Some(env_profile) = e.profile {
profile = env_profile;
}

if let Some(env_set) = e.set {
set = env_set;
}
if let Some(env_set) = e.set {
set = env_set;
}

rows.push(vec![
e.name.cell(),
e.target.cell(),
org_id.cell(),
profile.cell(),
set.cell(),
]);
}
rows.push(vec![
e.name.cell(),
e.target.cell(),
org_id.cell(),
profile.cell(),
set.cell(),
]);
}

let table = rows
.table()
.title(vec![
"Name".color(sql_u()).cell().bold(true),
"Target".color(sql_u()).cell().bold(true),
"Org ID".color(sql_u()).cell().bold(true),
"Profile".color(sql_u()).cell().bold(true),
"Set".color(sql_u()).cell().bold(true),
])
.bold(true);
let table = rows
.table()
.title(vec![
"Name".color(sql_u()).cell().bold(true),
"Target".color(sql_u()).cell().bold(true),
"Org ID".color(sql_u()).cell().bold(true),
"Profile".color(sql_u()).cell().bold(true),
"Set".color(sql_u()).cell().bold(true),
])
.bold(true);

let table_display = table
.display()
.expect("Error: could not parse `tembo context list` table contents!");
let table_display = table
.display()
.expect("Error: could not parse `tembo context list` table contents!");

label_with_value("Your current Tembo context:", &current_context_profile);
println!("{}", indent(1));
println!("{}", table_display);
label_with_value("Your current Tembo context:", &current_context_profile);
println!("{}", indent(1));
println!("{}", table_display);
}

Ok(())
}
27 changes: 9 additions & 18 deletions tembo-cli/src/cmd/top.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
use crate::cli::context::{get_current_context, Environment, Profile, Target};
use crate::cli::context::{get_current_context, Environment};
use crate::cli::tembo_config::InstanceSettings;
use crate::cmd::apply::get_instance_settings;
use crate::Args;
use anyhow::anyhow;
use anyhow::{Context, Result};
use crossterm::{
cursor::{MoveTo, MoveUp},
execute,
terminal::{Clear, ClearType},
};
use hyper::header::ACCEPT;
use reqwest::header::HeaderMap;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt;
use std::io::{stdout, Write};
use temboclient::models::{instance, instance_event};
use temboclient::{
apis::{
configuration::Configuration,
instance_api::{create_instance, get_all, get_instance, put_instance},
},
models::connection_info,
};
use temboclient::apis::configuration::Configuration;
use temboclient::apis::instance_api::get_all;
use temboclient::apis::instance_api::get_instance;
use tokio::runtime::Runtime;
use tokio::time::{interval, Duration};
use tokio::time::Duration;

#[derive(Args)]
pub struct TopCommand {}
Expand All @@ -39,7 +30,7 @@ pub struct MetricsResponse {

#[derive(Serialize, Deserialize, Debug)]
pub struct MetricsData {
pub resultType: String,
pub result_type: String,
pub result: Vec<MetricResult>,
}

Expand Down Expand Up @@ -101,8 +92,8 @@ async fn fetch_metrics_loop(
loop {
execute!(stdout, Clear(ClearType::All))?;

for (key, value) in &instance_settings {
let org_name = get_instance_org_name(&config, &env, &value.instance_name).await?;
for value in instance_settings.values() {
let org_name = get_instance_org_name(config, &env, &value.instance_name).await?;
let namespace = format!("org-{}-inst-{}", org_name, &value.instance_name);
let namespace_encoded = urlencoding::encode(&namespace);

Expand Down Expand Up @@ -249,7 +240,7 @@ async fn get_instance_org_name(
instance_name
))
}
Err(e) => return Err(e.into()),
Err(e) => return Err(e),
};
let org_id = env
.org_id
Expand Down
6 changes: 5 additions & 1 deletion tembo-cli/src/cmd/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use crate::cli::file_utils::FileUtils;
use crate::cli::tembo_config::InstanceSettings;
use crate::tui::{error, info, white_confirmation};
use anyhow::Error;
use anyhow::Ok;
use clap::Args;
use std::{collections::HashMap, fs, path::Path, str::FromStr};
use tembo::cli::context::{list_context, list_credential_profiles};

/// Validates the tembo.toml file, context file, etc.
#[derive(Args)]
Expand All @@ -20,6 +20,8 @@ pub fn execute(verbose: bool) -> Result<(), anyhow::Error> {
tembo_context_file_path()
));
has_error = true
} else {
list_context()?;
}
if verbose {
info("Context file exists");
Expand All @@ -31,6 +33,8 @@ pub fn execute(verbose: bool) -> Result<(), anyhow::Error> {
tembo_credentials_file_path()
);
has_error = true
} else {
list_credential_profiles()?;
}
if verbose {
info("Credentials file exists");
Expand Down