feat: add run_backup_container skeleton
This commit is contained in:
parent
1f194ca7f1
commit
d0afb2955b
5 changed files with 299 additions and 27 deletions
122
Cargo.lock
generated
122
Cargo.lock
generated
|
|
@ -17,6 +17,15 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-tzdata"
|
name = "android-tzdata"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -65,6 +74,12 @@ version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bollard"
|
name = "bollard"
|
||||||
version = "0.19.1"
|
version = "0.19.1"
|
||||||
|
|
@ -195,6 +210,7 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -307,6 +323,18 @@ dependencies = [
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasi 0.14.2+wasi-0.2.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
|
|
@ -651,6 +679,15 @@ version = "0.4.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata 0.1.10",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.5"
|
version = "2.7.5"
|
||||||
|
|
@ -673,7 +710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -774,6 +811,12 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ref-cast"
|
name = "ref-cast"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
|
|
@ -794,6 +837,50 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata 0.4.9",
|
||||||
|
"regex-syntax 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax 0.6.29",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.25"
|
version = "0.1.25"
|
||||||
|
|
@ -1142,10 +1229,14 @@ version = "0.3.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
"nu-ansi-term",
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
@ -1179,6 +1270,17 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -1206,6 +1308,15 @@ version = "0.11.1+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.14.2+wasi-0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.100"
|
version = "0.2.100"
|
||||||
|
|
@ -1427,6 +1538,15 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rt"
|
||||||
|
version = "0.39.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "writeable"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,5 @@ serde_yml = "0.0.12"
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
tokio = { version = "1.45.1", features = ["macros", "rt", "rt-multi-thread"] }
|
tokio = { version = "1.45.1", features = ["macros", "rt", "rt-multi-thread"] }
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
tracing-subscriber = "0.3.19"
|
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "std"] }
|
||||||
|
uuid = { version = "1.17.0", features = ["v4"] }
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use bollard::models::{ContainerSummary, ContainerSummaryStateEnum, MountPoint};
|
use bollard::models::{ContainerSummary, ContainerSummaryStateEnum, MountPoint};
|
||||||
|
use bollard::secret::ContainerCreateBody;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde_yml::Value;
|
use serde_yml::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tracing::field::{Field, Visit};
|
|
||||||
|
|
||||||
mod labels;
|
mod labels;
|
||||||
|
|
||||||
|
|
@ -16,6 +16,20 @@ pub struct Container {
|
||||||
pub labels: Labels,
|
pub labels: Labels,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Container {
|
||||||
|
fn default() -> Self {
|
||||||
|
Container {
|
||||||
|
id: String::default(),
|
||||||
|
name: String::default(),
|
||||||
|
image: String::default(),
|
||||||
|
state: ContainerSummaryStateEnum::EMPTY,
|
||||||
|
|
||||||
|
mounts: vec![],
|
||||||
|
labels: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<ContainerSummary> for Container {
|
impl From<ContainerSummary> for Container {
|
||||||
fn from(value: ContainerSummary) -> Self {
|
fn from(value: ContainerSummary) -> Self {
|
||||||
let container_name: String = value
|
let container_name: String = value
|
||||||
|
|
@ -36,13 +50,65 @@ impl From<ContainerSummary> for Container {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl From<&Container> for ContainerCreateBody {
|
||||||
|
fn from(value: &Container) -> Self {
|
||||||
|
ContainerCreateBody {
|
||||||
|
image: Some(value.image.clone()),
|
||||||
|
labels: Some(HashMap::from([
|
||||||
|
(String::from("epoch.internal.managed"), String::from("true")),
|
||||||
|
(
|
||||||
|
String::from("epoch.internal.ephemeral"),
|
||||||
|
String::from("true"),
|
||||||
|
),
|
||||||
|
])),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ContainerBuilder {
|
||||||
|
container: Container
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContainerBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
container: Container::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Container {
|
||||||
|
self.container
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_id(mut self, id: impl Into<String>) -> Self {
|
||||||
|
self.container.id = id.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_image(mut self, image: impl Into<String>) -> Self {
|
||||||
|
self.container.image = image.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_mounts(mut self, mounts: Vec<MountPoint>) -> Self {
|
||||||
|
self.container.mounts = mounts;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_labels(mut self, labels: HashMap<String, String>) -> Self {
|
||||||
|
self.container.labels = labels.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
pub struct Labels {
|
pub struct Labels {
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
pub service: ServiceConfig,
|
pub service: ServiceConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ServiceConfig {
|
pub struct ServiceConfig {
|
||||||
pub compose_hash: Option<String>,
|
pub compose_hash: Option<String>,
|
||||||
pub group: Option<String>,
|
pub group: Option<String>,
|
||||||
|
|
|
||||||
14
src/main.rs
14
src/main.rs
|
|
@ -1,22 +1,34 @@
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tokio;
|
use tokio;
|
||||||
|
use tracing::info;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> epoch::Result<()> {
|
async fn main() -> epoch::Result<()> {
|
||||||
// construct a subscriber that prints formatted traces to stdout
|
// construct a subscriber that prints formatted traces to stdout
|
||||||
tracing_subscriber::fmt().with_ansi(true).compact().init();
|
tracing_subscriber::fmt()
|
||||||
|
.with_ansi(true)
|
||||||
|
.with_line_number(true)
|
||||||
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
|
.init();
|
||||||
|
|
||||||
let docker = Docker::connect_with_local_defaults()?;
|
let docker = Docker::connect_with_local_defaults()?;
|
||||||
|
|
||||||
let filters: HashMap<&str, Vec<&str>> = HashMap::from([("label", vec!["epoch.manage=true"])]);
|
let filters: HashMap<&str, Vec<&str>> = HashMap::from([("label", vec!["epoch.manage=true"])]);
|
||||||
|
|
||||||
let opts = bollard::query_parameters::ListContainersOptionsBuilder::new()
|
let opts = bollard::query_parameters::ListContainersOptionsBuilder::new()
|
||||||
|
.all(true)
|
||||||
.filters(&filters)
|
.filters(&filters)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let containers = docker.list_containers(Some(opts)).await?;
|
let containers = docker.list_containers(Some(opts)).await?;
|
||||||
|
|
||||||
|
if containers.is_empty() {
|
||||||
|
info!("No containers found, exiting");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
epoch::manager::manage(&containers).await?;
|
epoch::manager::manage(&containers).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
115
src/manager.rs
115
src/manager.rs
|
|
@ -1,10 +1,11 @@
|
||||||
use crate::docker::Container;
|
use crate::docker::{Container, ContainerBuilder};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use bollard::models::ContainerSummary;
|
use bollard::models::ContainerSummary;
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
|
use futures::StreamExt;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tracing::info;
|
use tracing::{debug, info, instrument};
|
||||||
|
|
||||||
/// Namespace to manage containers together (like compose projects)
|
/// Namespace to manage containers together (like compose projects)
|
||||||
type ServiceGroup = String;
|
type ServiceGroup = String;
|
||||||
|
|
@ -12,7 +13,7 @@ type ServiceGroup = String;
|
||||||
const DEFAULT_GROUP: &str = "NONE";
|
const DEFAULT_GROUP: &str = "NONE";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Services(HashMap<ServiceGroup, Vec<crate::docker::Container>>);
|
struct Services(HashMap<ServiceGroup, Vec<Container>>);
|
||||||
|
|
||||||
impl From<&Vec<ContainerSummary>> for Services {
|
impl From<&Vec<ContainerSummary>> for Services {
|
||||||
fn from(value: &Vec<ContainerSummary>) -> Self {
|
fn from(value: &Vec<ContainerSummary>) -> Self {
|
||||||
|
|
@ -38,7 +39,7 @@ impl From<&Vec<ContainerSummary>> for Services {
|
||||||
Some(group) => group.to_owned(),
|
Some(group) => group.to_owned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let list: &mut Vec<crate::docker::Container> = services.entry(group).or_default();
|
let list: &mut Vec<Container> = services.entry(group).or_default();
|
||||||
list.push(container);
|
list.push(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,43 +49,115 @@ impl From<&Vec<ContainerSummary>> for Services {
|
||||||
|
|
||||||
#[tracing::instrument(skip(containers))]
|
#[tracing::instrument(skip(containers))]
|
||||||
pub async fn manage(containers: &Vec<ContainerSummary>) -> crate::Result<()> {
|
pub async fn manage(containers: &Vec<ContainerSummary>) -> crate::Result<()> {
|
||||||
|
let total_containers = containers.len();
|
||||||
let services = Services::from(containers);
|
let services = Services::from(containers);
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Found {} containers, grouped into {} groups",
|
||||||
|
total_containers,
|
||||||
|
services.0.len()
|
||||||
|
);
|
||||||
|
|
||||||
// TODO: reuse main instance
|
// TODO: reuse main instance
|
||||||
let docker = Docker::connect_with_local_defaults()?;
|
let docker = Docker::connect_with_local_defaults()?;
|
||||||
|
|
||||||
// TODO: iterate over groups in parallel
|
// TODO: iterate over groups in parallel
|
||||||
for (group, containers) in services.0.iter() {
|
for (group, containers) in services.0.iter() {
|
||||||
// stop containers of service group
|
handle_group(&docker, group, containers).await?;
|
||||||
try_join_all(containers.into_iter().map(|container | stop_container(&docker, container))).await?;
|
|
||||||
|
|
||||||
// create container with the same mounts as each container in the group
|
|
||||||
|
|
||||||
// run the new container
|
|
||||||
|
|
||||||
// restart the containers
|
|
||||||
try_join_all(containers.into_iter().map(|container| start_container(&docker, container))).await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do cleanup to ensure all containers that are created are also deleted
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn stop_container(docker: &Docker, container: &crate::docker::Container) -> crate::Result<()> {
|
#[tracing::instrument(skip(docker, containers))]
|
||||||
info!("Stoping container: {:#?}", container.id);
|
async fn handle_group(
|
||||||
|
docker: &Docker,
|
||||||
|
_group: &ServiceGroup,
|
||||||
|
containers: &Vec<Container>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// stop containers of service group
|
||||||
|
try_join_all(
|
||||||
|
containers
|
||||||
|
.into_iter()
|
||||||
|
.map(|container| stop_container(&docker, &container.id)),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// create container with the same mounts as each container in the group
|
||||||
|
let backup_container = ContainerBuilder::new().with_image("hello-world").build();
|
||||||
|
|
||||||
|
run_backup_container(&docker, &backup_container).await?;
|
||||||
|
|
||||||
|
// run the new container
|
||||||
|
|
||||||
|
// restart the containers
|
||||||
|
try_join_all(
|
||||||
|
containers
|
||||||
|
.into_iter()
|
||||||
|
.map(|container| start_container(&docker, &container.id)),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn stop_container(
|
||||||
|
docker: &Docker,
|
||||||
|
container_id: impl AsRef<str>,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let container_id = container_id.as_ref();
|
||||||
|
info!("Stoping container: {}", container_id);
|
||||||
|
|
||||||
let stop_opts = bollard::query_parameters::StopContainerOptionsBuilder::new().build();
|
let stop_opts = bollard::query_parameters::StopContainerOptionsBuilder::new().build();
|
||||||
|
|
||||||
docker.stop_container(&container.id, Some(stop_opts)).await?;
|
docker
|
||||||
|
.stop_container(container_id, Some(stop_opts))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok::<(), crate::Error>(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start_container(docker: &Docker, container: &crate::docker::Container) -> crate::Result<()> {
|
async fn start_container(
|
||||||
info!("Starting container: {:#?}", container.id);
|
docker: &Docker,
|
||||||
|
container_id: impl AsRef<str>,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let container_id = container_id.as_ref();
|
||||||
|
info!("Starting container: {}", container_id);
|
||||||
|
|
||||||
let start_opts = bollard::query_parameters::StartContainerOptionsBuilder::new().build();
|
let start_opts = bollard::query_parameters::StartContainerOptionsBuilder::new().build();
|
||||||
|
|
||||||
docker.start_container(&container.id, Some(start_opts)).await?;
|
docker
|
||||||
|
.start_container(container_id, Some(start_opts))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok::<(), crate::Error>(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip_all, fields(container_id))]
|
||||||
|
async fn run_backup_container(docker: &Docker, container: &Container) -> crate::Result<()> {
|
||||||
|
info!("Creating container from image {:?}",&container.image);
|
||||||
|
debug!("{:#?}", &container);
|
||||||
|
|
||||||
|
let create_opts = bollard::query_parameters::CreateContainerOptionsBuilder::default().build();
|
||||||
|
let create_conf = bollard::models::ContainerCreateBody::from(container);
|
||||||
|
|
||||||
|
let response = docker
|
||||||
|
.create_container(Some(create_opts), create_conf)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
tracing::Span::current().record("container_id", &response.id);
|
||||||
|
|
||||||
|
start_container(docker, &response.id).await?;
|
||||||
|
|
||||||
|
let wait_opts = bollard::query_parameters::WaitContainerOptionsBuilder::default().build();
|
||||||
|
let mut stream = docker.wait_container(&response.id, Some(wait_opts));
|
||||||
|
|
||||||
|
while let Some(status) = stream.next().await {
|
||||||
|
debug!("Received status: {:?}", status?);
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_container(docker, &response.id).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue