Skip to content

Commit

Permalink
continue mess
Browse files Browse the repository at this point in the history
  • Loading branch information
leon3s committed Jan 5, 2024
1 parent 4e8a48e commit 4d29fd5
Show file tree
Hide file tree
Showing 18 changed files with 426 additions and 561 deletions.
49 changes: 0 additions & 49 deletions bin/nanocld/specs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -499,46 +499,6 @@ paths:
description: Cargo restarted
'404':
description: Cargo does not exist
/cargoes/{name}/scale:
patch:
tags:
- Cargoes
summary: Scale or Downscale number of instances
description: Scale or Downscale number of instances
operationId: scale_cargo
parameters:
- name: name
in: path
description: Name of the cargo
required: true
schema:
type: string
- name: namespace
in: query
description: Namespace where the cargo belongs
required: false
schema:
type: string
nullable: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CargoScale'
required: true
responses:
'200':
description: Cargo scaled
content:
application/json:
schema:
$ref: '#/components/schemas/Cargo'
'404':
description: Cargo does not exist
content:
application/json:
schema:
$ref: '#/components/schemas/ApiError'
/cargoes/{name}/stats:
get:
tags:
Expand Down Expand Up @@ -2168,15 +2128,6 @@ components:
signal:
type: string
description: 'Signal to send to the container default: SIGKILL'
CargoScale:
type: object
description: Payload for the cargo scale endpoint
required:
- Replicas
properties:
Replicas:
type: integer
description: Number of replicas to scale up or down can be negative value
CargoSpec:
type: object
description: |-
Expand Down
12 changes: 11 additions & 1 deletion bin/nanocld/src/models/cargo.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use diesel::prelude::*;
use nanocl_stubs::cargo_spec::CargoSpecPartial;
use nanocl_stubs::cargo_spec::{CargoSpecPartial, CargoSpecUpdate};

use crate::schema::cargoes;

Expand Down Expand Up @@ -45,3 +45,13 @@ pub struct CargoObjCreateIn {
pub spec: CargoSpecPartial,
pub version: String,
}

pub struct CargoObjPutIn {
pub spec: CargoSpecPartial,
pub version: String,
}

pub struct CargoObjPatchIn {
pub spec: CargoSpecUpdate,
pub version: String,
}
12 changes: 11 additions & 1 deletion bin/nanocld/src/models/vm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use diesel::prelude::*;
use nanocl_stubs::vm_spec::VmSpecPartial;
use nanocl_stubs::vm_spec::{VmSpecPartial, VmSpecUpdate};

use crate::schema::vms;

Expand Down Expand Up @@ -46,3 +46,13 @@ pub struct VmObjCreateIn {
pub spec: VmSpecPartial,
pub version: String,
}

pub struct VmObjPutIn {
pub spec: VmSpecPartial,
pub version: String,
}

pub struct VmObjPatchIn {
pub spec: VmSpecUpdate,
pub version: String,
}
207 changes: 200 additions & 7 deletions bin/nanocld/src/objects/cargo.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
use futures_util::{stream::FuturesUnordered, StreamExt};
use bollard_next::container::RemoveContainerOptions;
use bollard_next::{
container::{RemoveContainerOptions, Config},
service::HostConfig,
};

use nanocl_error::http::{HttpResult, HttpError};
use nanocl_stubs::{
cargo::{Cargo, CargoDeleteQuery},
cargo_spec::ReplicationMode,
cargo_spec::{ReplicationMode, CargoSpecPartial},
process::ProcessKind,
};

use crate::{
utils,
repositories::generic::*,
models::{CargoDb, SystemState, CargoObjCreateIn, ProcessDb, SpecDb},
models::{
CargoDb, SystemState, CargoObjCreateIn, ProcessDb, SpecDb, CargoObjPutIn,
CargoObjPatchIn,
},
};

use super::generic::*;
Expand Down Expand Up @@ -58,11 +65,11 @@ impl ObjDelByPk for CargoDb {
type ObjDelOpts = CargoDeleteQuery;

async fn fn_del_obj_by_pk(
key: &str,
pk: &str,
opts: &Self::ObjDelOpts,
state: &SystemState,
) -> HttpResult<Self::ObjDelOut> {
let cargo = CargoDb::transform_read_by_pk(key, &state.pool).await?;
let cargo = CargoDb::transform_read_by_pk(pk, &state.pool).await?;
let processes =
ProcessDb::read_by_kind_key(&cargo.spec.cargo_key, &state.pool).await?;
processes
Expand All @@ -83,8 +90,194 @@ impl ObjDelByPk for CargoDb {
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()?;
CargoDb::del_by_pk(key, &state.pool).await?;
SpecDb::del_by_kind_key(key, &state.pool).await?;
CargoDb::del_by_pk(pk, &state.pool).await?;
SpecDb::del_by_kind_key(pk, &state.pool).await?;
Ok(cargo)
}
}

impl ObjPutByPk for CargoDb {
type ObjPutIn = CargoObjPutIn;
type ObjPutOut = Cargo;

async fn fn_put_obj_by_pk(
pk: &str,
obj: &Self::ObjPutIn,
state: &SystemState,
) -> HttpResult<Self::ObjPutOut> {
let cargo =
CargoDb::update_from_spec(pk, &obj.spec, &obj.version, &state.pool)
.await?;
// Get the number of instance to create
let number = if let Some(mode) = &cargo.spec.replication {
match mode {
ReplicationMode::Static(replication_static) => {
replication_static.number

Check warning on line 115 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L113-L115

Added lines #L113 - L115 were not covered by tests
}
ReplicationMode::Auto => 1,
ReplicationMode::Unique => 1,
ReplicationMode::UniqueByNode => 1,
_ => 1,

Check warning on line 120 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L117-L120

Added lines #L117 - L120 were not covered by tests
}
} else {
1
};
let processes = ProcessDb::read_by_kind_key(pk, &state.pool).await?;
utils::cargo::restore_instances_backup(&processes, state).await?;
// Create instance with the new spec
let new_instances =
match utils::cargo::create_instances(&cargo, number, state).await {
// If the creation of the new instance failed, we rename the old containers
Err(err) => {
log::warn!("Unable to create cargo instance: {}", err);
log::warn!("Rollback to previous instance");
utils::cargo::rename_instances_original(&processes, state).await?;
Vec::default()

Check warning on line 135 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L131-L135

Added lines #L131 - L135 were not covered by tests
}
Ok(instances) => instances,
};
// start created containers
match utils::process::start_by_kind(&ProcessKind::Cargo, pk, state).await {
Err(err) => {

Check warning on line 141 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L141

Added line #L141 was not covered by tests
log::error!(
"Unable to start cargo instance {} : {err}",

Check warning on line 143 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L143

Added line #L143 was not covered by tests
cargo.spec.cargo_key
);
utils::cargo::delete_instances(
&new_instances
.iter()
.map(|i| i.key.clone())
.collect::<Vec<_>>(),
state,
)
.await?;
utils::cargo::rename_instances_original(&processes, state).await?;

Check warning on line 154 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L146-L154

Added lines #L146 - L154 were not covered by tests
}
Ok(_) => {
// Delete old containers
utils::cargo::delete_instances(
&processes.iter().map(|c| c.key.clone()).collect::<Vec<_>>(),
state,
)
.await?;
}
}
Ok(cargo)
}
}

impl ObjPatchByPk for CargoDb {
type ObjPatchIn = CargoObjPatchIn;
type ObjPatchOut = Cargo;

async fn fn_patch_obj_by_pk(
pk: &str,
obj: &Self::ObjPatchIn,
state: &SystemState,
) -> HttpResult<Self::ObjPatchOut> {
let payload = &obj.spec;
let version = &obj.version;
let cargo = CargoDb::transform_read_by_pk(pk, &state.pool).await?;
let container = if let Some(container) = payload.container.clone() {

Check warning on line 181 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L173-L181

Added lines #L173 - L181 were not covered by tests
// merge env and ensure no duplicate key
let new_env = container.env.unwrap_or_default();
let mut env_vars: Vec<String> =
cargo.spec.container.env.unwrap_or_default();

Check warning on line 185 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L183-L185

Added lines #L183 - L185 were not covered by tests
// Merge environment variables from new_env into the merged array
for env_var in new_env {
let parts: Vec<&str> = env_var.split('=').collect();
if parts.len() < 2 {
continue;
}
let name = parts[0].to_owned();
let value = parts[1..].join("=");
if let Some(pos) = env_vars
.iter()
.position(|x| x.starts_with(&format!("{name}=")))

Check warning on line 196 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L187-L196

Added lines #L187 - L196 were not covered by tests
{
let old_value = env_vars[pos].to_owned();

Check warning on line 198 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L198

Added line #L198 was not covered by tests
log::trace!(
"env var: {name} old_value: {old_value} new_value: {value}"

Check warning on line 200 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L200

Added line #L200 was not covered by tests
);
if old_value != value && !value.is_empty() {
// Update the value if it has changed
env_vars[pos] = format!("{}={}", name, value);
} else if value.is_empty() {
// Remove the variable if the value is empty
env_vars.remove(pos);
}
} else {
// Add new environment variables
env_vars.push(env_var);
}

Check warning on line 212 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L202-L212

Added lines #L202 - L212 were not covered by tests
}
// merge volumes and ensure no duplication
let new_volumes = container
.host_config
.clone()
.unwrap_or_default()
.binds
.unwrap_or_default();
let mut volumes: Vec<String> = cargo
.spec
.container
.host_config
.clone()
.unwrap_or_default()
.binds
.unwrap_or_default();
for volume in new_volumes {
if !volumes.contains(&volume) {
volumes.push(volume);
}

Check warning on line 232 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L215-L232

Added lines #L215 - L232 were not covered by tests
}
let image = if let Some(image) = container.image.clone() {
Some(image)

Check warning on line 235 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L234-L235

Added lines #L234 - L235 were not covered by tests
} else {
cargo.spec.container.image

Check warning on line 237 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L237

Added line #L237 was not covered by tests
};
let cmd = if let Some(cmd) = container.cmd {
Some(cmd)

Check warning on line 240 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L239-L240

Added lines #L239 - L240 were not covered by tests
} else {
cargo.spec.container.cmd

Check warning on line 242 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L242

Added line #L242 was not covered by tests
};
Config {
cmd,
image,
env: Some(env_vars),
host_config: Some(HostConfig {
binds: Some(volumes),
..cargo.spec.container.host_config.unwrap_or_default()
}),
..cargo.spec.container
}

Check warning on line 253 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L244-L253

Added lines #L244 - L253 were not covered by tests
} else {
cargo.spec.container

Check warning on line 255 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L255

Added line #L255 was not covered by tests
};
let spec = CargoSpecPartial {
name: cargo.spec.name.clone(),
container,
init_container: if payload.init_container.is_some() {
payload.init_container.clone()

Check warning on line 261 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L257-L261

Added lines #L257 - L261 were not covered by tests
} else {
cargo.spec.init_container

Check warning on line 263 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L263

Added line #L263 was not covered by tests
},
replication: payload.replication.clone(),
secrets: if payload.secrets.is_some() {
payload.secrets.clone()

Check warning on line 267 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L265-L267

Added lines #L265 - L267 were not covered by tests
} else {
cargo.spec.secrets

Check warning on line 269 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L269

Added line #L269 was not covered by tests
},
metadata: if payload.metadata.is_some() {
payload.metadata.clone()

Check warning on line 272 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L271-L272

Added lines #L271 - L272 were not covered by tests
} else {
cargo.spec.metadata

Check warning on line 274 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L274

Added line #L274 was not covered by tests
},
};
let obj = &CargoObjPutIn {
spec,
version: version.to_owned(),
};
CargoDb::fn_put_obj_by_pk(pk, obj, state).await
}

Check warning on line 282 in bin/nanocld/src/objects/cargo.rs

View check run for this annotation

Codecov / codecov/patch

bin/nanocld/src/objects/cargo.rs#L277-L282

Added lines #L277 - L282 were not covered by tests
}
6 changes: 3 additions & 3 deletions bin/nanocld/src/objects/generic/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ pub trait ObjDelByPk {
type ObjDelOpts;

async fn fn_del_obj_by_pk(
key: &str,
pk: &str,
opts: &Self::ObjDelOpts,
state: &SystemState,
) -> HttpResult<Self::ObjDelOut>;

async fn del_obj_by_pk(
key: &str,
pk: &str,
opts: &Self::ObjDelOpts,
state: &SystemState,
) -> HttpResult<Self::ObjDelOut>
where
Self::ObjDelOut: Into<EventActor> + Clone,
{
let obj = Self::fn_del_obj_by_pk(key, opts, state).await?;
let obj = Self::fn_del_obj_by_pk(pk, opts, state).await?;
state.emit_normal_native_action(&obj, NativeEventAction::Delete);
Ok(obj)
}
Expand Down
2 changes: 2 additions & 0 deletions bin/nanocld/src/objects/generic/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod create;
mod delete;
mod patch;
mod put;

pub use create::*;
pub use delete::*;
pub use patch::*;
pub use put::*;
Loading

0 comments on commit 4d29fd5

Please sign in to comment.