Skip to content

Commit

Permalink
chore: Move config to subdir and break into multiple files
Browse files Browse the repository at this point in the history
  • Loading branch information
DaRacci committed Jun 13, 2023
1 parent 1038605 commit 77110c9
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 124 deletions.
7 changes: 4 additions & 3 deletions crates/backup/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::config::{AutoPrune, RuntimeConfig};
use crate::config::rules::AutoPrune;
use crate::config::runtime::RuntimeConfig;
use clap::Parser;
use lib::anyhow::{anyhow, Result};
use lib::cli::Flags;
use lib::simplelog::debug;
use lib::simplelog::{debug, error, info, trace};
use std::fmt::Debug;
use std::path::PathBuf;

Expand Down Expand Up @@ -31,7 +32,7 @@ pub async fn main(destination: PathBuf, cli: Cli, is_interactive: bool) -> Resul
todo!("Non-interactive mode not yet implemented")
}

let config = RuntimeConfig::new(cli, destination)?;
let config = RuntimeConfig::new(cli, destination).await?;
debug!("Config: {:?}", config);

for mut e in config.config.exporters.clone() {
Expand Down
51 changes: 51 additions & 0 deletions crates/backup/src/config/backend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::config::runtime::RuntimeConfig;
use crate::sources::auto_prune::Prune;
use crate::sources::bitwarden::BitWardenCore;
use crate::sources::exporter::Exporter;
use crate::sources::op::core::OnePasswordCore;
use crate::sources::s3::S3Core;
use lib::anyhow::Result;
use std::fmt::{Display, Formatter};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Backend {
S3(S3Core),
BitWarden(BitWardenCore),
OnePassword(OnePasswordCore),
}

impl Display for Backend {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Backend::S3(s3) => write!(
f,
"S3 ({}:{})",
&s3.base.backend.get("bucket").unwrap(),
&s3.base.object.display()
),
Backend::BitWarden(bw) => write!(f, "BitWarden ({})", &bw.org_name),
Backend::OnePassword(op) => write!(f, "1Password ({})", &op.account),
}
}
}

impl Backend {
pub async fn run(&mut self, config: &RuntimeConfig) -> Result<()> {
match self {
Backend::S3(ref mut core) => {
core.prune(&config)?;
core.export(&config).await?;
}
Backend::BitWarden(ref mut core) => {
core.prune(&config)?;
core.export(&config).await?;
}
Backend::OnePassword(ref mut core) => {
core.prune(&config)?;
core.export(&config).await?;
}
}

Ok(())
}
}
7 changes: 7 additions & 0 deletions crates/backup/src/config/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub rules: super::rules::Rules,
pub exporters: Vec<super::backend::Backend>,
}
4 changes: 4 additions & 0 deletions crates/backup/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod runtime;
pub mod config;
pub mod backend;
pub mod rules;
45 changes: 45 additions & 0 deletions crates/backup/src/config/rules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use lib::anyhow::Result;
use std::path::PathBuf;
use std::time::SystemTime;

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Rules {
/// The AutoPrune configuration.
pub auto_prune: AutoPrune,
}

#[derive(Parser, Debug, Clone, Serialize, Deserialize)]
pub struct AutoPrune {
/// Whether or not the auto prune feature is enabled.
#[arg(long = "prune", action = clap::ArgAction::SetTrue)]
pub enabled: bool,

/// How long backups should be kept for in days.
#[arg(long = "prune-keep-days", default_value = "28")]
pub keep_for: usize,

/// The minimum number of backups to keep ignoring the keep_for duration.
#[arg(long = "prune-keep-count", default_value = "5")]
pub keep_latest: usize,
}

impl AutoPrune {
pub fn should_prune(&self, file: &PathBuf, remaining_files: usize) -> Result<bool> {
let mtime = file.metadata()?.modified()?;
let now = SystemTime::now();
let age = now.duration_since(mtime)?;
let days = chrono::Duration::from_std(age)?.num_days();

Ok(days > self.keep_for.clone() as i64 && remaining_files > *&self.keep_latest)
}
}

impl Default for AutoPrune {
fn default() -> Self {
Self {
enabled: false,
keep_for: 28,
keep_latest: 5,
}
}
}
107 changes: 22 additions & 85 deletions crates/backup/src/config.rs → crates/backup/src/config/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,15 @@
use crate::application::Cli;
use crate::config::config::Config;
use crate::continue_loop;
use crate::sources::auto_prune::Prune;
use crate::sources::bitwarden::BitWardenCore;
use crate::sources::exporter::{Exporter, ExporterSource};
use crate::sources::s3::S3Core;
use clap::Parser;
use crate::sources::exporter::ExporterSource;
use clap::ValueEnum;
use inquire::validator::Validation;
use lib::anyhow::{Context, Result};
use lib::simplelog::{debug, info, trace};
use serde::{Deserialize, Serialize};
use lib::simplelog::{debug, error, info, trace};
use std::path::PathBuf;
use std::str::FromStr;
use std::time::SystemTime;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Backend {
S3(S3Core),
BitWarden(BitWardenCore),
}

impl Backend {
pub async fn run(&mut self, config: &RuntimeConfig) -> Result<()> {
match self {
Backend::S3(ref mut core) => {
core.prune(&config)?;
core.export(&config).await?;
}
Backend::BitWarden(ref mut core) => {
core.prune(&config)?;
core.export(&config).await?;
}
}

Ok(())
}
}
use crate::config::backend::Backend;
use crate::config::rules::{AutoPrune, Rules};

#[derive(Clone, Debug)]
pub struct RuntimeConfig {
Expand All @@ -47,7 +21,7 @@ pub struct RuntimeConfig {
}

impl RuntimeConfig {
pub(crate) fn new(cli: Cli, directory: PathBuf) -> Result<Self> {
pub(crate) async fn new(cli: Cli, directory: PathBuf) -> Result<Self> {
let config_path = directory.join("settings.json");

if config_path.exists() {
Expand All @@ -70,7 +44,7 @@ impl RuntimeConfig {
};

if config.cli.append {
let exporters = Self::new_exporters(&config)?;
let exporters = Self::new_exporters(&config).await?;
if !exporters.is_empty() {
config.config.exporters.extend(exporters);
config.mutated = true;
Expand All @@ -91,7 +65,7 @@ impl RuntimeConfig {
},
};

config.config.exporters = Self::new_exporters(&config)?;
config.config.exporters = Self::new_exporters(&config).await?;
Ok(config)
}

Expand Down Expand Up @@ -125,7 +99,18 @@ impl RuntimeConfig {

let serialised = serde_json::to_string_pretty(&self.config)?;
info!("Saving settings to {}", &destination.display());
std::fs::write(destination, serialised).context("Saving settings.json")
if let Err(e) = std::fs::write(destination, &serialised) {
error!("Failed to save settings: {}", e);
if inquire::Confirm::new("Failed to save settings, print to stdout?")
.with_default(true)
.prompt()
.is_ok_and(|b| !b)
{
println!("{}", serialised);
}
}

Ok(())
}

fn new_rules() -> Result<Rules> {
Expand Down Expand Up @@ -174,7 +159,7 @@ impl RuntimeConfig {
Ok(Rules { auto_prune: prune })
}

fn new_exporters(config: &RuntimeConfig) -> Result<Vec<Backend>> {
async fn new_exporters(config: &RuntimeConfig) -> Result<Vec<Backend>> {
let mut exporters = Vec::new();
while continue_loop(&exporters, "Export Source") {
let source_type = inquire::Select::new(
Expand All @@ -186,7 +171,7 @@ impl RuntimeConfig {

match source_type {
Ok(t) => {
let vec = t.create(&config)?;
let vec = t.create(&config).await?;
exporters.extend(vec);
}
Err(_) => {
Expand All @@ -199,51 +184,3 @@ impl RuntimeConfig {
Ok(exporters)
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub rules: Rules,
pub exporters: Vec<Backend>,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Rules {
/// The AutoPrune configuration.
pub auto_prune: AutoPrune,
}

#[derive(Parser, Debug, Clone, Serialize, Deserialize)]
pub struct AutoPrune {
/// Whether or not the auto prune feature is enabled.
#[arg(long = "prune", action = clap::ArgAction::SetTrue)]
pub enabled: bool,

/// How long backups should be kept for in days.
#[arg(long = "prune-keep-days", default_value = "28")]
pub keep_for: usize,

/// The minimum number of backups to keep ignoring the keep_for duration.
#[arg(long = "prune-keep-count", default_value = "5")]
pub keep_latest: usize,
}

impl AutoPrune {
pub fn should_prune(&self, file: &PathBuf, remaining_files: usize) -> Result<bool> {
let mtime = file.metadata()?.modified()?;
let now = SystemTime::now();
let age = now.duration_since(mtime)?;
let days = chrono::Duration::from_std(age)?.num_days();

Ok(days > self.keep_for.clone() as i64 && remaining_files > *&self.keep_latest)
}
}

impl Default for AutoPrune {
fn default() -> Self {
Self {
enabled: false,
keep_for: 28,
keep_latest: 5,
}
}
}
4 changes: 3 additions & 1 deletion crates/backup/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#![feature(exit_status_error)]
#![feature(unwrap_infallible)]
#![feature(slice_pattern)]
#![feature(let_chains)]
#![feature(return_position_impl_trait_in_trait)]

extern crate core;

Expand All @@ -12,8 +14,8 @@ use lib::anyhow::{anyhow, Context, Result};
use lib::simplelog::{trace, warn};

pub mod application;
pub mod config;
pub mod sources;
pub mod config;

fn continue_loop<I>(vec: &Vec<I>, prompt_type: &str) -> bool {
if vec.is_empty() {
Expand Down
4 changes: 1 addition & 3 deletions crates/backup/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,11 @@ async fn main() -> Result<()> {

trace!("Selected destination: {}", &destination.display());

application::main(destination, cli, true).await?;
application::main(destination, cli, true).await

// TODO :: Verify writable
// TODO :: Verify enough space
// TODO :: Verify dir is either empty, or has existing backup data

Ok(())
}

fn interactive_select_drive() -> core::result::Result<PathBuf, impl Error> {
Expand Down
2 changes: 1 addition & 1 deletion crates/backup/src/sources/auto_prune.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::config::RuntimeConfig;
use crate::config::runtime::RuntimeConfig;
use lib::anyhow::Result;
use lib::simplelog::debug;
use std::path::PathBuf;
Expand Down
Loading

0 comments on commit 77110c9

Please sign in to comment.