feat: ApplicationModule with tentative architecture and placeholder implementation of first few features
This commit is contained in:
75
harmony/src/modules/application/features/endpoint.rs
Normal file
75
harmony/src/modules/application/features/endpoint.rs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use crate::modules::application::{Application, ApplicationFeature};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PublicEndpoint {
|
||||||
|
application_port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use port 3000 as default port. Harmony wants to provide "sane defaults" in general, and in this
|
||||||
|
/// particular context, using port 80 goes against our philosophy to provide production grade
|
||||||
|
/// defaults out of the box. Using an unprivileged port is a good security practice and will allow
|
||||||
|
/// for unprivileged containers to work with this out of the box.
|
||||||
|
///
|
||||||
|
/// Now, why 3000 specifically? Many popular web/network frameworks use it by default, there is no
|
||||||
|
/// perfect answer for this but many Rust and Python libraries tend to use 3000.
|
||||||
|
impl Default for PublicEndpoint {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
application_port: 3000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ApplicationFeature for PublicEndpoint {
|
||||||
|
async fn ensure_installed(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn is_installed(&self) -> Result<bool, String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn uninstall(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Design options here :
|
||||||
|
//
|
||||||
|
// 1. Forget about ApplicationFeature trait. The Features are just other scores that are passed on to
|
||||||
|
// the ApplicationInterpret as children (and we can rename children dependencies maybe?)
|
||||||
|
//
|
||||||
|
// 2. Go forward with the ApplicationFeature trait. There are important question marks here :
|
||||||
|
// - What about the installation lifecycle management? This was defined as being handled by a
|
||||||
|
// Topology. The thing here is that I am not sure wether application features belong at the
|
||||||
|
// Topology level or not. Functionnaly they are pretty similar. Topology provides software
|
||||||
|
// infrastructure features that Scores will then install themselves on. Most of the time those very
|
||||||
|
// features are installed using Scores with lower level dependencies. For example, :
|
||||||
|
//
|
||||||
|
// AlertingFeature depends on T: Topology + AlertSender
|
||||||
|
// AlertSender is implemented as KubePrometheus which depends on T: Topology + HelmCommand
|
||||||
|
// HelmCommand relies on T: Topology + K8sClient
|
||||||
|
//
|
||||||
|
// With that said, would it work with `features: Vec<box dyn Score<T>>` instead of `features:
|
||||||
|
// Vec<box dyn ApplicationFeature>>` ?
|
||||||
|
//
|
||||||
|
// Let's unpack this :
|
||||||
|
//
|
||||||
|
// RustWebappScore<T: Topology> {
|
||||||
|
// features: Vec<box dyn Score<T>>,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// This brings in a significant problem : RustWebappScore becomes generic, which is a problem for
|
||||||
|
// Clone and Serialize bounds.
|
||||||
|
//
|
||||||
|
// But that can be fixed easily I think ?
|
||||||
|
//
|
||||||
|
// RustWebappScore<T: Topology + Clone + Serialize> {
|
||||||
|
// features: Vec<box dyn Score<T>>,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Oh right not quite because it is `dyn`.
|
||||||
|
//
|
||||||
54
harmony/src/modules/application/features/mod.rs
Normal file
54
harmony/src/modules/application/features/mod.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
mod endpoint;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
pub use endpoint::*;
|
||||||
|
|
||||||
|
use super::ApplicationFeature;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct SoftwareQualityChecks {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ApplicationFeature for SoftwareQualityChecks {
|
||||||
|
async fn ensure_installed(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
async fn is_installed(&self) -> Result<bool, String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
async fn uninstall(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ContinuousDelivery {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ApplicationFeature for ContinuousDelivery {
|
||||||
|
async fn ensure_installed(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
async fn is_installed(&self) -> Result<bool, String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
async fn uninstall(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Monitoring {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl ApplicationFeature for Monitoring {
|
||||||
|
async fn ensure_installed(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
async fn is_installed(&self) -> Result<bool, String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn uninstall(&self) -> Result<(), String> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
mod rust;
|
||||||
|
pub mod features;
|
||||||
|
pub use rust::*;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@@ -29,7 +33,7 @@ impl<T: Topology> Score<T> for GoApplicationScore {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ApplicationInterpret {
|
pub struct ApplicationInterpret {
|
||||||
pub features: Vec<Box<dyn ApplicationFeature>>,
|
features: Vec<Box<dyn ApplicationFeature>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -55,6 +59,8 @@ impl<T: Topology> Interpret<T> for ApplicationInterpret {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Application {}
|
||||||
|
|
||||||
/// An ApplicationFeature provided by harmony, such as Backups, Monitoring, MultisiteAvailability,
|
/// An ApplicationFeature provided by harmony, such as Backups, Monitoring, MultisiteAvailability,
|
||||||
/// ContinuousIntegration, ContinuousDelivery
|
/// ContinuousIntegration, ContinuousDelivery
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -64,6 +70,21 @@ pub trait ApplicationFeature: std::fmt::Debug + Send + Sync {
|
|||||||
async fn uninstall(&self) -> Result<(), String>;
|
async fn uninstall(&self) -> Result<(), String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for Box<dyn ApplicationFeature> {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Box<dyn ApplicationFeature> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BackupFeature;
|
pub struct BackupFeature;
|
||||||
|
|
||||||
|
|||||||
26
harmony/src/modules/application/rust.rs
Normal file
26
harmony/src/modules/application/rust.rs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
score::Score,
|
||||||
|
topology::{Topology, Url},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{ApplicationFeature, ApplicationInterpret};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Clone)]
|
||||||
|
pub struct RustWebappScore {
|
||||||
|
pub name: String,
|
||||||
|
pub domain: Url,
|
||||||
|
pub features: Vec<Box<dyn ApplicationFeature>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Topology> Score<T> for RustWebappScore {
|
||||||
|
fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
|
||||||
|
Box::new(ApplicationInterpret { features: todo!() })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
format!("{}-RustWebapp", self.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user