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

implements overlay-configs options for tembo apply #466

Merged
merged 40 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
c8da717
setting up get_instance_settings
joshuajerin Jan 4, 2024
38ea283
Updating tests on apply.rs
joshuajerin Jan 4, 2024
d74cca1
modifying second instance not to use default
joshuajerin Jan 4, 2024
8451970
Merge branch 'overlay-configs' of https://github.com/tembo-io/tembo i…
joshuajerin Jan 4, 2024
6df4476
removing testing arguments
joshuajerin Jan 4, 2024
966f34e
deleting some unused crates
joshuajerin Jan 4, 2024
d142e85
Merge branch 'main' into overlay-configs
joshuajerin Jan 4, 2024
1f9267f
added all changes
joshuajerin Jan 5, 2024
a896f14
Merge branch 'overlay-configs' of https://github.com/tembo-io/tembo i…
joshuajerin Jan 5, 2024
130186c
Merge branch 'main' into overlay-configs
joshuajerin Jan 5, 2024
a423436
adding cargo.lock
joshuajerin Jan 5, 2024
78f1154
Merge branch 'overlay-configs' of https://github.com/tembo-io/tembo i…
joshuajerin Jan 5, 2024
1864e4c
getting rid of errors
joshuajerin Jan 5, 2024
26d86bd
changing tests
joshuajerin Jan 5, 2024
e75aef8
changes to overlay_to_instance_settings
joshuajerin Jan 5, 2024
4c56557
removing stdout constraints in tests
joshuajerin Jan 5, 2024
e77f70d
Merge branch 'main' into overlay-configs
joshuajerin Jan 5, 2024
3e2b1da
Update Cargo.lock
joshuajerin Jan 5, 2024
9fd4ebd
formatting the code
joshuajerin Jan 7, 2024
5d4899a
Merge branch 'overlay-configs' of https://github.com/tembo-io/tembo i…
joshuajerin Jan 7, 2024
f42e558
adding temporary changes
joshuajerin Jan 8, 2024
b39b9e6
adding requested tests
joshuajerin Jan 8, 2024
b7c0f02
updating fmt
joshuajerin Jan 8, 2024
6a96ecb
final format changes
joshuajerin Jan 8, 2024
ca31b4f
removing postgres files from merge
joshuajerin Jan 8, 2024
7125192
Merge branch 'main' into overlay-configs
joshuajerin Jan 8, 2024
97222de
removing unnecessary data-warehouse files
joshuajerin Jan 8, 2024
459e849
adding instance_settings inside execute_docker
joshuajerin Jan 8, 2024
4b051cb
Merge branch 'overlay-configs' of https://github.com/tembo-io/tembo i…
joshuajerin Jan 8, 2024
415cb9a
changing default_instance_settings for changed code
joshuajerin Jan 8, 2024
f30749b
adding merge test in main.rs
joshuajerin Jan 8, 2024
a281fb3
removed printing instance_settings in execute
joshuajerin Jan 9, 2024
939b07e
removing ref in apply_cmd
joshuajerin Jan 9, 2024
57da399
Merge branch 'main' into overlay-configs
shahadarsh Jan 9, 2024
f9e0bac
some final changes
joshuajerin Jan 9, 2024
0c1606a
Merge branch 'overlay-configs' of https://github.com/tembo-io/tembo i…
joshuajerin Jan 9, 2024
9992a8c
lint tests
joshuajerin Jan 9, 2024
3479cec
making consistent code
joshuajerin Jan 9, 2024
4dabd49
Merge branch 'main' into overlay-configs
joshuajerin Jan 9, 2024
1fb4875
Merge branch 'main' into overlay-configs
shahadarsh Jan 10, 2024
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
12 changes: 12 additions & 0 deletions tembo-cli/src/cli/tembo_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ pub struct InstanceSettings {
pub extra_domains_rw: Option<Vec<String>>,
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct OverlayInstanceSettings {
pub cpu: Option<String>,
pub memory: Option<String>,
pub storage: Option<String>,
pub replicas: Option<i32>,
pub stack_type: Option<String>,
pub postgres_configurations: Option<HashMap<String, Value>>,
pub extensions: Option<HashMap<String, Extension>>,
pub extra_domains_rw: Option<Vec<String>>,
}

// If a trunk project name is not specified, then assume
// it's the same name as the extension.
fn deserialize_extensions<'de, D>(
Expand Down
92 changes: 65 additions & 27 deletions tembo-cli/src/cmd/apply.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use anyhow::Context as AnyhowContext;
use anyhow::Error;
use clap::Args;
use colorful::{Color, Colorful};
use colorful::Colorful;
use controller::stacks::get_stack;
use controller::stacks::types::StackType as ControllerStackType;
use log::info;
Expand Down Expand Up @@ -29,7 +30,8 @@ use crate::cli::file_utils::FileUtils;
use crate::cli::sqlx_utils::SqlxUtils;
use crate::cli::tembo_config;
use crate::cli::tembo_config::InstanceSettings;
use crate::tui::{indent, instance_started};
use crate::cli::tembo_config::OverlayInstanceSettings;
use crate::tui::instance_started;
use crate::{
cli::context::{get_current_context, Environment, Profile, Target},
tui::{clean_console, colors, white_confirmation},
Expand All @@ -41,28 +43,31 @@ const POSTGRESCONF_NAME: &str = "postgres.conf";

/// Deploys a tembo.toml file
#[derive(Args)]
pub struct ApplyCommand {}
pub struct ApplyCommand {
#[clap(long, short = 'm')]
pub merge: Option<String>,
}

pub fn execute(verbose: bool) -> Result<(), anyhow::Error> {
pub fn execute(verbose: bool, _merge_path: Option<String>) -> Result<(), anyhow::Error> {
joshuajerin marked this conversation as resolved.
Show resolved Hide resolved
info!("Running validation!");
super::validate::execute(verbose)?;
info!("Validation completed!");

let env = get_current_context()?;

if env.target == Target::Docker.to_string() {
return execute_docker(verbose);
return execute_docker(verbose, _merge_path);
} else if env.target == Target::TemboCloud.to_string() {
return execute_tembo_cloud(env.clone());
return execute_tembo_cloud(env.clone(), _merge_path);
}

Ok(())
}

fn execute_docker(verbose: bool) -> Result<(), anyhow::Error> {
fn execute_docker(verbose: bool, _merge_path: Option<String>) -> Result<(), anyhow::Error> {
Docker::installed_and_running()?;

let instance_settings: HashMap<String, InstanceSettings> = get_instance_settings()?;
let instance_settings = get_instance_settings(_merge_path)?;
let rendered_dockerfile: String = get_rendered_dockerfile(instance_settings.clone())?;

FileUtils::create_file(
Expand Down Expand Up @@ -111,13 +116,17 @@ fn execute_docker(verbose: bool) -> Result<(), anyhow::Error> {
&value.stack_type,
"local",
);
println!("Instance settings: {:?}", instance_settings);
}

Ok(())
}

pub fn execute_tembo_cloud(env: Environment) -> Result<(), anyhow::Error> {
let instance_settings: HashMap<String, InstanceSettings> = get_instance_settings()?;
pub fn execute_tembo_cloud(
env: Environment,
_merge_path: Option<String>,
) -> Result<(), anyhow::Error> {
let instance_settings = get_instance_settings(_merge_path)?;

let profile = env.clone().selected_profile.unwrap();
let config = Configuration {
Expand Down Expand Up @@ -434,25 +443,55 @@ fn get_trunk_installs(
vec_trunk_installs
}

pub fn get_instance_settings() -> Result<HashMap<String, InstanceSettings>, anyhow::Error> {
let mut file_path = FileUtils::get_current_working_dir();
file_path.push_str("/tembo.toml");

let contents = match fs::read_to_string(file_path.clone()) {
Ok(c) => c,
Err(e) => {
panic!("Couldn't read context file {}: {}", file_path, e);
}
};
fn merge_settings(base: &InstanceSettings, overlay: OverlayInstanceSettings) -> InstanceSettings {
joshuajerin marked this conversation as resolved.
Show resolved Hide resolved
InstanceSettings {
environment: base.environment.clone(), // Retain the base environment
instance_name: base.instance_name.clone(), // Retain the base instance_name
cpu: overlay.cpu.unwrap_or_else(|| base.cpu.clone()),
memory: overlay.memory.unwrap_or_else(|| base.memory.clone()),
storage: overlay.storage.unwrap_or_else(|| base.storage.clone()),
replicas: overlay.replicas.unwrap_or(base.replicas),
stack_type: overlay
.stack_type
.unwrap_or_else(|| base.stack_type.clone()),
postgres_configurations: overlay
.postgres_configurations
.or_else(|| base.postgres_configurations.clone()),
extensions: overlay.extensions.or_else(|| base.extensions.clone()),
extra_domains_rw: overlay
.extra_domains_rw
.or_else(|| base.extra_domains_rw.clone()),
}
}

let instance_settings: HashMap<String, InstanceSettings> = match toml::from_str(&contents) {
Ok(d) => d,
Err(e) => {
panic!("Unable to load data. Error: `{}`", e);
pub fn get_instance_settings(
overlay_file_path: Option<String>,
) -> Result<HashMap<String, InstanceSettings>, Error> {
let mut base_path = FileUtils::get_current_working_dir();
base_path.push_str("/tembo.toml");
let base_contents = fs::read_to_string(&base_path)
.with_context(|| format!("Couldn't read base file {}", base_path))?;
let base_settings: HashMap<String, InstanceSettings> =
toml::from_str(&base_contents).context("Unable to load data from the base config")?;

let mut final_settings = base_settings.clone();

if let Some(overlay_path) = overlay_file_path {
let overlay_contents = fs::read_to_string(&overlay_path)
.with_context(|| format!("Couldn't read overlay file {}", overlay_path))?;
let overlay_settings: HashMap<String, OverlayInstanceSettings> =
toml::from_str(&overlay_contents)
.context("Unable to load data from the overlay config")?;

for (key, overlay_value) in overlay_settings {
if let Some(base_value) = base_settings.get(&key) {
let merged_value = merge_settings(base_value, overlay_value);
final_settings.insert(key, merged_value);
}
}
};
}

Ok(instance_settings)
Ok(final_settings)
}

pub fn get_rendered_dockerfile(
Expand Down Expand Up @@ -557,7 +596,6 @@ fn get_postgres_config(instance_settings: HashMap<String, InstanceSettings>) ->
}
}
}

postgres_config
}

Expand Down
2 changes: 1 addition & 1 deletion tembo-cli/src/cmd/context/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn execute() -> Result<(), anyhow::Error> {
org_id = env_org;
}

if e.target == String::from("docker") {
if e.target == *"docker" {
profile = String::from("local")
} else if let Some(env_profile) = e.profile {
profile = env_profile;
Expand Down
10 changes: 4 additions & 6 deletions tembo-cli/src/cmd/delete.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::collections::HashMap;

use crate::cli::context::{get_current_context, Environment, Target};
use crate::cli::docker::Docker;
use crate::cli::tembo_config::InstanceSettings;
use crate::tui::{confirmation, label};

use crate::tui::confirmation;
use clap::Args;
use core::result::Result::Ok;
use temboclient::apis::{configuration::Configuration, instance_api::delete_instance};
Expand All @@ -18,7 +16,7 @@ pub struct DeleteCommand {}
pub fn execute() -> Result<(), anyhow::Error> {
let env = get_current_context()?;

let instance_settings: HashMap<String, InstanceSettings> = get_instance_settings()?;
let instance_settings = get_instance_settings(None)?;

if env.target == Target::Docker.to_string() {
for (_key, value) in instance_settings.iter() {
Expand All @@ -32,7 +30,7 @@ pub fn execute() -> Result<(), anyhow::Error> {
}

fn execute_tembo_cloud(env: Environment) -> Result<(), anyhow::Error> {
let instance_settings: HashMap<String, InstanceSettings> = get_instance_settings()?;
let instance_settings = get_instance_settings(None)?;

joshuajerin marked this conversation as resolved.
Show resolved Hide resolved
let profile = env.clone().selected_profile.unwrap();
let config = Configuration {
Expand Down
1 change: 0 additions & 1 deletion tembo-cli/src/cmd/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::cli::context::{
use crate::cli::file_utils::FileUtils;
use crate::tui::confirmation;
use clap::Args;
use colorful::Colorful;

/// Initializes a local environment. Creates a sample context and configuration files.
#[derive(Args)]
Expand Down
88 changes: 87 additions & 1 deletion tembo-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn main() -> Result<(), anyhow::Error> {
init::execute()?;
}
SubCommands::Apply(_apply_cmd) => {
apply::execute(app.global_opts.verbose)?;
apply::execute(app.global_opts.verbose, _apply_cmd.merge.clone())?;
}
SubCommands::Validate(_validate_cmd) => {
validate::execute(app.global_opts.verbose)?;
Expand All @@ -65,3 +65,89 @@ fn main() -> Result<(), anyhow::Error> {

Ok(())
}

#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
use std::process::Command;

const CARGO_BIN_PATH: &str = "cargo run ";
const root_dir: &str = env!("CARGO_MANIFEST_DIR");

#[tokio::test]
async fn default_instance_settings() -> Result<(), Box<dyn std::error::Error>> {
std::env::set_current_dir(
PathBuf::from(root_dir)
.join("tests")
.join("tomls")
.join("merge"),
)?;

// Path to the overlay.toml file
let overlay_config_path = PathBuf::from(root_dir)
.join("tests")
.join("tomls")
.join("merge")
.join("overlay.toml");
let overlay_config_str = overlay_config_path.to_str().ok_or("Invalid path")?;

// Running `tembo init`
let _output = Command::new(CARGO_BIN_PATH).arg("init");

let _output = Command::new(CARGO_BIN_PATH)
.arg("apply")
.arg("--merge")
.arg(overlay_config_str);

let merged_settings = apply::get_instance_settings(Some(overlay_config_str.to_string()))?;
if let Some(setting) = merged_settings.get("defaults") {
assert_ne!(setting.cpu, "0.25", "Default setting was overwritten");
} else {
return Err("Setting key not found".into());
}

// Running `tembo delete`
let _output = Command::new(CARGO_BIN_PATH).arg("delete");

Ok(())
}

#[tokio::test]
async fn merge() -> Result<(), Box<dyn std::error::Error>> {
std::env::set_current_dir(
PathBuf::from(root_dir)
.join("tests")
.join("tomls")
.join("merge"),
)?;

// Path to the overlay.toml file
let overlay_config_path = PathBuf::from(root_dir)
.join("tests")
.join("tomls")
.join("merge")
.join("overlay.toml");
let overlay_config_str = overlay_config_path.to_str().ok_or("Invalid path")?;

// Running `tembo init`
let _output = Command::new(CARGO_BIN_PATH).arg("init");

let _output = Command::new(CARGO_BIN_PATH)
.arg("apply")
.arg("--merge")
.arg(overlay_config_str);

let merged_settings = apply::get_instance_settings(Some(overlay_config_str.to_string()))?;
if let Some(setting) = merged_settings.get("defaults") {
assert_eq!(setting.memory, "10Gi", "Base settings was not overwritten");
} else {
return Err("Setting key not found".into());
}

// Running `tembo delete`
let _output = Command::new(CARGO_BIN_PATH).arg("delete");

Ok(())
}
}
4 changes: 2 additions & 2 deletions tembo-cli/src/tui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub mod colors {
ColorfulRgb::new(255, 244, 228)
}

pub fn gradient_p<'a>(log: &'a str) -> GradientDisplay<'a, [RGB; 4]> {
pub fn gradient_p(log: &str) -> GradientDisplay<'_, [RGB; 4]> {
GradientStr::gradient(
log,
[
Expand All @@ -112,7 +112,7 @@ pub mod colors {
)
}

pub fn gradient_rainbow<'a>(log: &'a str) -> GradientDisplay<'a, [RGB; 3]> {
pub fn gradient_rainbow(log: &str) -> GradientDisplay<'_, [RGB; 3]> {
GradientStr::gradient(
log,
[
Expand Down
3 changes: 3 additions & 0 deletions tembo-cli/tests/tomls/merge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
postgres.conf
1_extensions.sql
Dockerfile
4 changes: 4 additions & 0 deletions tembo-cli/tests/tomls/merge/overlay.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[defaults]
environment = "prod"
instance_name = "overlay_instance"
memory = "10Gi"
7 changes: 7 additions & 0 deletions tembo-cli/tests/tomls/merge/tembo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[defaults]
environment = "dev"
instance_name = "defaults_instance"
cpu = "1"
storage = "50Gi"
replicas = 1
stack_type = "Standard"
Loading