diff --git a/crates/tower-cmd/src/api.rs b/crates/tower-cmd/src/api.rs index 522abc7e..6df7a300 100644 --- a/crates/tower-cmd/src/api.rs +++ b/crates/tower-cmd/src/api.rs @@ -708,6 +708,50 @@ impl ResponseEntity for tower_api::apis::default_api::DescribeRunSuccess { } } +impl ResponseEntity for tower_api::apis::default_api::ListEnvironmentsSuccess { + type Data = tower_api::models::ListEnvironmentsResponse; + + fn extract_data(self) -> Option { + match self { + Self::Status200(resp) => Some(resp), + Self::UnknownValue(_) => None, + } + } +} + + +pub async fn list_environments( + config: &Config, +) -> Result< + tower_api::models::ListEnvironmentsResponse, + Error, +> { + let api_config = &config.into(); + unwrap_api_response(tower_api::apis::default_api::list_environments(api_config)).await +} + +pub async fn create_environment( + config: &Config, + name: &str, +) -> Result< + tower_api::models::CreateEnvironmentResponse, + Error, +> { + let api_config = &config.into(); + + let params = tower_api::apis::default_api::CreateEnvironmentParams { + create_environment_params: tower_api::models::CreateEnvironmentParams { + schema: None, + name: name.to_string(), + }, + }; + + unwrap_api_response(tower_api::apis::default_api::create_environment( + api_config, params, + )) + .await +} + pub async fn list_schedules( config: &Config, _app_name: Option<&str>, @@ -835,6 +879,17 @@ impl ResponseEntity for tower_api::apis::default_api::ListSchedulesSuccess { } } +impl ResponseEntity for tower_api::apis::default_api::CreateEnvironmentSuccess { + type Data = tower_api::models::CreateEnvironmentResponse; + + fn extract_data(self) -> Option { + match self { + Self::Status201(data) => Some(data), + Self::UnknownValue(_) => None, + } + } +} + impl ResponseEntity for tower_api::apis::default_api::CreateScheduleSuccess { type Data = tower_api::models::CreateScheduleResponse; diff --git a/crates/tower-cmd/src/environments.rs b/crates/tower-cmd/src/environments.rs new file mode 100644 index 00000000..cbc0ed9e --- /dev/null +++ b/crates/tower-cmd/src/environments.rs @@ -0,0 +1,67 @@ +use clap::{value_parser, Arg, ArgMatches, Command}; +use colored::Colorize; +use config::Config; + +use crate::{api, output}; + +pub fn environments_cmd() -> Command { + Command::new("environments") + .about("Manage the environments in your current Tower account") + .arg_required_else_help(true) + .subcommand(Command::new("list").about("List all of your environments")) + .subcommand( + Command::new("create") + .arg( + Arg::new("name") + .short('n') + .long("name") + .value_parser(value_parser!(String)) + .required(true) + .action(clap::ArgAction::Set), + ) + .about("Create a new environment in Tower"), + ) +} + +pub async fn do_list(config: Config) { + let resp = api::list_environments(&config).await; + + match resp { + Ok(resp) => { + let headers = vec!["Name"] + .into_iter() + .map(|h| h.yellow().to_string()) + .collect(); + + let envs_data: Vec> = resp + .environments + .into_iter() + .map(|env| { + vec![env.name] + }) + .collect(); + + // Display the table using the existing table function + output::table(headers, envs_data); + } + Err(err) => { + output::tower_error(err); + } + } +} + +pub async fn do_create(config: Config, args: &ArgMatches) { + let name = args.get_one::("name").unwrap_or_else(|| { + output::die("Environment name (--name) is required"); + }); + + let mut spinner = output::spinner("Creating environment"); + + if let Err(err) = api::create_environment(&config, name).await { + spinner.failure(); + output::tower_error(err); + } else { + spinner.success(); + output::success(&format!("Environment '{}' created", name)); + } +} diff --git a/crates/tower-cmd/src/lib.rs b/crates/tower-cmd/src/lib.rs index 81d35fcc..2ecb8bfb 100644 --- a/crates/tower-cmd/src/lib.rs +++ b/crates/tower-cmd/src/lib.rs @@ -4,6 +4,7 @@ use config::{Config, Session}; pub mod api; mod apps; mod deploy; +mod environments; pub mod error; pub mod output; mod run; @@ -119,6 +120,19 @@ impl App { } } } + Some(("environments", sub_matches)) => { + let environments_command = sub_matches.subcommand(); + + match environments_command { + Some(("list", _)) => environments::do_list(sessionized_config).await, + Some(("create", args)) => { + environments::do_create(sessionized_config, args).await + } + _ => { + environments::environments_cmd().print_help().unwrap(); + } + } + } Some(("schedules", sub_matches)) => { let schedules_command = sub_matches.subcommand(); @@ -179,6 +193,7 @@ fn root_cmd() -> Command { .subcommand(apps::apps_cmd()) .subcommand(schedules::schedules_cmd()) .subcommand(secrets::secrets_cmd()) + .subcommand(environments::environments_cmd()) .subcommand(deploy::deploy_cmd()) .subcommand(run::run_cmd()) .subcommand(version::version_cmd())