Skip to content

Commit

Permalink
George/514 220 ensure docker running before running commands (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
phiSgr authored Jan 11, 2024
1 parent 9c54f6a commit 5404aa6
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 57 deletions.
6 changes: 3 additions & 3 deletions apps/igloo-kit-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use log::{debug, info};
use self::{
display::{Message, MessageType},
routines::{
clean::CleanProject, initialize::InitializeProject, start::RunLocalInfratructure,
clean::CleanProject, initialize::InitializeProject, start::RunLocalInfrastructure,
stop::StopLocalInfrastructure, validate::ValidateRedPandaCluster, RoutineController,
RunMode,
},
Expand Down Expand Up @@ -83,7 +83,7 @@ async fn top_command_handler(settings: Settings, commands: &Option<Commands>) {
let mut controller = RoutineController::new();
let run_mode = RunMode::Explicit {};

controller.add_routine(Box::new(RunLocalInfratructure::new(project.clone())));
controller.add_routine(Box::new(RunLocalInfrastructure::new(project.clone())));

controller.add_routine(Box::new(ValidateRedPandaCluster::new()));

Expand All @@ -98,7 +98,7 @@ async fn top_command_handler(settings: Settings, commands: &Option<Commands>) {
}
Some(Commands::Update {}) => {
// This command may not be needed if we have incredible automation
todo!("Will update the project's underlying infrascructure based on any added objects")
todo!("Will update the project's underlying infrastructure based on any added objects")
}
Some(Commands::Stop {}) => {
let mut controller = RoutineController::new();
Expand Down
23 changes: 20 additions & 3 deletions apps/igloo-kit-cli/src/cli/routines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub mod clean;
pub mod initialize;
pub mod start;
pub mod stop;
mod util;
pub mod validate;

#[derive(Clone)]
Expand Down Expand Up @@ -133,14 +134,23 @@ impl RoutineSuccess {
pub struct RoutineFailure {
message: Message,
message_type: MessageType,
error: Error,
error: Option<Error>,
}
impl RoutineFailure {
pub fn new(message: Message, error: Error) -> Self {
Self {
message,
message_type: MessageType::Error,
error,
error: Some(error),
}
}

/// create a RoutineFailure error without an io error
pub fn error(message: Message) -> Self {
Self {
message,
message_type: MessageType::Error,
error: None,
}
}
}
Expand Down Expand Up @@ -173,7 +183,14 @@ pub trait Routine {
failure.message_type,
Message::new(
failure.message.action.clone(),
format!("{}: {}", failure.message.details.clone(), failure.error),
match &failure.error {
None => {
failure.message.details.clone()
}
Some(error) => {
format!("{}: {}", failure.message.details.clone(), error)
}
},
)
);
Err(failure)
Expand Down
2 changes: 2 additions & 0 deletions apps/igloo-kit-cli/src/cli/routines/clean.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{fs, path::PathBuf};

use crate::cli::routines::util::ensure_docker_running;
use crate::{
cli::display::Message, project::Project, utilities::constants::PANDA_NETWORK, utilities::docker,
};
Expand Down Expand Up @@ -30,6 +31,7 @@ impl Routine for CleanProject {
)
})?;

ensure_docker_running()?;
StopLocalInfrastructure::new(run_mode).run(run_mode)?;
RemoveDockerNetwork::new(PANDA_NETWORK).run(run_mode)?;
DeleteRedpandaMountVolume::new(internal_dir.clone()).run(run_mode)?;
Expand Down
18 changes: 9 additions & 9 deletions apps/igloo-kit-cli/src/cli/routines/initialize.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::{
fs,
io::{Error, ErrorKind},
path::PathBuf,
};
use std::io::ErrorKind;
use std::{fs, path::PathBuf};

use crate::cli::routines::util::ensure_docker_running;
use crate::{
cli::display::Message,
framework::{languages::create_models_dir, typescript::create_typescript_models_dir},
Expand Down Expand Up @@ -39,6 +37,8 @@ impl Routine for InitializeProject {
)
})?;

ensure_docker_running()?;

CreateModelsVolume::new(self.project.clone()).run(run_mode)?;
CreateDockerNetwork::new(PANDA_NETWORK).run(run_mode)?;

Expand Down Expand Up @@ -97,10 +97,10 @@ impl Routine for ValidateMountVolumes {
)))
} else {
let message = format!("redpanda: {panda_house}, clickhouse: {clickhouse}");
Err(RoutineFailure::new(
Message::new("Mount volume status".to_string(), message.clone()),
Error::new(ErrorKind::NotFound, message),
))
Err(RoutineFailure::error(Message::new(
"Mount volume status".to_string(),
message.clone(),
)))
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions apps/igloo-kit-cli/src/cli/routines/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@ use super::{
Routine, RoutineFailure, RoutineSuccess, RunMode,
};
use crate::cli::routines::initialize::CreateIglooTempDirectoryTree;
use crate::cli::routines::util::ensure_docker_running;
use crate::{
cli::display::Message,
project::Project,
utilities::docker::{self},
};

pub struct RunLocalInfratructure {
pub struct RunLocalInfrastructure {
project: Project,
}
impl RunLocalInfratructure {
impl RunLocalInfrastructure {
pub fn new(project: Project) -> Self {
Self { project }
}
}

impl Routine for RunLocalInfratructure {
impl Routine for RunLocalInfrastructure {
fn run_silent(&self) -> Result<RoutineSuccess, RoutineFailure> {
ensure_docker_running()?;
let igloo_dir = self.project.internal_dir().map_err(|err| {
RoutineFailure::new(
Message::new(
Expand Down
2 changes: 2 additions & 0 deletions apps/igloo-kit-cli/src/cli/routines/stop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{Routine, RoutineFailure, RoutineSuccess, RunMode};
use crate::cli::routines::util::ensure_docker_running;
use crate::{cli::display::Message, utilities::docker};

pub struct StopLocalInfrastructure {
Expand All @@ -11,6 +12,7 @@ impl StopLocalInfrastructure {
}
impl Routine for StopLocalInfrastructure {
fn run_silent(&self) -> Result<RoutineSuccess, RoutineFailure> {
ensure_docker_running()?;
let run_mode = self.run_mode;
StopRedPandaContainer::new().run(run_mode)?;
StopClickhouseContainer::new().run(run_mode)?;
Expand Down
29 changes: 29 additions & 0 deletions apps/igloo-kit-cli/src/cli/routines/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::cli::display::Message;
use crate::cli::routines::RoutineFailure;
use crate::utilities::docker;

pub fn ensure_docker_running() -> Result<(), RoutineFailure> {
let errors = docker::check_status().map_err(|err| {
RoutineFailure::new(
Message::new("Failed".to_string(), "to run `docker info`".to_string()),
err,
)
})?;

if errors.is_empty() {
Ok(())
} else if errors
.iter()
.any(|s| s.ends_with("Is the docker daemon running?"))
{
Err(RoutineFailure::error(Message::new(
"Failed".to_string(),
"to run docker commands. Is docker running?".to_string(),
)))
} else {
Err(RoutineFailure::error(Message::new(
"Failed".to_string(),
errors.join("\n"),
)))
}
}
54 changes: 16 additions & 38 deletions apps/igloo-kit-cli/src/cli/routines/validate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use super::{Routine, RoutineFailure, RoutineSuccess};
use crate::{cli::display::Message, utilities::constants::PANDA_NETWORK, utilities::docker};
use std::io::{Error, ErrorKind};

pub struct ValidateClickhouseRun;
impl ValidateClickhouseRun {
Expand All @@ -22,16 +21,10 @@ impl Routine for ValidateClickhouseRun {
.iter()
.find(|container| container.names.contains("clickhousedb-1"))
.ok_or_else(|| {
RoutineFailure::new(
Message::new(
"Failed".to_string(),
"to find clickhouse docker container".to_string(),
),
Error::new(
ErrorKind::Other,
"Failed to validate clickhouse container exists",
),
)
RoutineFailure::error(Message::new(
"Failed".to_string(),
"to find clickhouse docker container".to_string(),
))
})?;
Ok(RoutineSuccess::success(Message::new(
"Successfully".to_string(),
Expand Down Expand Up @@ -61,16 +54,10 @@ impl Routine for ValidateRedPandaRun {
.iter()
.find(|container| container.names.contains("redpanda-1"))
.ok_or_else(|| {
RoutineFailure::new(
Message::new(
"Failed".to_string(),
"to find redpanda docker container".to_string(),
),
Error::new(
ErrorKind::Other,
"Failed to validate redpanda container exists",
),
)
RoutineFailure::error(Message::new(
"Failed".to_string(),
"to find redpanda docker container".to_string(),
))
})?;
Ok(RoutineSuccess::success(Message::new(
"Successfully".to_string(),
Expand Down Expand Up @@ -101,16 +88,10 @@ impl Routine for ValidatePandaHouseNetwork {
.iter()
.find(|network| network.name == PANDA_NETWORK)
.ok_or_else(|| {
RoutineFailure::new(
Message::new(
"Failed".to_string(),
"to find panda house docker network".to_string(),
),
Error::new(
ErrorKind::Other,
"Failed to validate panda house docker network",
),
)
RoutineFailure::error(Message::new(
"Failed".to_string(),
"to find panda house docker network".to_string(),
))
})?;

Ok(RoutineSuccess::success(Message::new(
Expand Down Expand Up @@ -144,13 +125,10 @@ impl Routine for ValidateRedPandaCluster {
"validated red panda cluster".to_string(),
)))
} else {
Err(RoutineFailure::new(
Message::new(
"Failed".to_string(),
"to validate red panda cluster".to_string(),
),
Error::new(ErrorKind::Other, "Failed to validate red panda cluster"),
))
Err(RoutineFailure::error(Message::new(
"Failed".to_string(),
"to validate red panda cluster".to_string(),
)))
}
}
}
24 changes: 23 additions & 1 deletion apps/igloo-kit-cli/src/utilities/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use crate::infrastructure::olap::clickhouse::config::ClickhouseConfig;
use crate::utilities::constants::PANDA_NETWORK;
use serde::{Deserialize, Serialize};
use serde_json::from_str;
use serde_json::{from_slice, from_str};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
Expand Down Expand Up @@ -357,6 +357,28 @@ fn start_container(name: &str) -> std::io::Result<String> {
output_to_result(output)
}

pub fn check_status() -> std::io::Result<Vec<String>> {
let child = Command::new("docker")
.arg("info")
.arg("--format")
.arg("{{json .ServerErrors}}")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()?;

let output = child.wait_with_output()?;

if !output.status.success() {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Failed to get Docker info",
));
}

let errors: Option<Vec<String>> = from_slice(&output.stdout)?;
Ok(errors.unwrap_or_default())
}

fn output_to_result(output: std::process::Output) -> std::io::Result<String> {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
Expand Down

0 comments on commit 5404aa6

Please sign in to comment.