Skip to content

Commit

Permalink
feat: add recreate command
Browse files Browse the repository at this point in the history
  • Loading branch information
pxseu committed May 15, 2023
1 parent 36ee04b commit aec28d5
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/commands/containers/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub async fn handle(options: Options, state: State) -> Result<()> {
for container in &containers {
log::info!("Deleting container `{}`", container);

if let Err(err) = delete_container(&state.http, container).await {
if let Err(err) = delete_container(&state.http, container, false).await {
log::error!("Failed to delete container `{}`: {}", container, err);
} else {
delete_count += 1;
Expand Down
4 changes: 4 additions & 0 deletions src/commands/containers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod create;
mod delete;
mod list;
mod logs;
mod recreate;
pub mod types;
pub mod utils;

Expand All @@ -16,6 +17,8 @@ pub enum Commands {
Create(create::Options),
#[clap(name = "rm", alias = "delete")]
Delete(delete::Options),
#[clap(name = "recreate")]
Recreate(recreate::Options),
#[clap(name = "ls", alias = "list")]
List(list::Options),

Expand All @@ -36,5 +39,6 @@ pub async fn handle(options: Options, state: State) -> Result<()> {
Commands::Delete(options) => delete::handle(options, state).await,
Commands::List(options) => list::handle(options, state).await,
Commands::Log(options) => logs::handle(options, state).await,
Commands::Recreate(options) => recreate::handle(options, state).await,
}
}
86 changes: 86 additions & 0 deletions src/commands/containers/recreate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use anyhow::{bail, ensure, Result};
use clap::Parser;

use super::utils::delete_container;
use crate::commands::containers::types::Container;
use crate::commands::containers::utils::{format_containers, get_all_containers};
use crate::commands::ignite::utils::{format_deployments, get_all_deployments};
use crate::state::State;

#[derive(Debug, Parser)]
#[clap(about = "Recreate containers")]
pub struct Options {
#[clap(help = "IDs of the containers")]
containers: Vec<String>,

#[clap(short, long, help = "Skip confirmation")]
force: bool,
}

pub async fn handle(options: Options, state: State) -> Result<()> {
let containers = if !options.containers.is_empty() {
options.containers
} else {
let project_id = state.ctx.current_project_error()?.id;

let deployments = get_all_deployments(&state.http, &project_id).await?;
ensure!(!deployments.is_empty(), "No deployments found");
let deployments_fmt = format_deployments(&deployments, false);

let idx = dialoguer::Select::new()
.with_prompt("Select a deployment")
.items(&deployments_fmt)
.default(0)
.interact()?;

let containers = get_all_containers(&state.http, &deployments[idx].id).await?;
ensure!(!containers.is_empty(), "No containers found");
let containers_fmt = format_containers(&containers, false);

let idxs = dialoguer::MultiSelect::new()
.with_prompt("Select containers to recreate")
.items(&containers_fmt)
.interact()?;

containers
.iter()
.enumerate()
.filter(|(i, _)| idxs.contains(i))
.map(|(_, c)| c.id.clone())
.collect()
};

if !options.force
&& !dialoguer::Confirm::new()
.with_prompt(format!(
"Are you sure you want to recreate {} containers?",
containers.len()
))
.interact_opt()?
.unwrap_or(false)
{
bail!("Aborted");
}

let mut recreated_count = 0;

for container in &containers {
log::info!("Recreating container `{container}`");

match delete_container(&state.http, container, true).await {
Ok(Some(Container { id, .. })) => {
log::info!("Recreated container `{container}`, new ID: `{id}`");
recreated_count += 1;
}
Ok(None) => log::error!("Failed to recreate container `{container}`"),
Err(err) => log::error!("Failed to recreate container `{container}`: {err}"),
}
}

log::info!(
"Recreated {recreated_count}/{} containers",
containers.len()
);

Ok(())
}
5 changes: 5 additions & 0 deletions src/commands/containers/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,8 @@ pub struct Log {
pub struct LogsResponse {
pub logs: Vec<Log>,
}

#[derive(Debug, Deserialize)]
pub struct SingleContainer {
pub container: Container,
}
24 changes: 14 additions & 10 deletions src/commands/containers/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use std::io::Write;

use anyhow::{anyhow, Result};
use console::style;
use serde_json::Value;
use tabwriter::TabWriter;

use super::types::{
Container, ContainerState, CreateContainers, Log, LogsResponse, MultipleContainersResponse,
SingleContainer,
};
use crate::state::http::HttpClient;
use crate::utils::relative_time;
Expand All @@ -34,15 +34,19 @@ pub async fn create_containers(
Ok(response.containers)
}

pub async fn delete_container(http: &HttpClient, container_id: &str) -> Result<()> {
http.request::<Value>(
"DELETE",
&format!("/ignite/containers/{container_id}"),
None,
)
.await?;

Ok(())
pub async fn delete_container(
http: &HttpClient,
container_id: &str,
recreate: bool,
) -> Result<Option<Container>> {
Ok(http
.request::<SingleContainer>(
"DELETE",
&format!("/ignite/containers/{container_id}?recreate={recreate}"),
None,
)
.await?
.map(|response| response.container))
}

pub async fn get_all_containers(http: &HttpClient, deployment_id: &str) -> Result<Vec<Container>> {
Expand Down

0 comments on commit aec28d5

Please sign in to comment.