This commit is contained in:
Benjamin Chastanier
2022-02-16 17:25:31 +01:00
parent 3244aaa1ae
commit d2c331552c
12 changed files with 407 additions and 141 deletions

View File

@@ -14,10 +14,9 @@ use crate::cloud_provider::utilities::{print_action, sanitize_name};
use crate::cloud_provider::DeploymentTarget;
use crate::cmd::helm::Timeout;
use crate::cmd::kubectl::ScalingKind::{Deployment, Statefulset};
use crate::error::EngineErrorCause::Internal;
use crate::error::{EngineError, EngineErrorScope};
use crate::events::{EnvironmentStep, Stage, ToTransmitter, Transmitter};
use crate::logger::Logger;
use crate::errors::EngineError;
use crate::events::{EngineEvent, EnvironmentStep, EventMessage, Stage, ToTransmitter, Transmitter};
use crate::logger::{LogLevel, Logger};
use crate::models::{Context, Listen, Listener, Listeners, ListenersHelper, Port};
use ::function_name::named;
@@ -92,7 +91,7 @@ impl<'a> Application<'a> {
}
}
impl crate::cloud_provider::service::Application for Application {
impl<'a> crate::cloud_provider::service::Application<'a> for Application<'a> {
fn image(&self) -> &Image {
&self.image
}
@@ -102,7 +101,7 @@ impl crate::cloud_provider::service::Application for Application {
}
}
impl Helm for Application {
impl<'a> Helm for Application<'a> {
fn helm_selector(&self) -> Option<String> {
self.selector()
}
@@ -124,15 +123,15 @@ impl Helm for Application {
}
}
impl StatelessService for Application {}
impl<'a> StatelessService<'a> for Application<'a> {}
impl ToTransmitter for Application {
impl<'a> ToTransmitter for Application<'a> {
fn to_transmitter(&self) -> Transmitter {
Transmitter::Application(self.id.to_string(), self.name.to_string())
}
}
impl Service for Application {
impl<'a> Service for Application<'a> {
fn context(&self) -> &Context {
&self.context
}
@@ -197,6 +196,7 @@ impl Service for Application {
}
fn tera_context(&self, target: &DeploymentTarget) -> Result<TeraContext, EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::LoadConfiguration));
let mut context = default_tera_context(self, target.kubernetes, target.environment);
let commit_id = self.image().commit_id.as_str();
@@ -206,10 +206,18 @@ impl Service for Application {
Some(registry_url) => context.insert("image_name_with_tag", registry_url.as_str()),
None => {
let image_name_with_tag = self.image().name_with_tag();
warn!(
"there is no registry url, use image name with tag with the default container registry: {}",
image_name_with_tag.as_str()
self.logger().log(
LogLevel::Warning,
EngineEvent::Warning(
event_details.clone(),
EventMessage::new_from_safe(format!(
"there is no registry url, use image name with tag with the default container registry: {}",
image_name_with_tag.as_str()
)),
),
);
context.insert("image_name_with_tag", image_name_with_tag.as_str());
}
}
@@ -242,14 +250,16 @@ impl Service for Application {
&self.id,
self.total_cpus(),
self.cpu_burst(),
event_details.clone(),
self.logger(),
) {
Ok(l) => l,
Err(e) => {
return Err(EngineError::new(
Internal,
EngineErrorScope::Application(self.id().to_string(), self.name().to_string()),
self.context.execution_id(),
Some(e.to_string()),
return Err(EngineError::new_k8s_validate_required_cpu_and_burstable_error(
event_details.clone(),
self.total_cpus(),
self.cpu_burst(),
e,
));
}
};
@@ -301,7 +311,7 @@ impl Service for Application {
}
}
impl Create for Application {
impl<'a> Create for Application<'a> {
#[named]
fn on_create(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
@@ -310,9 +320,11 @@ impl Create for Application {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
deploy_user_stateless_service(target, self, event_details.clone())
deploy_user_stateless_service(target, self, event_details)
})
}
@@ -322,11 +334,14 @@ impl Create for Application {
#[named]
fn on_create_error(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
@@ -335,14 +350,17 @@ impl Create for Application {
}
}
impl Pause for Application {
impl<'a> Pause for Application<'a> {
#[named]
fn on_pause(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Pause, || {
@@ -361,18 +379,21 @@ impl Pause for Application {
#[named]
fn on_pause_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Delete for Application {
impl<'a> Delete for Application<'a> {
#[named]
fn on_delete(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
@@ -381,10 +402,12 @@ impl Delete for Application {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Delete, || {
delete_stateless_service(target, self, false, event_details.clone())
delete_stateless_service(target, self, false, event_details)
})
}
@@ -400,15 +423,17 @@ impl Delete for Application {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Delete, || {
delete_stateless_service(target, self, true, event_details.clone())
delete_stateless_service(target, self, true, event_details)
})
}
}
impl Listen for Application {
impl<'a> Listen for Application<'a> {
fn listeners(&self) -> &Listeners {
&self.listeners
}

View File

@@ -293,7 +293,7 @@ impl<'a> Create for MongoDB<'a> {
function_name!(),
self.name(),
event_details.clone(),
self.logger,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
@@ -307,11 +307,14 @@ impl<'a> Create for MongoDB<'a> {
#[named]
fn on_create_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
@@ -320,11 +323,14 @@ impl<'a> Create for MongoDB<'a> {
impl<'a> Pause for MongoDB<'a> {
#[named]
fn on_pause(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Pause, || {
@@ -338,11 +344,14 @@ impl<'a> Pause for MongoDB<'a> {
#[named]
fn on_pause_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
@@ -358,6 +367,8 @@ impl<'a> Delete for MongoDB<'a> {
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Delete, || {
@@ -371,11 +382,14 @@ impl<'a> Delete for MongoDB<'a> {
#[named]
fn on_delete_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}

View File

@@ -6,7 +6,7 @@ use crate::cloud_provider::aws::databases::utilities::{aws_final_snapshot_name,
use crate::cloud_provider::service::{
check_service_version, default_tera_context, delete_stateful_service, deploy_stateful_service, get_tfstate_name,
get_tfstate_suffix, scale_down_database, send_progress_on_long_task, Action, Create, Database, DatabaseOptions,
DatabaseType, Delete, Helm, Pause, Service, ServiceType, StatefulService, Terraform,
DatabaseType, Delete, Helm, Pause, Service, ServiceType, ServiceVersionCheckResult, StatefulService, Terraform,
};
use crate::cloud_provider::utilities::{
generate_supported_version, get_self_hosted_mysql_version, get_supported_version_to_use, managed_db_name_sanitizer,
@@ -15,13 +15,14 @@ use crate::cloud_provider::utilities::{
use crate::cloud_provider::DeploymentTarget;
use crate::cmd::helm::Timeout;
use crate::cmd::kubectl;
use crate::error::{EngineError, EngineErrorCause, EngineErrorScope, StringError};
use crate::events::{EnvironmentStep, Stage, ToTransmitter, Transmitter};
use crate::errors::{CommandError, EngineError};
use crate::events::{EnvironmentStep, EventDetails, Stage, ToTransmitter, Transmitter};
use crate::logger::Logger;
use crate::models::DatabaseMode::MANAGED;
use crate::models::{Context, DatabaseKind, Listen, Listener, Listeners};
use ::function_name::named;
pub struct MySQL {
pub struct MySQL<'a> {
context: Context,
id: String,
action: Action,
@@ -34,9 +35,10 @@ pub struct MySQL {
database_instance_type: String,
options: DatabaseOptions,
listeners: Listeners,
logger: &'a dyn Logger,
}
impl MySQL {
impl<'a> MySQL<'a> {
pub fn new(
context: Context,
id: &str,
@@ -50,6 +52,7 @@ impl MySQL {
database_instance_type: &str,
options: DatabaseOptions,
listeners: Listeners,
logger: &dyn Logger,
) -> Self {
Self {
context,
@@ -64,11 +67,20 @@ impl MySQL {
database_instance_type: database_instance_type.to_string(),
options,
listeners,
logger,
}
}
fn matching_correct_version(&self, is_managed_services: bool) -> Result<String, EngineError> {
check_service_version(get_mysql_version(self.version(), is_managed_services), self)
fn matching_correct_version(
&self,
is_managed_services: bool,
event_details: EventDetails,
) -> Result<ServiceVersionCheckResult, EngineError> {
check_service_version(
get_mysql_version(self.version(), is_managed_services),
self,
event_details,
)
}
fn cloud_provider_name(&self) -> &str {
@@ -161,17 +173,13 @@ impl Service for MySQL {
}
fn tera_context(&self, target: &DeploymentTarget) -> Result<TeraContext, EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::LoadConfiguration));
let kubernetes = target.kubernetes;
let environment = target.environment;
let mut context = default_tera_context(self, kubernetes, environment);
// we need the kubernetes config file to store tfstates file in kube secrets
let kube_config_file_path = match kubernetes.get_kubeconfig_file_path() {
Ok(path) => path,
Err(e) => {
return Err(e.to_legacy_engine_error());
}
};
let kube_config_file_path = kubernetes.get_kubeconfig_file_path()?;
context.insert("kubeconfig_path", &kube_config_file_path);
kubectl::kubectl_exec_create_namespace_without_labels(
@@ -182,21 +190,23 @@ impl Service for MySQL {
context.insert("namespace", environment.namespace());
let version = &self.matching_correct_version(self.is_managed_service())?;
let version = &self.matching_correct_version(self.is_managed_service(), event_details.clone())?;
context.insert("version", &version);
if self.is_managed_service() {
let parameter_group_family = match get_parameter_group_from_version(&version, DatabaseKind::Mysql) {
Ok(v) => v,
Err(e) => {
return Err(EngineError {
cause: EngineErrorCause::Internal,
scope: EngineErrorScope::Engine,
execution_id: (&self.context.execution_id()).to_string(),
message: Some(e),
})
}
};
let parameter_group_family =
match get_parameter_group_from_version(&version.matched_version(), DatabaseKind::Mysql) {
Ok(v) => v,
Err(e) => {
return Err(EngineError::new_terraform_unsupported_context_parameter_value(
event_details.clone(),
"MySQL".to_string(),
"parameter_group_family".to_string(),
version.matched_version(),
Some(e),
))
}
};
context.insert("parameter_group_family", &parameter_group_family);
};
@@ -242,6 +252,10 @@ impl Service for MySQL {
Ok(context)
}
fn logger(&self) -> &dyn Logger {
self.logger
}
fn selector(&self) -> Option<String> {
Some(format!("app={}", self.sanitized_name()))
}
@@ -290,10 +304,12 @@ impl Create for MySQL {
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
deploy_stateful_service(target, self, event_details.clone())
deploy_stateful_service(target, self, event_details.clone(), self.logger)
})
}
@@ -303,11 +319,14 @@ impl Create for MySQL {
#[named]
fn on_create_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
@@ -317,11 +336,14 @@ impl Create for MySQL {
impl Pause for MySQL {
#[named]
fn on_pause(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Pause, || {
@@ -335,11 +357,14 @@ impl Pause for MySQL {
#[named]
fn on_pause_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
@@ -354,10 +379,12 @@ impl Delete for MySQL {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Delete, || {
delete_stateful_service(target, self, event_details.clone())
delete_stateful_service(target, self, event_details, self.logger)
})
}
@@ -367,11 +394,14 @@ impl Delete for MySQL {
#[named]
fn on_delete_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
@@ -387,7 +417,7 @@ impl Listen for MySQL {
}
}
fn get_mysql_version(requested_version: String, is_managed_service: bool) -> Result<String, StringError> {
fn get_mysql_version(requested_version: String, is_managed_service: bool) -> Result<String, CommandError> {
if is_managed_service {
get_managed_mysql_version(requested_version)
} else {
@@ -395,7 +425,7 @@ fn get_mysql_version(requested_version: String, is_managed_service: bool) -> Res
}
}
fn get_managed_mysql_version(requested_version: String) -> Result<String, StringError> {
fn get_managed_mysql_version(requested_version: String) -> Result<String, CommandError> {
let mut supported_mysql_versions = HashMap::new();
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt
@@ -424,6 +454,7 @@ fn get_managed_mysql_version(requested_version: String) -> Result<String, String
mod tests_mysql {
use crate::cloud_provider::aws::databases::mysql::{get_mysql_version, MySQL};
use crate::cloud_provider::service::{Action, DatabaseOptions, Service};
use crate::logger::StdIoLogger;
use crate::models::{Context, DatabaseMode};
#[test]
@@ -486,6 +517,7 @@ mod tests_mysql {
publicly_accessible: false,
},
vec![],
&StdIoLogger::new(),
);
assert_eq!(database.sanitized_name(), db_expected_name);
}

View File

@@ -6,7 +6,7 @@ use tera::Context as TeraContext;
use crate::cloud_provider::service::{
check_service_version, default_tera_context, delete_stateful_service, deploy_stateful_service, get_tfstate_name,
get_tfstate_suffix, scale_down_database, send_progress_on_long_task, Action, Create, Database, DatabaseOptions,
DatabaseType, Delete, Helm, Pause, Service, ServiceType, StatefulService, Terraform,
DatabaseType, Delete, Helm, Pause, Service, ServiceType, ServiceVersionCheckResult, StatefulService, Terraform,
};
use crate::cloud_provider::utilities::{
generate_supported_version, get_self_hosted_postgres_version, get_supported_version_to_use,
@@ -15,13 +15,14 @@ use crate::cloud_provider::utilities::{
use crate::cloud_provider::DeploymentTarget;
use crate::cmd::helm::Timeout;
use crate::cmd::kubectl;
use crate::errors::EngineError;
use crate::events::{EnvironmentStep, Stage, ToTransmitter, Transmitter};
use crate::errors::{CommandError, EngineError};
use crate::events::{EnvironmentStep, EventDetails, Stage, ToTransmitter, Transmitter};
use crate::logger::Logger;
use crate::models::DatabaseMode::MANAGED;
use crate::models::{Context, Listen, Listener, Listeners};
use ::function_name::named;
pub struct PostgreSQL {
pub struct PostgreSQL<'a> {
context: Context,
id: String,
action: Action,
@@ -34,9 +35,10 @@ pub struct PostgreSQL {
database_instance_type: String,
options: DatabaseOptions,
listeners: Listeners,
logger: &'a dyn Logger,
}
impl PostgreSQL {
impl<'a> PostgreSQL<'a> {
pub fn new(
context: Context,
id: &str,
@@ -50,6 +52,7 @@ impl PostgreSQL {
database_instance_type: &str,
options: DatabaseOptions,
listeners: Listeners,
logger: &dyn Logger,
) -> Self {
PostgreSQL {
context,
@@ -64,11 +67,20 @@ impl PostgreSQL {
database_instance_type: database_instance_type.to_string(),
options,
listeners,
logger,
}
}
fn matching_correct_version(&self, is_managed_services: bool) -> Result<String, EngineError> {
check_service_version(get_postgres_version(self.version(), is_managed_services), self)
fn matching_correct_version(
&self,
is_managed_services: bool,
event_details: EventDetails,
) -> Result<ServiceVersionCheckResult, EngineError> {
check_service_version(
get_postgres_version(self.version(), is_managed_services),
self,
event_details,
)
}
fn cloud_provider_name(&self) -> &str {
@@ -80,13 +92,13 @@ impl PostgreSQL {
}
}
impl StatefulService for PostgreSQL {
impl<'a> StatefulService for PostgreSQL<'a> {
fn is_managed_service(&self) -> bool {
self.options.mode == MANAGED
}
}
impl ToTransmitter for PostgreSQL {
impl<'a> ToTransmitter for PostgreSQL<'a> {
fn to_transmitter(&self) -> Transmitter {
Transmitter::Database(
self.id().to_string(),
@@ -96,7 +108,7 @@ impl ToTransmitter for PostgreSQL {
}
}
impl Service for PostgreSQL {
impl<'a> Service for PostgreSQL<'a> {
fn context(&self) -> &Context {
&self.context
}
@@ -161,17 +173,13 @@ impl Service for PostgreSQL {
}
fn tera_context(&self, target: &DeploymentTarget) -> Result<TeraContext, EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::LoadConfiguration));
let kubernetes = target.kubernetes;
let environment = target.environment;
let mut context = default_tera_context(self, kubernetes, environment);
// we need the kubernetes config file to store tfstates file in kube secrets
let kube_config_file_path = match kubernetes.get_kubeconfig_file_path() {
Ok(path) => path,
Err(e) => {
return Err(e.to_legacy_engine_error());
}
};
let kube_config_file_path = kubernetes.get_kubeconfig_file_path()?;
context.insert("kubeconfig_path", &kube_config_file_path);
kubectl::kubectl_exec_create_namespace_without_labels(
@@ -182,7 +190,7 @@ impl Service for PostgreSQL {
context.insert("namespace", environment.namespace());
let version = self.matching_correct_version(self.is_managed_service())?;
let version = self.matching_correct_version(self.is_managed_service(), event_details.clone())?;
context.insert("version", &version);
for (k, v) in kubernetes.cloud_provider().tera_context_environment_variables() {
@@ -229,14 +237,18 @@ impl Service for PostgreSQL {
Ok(context)
}
fn logger(&self) -> &dyn Logger {
self.logger
}
fn selector(&self) -> Option<String> {
Some(format!("app={}", self.sanitized_name()))
}
}
impl Database for PostgreSQL {}
impl<'a> Database for PostgreSQL<'a> {}
impl Helm for PostgreSQL {
impl<'a> Helm for PostgreSQL<'a> {
fn helm_selector(&self) -> Option<String> {
self.selector()
}
@@ -258,7 +270,7 @@ impl Helm for PostgreSQL {
}
}
impl Terraform for PostgreSQL {
impl<'a> Terraform for PostgreSQL<'a> {
fn terraform_common_resource_dir_path(&self) -> String {
format!("{}/aws/services/common", self.context.lib_root_dir())
}
@@ -268,7 +280,7 @@ impl Terraform for PostgreSQL {
}
}
impl Create for PostgreSQL {
impl<'a> Create for PostgreSQL<'a> {
#[named]
fn on_create(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
@@ -277,10 +289,12 @@ impl Create for PostgreSQL {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
deploy_stateful_service(target, self, event_details.clone())
deploy_stateful_service(target, self, event_details, self.logger)
})
}
@@ -290,25 +304,31 @@ impl Create for PostgreSQL {
#[named]
fn on_create_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Pause for PostgreSQL {
impl<'a> Pause for PostgreSQL<'a> {
#[named]
fn on_pause(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Pause, || {
@@ -322,18 +342,21 @@ impl Pause for PostgreSQL {
#[named]
fn on_pause_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Delete for PostgreSQL {
impl<'a> Delete for PostgreSQL<'a> {
#[named]
fn on_delete(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
@@ -342,10 +365,12 @@ impl Delete for PostgreSQL {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Delete, || {
delete_stateful_service(target, self, event_details.clone())
delete_stateful_service(target, self, event_details, self.logger)
})
}
@@ -355,18 +380,21 @@ impl Delete for PostgreSQL {
#[named]
fn on_delete_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
Ok(())
}
}
impl Listen for PostgreSQL {
impl<'a> Listen for PostgreSQL<'a> {
fn listeners(&self) -> &Listeners {
&self.listeners
}
@@ -376,7 +404,7 @@ impl Listen for PostgreSQL {
}
}
fn get_postgres_version(requested_version: String, is_managed_service: bool) -> Result<String, StringError> {
fn get_postgres_version(requested_version: String, is_managed_service: bool) -> Result<String, CommandError> {
if is_managed_service {
get_managed_postgres_version(requested_version)
} else {
@@ -384,7 +412,7 @@ fn get_postgres_version(requested_version: String, is_managed_service: bool) ->
}
}
fn get_managed_postgres_version(requested_version: String) -> Result<String, StringError> {
fn get_managed_postgres_version(requested_version: String) -> Result<String, CommandError> {
let mut supported_postgres_versions = HashMap::new();
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts
@@ -415,6 +443,7 @@ fn get_managed_postgres_version(requested_version: String) -> Result<String, Str
mod tests_postgres {
use crate::cloud_provider::aws::databases::postgresql::{get_postgres_version, PostgreSQL};
use crate::cloud_provider::service::{Action, DatabaseOptions, Service};
use crate::logger::StdIoLogger;
use crate::models::{Context, DatabaseMode};
#[test]
@@ -480,6 +509,7 @@ mod tests_postgres {
publicly_accessible: false,
},
vec![],
&StdIoLogger::new(),
);
assert_eq!(database.sanitized_name(), db_expected_name);
}

View File

@@ -12,14 +12,14 @@ use crate::cloud_provider::utilities::{get_self_hosted_redis_version, get_suppor
use crate::cloud_provider::DeploymentTarget;
use crate::cmd::helm::Timeout;
use crate::cmd::kubectl;
use crate::error::EngineErrorScope::Engine;
use crate::errors::{CommandError, EngineError};
use crate::events::{EnvironmentStep, EventDetails, Stage, ToTransmitter, Transmitter};
use crate::logger::Logger;
use crate::models::DatabaseMode::MANAGED;
use crate::models::{Context, Listen, Listener, Listeners};
use ::function_name::named;
pub struct Redis {
pub struct Redis<'a> {
context: Context,
id: String,
action: Action,
@@ -32,9 +32,10 @@ pub struct Redis {
database_instance_type: String,
options: DatabaseOptions,
listeners: Listeners,
logger: &'a dyn Logger,
}
impl Redis {
impl<'a> Redis<'a> {
pub fn new(
context: Context,
id: &str,
@@ -48,6 +49,7 @@ impl Redis {
database_instance_type: &str,
options: DatabaseOptions,
listeners: Listeners,
logger: &'a dyn Logger,
) -> Self {
Self {
context,
@@ -62,6 +64,7 @@ impl Redis {
database_instance_type: database_instance_type.to_string(),
options,
listeners,
logger,
}
}
@@ -86,13 +89,13 @@ impl Redis {
}
}
impl StatefulService for Redis {
impl<'a> StatefulService for Redis<'a> {
fn is_managed_service(&self) -> bool {
self.options.mode == MANAGED
}
}
impl ToTransmitter for Redis {
impl<'a> ToTransmitter for Redis<'a> {
fn to_transmitter(&self) -> Transmitter {
Transmitter::Database(
self.id().to_string(),
@@ -102,7 +105,7 @@ impl ToTransmitter for Redis {
}
}
impl Service for Redis {
impl<'a> Service for Redis<'a> {
fn context(&self) -> &Context {
&self.context
}
@@ -203,6 +206,7 @@ impl Service for Redis {
"Elasicache".to_string(),
"database_elasticache_parameter_group_name".to_string(),
format!("default.redis{}", version),
None,
));
};
@@ -251,14 +255,18 @@ impl Service for Redis {
Ok(context)
}
fn logger(&self) -> &dyn Logger {
self.logger
}
fn selector(&self) -> Option<String> {
Some(format!("app={}", self.sanitized_name()))
}
}
impl Database for Redis {}
impl<'a> Database for Redis<'a> {}
impl Helm for Redis {
impl<'a> Helm for Redis<'a> {
fn helm_selector(&self) -> Option<String> {
self.selector()
}
@@ -280,7 +288,7 @@ impl Helm for Redis {
}
}
impl Terraform for Redis {
impl<'a> Terraform for Redis<'a> {
fn terraform_common_resource_dir_path(&self) -> String {
format!("{}/aws/services/common", self.context.lib_root_dir())
}
@@ -290,7 +298,7 @@ impl Terraform for Redis {
}
}
impl Create for Redis {
impl<'a> Create for Redis<'a> {
#[named]
fn on_create(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
@@ -299,10 +307,12 @@ impl Create for Redis {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
deploy_stateful_service(target, self, event_details.clone(), self.logger())
deploy_stateful_service(target, self, event_details, self.logger())
})
}
@@ -312,24 +322,30 @@ impl Create for Redis {
#[named]
fn on_create_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Pause for Redis {
impl<'a> Pause for Redis<'a> {
#[named]
fn on_pause(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Pause, || {
@@ -343,18 +359,21 @@ impl Pause for Redis {
#[named]
fn on_pause_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Delete for Redis {
impl<'a> Delete for Redis<'a> {
#[named]
fn on_delete(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
@@ -363,10 +382,12 @@ impl Delete for Redis {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Delete, || {
delete_stateful_service(target, self, event_details.clone(), self.logger())
delete_stateful_service(target, self, event_details, self.logger())
})
}
@@ -376,17 +397,20 @@ impl Delete for Redis {
#[named]
fn on_delete_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Listen for Redis {
impl<'a> Listen for Redis<'a> {
fn listeners(&self) -> &Listeners {
&self.listeners
}
@@ -418,6 +442,7 @@ fn get_managed_redis_version(requested_version: String) -> Result<String, Comman
mod tests {
use crate::cloud_provider::aws::databases::redis::{get_redis_version, Redis};
use crate::cloud_provider::service::{Action, DatabaseOptions, Service};
use crate::logger::StdIoLogger;
use crate::models::{Context, DatabaseMode};
#[test]
@@ -479,6 +504,7 @@ mod tests {
publicly_accessible: false,
},
vec![],
&StdIoLogger::new(),
);
assert_eq!(database.sanitized_name(), db_expected_name);
}

View File

@@ -1,20 +1,21 @@
use crate::cloud_provider::utilities::VersionsNumber;
use crate::error::StringError;
use crate::errors::CommandError;
use crate::models::DatabaseKind;
use std::str::FromStr;
pub fn get_parameter_group_from_version(version: &str, database_kind: DatabaseKind) -> Result<String, StringError> {
pub fn get_parameter_group_from_version(version: &str, database_kind: DatabaseKind) -> Result<String, CommandError> {
let version_number = match VersionsNumber::from_str(version) {
Ok(v) => {
if v.minor.is_none() {
return Err(format!(
return Err(CommandError::new_from_safe_message(format!(
"Can't determine the minor version, to select parameter group for {:?} version {}",
database_kind, version
));
)));
};
v
}
Err(e) => return Err(e),
Err(e) => return Err(CommandError::new_from_safe_message(e.to_string())),
};
match database_kind {

View File

@@ -7,7 +7,6 @@ use uuid::Uuid;
use crate::cloud_provider::{CloudProvider, EngineError, Kind, TerraformStateCredentials};
use crate::constants::{AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY};
use crate::error::EngineErrorCause;
use crate::models::{Context, Listen, Listener, Listeners};
use crate::runtime::block_on;

View File

@@ -9,8 +9,8 @@ use crate::cloud_provider::utilities::{check_cname_for, print_action, sanitize_n
use crate::cloud_provider::DeploymentTarget;
use crate::cmd::helm::Timeout;
use crate::errors::EngineError;
use crate::events::{EnvironmentStep, Stage, ToTransmitter, Transmitter};
use crate::logger::Logger;
use crate::events::{EngineEvent, EnvironmentStep, EventMessage, Stage, ToTransmitter, Transmitter};
use crate::logger::{LogLevel, Logger};
use crate::models::{Context, Listen, Listener, Listeners};
use ::function_name::named;
@@ -125,6 +125,7 @@ impl<'a> Service for Router<'a> {
}
fn tera_context(&self, target: &DeploymentTarget) -> Result<TeraContext, EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::LoadConfiguration));
let kubernetes = target.kubernetes;
let environment = target.environment;
let mut context = default_tera_context(self, kubernetes, environment);
@@ -190,12 +191,22 @@ impl<'a> Service for Router<'a> {
Ok(external_ingress_hostname_default) => match external_ingress_hostname_default {
Some(hostname) => context.insert("external_ingress_hostname_default", hostname.as_str()),
None => {
warn!("unable to get external_ingress_hostname_default - what's wrong? This must never happened");
// TODO(benjaminch): Handle better this one via a proper error eventually
self.logger().log(LogLevel::Warning, EngineEvent::Warning(event_details.clone(), EventMessage::new_from_safe("unable to get external_ingress_hostname_default - what's wrong? This must never happened".to_string())));
}
},
_ => {
// FIXME really?
warn!("can't fetch kubernetes config file - what's wrong? This must never happened");
// TODO(benjaminch): Handle better this one via a proper error eventually
self.logger().log(
LogLevel::Warning,
EngineEvent::Warning(
event_details.clone(),
EventMessage::new_from_safe(
"can't fetch kubernetes config file - what's wrong? This must never happened".to_string(),
),
),
);
}
}
@@ -231,7 +242,7 @@ impl<'a> Service for Router<'a> {
}
}
impl crate::cloud_provider::service::Router for Router {
impl<'a> crate::cloud_provider::service::Router for Router<'a> {
fn domains(&self) -> Vec<&str> {
let mut _domains = vec![self.default_domain.as_str()];
@@ -247,7 +258,7 @@ impl crate::cloud_provider::service::Router for Router {
}
}
impl Helm for Router {
impl<'a> Helm for Router<'a> {
fn helm_selector(&self) -> Option<String> {
self.selector()
}
@@ -269,7 +280,7 @@ impl Helm for Router {
}
}
impl Listen for Router {
impl<'a> Listen for Router<'a> {
fn listeners(&self) -> &Listeners {
&self.listeners
}
@@ -279,24 +290,26 @@ impl Listen for Router {
}
}
impl StatelessService for Router {}
impl<'a> StatelessService for Router<'a> {}
impl ToTransmitter for Router {
impl<'a> ToTransmitter for Router<'a> {
fn to_transmitter(&self) -> Transmitter {
Transmitter::Router(self.id().to_string(), self.name().to_string())
}
}
impl Create for Router {
impl<'a> Create for Router<'a> {
#[named]
fn on_create(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
let kubernetes = target.kubernetes;
let environment = target.environment;
let workspace_dir = self.workspace_directory();
@@ -341,6 +354,8 @@ impl Create for Router {
}
fn on_create_check(&self) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
// check non custom domains
self.check_domains()?;
@@ -356,9 +371,19 @@ impl Create for Router {
continue
}
Ok(err) | Err(err) => {
warn!(
"Invalid CNAME for {}. Might not be an issue if user is using a CDN: {}",
domain_to_check.domain, err
// TODO(benjaminch): Handle better this one via a proper error eventually
self.logger().log(
LogLevel::Warning,
EngineEvent::Warning(
event_details.clone(),
EventMessage::new(
format!(
"Invalid CNAME for {}. Might not be an issue if user is using a CDN.",
domain_to_check.domain,
),
Some(err.to_string()),
),
),
);
}
}
@@ -369,11 +394,14 @@ impl Create for Router {
#[named]
fn on_create_error(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Deploy));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
send_progress_on_long_task(self, crate::cloud_provider::service::Action::Create, || {
@@ -382,9 +410,18 @@ impl Create for Router {
}
}
impl Pause for Router {
impl<'a> Pause for Router<'a> {
#[named]
fn on_pause(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
info!("AWS.router.on_pause() called for {}, doing nothing", self.name());
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
@@ -394,17 +431,20 @@ impl Pause for Router {
#[named]
fn on_pause_error(&self, _target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Pause));
print_action(
self.cloud_provider_name(),
self.struct_name(),
function_name!(),
self.name(),
event_details,
self.logger(),
);
Ok(())
}
}
impl Delete for Router {
impl<'a> Delete for Router<'a> {
#[named]
fn on_delete(&self, target: &DeploymentTarget) -> Result<(), EngineError> {
let event_details = self.get_event_details(Stage::Environment(EnvironmentStep::Delete));
@@ -413,6 +453,8 @@ impl Delete for Router {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
delete_router(target, self, false, event_details)
}
@@ -429,6 +471,8 @@ impl Delete for Router {
self.struct_name(),
function_name!(),
self.name(),
event_details.clone(),
self.logger(),
);
delete_router(target, self, true, event_details)
}

View File

@@ -16,7 +16,6 @@ use serde::{Deserialize, Serialize};
use crate::cloud_provider::aws::regions::AwsZones;
use crate::cloud_provider::environment::Environment;
use crate::cloud_provider::models::NodeGroups;
use crate::cloud_provider::models::{CpuLimits, NodeGroups};
use crate::cloud_provider::service::CheckAction;
use crate::cloud_provider::utilities::VersionsNumber;
@@ -100,7 +99,8 @@ pub trait Kubernetes: Listen {
.to_string(),
),
);
self.logger().log(LogLevel::Error, EngineEvent::Error(error.clone()));
self.logger()
.log(LogLevel::Error, EngineEvent::Error(error.clone(), None));
return Err(error);
}
};
@@ -114,7 +114,8 @@ pub trait Kubernetes: Listen {
format!("Error getting file metadata, error: {}", err.to_string(),).to_string(),
),
);
self.logger().log(LogLevel::Error, EngineEvent::Error(error.clone()));
self.logger()
.log(LogLevel::Error, EngineEvent::Error(error.clone(), None));
return Err(error);
}
};
@@ -129,7 +130,8 @@ pub trait Kubernetes: Listen {
err.to_string(),
)),
);
self.logger().log(LogLevel::Error, EngineEvent::Error(error.clone()));
self.logger()
.log(LogLevel::Error, EngineEvent::Error(error.clone(), None));
return Err(error);
}
@@ -158,7 +160,8 @@ pub trait Kubernetes: Listen {
),
);
self.logger().log(LogLevel::Error, EngineEvent::Error(error.clone()));
self.logger()
.log(LogLevel::Error, EngineEvent::Error(error.clone(), None));
return Err(error);
}
@@ -367,6 +370,7 @@ pub fn deploy_environment(
kubernetes: &dyn Kubernetes,
environment: &Environment,
event_details: EventDetails,
logger: &dyn Logger,
) -> Result<(), EngineError> {
let listeners_helper = ListenersHelper::new(kubernetes.listeners());
@@ -397,6 +401,7 @@ pub fn deploy_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"deployment",
@@ -409,6 +414,7 @@ pub fn deploy_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"check deployment",
@@ -432,6 +438,7 @@ pub fn deploy_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"deployment",
@@ -447,6 +454,7 @@ pub fn deploy_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"check deployment",
@@ -462,6 +470,7 @@ pub fn deploy_environment_error(
kubernetes: &dyn Kubernetes,
environment: &Environment,
event_details: EventDetails,
logger: &dyn Logger,
) -> Result<(), EngineError> {
let listeners_helper = ListenersHelper::new(kubernetes.listeners());
@@ -486,6 +495,7 @@ pub fn deploy_environment_error(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"revert deployment",
@@ -509,6 +519,7 @@ pub fn deploy_environment_error(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"revert deployment",
@@ -524,6 +535,7 @@ pub fn pause_environment(
kubernetes: &dyn Kubernetes,
environment: &Environment,
event_details: EventDetails,
logger: &dyn Logger,
) -> Result<(), EngineError> {
let listeners_helper = ListenersHelper::new(kubernetes.listeners());
@@ -545,6 +557,7 @@ pub fn pause_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"pause",
@@ -562,6 +575,7 @@ pub fn pause_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"pause",
@@ -578,6 +592,7 @@ pub fn pause_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"check pause",
@@ -595,6 +610,7 @@ pub fn pause_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"check pause",
@@ -610,6 +626,7 @@ pub fn delete_environment(
kubernetes: &dyn Kubernetes,
environment: &Environment,
event_details: EventDetails,
logger: &dyn Logger,
) -> Result<(), EngineError> {
let listeners_helper = ListenersHelper::new(kubernetes.listeners());
@@ -631,6 +648,7 @@ pub fn delete_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"delete",
@@ -648,6 +666,7 @@ pub fn delete_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"delete",
@@ -664,6 +683,7 @@ pub fn delete_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateless_deployment_target,
&listeners_helper,
"delete check",
@@ -681,6 +701,7 @@ pub fn delete_environment(
kubernetes,
service,
event_details.clone(),
logger,
&stateful_deployment_target,
&listeners_helper,
"delete check",
@@ -1340,6 +1361,8 @@ pub fn validate_k8s_required_cpu_and_burstable(
context_id: &str,
total_cpu: String,
cpu_burst: String,
event_details: EventDetails,
logger: &dyn Logger,
) -> Result<CpuLimits, CommandError> {
let total_cpu_float = convert_k8s_cpu_value_to_f32(total_cpu.clone())?;
let cpu_burst_float = convert_k8s_cpu_value_to_f32(cpu_burst.clone())?;
@@ -1347,9 +1370,8 @@ pub fn validate_k8s_required_cpu_and_burstable(
if cpu_burst_float < total_cpu_float {
let message = format!(
"CPU burst value '{}' was lower than the desired total of CPUs {}, using burstable value. Please ensure your configuration is valid",
cpu_burst,
total_cpu,
"CPU burst value '{}' was lower than the desired total of CPUs {}, using burstable value.",
cpu_burst, total_cpu,
);
listener_helper.error(ProgressInfo::new(
@@ -1357,10 +1379,15 @@ pub fn validate_k8s_required_cpu_and_burstable(
id: execution_id.to_string(),
},
ProgressLevel::Warn,
Some(message),
Some(message.to_string()),
context_id,
));
logger.log(
LogLevel::Warning,
EngineEvent::Warning(event_details, EventMessage::new_from_safe(message)),
);
set_cpu_burst = total_cpu.clone();
}
@@ -1380,7 +1407,10 @@ pub fn convert_k8s_cpu_value_to_f32(value: String) -> Result<f32, CommandError>
}
Err(e) => Err(CommandError::new(
e.to_string(),
Some(format!("Error while trying to parse `{}` to float 32.", m.as_str())),
Some(format!(
"Error while trying to parse `{}` to float 32.",
value_number_string.as_str()
)),
)),
};
}
@@ -1389,13 +1419,14 @@ pub fn convert_k8s_cpu_value_to_f32(value: String) -> Result<f32, CommandError>
Ok(n) => Ok(n),
Err(e) => Err(CommandError::new(
e.to_string(),
Some(format!("Error while trying to parse `{}` to float 32.", m.as_str())),
Some(format!("Error while trying to parse `{}` to float 32.", value.as_str())),
)),
}
}
#[cfg(test)]
mod tests {
use crate::cloud_provider::Kind::Aws;
use std::str::FromStr;
use crate::cloud_provider::kubernetes::{
@@ -1406,7 +1437,7 @@ mod tests {
use crate::cloud_provider::utilities::VersionsNumber;
use crate::cmd::structs::{KubernetesList, KubernetesNode, KubernetesVersion};
use crate::events::{EngineEvent, EventDetails, InfrastructureStep, Stage, Transmitter};
use crate::logger::{LogLevel, Logger};
use crate::logger::{LogLevel, Logger, StdIoLogger};
use crate::models::{ListenersHelper, QoveryIdentifier};
#[test]
@@ -1422,7 +1453,7 @@ mod tests {
Stage::Infrastructure(InfrastructureStep::Upgrade),
Transmitter::Kubernetes(QoveryIdentifier::new_random().to_string(), "test".to_string()),
);
let logger = FakeLogger::new();
let logger = StdIoLogger::new();
// test full cluster upgrade (masters + workers)
let result = check_kubernetes_upgrade_status(
@@ -1988,14 +2019,35 @@ mod tests {
pub fn test_cpu_set() {
let v = vec![];
let listener_helper = ListenersHelper::new(&v);
let logger = StdIoLogger::new();
let execution_id = "execution_id";
let context_id = "context_id";
let organization_id = "organization_id";
let cluster_id = "cluster_id";
let event_details = EventDetails::new(
Some(Aws),
QoveryIdentifier::new(organization_id.to_string()),
QoveryIdentifier::new(cluster_id.to_string()),
QoveryIdentifier::new(execution_id.to_string()),
Some("region_fake".to_string()),
Stage::Infrastructure(InfrastructureStep::LoadConfiguration),
Transmitter::Kubernetes(cluster_id.to_string(), format!("{}-name", cluster_id)),
);
let mut total_cpu = "0.25".to_string();
let mut cpu_burst = "1".to_string();
assert_eq!(
validate_k8s_required_cpu_and_burstable(&listener_helper, execution_id, context_id, total_cpu, cpu_burst)
.unwrap(),
validate_k8s_required_cpu_and_burstable(
&listener_helper,
execution_id,
context_id,
total_cpu,
cpu_burst,
event_details.clone(),
&logger
)
.unwrap(),
CpuLimits {
cpu_request: "0.25".to_string(),
cpu_limit: "1".to_string()
@@ -2005,8 +2057,16 @@ mod tests {
total_cpu = "1".to_string();
cpu_burst = "0.5".to_string();
assert_eq!(
validate_k8s_required_cpu_and_burstable(&listener_helper, execution_id, context_id, total_cpu, cpu_burst)
.unwrap(),
validate_k8s_required_cpu_and_burstable(
&listener_helper,
execution_id,
context_id,
total_cpu,
cpu_burst,
event_details.clone(),
&logger
)
.unwrap(),
CpuLimits {
cpu_request: "1".to_string(),
cpu_limit: "1".to_string()

View File

@@ -3,8 +3,7 @@ use std::collections::HashMap;
use crate::cloud_provider::models::CpuLimits;
use crate::error::{EngineError, StringError};
use crate::errors::CommandError;
use crate::events::io::EngineEvent;
use crate::events::EventDetails;
use crate::events::{EngineEvent, EventDetails, EventMessage};
use crate::logger::{LogLevel, Logger};
use crate::models::{Listeners, ListenersHelper, ProgressInfo, ProgressLevel, ProgressScope};
use chrono::Duration;
@@ -524,8 +523,14 @@ pub fn print_action(
cloud_provider_name, struct_name, fn_name, item_name
);
match fn_name.contains("error") {
true => logger.log(LogLevel),
false => info!("{}", msg),
true => logger.log(
LogLevel::Warning,
EngineEvent::Warning(event_details, EventMessage::new_from_safe(msg)),
),
false => logger.log(
LogLevel::Info,
EngineEvent::Info(event_details, EventMessage::new_from_safe(msg)),
),
}
}

View File

@@ -6,6 +6,7 @@ pub type Id = String;
pub type Name = String;
#[derive(Debug)]
#[deprecated(note = "errors.EngineError to be used instead")]
pub struct EngineError {
pub cause: EngineErrorCause,
pub scope: EngineErrorScope,

View File

@@ -152,6 +152,8 @@ pub enum Tag {
K8sNodeIsNotReadyWithTheRequestedVersion,
/// K8sNodeIsNotReady: represents an error where the given node is not ready.
K8sNodeIsNotReady,
/// K8sValidateRequiredCPUandBurstableError: represents an error validating required CPU and burstable.
K8sValidateRequiredCPUandBurstableError,
/// CannotFindRequiredBinary: represents an error where a required binary is not found on the system.
CannotFindRequiredBinary,
/// SubnetsCountShouldBeEven: represents an error where subnets count should be even to have as many public than private subnets.
@@ -1201,6 +1203,31 @@ impl EngineError {
)
}
/// Creates new error for kubernetes validate required CPU and burstable.
///
/// Arguments:
///
/// * `event_details`: Error linked event details.
/// * `raw_error`: Raw error message.
pub fn new_k8s_validate_required_cpu_and_burstable_error(
event_details: EventDetails,
total_cpus_raw: String,
cpu_burst_raw: String,
raw_error: CommandError,
) -> EngineError {
let message = "Error while trying to validate required CPU and burstable.";
EngineError::new(
event_details,
Tag::K8sValidateRequiredCPUandBurstableError,
message.to_string(),
message.to_string(),
Some(raw_error),
None,
Some("Please ensure your configuration is valid.".to_string()),
)
}
/// Creates new error for kubernetes not being able to get crash looping pods.
///
/// Arguments:
@@ -1425,11 +1452,13 @@ impl EngineError {
/// * `service_type`: Service type.
/// * `parameter_name`: Context parameter name.
/// * `parameter_value`: Context parameter value.
/// * `raw_error`: Raw error message.
pub fn new_terraform_unsupported_context_parameter_value(
event_details: EventDetails,
service_type: String,
parameter_name: String,
parameter_value: String,
raw_error: Option<CommandError>,
) -> EngineError {
let message = format!(
"{} value `{}` not supported for parameter `{}`",
@@ -1441,7 +1470,7 @@ impl EngineError {
Tag::TerraformContextUnsupportedParameterValue,
message.to_string(),
message.to_string(),
None,
raw_error,
None,
None,
)