Compare commits
No commits in common. "6e6f57e38c45f31ba516c417570bfd330a240a39" and "49370af176b4c809a489f7c494373b0718120194" have entirely different histories.
6e6f57e38c
...
49370af176
69
README.md
69
README.md
@ -36,59 +36,48 @@ These principles surface as simple, ergonomic Rust APIs that let teams focus on
|
|||||||
|
|
||||||
## 2 · Quick Start
|
## 2 · Quick Start
|
||||||
|
|
||||||
The snippet below spins up a complete **production-grade Rust + Leptos Webapp** with monitoring. Swap it for your own scores to deploy anything from microservices to machine-learning pipelines.
|
The snippet below spins up a complete **production-grade LAMP stack** with monitoring. Swap it for your own scores to deploy anything from microservices to machine-learning pipelines.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use harmony::{
|
use harmony::{
|
||||||
|
data::Version,
|
||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
|
maestro::Maestro,
|
||||||
modules::{
|
modules::{
|
||||||
application::{
|
lamp::{LAMPConfig, LAMPScore},
|
||||||
ApplicationScore, RustWebFramework, RustWebapp,
|
monitoring::monitoring_alerting::MonitoringAlertingStackScore,
|
||||||
features::{PackagingDeployment, rhob_monitoring::Monitoring},
|
|
||||||
},
|
},
|
||||||
monitoring::alert_channel::discord_alert_channel::DiscordWebhook,
|
topology::{K8sAnywhereTopology, Url},
|
||||||
},
|
|
||||||
topology::K8sAnywhereTopology,
|
|
||||||
};
|
};
|
||||||
use harmony_macros::hurl;
|
|
||||||
use std::{path::PathBuf, sync::Arc};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let application = Arc::new(RustWebapp {
|
// 1. Describe what you want
|
||||||
name: "harmony-example-leptos".to_string(),
|
let lamp_stack = LAMPScore {
|
||||||
project_root: PathBuf::from(".."), // <== Your project root, usually .. if you use the standard `/harmony` folder
|
name: "harmony-lamp-demo".into(),
|
||||||
framework: Some(RustWebFramework::Leptos),
|
domain: Url::Url(url::Url::parse("https://lampdemo.example.com").unwrap()),
|
||||||
service_port: 8080,
|
php_version: Version::from("8.3.0").unwrap(),
|
||||||
});
|
config: LAMPConfig {
|
||||||
|
project_root: "./php".into(),
|
||||||
// Define your Application deployment and the features you want
|
database_size: "4Gi".into(),
|
||||||
let app = ApplicationScore {
|
..Default::default()
|
||||||
features: vec![
|
},
|
||||||
Box::new(PackagingDeployment {
|
|
||||||
application: application.clone(),
|
|
||||||
}),
|
|
||||||
Box::new(Monitoring {
|
|
||||||
application: application.clone(),
|
|
||||||
alert_receiver: vec![
|
|
||||||
Box::new(DiscordWebhook {
|
|
||||||
name: "test-discord".to_string(),
|
|
||||||
url: hurl!("https://discord.doesnt.exist.com"), // <== Get your discord webhook url
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
application,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 2. Enhance with extra scores (monitoring, CI/CD, …)
|
||||||
|
let mut monitoring = MonitoringAlertingStackScore::new();
|
||||||
|
monitoring.namespace = Some(lamp_stack.config.namespace.clone());
|
||||||
|
|
||||||
|
// 3. Run your scores on the desired topology & inventory
|
||||||
harmony_cli::run(
|
harmony_cli::run(
|
||||||
Inventory::autoload(),
|
Inventory::autoload(), // auto-detect hardware / kube-config
|
||||||
K8sAnywhereTopology::from_env(), // <== Deploy to local automatically provisioned local k3d by default or connect to any kubernetes cluster
|
K8sAnywhereTopology::from_env(), // local k3d, CI, staging, prod…
|
||||||
vec![Box::new(app)],
|
vec![
|
||||||
None,
|
Box::new(lamp_stack),
|
||||||
)
|
Box::new(monitoring)
|
||||||
.await
|
],
|
||||||
.unwrap();
|
None
|
||||||
|
).await.unwrap();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.3 KiB |
File diff suppressed because one or more lines are too long
@ -225,17 +225,3 @@ Demo time
|
|||||||
---
|
---
|
||||||
|
|
||||||
<img src="./Happy_swimmer.jpg" width="300"/>
|
<img src="./Happy_swimmer.jpg" width="300"/>
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🎼
|
|
||||||
|
|
||||||
Harmony : [https://git.nationtech.io/nationtech/harmony](https://git.nationtech.io/nationtech/harmony)
|
|
||||||
|
|
||||||
|
|
||||||
<img src="./qrcode_gitea_nationtech.png" width="120"/>
|
|
||||||
|
|
||||||
|
|
||||||
LinkedIn : [https://www.linkedin.com/in/jean-gabriel-gill-couture/](https://www.linkedin.com/in/jean-gabriel-gill-couture/)
|
|
||||||
|
|
||||||
Courriel : [jg@nationtech.io](mailto:jg@nationtech.io)
|
|
||||||
|
|||||||
@ -16,13 +16,16 @@ use std::{path::PathBuf, sync::Arc};
|
|||||||
async fn main() {
|
async fn main() {
|
||||||
let application = Arc::new(RustWebapp {
|
let application = Arc::new(RustWebapp {
|
||||||
name: "harmony-example-tryrust".to_string(),
|
name: "harmony-example-tryrust".to_string(),
|
||||||
project_root: PathBuf::from("./tryrust.org"), // <== Project root, in this case it is a
|
project_root: PathBuf::from("./tryrust.org"),
|
||||||
// submodule
|
|
||||||
framework: Some(RustWebFramework::Leptos),
|
framework: Some(RustWebFramework::Leptos),
|
||||||
service_port: 8080,
|
service_port: 8080,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Define your Application deployment and the features you want
|
let discord_receiver = DiscordWebhook {
|
||||||
|
name: "test-discord".to_string(),
|
||||||
|
url: hurl!("https://discord.doesnt.exist.com"),
|
||||||
|
};
|
||||||
|
|
||||||
let app = ApplicationScore {
|
let app = ApplicationScore {
|
||||||
features: vec![
|
features: vec![
|
||||||
Box::new(PackagingDeployment {
|
Box::new(PackagingDeployment {
|
||||||
@ -30,10 +33,7 @@ async fn main() {
|
|||||||
}),
|
}),
|
||||||
Box::new(Monitoring {
|
Box::new(Monitoring {
|
||||||
application: application.clone(),
|
application: application.clone(),
|
||||||
alert_receiver: vec![Box::new(DiscordWebhook {
|
alert_receiver: vec![Box::new(discord_receiver)],
|
||||||
name: "test-discord".to_string(),
|
|
||||||
url: hurl!("https://discord.doesnt.exist.com"),
|
|
||||||
})],
|
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
application,
|
application,
|
||||||
@ -41,7 +41,7 @@ async fn main() {
|
|||||||
|
|
||||||
harmony_cli::run(
|
harmony_cli::run(
|
||||||
Inventory::autoload(),
|
Inventory::autoload(),
|
||||||
K8sAnywhereTopology::from_env(), // <== Deploy to local automatically provisioned k3d by default or connect to any kubernetes cluster
|
K8sAnywhereTopology::from_env(),
|
||||||
vec![Box::new(app)],
|
vec![Box::new(app)],
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -55,8 +55,7 @@ impl<T: Topology + K8sclient + HelmCommand + Ingress> Interpret<T> for ArgoInter
|
|||||||
topology: &T,
|
topology: &T,
|
||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
let k8s_client = topology.k8s_client().await?;
|
let k8s_client = topology.k8s_client().await?;
|
||||||
let svc = format!("argo-{}", self.score.namespace.clone());
|
let domain = topology.get_domain("argo").await?;
|
||||||
let domain = topology.get_domain(&svc).await?;
|
|
||||||
let helm_score =
|
let helm_score =
|
||||||
argo_helm_chart_score(&self.score.namespace, self.score.openshift, &domain);
|
argo_helm_chart_score(&self.score.namespace, self.score.openshift, &domain);
|
||||||
|
|
||||||
@ -67,17 +66,14 @@ impl<T: Topology + K8sclient + HelmCommand + Ingress> Interpret<T> for ArgoInter
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Ok(Outcome::success_with_details(
|
Ok(Outcome::success(format!(
|
||||||
format!(
|
"ArgoCD installed with {} {}",
|
||||||
"ArgoCD {} {}",
|
|
||||||
self.argo_apps.len(),
|
self.argo_apps.len(),
|
||||||
match self.argo_apps.len() {
|
match self.argo_apps.len() {
|
||||||
1 => "application",
|
1 => "application",
|
||||||
_ => "applications",
|
_ => "applications",
|
||||||
}
|
}
|
||||||
),
|
)))
|
||||||
vec![format!("argo application: http://{}", domain)],
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_name(&self) -> InterpretName {
|
fn get_name(&self) -> InterpretName {
|
||||||
|
|||||||
@ -141,10 +141,7 @@ impl<T: Topology + K8sclient> Interpret<T> for K8sIngressInterpret {
|
|||||||
InterpretStatus::SUCCESS => {
|
InterpretStatus::SUCCESS => {
|
||||||
let details = match &self.namespace {
|
let details = match &self.namespace {
|
||||||
Some(namespace) => {
|
Some(namespace) => {
|
||||||
vec![format!(
|
vec![format!("{} ({namespace}): {}", self.service, self.host)]
|
||||||
"{} ({namespace}): http://{}",
|
|
||||||
self.service, self.host
|
|
||||||
)]
|
|
||||||
}
|
}
|
||||||
None => vec![format!("{}: {}", self.service, self.host)],
|
None => vec![format!("{}: {}", self.service, self.host)],
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user