-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0020c60
commit ba256a8
Showing
7 changed files
with
310 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
pub use super::Result; | ||
use crate::jeweler::deployment::{Deployment, DeploymentId}; | ||
use crate::jeweler::instance::{Instance, InstanceConfig, InstanceId, InstanceStatus}; | ||
use crate::vault::pouch::AppKey; | ||
use anyhow::anyhow; | ||
use async_trait::async_trait; | ||
use flecs_app_manifest::AppManifest; | ||
use std::collections::HashMap; | ||
use std::sync::Arc; | ||
|
||
type AppId = String; | ||
#[async_trait] | ||
pub trait AppDeployment { | ||
async fn install_app(&self, manifest: &AppManifest) -> Result<AppId>; | ||
async fn uninstall_app(&self, id: AppId) -> Result<()>; | ||
async fn is_app_installed(&self, id: AppId) -> Result<bool>; | ||
} | ||
#[derive(Default)] | ||
pub enum AppStatus { | ||
#[default] | ||
None, | ||
Installed, | ||
NotInstalled, | ||
} | ||
|
||
pub struct AppData { | ||
desired: AppStatus, | ||
instances: HashMap<InstanceId, Instance>, | ||
id: Option<AppId>, | ||
deployment: Arc<dyn Deployment>, | ||
} | ||
|
||
pub struct App { | ||
key: AppKey, | ||
properties: HashMap<DeploymentId, AppData>, | ||
manifest: Option<Arc<AppManifest>>, | ||
} | ||
|
||
impl App { | ||
pub async fn install(&mut self) -> Result<()> { | ||
match &self.manifest { | ||
None => Err(anyhow!( | ||
"Can not install {:?}, no manifest present.", | ||
self.key | ||
))?, | ||
Some(manifest) => { | ||
for data in self.properties.values_mut() { | ||
data.desired = AppStatus::Installed; | ||
// TODO: Installing app in one deployment should not fail the whole install process for all deployments | ||
if let Some(id) = &data.id { | ||
if !data.deployment.is_app_installed(id.clone()).await? { | ||
data.id = Some(data.deployment.install_app(manifest.as_ref()).await?); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub async fn uninstall(&mut self) -> Result<()> { | ||
for data in self.properties.values_mut() { | ||
data.desired = AppStatus::NotInstalled; | ||
// TODO: Uninstalling app in one deployment should not fail the whole uninstall process for all deployments | ||
if let Some(id) = &data.id { | ||
if data.deployment.is_app_installed(id.clone()).await? { | ||
data.deployment.uninstall_app(id.clone()).await?; | ||
data.id = None; | ||
} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub async fn create_instance(&mut self, instance_config: InstanceConfig) -> Result<()> { | ||
for data in self.properties.values_mut() { | ||
// TODO: Creating app in one deployment should not fail the whole creation process for all deployments | ||
let id = data | ||
.deployment | ||
.create_instance(instance_config.clone()) | ||
.await?; | ||
data.instances.insert( | ||
id.clone(), | ||
Instance::new( | ||
id, | ||
instance_config.clone(), | ||
data.deployment.clone(), | ||
InstanceStatus::Created, | ||
), | ||
); | ||
} | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use crate::jeweler::app::AppDeployment; | ||
use crate::jeweler::instance::InstanceDeployment; | ||
use crate::jeweler::network::NetworkDeployment; | ||
use async_trait::async_trait; | ||
|
||
pub type DeploymentId = String; | ||
|
||
#[async_trait] | ||
pub trait Deployment: Send + Sync + AppDeployment + InstanceDeployment + NetworkDeployment { | ||
async fn id(&self) -> DeploymentId; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
use super::Result; | ||
use crate::jeweler::deployment::Deployment; | ||
use crate::jeweler::volume::VolumeDeployment; | ||
use async_trait::async_trait; | ||
use std::collections::HashMap; | ||
use std::path::Path; | ||
use std::sync::Arc; | ||
|
||
#[async_trait] | ||
pub trait InstanceDeployment: VolumeDeployment { | ||
async fn create_instance(&self, config: InstanceConfig) -> Result<InstanceId>; | ||
async fn delete_instance(&self, id: InstanceId) -> Result<()>; | ||
async fn start_instance(&self, id: InstanceId) -> Result<()>; | ||
async fn stop_instance(&self, id: InstanceId) -> Result<()>; | ||
async fn ready_instance(&self, id: InstanceId) -> Result<()>; | ||
async fn import_instance(&self, path: &Path) -> Result<InstanceId>; | ||
async fn export_instance(&self, id: InstanceId, path: &Path) -> Result<()> { | ||
let config = self.instance_config(id.clone()).await?; | ||
self.export_config(config, path).await?; | ||
self.export_volumes(id, path).await?; | ||
Ok(()) | ||
} | ||
async fn export_config(&self, config: InstanceConfig, path: &Path) -> Result<()>; | ||
async fn instance_status(&self, id: InstanceId) -> Result<InstanceStatus>; | ||
async fn instance_config(&self, id: InstanceId) -> Result<InstanceConfig>; | ||
async fn instance(&self, id: InstanceId) -> Result<(InstanceConfig, InstanceStatus)> { | ||
Ok(( | ||
self.instance_config(id.clone()).await?, | ||
self.instance_status(id).await?, | ||
)) | ||
} | ||
async fn instances(&self) -> Result<HashMap<InstanceId, (InstanceConfig, InstanceStatus)>>; | ||
async fn export_instances(&self, path: &Path) -> Result<()> { | ||
for id in self.instances().await?.keys() { | ||
self.export_instance(id.clone(), path).await?; | ||
} | ||
Ok(()) | ||
} | ||
async fn copy_from_instance(&self, id: InstanceId, src: &Path, dst: &Path) -> Result<()>; | ||
async fn copy_to_instance(&self, id: InstanceId, src: &Path, dst: &Path) -> Result<()>; | ||
// TODO: Maybe move function to enum InstanceStatus | ||
async fn is_instance_runnable(&self, id: InstanceId) -> Result<bool> { | ||
Ok(self.instance_status(id).await? == InstanceStatus::Created) | ||
} | ||
// TODO: Maybe move function to enum InstanceStatus | ||
async fn is_instance_running(&self, id: InstanceId) -> Result<bool> { | ||
Ok(self.instance_status(id).await? == InstanceStatus::Running) | ||
} | ||
} | ||
|
||
pub(crate) type InstanceId = String; | ||
#[derive(Default, Clone)] | ||
pub struct InstanceConfig { | ||
// TBD | ||
} | ||
|
||
#[derive(Debug, PartialEq)] | ||
pub enum InstanceStatus { | ||
// TBD | ||
NotCreated, | ||
Requested, | ||
ResourcesReady, | ||
Created, | ||
Stopped, | ||
Running, | ||
Orphaned, | ||
Unknown, | ||
} | ||
|
||
pub struct Instance { | ||
id: InstanceId, | ||
pub config: InstanceConfig, | ||
deployment: Arc<dyn Deployment>, | ||
desired: InstanceStatus, | ||
} | ||
|
||
impl Instance { | ||
pub(super) fn new( | ||
id: InstanceId, | ||
config: InstanceConfig, | ||
deployment: Arc<dyn Deployment>, | ||
desired: InstanceStatus, | ||
) -> Self { | ||
Self { | ||
id, | ||
config, | ||
deployment, | ||
desired, | ||
} | ||
} | ||
|
||
pub async fn start(&mut self) -> Result<()> { | ||
self.desired = InstanceStatus::Running; | ||
match self.deployment.instance_status(self.id.clone()).await? { | ||
InstanceStatus::Running => Ok(()), | ||
_ => self.deployment.start_instance(self.id.clone()).await, | ||
} | ||
} | ||
|
||
pub async fn stop(&mut self) -> Result<()> { | ||
self.desired = InstanceStatus::Stopped; | ||
match self.deployment.instance_status(self.id.clone()).await? { | ||
InstanceStatus::Stopped => Ok(()), | ||
_ => self.deployment.stop_instance(self.id.clone()).await, | ||
} | ||
} | ||
|
||
pub async fn delete(self) -> Result<(), (anyhow::Error, Self)> { | ||
self.deployment | ||
.delete_instance(self.id.clone()) | ||
.await | ||
.map_err(|e| (e, self)) | ||
} | ||
|
||
pub async fn ready(&mut self) -> Result<()> { | ||
// TODO: Check status, error handling | ||
self.deployment.ready_instance(self.id.clone()).await | ||
} | ||
|
||
pub async fn export(&self, path: &Path) -> Result<()> { | ||
self.deployment.export_instance(self.id.clone(), path).await | ||
} | ||
|
||
pub async fn status(&self) -> Result<InstanceStatus> { | ||
self.deployment.instance_status(self.id.clone()).await | ||
} | ||
|
||
pub async fn copy_from(&self, src: &Path, dst: &Path) -> Result<()> { | ||
self.deployment | ||
.copy_from_instance(self.id.clone(), src, dst) | ||
.await | ||
} | ||
|
||
pub async fn copy_to(&self, src: &Path, dst: &Path) -> Result<()> { | ||
self.deployment | ||
.copy_to_instance(self.id.clone(), src, dst) | ||
.await | ||
} | ||
|
||
pub async fn is_runnable(&self) -> Result<bool> { | ||
self.deployment.is_instance_runnable(self.id.clone()).await | ||
} | ||
|
||
pub async fn is_running(&self) -> Result<bool> { | ||
self.deployment.is_instance_running(self.id.clone()).await | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub mod app; | ||
pub mod deployment; | ||
pub mod instance; | ||
pub mod network; | ||
pub mod volume; | ||
pub use super::Result; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
use super::Result; | ||
use async_trait::async_trait; | ||
use std::collections::HashMap; | ||
use std::net::IpAddr; | ||
|
||
pub type NetworkId = String; | ||
pub struct Network { | ||
// TBD | ||
} | ||
#[derive(Default)] | ||
pub struct NetworkConfig { | ||
// TBD | ||
} | ||
|
||
#[async_trait] | ||
pub trait NetworkDeployment { | ||
async fn create_network(&self, config: NetworkConfig) -> Result<NetworkId>; | ||
async fn delete_network(&self, id: NetworkId) -> Result<()>; | ||
async fn network(&self, id: NetworkId) -> Result<Network>; | ||
async fn networks(&self) -> Result<HashMap<NetworkId, Network>>; | ||
async fn connect_network(&self, id: NetworkId, address: IpAddr) -> Result<()>; | ||
async fn disconnect_network(&self, id: NetworkId, address: IpAddr) -> Result<()>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use super::instance::InstanceId; | ||
use super::Result; | ||
use async_trait::async_trait; | ||
use std::collections::HashMap; | ||
use std::path::Path; | ||
|
||
type VolumeId = String; | ||
#[derive(Default)] | ||
pub struct VolumeConfig { | ||
// TBD | ||
} | ||
|
||
#[async_trait] | ||
pub trait VolumeDeployment { | ||
async fn create_volume(&self, config: VolumeConfig) -> Result<VolumeId>; | ||
async fn delete_volume(&self, id: VolumeId) -> Result<()>; | ||
async fn import_volume(&self, path: &Path) -> Result<VolumeId>; | ||
async fn export_volume(&self, id: VolumeId, path: &Path) -> Result<()>; // TODO: Arguments, return type | ||
async fn volumes(&self, instance_id: InstanceId) -> Result<HashMap<VolumeId, VolumeConfig>>; | ||
async fn export_volumes(&self, instance_id: InstanceId, path: &Path) -> Result<()> { | ||
// TODO: more logic | ||
for volume_id in self.volumes(instance_id).await?.keys() { | ||
self.export_volume(volume_id.clone(), path).await?; | ||
} | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters