diff --git a/src/cloud_provider/io.rs b/src/cloud_provider/io.rs new file mode 100644 index 00000000..dc8a5810 --- /dev/null +++ b/src/cloud_provider/io.rs @@ -0,0 +1,20 @@ +use crate::cloud_provider::Kind as KindModel; +use serde_derive::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum Kind { + Aws, + Do, + Scw, +} + +impl From for Kind { + fn from(kind: KindModel) -> Self { + match kind { + KindModel::Aws => Kind::Aws, + KindModel::Do => Kind::Do, + KindModel::Scw => Kind::Scw, + } + } +} diff --git a/src/cloud_provider/mod.rs b/src/cloud_provider/mod.rs index c1e8060a..2cc73f91 100644 --- a/src/cloud_provider/mod.rs +++ b/src/cloud_provider/mod.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::fmt::{Display, Formatter}; use serde::{Deserialize, Serialize}; @@ -11,6 +12,7 @@ pub mod aws; pub mod digitalocean; pub mod environment; pub mod helm; +pub mod io; pub mod kubernetes; pub mod metrics; pub mod models; @@ -60,13 +62,13 @@ pub enum Kind { Scw, } -impl Kind { - pub fn name(&self) -> &str { - match self { +impl Display for Kind { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { Kind::Aws => "AWS", Kind::Do => "Digital Ocean", Kind::Scw => "Scaleway", - } + }) } } diff --git a/src/cloud_provider/scaleway/kubernetes/mod.rs b/src/cloud_provider/scaleway/kubernetes/mod.rs index d8f9ef3e..e5297dd3 100644 --- a/src/cloud_provider/scaleway/kubernetes/mod.rs +++ b/src/cloud_provider/scaleway/kubernetes/mod.rs @@ -151,7 +151,8 @@ impl<'a> Kapsule<'a> { QoveryIdentifier::new(context.organization_id().to_string()), QoveryIdentifier::new(context.cluster_id().to_string()), QoveryIdentifier::new(context.execution_id().to_string()), - Stage::Infrastructure(InfrastructureStep::Instantiate), + zone.region_str().to_string(), + Stage::Infrastructure(InfrastructureStep::LoadConfiguration), Transmitter::Kubernetes(id, name), ), node_group.instance_type.as_str(), @@ -373,6 +374,7 @@ impl<'a> Kapsule<'a> { QoveryIdentifier::from(self.context.organization_id().to_string()), QoveryIdentifier::from(self.context.cluster_id().to_string()), QoveryIdentifier::from(self.context.execution_id().to_string()), + self.region().to_string(), Stage::Infrastructure(InfrastructureStep::Create), Transmitter::Kubernetes(self.id().to_string(), self.name().to_string()), ); diff --git a/src/cloud_provider/service.rs b/src/cloud_provider/service.rs index 7f5275c2..5a060417 100644 --- a/src/cloud_provider/service.rs +++ b/src/cloud_provider/service.rs @@ -548,7 +548,7 @@ where "deploy {} with name {} on {}", service.service_type().name(), service.name_with_id(), - kubernetes.cloud_provider().kind().name() + kubernetes.cloud_provider().kind().to_string() ); let context = service.tera_context(target)?; @@ -597,7 +597,7 @@ where "deploy {} with name {} on {:?} Kubernetes cluster id {}", service.service_type().name(), service.name_with_id(), - kubernetes.cloud_provider().kind().name(), + kubernetes.cloud_provider().kind().to_string(), kubernetes.id() ); diff --git a/src/error.rs b/src/error.rs index fdc47f2f..f4814158 100644 --- a/src/error.rs +++ b/src/error.rs @@ -46,7 +46,6 @@ pub enum EngineErrorScope { impl From for EngineErrorScope { fn from(transmitter: Transmitter) -> Self { match transmitter { - Transmitter::Engine => EngineErrorScope::Engine, Transmitter::BuildPlatform(id, name) => EngineErrorScope::BuildPlatform(id, name), Transmitter::ContainerRegistry(id, name) => EngineErrorScope::ContainerRegistry(id, name), Transmitter::CloudProvider(id, name) => EngineErrorScope::CloudProvider(id, name), diff --git a/src/errors/io.rs b/src/errors/io.rs index e861d889..66fe6f0f 100644 --- a/src/errors/io.rs +++ b/src/errors/io.rs @@ -1 +1,63 @@ -// TODO(benjaminch): implement +use crate::errors; +use crate::events::io::EventDetails; +use serde_derive::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub struct SimpleError { + message: String, + message_safe: String, +} + +impl From for SimpleError { + fn from(error: errors::SimpleError) -> Self { + SimpleError { + message: error.message, + message_safe: error.message_safe, + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum Tag { + Unknown, + UnsupportedInstanceType, +} + +impl From for Tag { + fn from(tag: errors::Tag) -> Self { + match tag { + errors::Tag::Unknown => Tag::Unknown, + errors::Tag::UnsupportedInstanceType => Tag::UnsupportedInstanceType, + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub struct EngineError { + tag: Tag, + event_details: EventDetails, + qovery_log_message: String, + user_log_message: String, + raw_message: Option, + raw_message_safe: Option, + link: Option, + hint_message: Option, +} + +impl From for EngineError { + fn from(error: errors::EngineError) -> Self { + EngineError { + tag: Tag::from(error.tag), + event_details: EventDetails::from(error.event_details), + qovery_log_message: error.qovery_log_message, + user_log_message: error.user_log_message, + raw_message: error.raw_message, + raw_message_safe: error.raw_message_safe, + link: error.link.map(|url| url.to_string()), + hint_message: error.hint_message, + } + } +} diff --git a/src/errors/mod.rs b/src/errors/mod.rs index b57a164e..82f386ac 100644 --- a/src/errors/mod.rs +++ b/src/errors/mod.rs @@ -6,85 +6,122 @@ use crate::error::{EngineError as LegacyEngineError, EngineErrorCause, EngineErr use crate::events::EventDetails; use url::Url; +/// SimpleError: simple error, mostly returned by third party tools. pub struct SimpleError { + /// message: full error message, can contains unsafe text such as passwords and tokens. message: String, + /// message_safe: error message omitting displaying any protected data such as passwords and tokens. message_safe: String, } -#[derive(Clone, Debug)] -pub enum Tag { - UnsupportedInstanceType(String), -} - impl SimpleError { + /// Returns SimpleError message. May contains unsafe text such as passwords and tokens. pub fn message(&self) -> &str { &self.message } + /// Returns SimpleError message_safe omitting all unsafe text such as passwords and tokens. pub fn message_safe(&self) -> &str { &self.message_safe } + /// Creates a new SimpleError from safe message. To be used when message is safe. pub fn new_from_safe_message(message: String) -> Self { SimpleError::new(message.clone(), message) } + /// Creates a new SimpleError having both a safe and an unsafe message. pub fn new(message: String, message_safe: String) -> Self { SimpleError { message, message_safe } } } #[derive(Clone, Debug)] +/// Tag: unique identifier for an error. +pub enum Tag { + /// Unknown: unknown error. + Unknown, + /// UnsupportedInstanceType: represents an unsupported instance type for the given cloud provider. + UnsupportedInstanceType, +} + +#[derive(Clone, Debug)] +/// EngineError: represents an engine error. Engine will always returns such errors carrying context infos easing monitoring and debugging. pub struct EngineError { + /// tag: error unique identifier tag: Tag, + /// event_details: holds context details in which error was triggered such as organization ID, cluster ID, etc. event_details: EventDetails, + /// qovery_log_message: message targeted toward Qovery team, carrying eventual debug / more fine grained messages easing investigations. qovery_log_message: String, + /// user_log_message: message targeted toward Qovery users, might avoid any useless info for users such as Qovery specific identifiers and so on. user_log_message: String, + /// raw_message: raw error message such as command input / output which may contains unsafe text such as plain passwords / tokens. raw_message: Option, + /// raw_message_safe: raw error message such as command input / output in which all unsafe data is omitted (passwords and tokens). raw_message_safe: Option, + /// link: link to error documentation (qovery blog, forum, etc.) link: Option, + /// hint_message: an hint message aiming to give an hint to the user. For example: "Happens when application port has been changed but application hasn't been restarted.". hint_message: Option, } impl EngineError { + /// Returns error's unique identifier. pub fn tag(&self) -> &Tag { &self.tag } + + /// Returns error's event details. pub fn event_details(&self) -> &EventDetails { &self.event_details } + + /// Returns qovery log message. pub fn qovery_log_message(&self) -> &str { &self.qovery_log_message } + + /// Returns user log message. pub fn user_log_message(&self) -> &str { &self.user_log_message } - /// returns proper error message (safe if exists, otherwise raw, otherwise default error - /// message). + + /// Returns proper error message (safe if exists, otherwise raw, otherwise default error message). pub fn message(&self) -> String { - if let Some(msg) = self.raw_message_safe() { - return msg; + if let Some(msg) = &self.raw_message_safe { + return msg.to_string(); } - if let Some(msg) = self.raw_message() { - return msg; + if let Some(msg) = &self.raw_message { + return msg.to_string(); } "no error message defined".to_string() } - pub fn raw_message(&self) -> Option { - self.raw_message.clone() - } - pub fn raw_message_safe(&self) -> Option { - self.raw_message_safe.clone() - } + + /// Returns error's link. pub fn link(&self) -> &Option { &self.link } + + /// Returns error's hint message. pub fn hint_message(&self) -> &Option { &self.hint_message } + /// Creates new EngineError. + /// + /// Arguments: + /// + /// * `event_details`: Error linked event details. + /// * `tag`: Error unique identifier. + /// * `qovery_log_message`: Error log message targeting Qovery team for investigation / monitoring purposes. + /// * `user_log_message`: Error log message targeting Qovery user, avoiding any extending pointless details. + /// * `raw_message`: Error raw message such as command input / output which may contains unsafe text such as plain passwords / tokens. + /// * `raw_message_safe`: Error raw message such as command input / output where any unsafe data as been omitted (such as plain passwords / tokens). + /// * `link`: Link documenting the given error. + /// * `hint_message`: hint message aiming to give an hint to the user. For example: "Happens when application port has been changed but application hasn't been restarted.". fn new( event_details: EventDetails, tag: Tag, @@ -107,6 +144,7 @@ impl EngineError { } } + /// Converts to legacy engine error easing migration. pub fn to_legacy_engine_error(self) -> LegacyEngineError { LegacyEngineError::new( EngineErrorCause::Internal, @@ -116,6 +154,49 @@ impl EngineError { ) } + /// Creates new unknown error. + /// + /// Note: do not use unless really needed, every error should have a clear type. + /// + /// Arguments: + /// + /// * `event_details`: Error linked event details. + /// * `qovery_log_message`: Error log message targeting Qovery team for investigation / monitoring purposes. + /// * `user_log_message`: Error log message targeting Qovery user, avoiding any extending pointless details. + /// * `raw_message`: Error raw message such as command input / output which may contains unsafe text such as plain passwords / tokens. + /// * `raw_message_safe`: Error raw message such as command input / output where any unsafe data as been omitted (such as plain passwords / tokens). + /// * `link`: Link documenting the given error. + /// * `hint_message`: hint message aiming to give an hint to the user. For example: "Happens when application port has been changed but application hasn't been restarted.". + pub fn new_unknown( + event_details: EventDetails, + qovery_log_message: String, + user_log_message: String, + raw_message: Option, + raw_message_safe: Option, + link: Option, + hint_message: Option, + ) -> EngineError { + EngineError::new( + event_details, + Tag::Unknown, + qovery_log_message, + user_log_message, + raw_message, + raw_message_safe, + link, + hint_message, + ) + } + + /// Creates new error for unsupported instance type. + /// + /// Cloud provider doesn't support the requested instance type. + /// + /// Arguments: + /// + /// * `event_details`: Error linked event details. + /// * `requested_instance_type`: Raw requested instance type string. + /// * `raw_message`: Error raw message such as command input / output which may contains unsafe text such as plain passwords / tokens. pub fn new_unsupported_instance_type( event_details: EventDetails, requested_instance_type: &str, @@ -124,9 +205,9 @@ impl EngineError { let message = format!("`{}` instance type is not supported", requested_instance_type); EngineError::new( event_details, - Tag::UnsupportedInstanceType(requested_instance_type.to_string()), - message.to_string(), + Tag::UnsupportedInstanceType, message.to_string(), + message, Some(raw_message.clone()), Some(raw_message), None, // TODO(documentation): Create a page entry to details this error diff --git a/src/events/io.rs b/src/events/io.rs index e861d889..58161dd1 100644 --- a/src/events/io.rs +++ b/src/events/io.rs @@ -1 +1,253 @@ -// TODO(benjaminch): implement +use crate::cloud_provider::io::Kind; +use crate::errors::io::EngineError; +use crate::events; +use serde_derive::{Deserialize, Serialize}; + +#[derive(Deserialize, Serialize)] +#[serde(tag = "type")] +#[serde(rename_all = "lowercase")] +pub enum EngineEvent { + Error { + error: EngineError, + }, + Waiting { + details: EventDetails, + message: EventMessage, + }, + Deploying { + details: EventDetails, + message: EventMessage, + }, + Pausing { + details: EventDetails, + message: EventMessage, + }, + Deleting { + details: EventDetails, + message: EventMessage, + }, + Deployed { + details: EventDetails, + message: EventMessage, + }, + Paused { + details: EventDetails, + message: EventMessage, + }, + Deleted { + details: EventDetails, + message: EventMessage, + }, +} + +impl From for EngineEvent { + fn from(event: events::EngineEvent) -> Self { + match event { + events::EngineEvent::Error(e) => EngineEvent::Error { + error: EngineError::from(e), + }, + events::EngineEvent::Waiting(d, m) => EngineEvent::Waiting { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + events::EngineEvent::Deploying(d, m) => EngineEvent::Deploying { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + events::EngineEvent::Pausing(d, m) => EngineEvent::Pausing { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + events::EngineEvent::Deleting(d, m) => EngineEvent::Deleting { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + events::EngineEvent::Deployed(d, m) => EngineEvent::Deployed { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + events::EngineEvent::Paused(d, m) => EngineEvent::Paused { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + events::EngineEvent::Deleted(d, m) => EngineEvent::Deleted { + details: EventDetails::from(d), + message: EventMessage::from(m), + }, + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub struct EventMessage { + raw: String, + safe: Option, +} + +impl From for EventMessage { + fn from(message: events::EventMessage) -> Self { + EventMessage { + raw: message.raw, + safe: message.safe, + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum Stage { + Infrastructure(InfrastructureStep), + Environment(EnvironmentStep), +} + +impl From for Stage { + fn from(stage: events::Stage) -> Self { + match stage { + events::Stage::Infrastructure(step) => Stage::Infrastructure(InfrastructureStep::from(step)), + events::Stage::Environment(step) => Stage::Environment(EnvironmentStep::from(step)), + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum InfrastructureStep { + LoadConfiguration, + Create, + Pause, + Resume, + Upgrade, + Delete, +} + +impl From for InfrastructureStep { + fn from(step: events::InfrastructureStep) -> Self { + match step { + events::InfrastructureStep::LoadConfiguration => InfrastructureStep::LoadConfiguration, + events::InfrastructureStep::Create => InfrastructureStep::Create, + events::InfrastructureStep::Pause => InfrastructureStep::Pause, + events::InfrastructureStep::Upgrade => InfrastructureStep::Upgrade, + events::InfrastructureStep::Delete => InfrastructureStep::Delete, + events::InfrastructureStep::Resume => InfrastructureStep::Resume, + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum EnvironmentStep { + Build, + Deploy, + Pause, + Resume, + Update, + Delete, +} + +impl From for EnvironmentStep { + fn from(step: events::EnvironmentStep) -> Self { + match step { + events::EnvironmentStep::Build => EnvironmentStep::Build, + events::EnvironmentStep::Deploy => EnvironmentStep::Deploy, + events::EnvironmentStep::Update => EnvironmentStep::Update, + events::EnvironmentStep::Delete => EnvironmentStep::Delete, + events::EnvironmentStep::Pause => EnvironmentStep::Pause, + events::EnvironmentStep::Resume => EnvironmentStep::Resume, + } + } +} + +type TransmitterId = String; +type TransmitterName = String; +type TransmitterType = String; + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +#[serde(tag = "type")] +pub enum Transmitter { + BuildPlatform { + id: TransmitterId, + name: TransmitterName, + }, + ContainerRegistry { + id: TransmitterId, + name: TransmitterName, + }, + CloudProvider { + id: TransmitterId, + name: TransmitterName, + }, + Kubernetes { + id: TransmitterId, + name: TransmitterName, + }, + DnsProvider { + id: TransmitterId, + name: TransmitterName, + }, + ObjectStorage { + id: TransmitterId, + name: TransmitterName, + }, + Environment { + id: TransmitterId, + name: TransmitterName, + }, + Database { + id: TransmitterId, + db_type: TransmitterType, + name: TransmitterName, + }, + Application { + id: TransmitterId, + name: TransmitterName, + }, + Router { + id: TransmitterId, + name: TransmitterName, + }, +} + +impl From for Transmitter { + fn from(transmitter: events::Transmitter) -> Self { + match transmitter { + events::Transmitter::BuildPlatform(id, name) => Transmitter::BuildPlatform { id, name }, + events::Transmitter::ContainerRegistry(id, name) => Transmitter::ContainerRegistry { id, name }, + events::Transmitter::CloudProvider(id, name) => Transmitter::CloudProvider { id, name }, + events::Transmitter::Kubernetes(id, name) => Transmitter::Kubernetes { id, name }, + events::Transmitter::DnsProvider(id, name) => Transmitter::DnsProvider { id, name }, + events::Transmitter::ObjectStorage(id, name) => Transmitter::ObjectStorage { id, name }, + events::Transmitter::Environment(id, name) => Transmitter::Environment { id, name }, + events::Transmitter::Database(id, db_type, name) => Transmitter::Database { id, db_type, name }, + events::Transmitter::Application(id, name) => Transmitter::Application { id, name }, + events::Transmitter::Router(id, name) => Transmitter::Router { id, name }, + } + } +} + +#[derive(Deserialize, Serialize)] +#[serde(rename_all = "lowercase")] +pub struct EventDetails { + provider_kind: Kind, + organisation_id: String, + cluster_id: String, + execution_id: String, + region: String, + stage: Stage, + transmitter: Transmitter, +} + +impl From for EventDetails { + fn from(details: events::EventDetails) -> Self { + EventDetails { + provider_kind: Kind::from(details.provider_kind), + organisation_id: details.organisation_id.to_string(), + cluster_id: details.cluster_id.to_string(), + execution_id: details.execution_id.to_string(), + region: details.region, + stage: Stage::from(details.stage), + transmitter: Transmitter::from(details.transmitter), + } + } +} diff --git a/src/events/mod.rs b/src/events/mod.rs index 877146a8..eae8b732 100644 --- a/src/events/mod.rs +++ b/src/events/mod.rs @@ -1,4 +1,4 @@ -mod io; +pub mod io; extern crate url; @@ -8,18 +8,30 @@ use crate::models::QoveryIdentifier; use std::fmt::{Display, Formatter}; #[derive(Debug, Clone)] +/// EngineEvent: represents an event happening in the Engine. pub enum EngineEvent { + /// Error: represents an error event. Error(EngineError), + /// Waiting: represents an engine waiting event. + /// + /// Engine is waiting for a task to be done. Waiting(EventDetails, EventMessage), + /// Deploying: represents an engine deploying event. Deploying(EventDetails, EventMessage), + /// Pausing: represents an engine pausing event. Pausing(EventDetails, EventMessage), + /// Deleting: represents an engine deleting event. Deleting(EventDetails, EventMessage), + /// Deployed: represents an engine deployed event. Deployed(EventDetails, EventMessage), + /// Paused: represents an engine paused event. Paused(EventDetails, EventMessage), + /// Deleted: represents an engine deleted event. Deleted(EventDetails, EventMessage), } impl EngineEvent { + /// Returns engine's event details. pub fn get_details(&self) -> &EventDetails { match self { EngineEvent::Error(engine_error) => engine_error.event_details(), @@ -33,6 +45,7 @@ impl EngineEvent { } } + /// Returns engine's event message. pub fn get_message(&self) -> String { match self { EngineEvent::Error(engine_error) => engine_error.message(), @@ -48,12 +61,21 @@ impl EngineEvent { } #[derive(Debug, Clone)] +/// EventMessage: represents an event message. pub struct EventMessage { + /// raw: represents a raw event message which may include unsafe elements such as passwords and tokens. raw: String, + /// safe: represents an event message from which unsafe elements have been removed (passwords and tokens). safe: Option, } impl EventMessage { + /// Creates e new EventMessage. + /// + /// Arguments + /// + /// * `raw`: Event raw message string (which may include unsafe text such as passwords and tokens). + /// * `safe`: Event safe message string (from which all unsafe text such as passwords and tokens has been removed). pub fn new(raw: String, safe: Option) -> Self { EventMessage { raw, safe } } @@ -78,12 +100,16 @@ impl Display for EventMessage { } #[derive(Debug, Clone)] +/// Stage: represents an engine event stage, can be Infrastructure or Environment. pub enum Stage { + /// Infrastructure: infrastructure stage in the engine (clusters operations). Infrastructure(InfrastructureStep), + /// Environment: environment stage in the engine (applications operations). Environment(EnvironmentStep), } impl Stage { + /// Returns stage's sub step name. pub fn sub_step_name(&self) -> String { match &self { Stage::Infrastructure(step) => step.to_string(), @@ -98,59 +124,111 @@ impl Display for Stage { f, "{}", match &self { - Stage::Infrastructure(_) => "Infrastructure", - Stage::Environment(_) => "Environment", + Stage::Infrastructure(_) => "infrastructure", + Stage::Environment(_) => "environment", }, ) } } #[derive(Debug, Clone)] +/// InfrastructureStep: represents an engine infrastructure step. pub enum InfrastructureStep { - Instantiate, + /// LoadConfiguration: first step in infrastructure, aiming to load all configuration (from Terraform, etc). + LoadConfiguration, + /// Create: creating a cluster. Create, + /// Pause: pausing a cluster. Pause, + /// Resume: resume a paused cluster. + Resume, + /// Upgrade: upgrade a cluster. Upgrade, + /// Delete: delete a cluster. Delete, } impl Display for InfrastructureStep { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "{:?}", self) + write!( + f, + "{}", + match &self { + InfrastructureStep::LoadConfiguration => "load-configuration", + InfrastructureStep::Create => "create", + InfrastructureStep::Pause => "pause", + InfrastructureStep::Upgrade => "upgrade", + InfrastructureStep::Delete => "delete", + InfrastructureStep::Resume => "resume", + }, + ) } } #[derive(Debug, Clone)] +/// EnvironmentStep: represents an engine environment step. pub enum EnvironmentStep { + /// Build: building an application (docker or build packs). Build, + /// Deploy: deploy an environment (application to kubernetes). Deploy, + /// Pause: pause an environment. + Pause, + /// Resume: resume a paused environment. + Resume, + /// Update: update an environment. Update, + /// Delete: delete an environment. Delete, } impl Display for EnvironmentStep { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - write!(f, "{:?}", self) + write!( + f, + "{}", + match &self { + EnvironmentStep::Build => "build", + EnvironmentStep::Deploy => "deploy", + EnvironmentStep::Update => "update", + EnvironmentStep::Delete => "delete", + EnvironmentStep::Pause => "pause", + EnvironmentStep::Resume => "resume", + }, + ) } } -type TranmsmitterId = String; +/// TransmitterId: represents a transmitter unique identifier. +type TransmitterId = String; +/// TransmitterName: represents a transmitter name. type TransmitterName = String; +/// TransmitterType: represents a transmitter type. type TransmitterType = String; #[derive(Debug, Clone)] +/// Transmitter: represents the event's source caller (transmitter). pub enum Transmitter { - Engine, - BuildPlatform(TranmsmitterId, TransmitterName), - ContainerRegistry(TranmsmitterId, TransmitterName), - CloudProvider(TranmsmitterId, TransmitterName), - Kubernetes(TranmsmitterId, TransmitterName), - DnsProvider(TranmsmitterId, TransmitterName), - ObjectStorage(TranmsmitterId, TransmitterName), - Environment(TranmsmitterId, TransmitterName), - Database(TranmsmitterId, TransmitterType, TransmitterName), - Application(TranmsmitterId, TransmitterName), - Router(TranmsmitterId, TransmitterName), + /// BuildPlatform: platform aiming to build applications images. + BuildPlatform(TransmitterId, TransmitterName), + /// ContainerRegistry: container registry engine part. + ContainerRegistry(TransmitterId, TransmitterName), + /// CloudProvider: cloud provider engine part. + CloudProvider(TransmitterId, TransmitterName), + /// Kubernetes: kubernetes infrastructure engine part. + Kubernetes(TransmitterId, TransmitterName), + /// DnsProvider: DNS provider engine part. + DnsProvider(TransmitterId, TransmitterName), + /// ObjectStorage: object storage engine part. + ObjectStorage(TransmitterId, TransmitterName), + /// Environment: environment engine part. + Environment(TransmitterId, TransmitterName), + /// Database: database engine part. + Database(TransmitterId, TransmitterType, TransmitterName), + /// Application: application engine part. + Application(TransmitterId, TransmitterName), + /// Router: router engine part. + Router(TransmitterId, TransmitterName), } impl Display for Transmitter { @@ -159,7 +237,6 @@ impl Display for Transmitter { f, "{}", match &self { - Transmitter::Engine => "engine".to_string(), Transmitter::BuildPlatform(id, name) => format!("build_platform({}, {})", id, name), Transmitter::ContainerRegistry(id, name) => format!("container_registry({}, {})", id, name), Transmitter::CloudProvider(id, name) => format!("cloud_provider({}, {})", id, name), @@ -175,27 +252,46 @@ impl Display for Transmitter { } } -#[derive(Debug, Clone)] -pub enum Tag { - UnsupportedInstanceType(String), -} +/// Region: represents event's cloud provider region. +type Region = String; #[derive(Debug, Clone)] +/// EventDetails: represents an event details, carrying all useful data such as Qovery identifiers, transmitter, stage etc. pub struct EventDetails { + /// provider_kind: cloud provider name provider_kind: Kind, + /// organisation_id: Qovery organisation identifier. organisation_id: QoveryIdentifier, + /// cluster_id: Qovery cluster identifier. cluster_id: QoveryIdentifier, + /// execution_id: Qovery execution identifier. execution_id: QoveryIdentifier, + /// region: event's region (cloud provider specific region). + region: Region, // TODO(benjaminch): find a way to make Region a real struct type + /// stage: stage in which this event has been triggered. stage: Stage, + /// transmitter: source triggering the event. transmitter: Transmitter, } impl EventDetails { + /// Creates a new EventDetails. + /// + /// Arguments + /// + /// * `provider_kind`: Cloud provider name. + /// * `organisation_id`: Qovery's organisation identifier. + /// * `cluster_id`: Qovery's cluster identifier. + /// * `execution_id`: Qovery's execution identifier. + /// * `region`: Event's region (cloud provider region). + /// * `stage`: Event's stage in which this event has been triggered. + /// * `transmitter`: Event's source transmitter. pub fn new( provider_kind: Kind, organisation_id: QoveryIdentifier, cluster_id: QoveryIdentifier, execution_id: QoveryIdentifier, + region: Region, stage: Stage, transmitter: Transmitter, ) -> Self { @@ -204,25 +300,43 @@ impl EventDetails { organisation_id, cluster_id, execution_id, + region, stage, transmitter, } } + + /// Returns event's provider name. pub fn provider_kind(&self) -> &Kind { &self.provider_kind } + + /// Returns event's Qovery organisation identifier. pub fn organisation_id(&self) -> &QoveryIdentifier { &self.organisation_id } + + /// Returns event's Qovery cluster identifier. pub fn cluster_id(&self) -> &QoveryIdentifier { &self.cluster_id } + + /// Returns event's Qovery execution identifier. pub fn execution_id(&self) -> &QoveryIdentifier { &self.execution_id } + + /// Returns event's region (cloud provider region). + pub fn region(&self) -> &Region { + &self.region + } + + /// Returns event's stage in which the event has been triggered. pub fn stage(&self) -> &Stage { &self.stage } + + /// Returns event's source transmitter. pub fn transmitter(&self) -> Transmitter { self.transmitter.clone() } diff --git a/src/logger.rs b/src/logger.rs index b16335ff..6e240657 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -11,7 +11,6 @@ pub enum LogLevel { pub trait Logger: Send { fn log(&self, log_level: LogLevel, event: EngineEvent); - fn heartbeat_log_for_task(&self, log_level: LogLevel, event: EngineEvent, f: &dyn Fn()); fn clone_dyn(&self) -> Box; } @@ -26,6 +25,7 @@ pub struct StdIoLogger {} impl StdIoLogger { pub fn new() -> StdIoLogger { + // TODO(benjaminch): configure tracing library in here, should be transparent for parent caller. StdIoLogger {} } } @@ -61,10 +61,6 @@ impl Logger for StdIoLogger { }); } - fn heartbeat_log_for_task(&self, _log_level: LogLevel, _event: EngineEvent, _f: &dyn Fn()) { - todo!() - } - fn clone_dyn(&self) -> Box { Box::new(self.clone()) }