parent
47eea11827
commit
6d24ccb248
|
@ -30,6 +30,13 @@ use datman::remote::backup_source_requester::backup_remote_source_to_destination
|
||||||
use datman::remote::backup_source_responder;
|
use datman::remote::backup_source_responder;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
pub const FAILURE_SYMBOL_OBNOXIOUS_FLASHING: &str = "\x1b[5m\x1b[31m⚠️ \x1b[25m\x1b[22m";
|
||||||
|
pub const BOLD: &str = "\x1b[1m";
|
||||||
|
pub const BOLD_OFF: &str = "\x1b[22m";
|
||||||
|
pub const WHITE: &str = "\x1b[37m";
|
||||||
|
pub const RED: &str = "\x1b[31m";
|
||||||
|
pub const GREEN: &str = "\x1b[32m";
|
||||||
|
|
||||||
#[derive(Clap)]
|
#[derive(Clap)]
|
||||||
pub enum DatmanCommand {
|
pub enum DatmanCommand {
|
||||||
/// Initialise a datman descriptor in this directory.
|
/// Initialise a datman descriptor in this directory.
|
||||||
|
@ -127,6 +134,33 @@ impl FromStr for HumanDateTime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_obvious_successfail_message<R>(result: anyhow::Result<R>) -> anyhow::Result<R> {
|
||||||
|
match &result {
|
||||||
|
Ok(_) => {
|
||||||
|
eprintln!("Operation {}successful{}.", GREEN, WHITE);
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
eprintln!("{:?}", error);
|
||||||
|
eprintln!(
|
||||||
|
"{}{}Operation {}{}FAILED{}!{}",
|
||||||
|
FAILURE_SYMBOL_OBNOXIOUS_FLASHING, WHITE, RED, BOLD, WHITE, BOLD_OFF
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_exitcode<R>(result: anyhow::Result<R>) {
|
||||||
|
match &result {
|
||||||
|
Ok(_) => {
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
std::process::exit(5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||||
|
|
||||||
|
@ -168,7 +202,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(remote_name) = remote {
|
let result = if let Some(remote_name) = remote {
|
||||||
let remote_host_descriptor =
|
let remote_host_descriptor =
|
||||||
if let Some(rhd) = descriptor.remote_hosts.get(&remote_name) {
|
if let Some(rhd) = descriptor.remote_hosts.get(&remote_name) {
|
||||||
rhd
|
rhd
|
||||||
|
@ -185,7 +219,6 @@ fn main() -> anyhow::Result<()> {
|
||||||
remote_host_descriptor,
|
remote_host_descriptor,
|
||||||
yama::utils::get_number_of_workers("YAMA_CHUNKERS"),
|
yama::utils::get_number_of_workers("YAMA_CHUNKERS"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
backup_source_to_destination(
|
backup_source_to_destination(
|
||||||
source,
|
source,
|
||||||
|
@ -196,8 +229,8 @@ fn main() -> anyhow::Result<()> {
|
||||||
&destination_name,
|
&destination_name,
|
||||||
yama::utils::get_number_of_workers("YAMA_CHUNKERS"),
|
yama::utils::get_number_of_workers("YAMA_CHUNKERS"),
|
||||||
)
|
)
|
||||||
.unwrap();
|
};
|
||||||
}
|
with_exitcode(with_obvious_successfail_message(result))
|
||||||
}
|
}
|
||||||
DatmanCommand::BackupAll { destination_name } => {
|
DatmanCommand::BackupAll { destination_name } => {
|
||||||
let descriptor = load_descriptor(Path::new(".")).unwrap();
|
let descriptor = load_descriptor(Path::new(".")).unwrap();
|
||||||
|
|
|
@ -5,7 +5,7 @@ from tempfile import TemporaryDirectory
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from helpers import DirectoryDescriptor, generate_random_dir, scan_dir
|
from helpers import DirectoryDescriptor, generate_random_dir, scan_dir
|
||||||
from helpers.datman_helpers import set_up_simple_datman
|
from helpers.datman_helpers import get_hostname, set_up_simple_datman
|
||||||
from helpers.yama_helpers import set_up_simple_yama
|
from helpers.yama_helpers import set_up_simple_yama
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,3 +59,71 @@ class TestBackupAndExtract(TestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
value.ignore_metadata(), later_expected_descriptor.ignore_metadata()
|
value.ignore_metadata(), later_expected_descriptor.ignore_metadata()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_backup_failure_is_loud(self):
|
||||||
|
"""
|
||||||
|
Tests that backup failure is noticeable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
td = TemporaryDirectory("test_backup_failure_is_loud")
|
||||||
|
tdpath = Path(td.name)
|
||||||
|
|
||||||
|
datman_path = tdpath.joinpath("datman")
|
||||||
|
src_path = datman_path.joinpath("srca")
|
||||||
|
yama_path = datman_path.joinpath("main")
|
||||||
|
|
||||||
|
set_up_simple_datman(
|
||||||
|
datman_path,
|
||||||
|
f"""
|
||||||
|
[source.srcimpossible]
|
||||||
|
directory = "/path/to/absolutely/nowhere"
|
||||||
|
hostname = "{get_hostname()}"
|
||||||
|
|
||||||
|
[source.srcimpossible2]
|
||||||
|
directory = "/path/to/absolutely/nowhere"
|
||||||
|
hostname = "notmymachine"
|
||||||
|
|
||||||
|
[source.srcimpossible3]
|
||||||
|
helper = "failedhelper"
|
||||||
|
label = "precious"
|
||||||
|
kind = {{ stdout = "blahblah.txt" }}
|
||||||
|
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
set_up_simple_yama(yama_path)
|
||||||
|
|
||||||
|
rng = Random()
|
||||||
|
seed = rng.randint(0, 9001)
|
||||||
|
print(f"seed: {seed}")
|
||||||
|
rng.seed(seed)
|
||||||
|
later_expected_descriptor, _ = generate_random_dir(rng, src_path, 32)
|
||||||
|
|
||||||
|
impossible_proc = subprocess.run(
|
||||||
|
("datman", "backup-one", "srcimpossible", "main"),
|
||||||
|
cwd=datman_path,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
self.assertNotEqual(impossible_proc.returncode, 0)
|
||||||
|
last_line = impossible_proc.stderr.decode().split("\n")[-2]
|
||||||
|
self.assertIn("\x1b[31m\x1b[1mFAILED", last_line)
|
||||||
|
|
||||||
|
# NOT YET SUPPORTED
|
||||||
|
print("TEST FOR REMOTE SRC LOUDNESS NOT YET SUPPORTED")
|
||||||
|
# impossible_proc = subprocess.run(("datman", "backup-one",
|
||||||
|
# "srcimpossible2", "main"),
|
||||||
|
# cwd=datman_path,
|
||||||
|
# stderr=subprocess.PIPE)
|
||||||
|
# self.assertNotEqual(impossible_proc.returncode, 0)
|
||||||
|
# last_line = impossible_proc.stderr.decode().split("\n")[-2]
|
||||||
|
# self.assertIn("\x1b[31m\x1b[1mFAILED", last_line)
|
||||||
|
|
||||||
|
impossible_proc = subprocess.run(
|
||||||
|
("datman", "backup-one", "srcimpossible3", "main"),
|
||||||
|
cwd=datman_path,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
self.assertNotEqual(impossible_proc.returncode, 0)
|
||||||
|
last_line = impossible_proc.stderr.decode().split("\n")[-2]
|
||||||
|
self.assertIn("\x1b[31m\x1b[1mFAILED", last_line)
|
||||||
|
|
||||||
|
td.cleanup()
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
def get_hostname():
|
def get_hostname():
|
||||||
return subprocess.check_output("hostname").strip().decode()
|
return subprocess.check_output("hostname").strip().decode()
|
||||||
|
|
||||||
|
|
||||||
def set_up_simple_datman(path: Path):
|
def set_up_simple_datman(path: Path, custom_extra_test: Optional[str]):
|
||||||
path.mkdir(exist_ok=True)
|
path.mkdir(exist_ok=True)
|
||||||
subprocess.check_call(("datman", "init"), cwd=path)
|
subprocess.check_call(("datman", "init"), cwd=path)
|
||||||
|
|
||||||
|
@ -22,3 +23,5 @@ path = "main"
|
||||||
included_labels = ["precious"]
|
included_labels = ["precious"]
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
if custom_extra_test:
|
||||||
|
file.write(custom_extra_test)
|
||||||
|
|
Loading…
Reference in New Issue