Add support for using a hostname identifier

This commit is contained in:
Eduard Tolosa 2024-02-07 00:01:10 -05:00
parent 14c0f371d2
commit 230b2babbe
8 changed files with 49 additions and 11 deletions

18
Cargo.lock generated
View file

@ -269,6 +269,17 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
[[package]]
name = "hostname"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
dependencies = [
"libc",
"match_cfg",
"winapi",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.60" version = "0.1.60"
@ -363,6 +374,12 @@ version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "match_cfg"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]] [[package]]
name = "md5" name = "md5"
version = "0.7.0" version = "0.7.0"
@ -455,6 +472,7 @@ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
"clap", "clap",
"hostname",
"md5", "md5",
"prettytable-rs", "prettytable-rs",
"serde", "serde",

View file

@ -16,6 +16,7 @@ chrono = "0.4.33"
prettytable-rs = "0.10.0" prettytable-rs = "0.10.0"
anyhow = "1.0.79" anyhow = "1.0.79"
toml = "0.8.9" toml = "0.8.9"
hostname = "0.3.1"
[profile.release] [profile.release]

View file

@ -62,6 +62,9 @@ pub struct Args {
/// Create read-write/rw snapshots. /// Create read-write/rw snapshots.
#[clap(short = 'w', long = "rw")] #[clap(short = 'w', long = "rw")]
pub read_write: bool, pub read_write: bool,
/// Machine name to be used in the metadata.
#[clap(short, long, default_value = "")]
pub machine: String,
} }
impl Args { impl Args {
@ -148,6 +151,12 @@ impl Args {
.parse() .parse()
.expect("Failed to parse timeout, make sure it's a number"); .expect("Failed to parse timeout, make sure it's a number");
} }
if let Some(machine) = config.get("machine") {
self.machine = machine
.to_string()
.parse()
.expect("Failed to parse machine");
}
Ok(()) Ok(())
} }

View file

@ -79,6 +79,7 @@ pub fn manage_listing(database_connection: &Connection) -> Result<()> {
"KIND", "KIND",
"SOURCE DIR", "SOURCE DIR",
"DESTINATION DIR", "DESTINATION DIR",
"MACHINE",
"RO/RW", "RO/RW",
"DATE" "DATE"
]); ]);
@ -90,6 +91,7 @@ pub fn manage_listing(database_connection: &Connection) -> Result<()> {
data.kind, data.kind,
data.source, data.source,
data.destination, data.destination,
data.machine,
data.ro_rw, data.ro_rw,
data.date, data.date,
]); ]);

View file

@ -8,7 +8,7 @@ use {
}; };
pub fn setup_initial_database(connection: &Connection) -> Result<()> { pub fn setup_initial_database(connection: &Connection) -> Result<()> {
connection.execute("CREATE TABLE IF NOT EXISTS snapshots (name TEXT NOT NULL, snap_id TEXT NOT NULL, kind TEXT NOT NULL, source TEXT NOT NULL, destination TEXT NOT NULL, ro_rw TEXT NOT NULL, date TEXT DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(name, snap_id))")?; connection.execute("CREATE TABLE IF NOT EXISTS snapshots (name TEXT NOT NULL, snap_id TEXT NOT NULL, kind TEXT NOT NULL, source TEXT NOT NULL, destination TEXT NOT NULL, machine TEXT NOT NULL, ro_rw TEXT NOT NULL, date TEXT DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(name, snap_id))")?;
connection.execute("PRAGMA journal_mode=WAL")?; connection.execute("PRAGMA journal_mode=WAL")?;
Ok(()) Ok(())
@ -16,8 +16,8 @@ pub fn setup_initial_database(connection: &Connection) -> Result<()> {
pub fn commit_to_database(args: &Args, extra_args: &ExtraArgs) -> Result<()> { pub fn commit_to_database(args: &Args, extra_args: &ExtraArgs) -> Result<()> {
let statement = format!( let statement = format!(
"INSERT INTO snapshots (name, snap_id, kind, source, destination, ro_rw) VALUES ('{}', '{}', '{}', '{}', '{}', '{}')", "INSERT INTO snapshots (name, snap_id, kind, source, destination, machine, ro_rw) VALUES ('{}', '{}', '{}', '{}', '{}', '{}', '{}')",
&extra_args.snapshot_name, args.snapshot_id, args.snapshot_kind, args.source_dir, args.dest_dir, args.read_write &extra_args.snapshot_name, args.snapshot_id, args.snapshot_kind, args.source_dir, args.dest_dir, args.machine, args.read_write
); );
extra_args.database_connection.execute(statement)?; extra_args.database_connection.execute(statement)?;
@ -52,7 +52,7 @@ pub fn return_all_data(connection: &Connection) -> Result<Vec<Database>> {
let mut snapshots_data: Vec<Database> = Vec::new(); let mut snapshots_data: Vec<Database> = Vec::new();
let mut statement = connection let mut statement = connection
.prepare("SELECT name,snap_id,kind,source,destination,ro_rw,datetime(date, 'localtime') FROM snapshots ORDER BY date DESC")?; .prepare("SELECT name,snap_id,kind,source,destination,machine,ro_rw,datetime(date, 'localtime') FROM snapshots ORDER BY date DESC")?;
while statement.next()? == State::Row { while statement.next()? == State::Row {
let db_struct = Database::default(); let db_struct = Database::default();
@ -65,7 +65,7 @@ pub fn return_all_data(connection: &Connection) -> Result<Vec<Database>> {
pub fn return_only_x_items(connection: &Connection, args: &Args) -> Result<Vec<Database>> { pub fn return_only_x_items(connection: &Connection, args: &Args) -> Result<Vec<Database>> {
let mut snapshots_data: Vec<Database> = Vec::new(); let mut snapshots_data: Vec<Database> = Vec::new();
let mut statement = connection.prepare(&format!("SELECT name,snap_id,kind,source,destination,ro_rw,date FROM (SELECT row_number() over(ORDER BY date DESC) n,* from snapshots WHERE name like '{}%' AND kind = '{}' AND ro_rw = '{}') WHERE n > {}", args.snapshot_prefix, args.snapshot_kind, args.read_write, args.keep_only))?; let mut statement = connection.prepare(&format!("SELECT name,snap_id,kind,source,destination,machine,ro_rw,date FROM (SELECT row_number() over(ORDER BY date DESC) n,* from snapshots WHERE name like '{}%' AND kind = '{}' AND ro_rw = '{}') WHERE n > {}", args.snapshot_prefix, args.snapshot_kind, args.read_write, args.keep_only))?;
while statement.next()? == State::Row { while statement.next()? == State::Row {
let db_struct = Database::default(); let db_struct = Database::default();
@ -83,8 +83,9 @@ fn populate_db_struct(row: &Statement, mut db_struct: Database) -> Result<Databa
db_struct.kind = row.read(2)?; db_struct.kind = row.read(2)?;
db_struct.source = row.read(3)?; db_struct.source = row.read(3)?;
db_struct.destination = row.read(4)?; db_struct.destination = row.read(4)?;
db_struct.ro_rw = row.read(5)?; db_struct.machine = row.read(5)?;
db_struct.date = row.read(6)?; db_struct.ro_rw = row.read(6)?;
db_struct.date = row.read(7)?;
Ok(db_struct) Ok(db_struct)
} }

View file

@ -1,7 +1,9 @@
use anyhow::Result; use {
use chrono::Utc; anyhow::Result,
use clap::Parser; chrono::Utc,
use rusnapshot::{args, controller, structs::ExtraArgs, utils}; clap::Parser,
rusnapshot::{args, controller, structs::ExtraArgs, utils},
};
fn try_run() -> Result<()> { fn try_run() -> Result<()> {
let mut arguments = args::Args::parse(); let mut arguments = args::Args::parse();

View file

@ -8,6 +8,7 @@ pub struct Database {
pub source: String, pub source: String,
pub destination: String, pub destination: String,
pub ro_rw: String, pub ro_rw: String,
pub machine: String,
pub date: String, pub date: String,
} }

View file

@ -42,5 +42,9 @@ pub fn check_creation_requirements(arguments: &mut Args, extra_args: &ExtraArgs)
.to_string(); .to_string();
} }
if arguments.machine.is_empty() {
arguments.machine = hostname::get()?.to_string_lossy().to_string();
}
Ok(()) Ok(())
} }