Merge pull request #513 from rustic-rs/rhai

Add scriptable snapshot filter option
This commit is contained in:
aawsome 2023-03-23 11:43:02 +01:00 committed by GitHub
commit db3d75019a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 2 deletions

99
Cargo.lock generated
View File

@ -44,6 +44,19 @@ dependencies = [
"zeroize",
]
[[package]]
name = "ahash"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
dependencies = [
"cfg-if",
"const-random",
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
@ -326,6 +339,28 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "const-random"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e"
dependencies = [
"const-random-macro",
"proc-macro-hack",
]
[[package]]
name = "const-random-macro"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb"
dependencies = [
"getrandom",
"once_cell",
"proc-macro-hack",
"tiny-keccak",
]
[[package]]
name = "convert_case"
version = "0.4.0"
@ -424,6 +459,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -1497,6 +1538,12 @@ dependencies = [
"version_check",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
version = "1.0.52"
@ -1676,6 +1723,33 @@ dependencies = [
"winreg",
]
[[package]]
name = "rhai"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd29fa1f740be6dc91982013957e08c3c4232d7efcfe19e12da87d50bad47758"
dependencies = [
"ahash",
"bitflags",
"instant",
"num-traits",
"rhai_codegen",
"serde",
"smallvec",
"smartstring",
]
[[package]]
name = "rhai_codegen"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db74e3fdd29d969a0ec1f8e79171a6f0f71d0429293656901db382d248c4c021"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "ring"
version = "0.16.20"
@ -1793,6 +1867,7 @@ dependencies = [
"rand",
"rayon",
"reqwest",
"rhai",
"rpassword",
"rstest",
"scrypt",
@ -2093,6 +2168,21 @@ name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
dependencies = [
"serde",
]
[[package]]
name = "smartstring"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
dependencies = [
"autocfg",
"serde",
"static_assertions",
"version_check",
]
[[package]]
name = "socket2"
@ -2267,6 +2357,15 @@ dependencies = [
"time-core",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
[[package]]
name = "tinyvec"
version = "1.6.0"

View File

@ -87,7 +87,8 @@ humantime = "2"
itertools = "0.10"
simplelog = "0.12"
comfy-table = "6.1.4"
libc="0.2"
libc = "0.2"
rhai = {version = "1.13", features = ["sync", "serde", "no_optimize", "no_module", "no_custom_syntax", "only_i64"]}
[target.'cfg(not(windows))'.dependencies]
users = "0.11"

View File

@ -9,6 +9,7 @@ Bugs fixed:
New features:
- Experimental windows support has been added.
- New option --filter-fn allows to implement your own snapshot filter using the Rhai language.
- New command dump has been added.
- New command merge has been added.
- Extra or wrong fields in the config file now lead to rustic complaining and aborting.

View File

@ -114,7 +114,7 @@ impl RcloneBackend {
bail!("url must start with http://! url: {url}");
}
let url = "http://".to_string() + &user + ":" + &password + "@" + &url[7..];
let url = "http://".to_string() + user.as_str() + ":" + password.as_str() + "@" + &url[7..];
debug!("using REST backend with url {url}.");
let rest = RestBackend::new(&url)?;

View File

@ -14,6 +14,8 @@ use itertools::Itertools;
use log::*;
use merge::Merge;
use path_dedot::ParseDot;
use rhai::serde::to_dynamic;
use rhai::{Dynamic, Engine, FnPtr, AST};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
@ -339,6 +341,19 @@ impl SnapshotFile {
}
pub fn matches(&self, filter: &SnapshotFilter) -> bool {
if let Some(filter_fn) = &filter.filter_fn {
match filter_fn.call::<bool>(self) {
Ok(result) => {
if !result {
return false;
}
}
Err(err) => {
warn!("Error evaluating filter-fn for snapshot {}: {err}", self.id);
}
}
}
self.paths.matches(&filter.filter_paths)
&& self.tags.matches(&filter.filter_tags)
&& (filter.filter_host.is_empty() || filter.filter_host.contains(&self.hostname))
@ -404,6 +419,25 @@ impl Ord for SnapshotFile {
}
}
struct SnapshotFn(FnPtr, AST);
impl FromStr for SnapshotFn {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
let engine = Engine::new();
let ast = engine.compile(s)?;
let func = engine.eval_ast::<FnPtr>(&ast)?;
Ok(Self(func, ast))
}
}
impl SnapshotFn {
fn call<T: Clone + Send + Sync + 'static>(&self, sn: &SnapshotFile) -> Result<T> {
let engine = Engine::new();
let sn: Dynamic = to_dynamic(sn)?;
Ok(self.0.call::<T>(&engine, &self.1, (sn,))?)
}
}
#[serde_as]
#[derive(Default, Parser, Deserialize, Merge)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
@ -429,6 +463,11 @@ pub struct SnapshotFilter {
#[serde_as(as = "Vec<DisplayFromStr>")]
#[merge(strategy=merge::vec::overwrite_empty)]
filter_tags: Vec<StringList>,
/// Function to filter snapshots
#[clap(long, value_name = "FUNC")]
#[serde_as(as = "Option<DisplayFromStr>")]
filter_fn: Option<SnapshotFn>,
}
#[derive(Clone, Default, Deserialize)]