summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-05-29 11:39:31 +0300
committerLars Wirzenius <liw@liw.fi>2021-05-29 15:11:53 +0300
commit08b71890de3407acc323f09330ebe8a8ee2782ec (patch)
tree859d2a26dcc5517105bf5078f273fd24672ad756
parente839c5f1c93e1fe024a2656d319721a7b23c6461 (diff)
downloadobnam2-08b71890de3407acc323f09330ebe8a8ee2782ec.tar.gz
refactor: only have client config without passwords
This means the config is always the config, and not sometimes the config or the config and passwords. Also, there's no config option for encrypting, anymore. It will not be optional now.
-rw-r--r--src/backup_run.rs2
-rw-r--r--src/bin/obnam.rs39
-rw-r--r--src/cmd/backup.rs2
-rw-r--r--src/cmd/init.rs8
-rw-r--r--src/cmd/show_config.rs2
-rw-r--r--src/config.rs92
-rw-r--r--subplot/client.py11
-rw-r--r--subplot/client.yaml5
8 files changed, 63 insertions, 98 deletions
diff --git a/src/backup_run.rs b/src/backup_run.rs
index 23c97f6..16d6700 100644
--- a/src/backup_run.rs
+++ b/src/backup_run.rs
@@ -41,7 +41,6 @@ pub type BackupResult<T> = Result<T, BackupError>;
impl<'a> InitialBackup<'a> {
pub fn new(config: &ClientConfig, client: &'a BackupClient) -> BackupResult<Self> {
let progress = BackupProgress::initial();
- let config = config.config();
Ok(Self {
client,
buffer_size: config.chunk_size,
@@ -81,7 +80,6 @@ impl<'a> InitialBackup<'a> {
impl<'a> IncrementalBackup<'a> {
pub fn new(config: &ClientConfig, client: &'a BackupClient) -> BackupResult<Self> {
- let config = config.config();
let policy = BackupPolicy::default();
Ok(Self {
client,
diff --git a/src/bin/obnam.rs b/src/bin/obnam.rs
index cdb5179..c8da6c2 100644
--- a/src/bin/obnam.rs
+++ b/src/bin/obnam.rs
@@ -3,6 +3,7 @@ use log::{debug, error, info, LevelFilter};
use log4rs::append::file::FileAppender;
use log4rs::config::{Appender, Logger, Root};
use obnam::cmd::backup::Backup;
+use obnam::cmd::chunk::{DecryptChunk, EncryptChunk};
use obnam::cmd::get_chunk::GetChunk;
use obnam::cmd::init::Init;
use obnam::cmd::list::List;
@@ -20,28 +21,24 @@ const APPLICATION: &str = "obnam";
fn main() -> anyhow::Result<()> {
let opt = Opt::from_args();
- let config = load_config_without_passwords(&opt)?;
- setup_logging(&config.config().log)?;
+ let config = ClientConfig::read(&config_filename(&opt))?;
+ setup_logging(&config.log)?;
info!("client starts");
debug!("{:?}", opt);
debug!("configuration: {:#?}", config);
let result = match opt.cmd {
- Command::Init(x) => x.run(config.config()),
- _ => {
- let config = load_config_with_passwords(&opt)?;
- match opt.cmd {
- Command::Init(_) => panic!("this can't happen"),
- Command::Backup(x) => x.run(&config),
- Command::List(x) => x.run(&config),
- Command::ShowGeneration(x) => x.run(&config),
- Command::ListFiles(x) => x.run(&config),
- Command::Restore(x) => x.run(&config),
- Command::GetChunk(x) => x.run(&config),
- Command::Config(x) => x.run(&config),
- }
- }
+ Command::Init(x) => x.run(&config),
+ Command::Backup(x) => x.run(&config),
+ Command::List(x) => x.run(&config),
+ Command::ShowGeneration(x) => x.run(&config),
+ Command::ListFiles(x) => x.run(&config),
+ Command::Restore(x) => x.run(&config),
+ Command::GetChunk(x) => x.run(&config),
+ Command::Config(x) => x.run(&config),
+ Command::EncryptChunk(x) => x.run(&config),
+ Command::DecryptChunk(x) => x.run(&config),
};
if let Err(ref e) = result {
@@ -66,14 +63,6 @@ fn setup_logging(filename: &Path) -> anyhow::Result<()> {
Ok(())
}
-fn load_config_with_passwords(opt: &Opt) -> Result<ClientConfig, anyhow::Error> {
- Ok(ClientConfig::read_with_passwords(&config_filename(opt))?)
-}
-
-fn load_config_without_passwords(opt: &Opt) -> Result<ClientConfig, anyhow::Error> {
- Ok(ClientConfig::read_without_passwords(&config_filename(opt))?)
-}
-
fn config_filename(opt: &Opt) -> PathBuf {
match opt.config {
None => default_config(),
@@ -109,4 +98,6 @@ enum Command {
ShowGeneration(ShowGeneration),
GetChunk(GetChunk),
Config(ShowConfig),
+ EncryptChunk(EncryptChunk),
+ DecryptChunk(DecryptChunk),
}
diff --git a/src/cmd/backup.rs b/src/cmd/backup.rs
index 0479844..22afd6e 100644
--- a/src/cmd/backup.rs
+++ b/src/cmd/backup.rs
@@ -60,7 +60,6 @@ fn initial_backup(
info!("fresh backup without a previous generation");
let newtemp = NamedTempFile::new()?;
let run = InitialBackup::new(config, &client)?;
- let config = config.config();
let mut all_warnings = vec![];
let count = {
let mut new = NascentGeneration::create(newtemp.path())?;
@@ -87,7 +86,6 @@ fn incremental_backup(
info!("incremental backup based on {}", old_ref);
let newtemp = NamedTempFile::new()?;
let mut run = IncrementalBackup::new(config, &client)?;
- let config = config.config();
let mut all_warnings = vec![];
let count = {
let oldtemp = NamedTempFile::new()?;
diff --git a/src/cmd/init.rs b/src/cmd/init.rs
index cb61fba..08060f7 100644
--- a/src/cmd/init.rs
+++ b/src/cmd/init.rs
@@ -1,4 +1,4 @@
-use crate::config::ClientConfigWithoutPasswords;
+use crate::config::ClientConfig;
use crate::error::ObnamError;
use crate::passwords::{passwords_filename, Passwords};
use structopt::StructOpt;
@@ -12,11 +12,7 @@ pub struct Init {
}
impl Init {
- pub fn run(&self, config: &ClientConfigWithoutPasswords) -> Result<(), ObnamError> {
- if !config.encrypt {
- panic!("no encryption specified");
- }
-
+ pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> {
let passphrase = match &self.insecure_passphrase {
Some(x) => x.to_string(),
None => rpassword::read_password_from_tty(Some(PROMPT)).unwrap(),
diff --git a/src/cmd/show_config.rs b/src/cmd/show_config.rs
index 424e2ed..05e83c1 100644
--- a/src/cmd/show_config.rs
+++ b/src/cmd/show_config.rs
@@ -7,7 +7,7 @@ pub struct ShowConfig {}
impl ShowConfig {
pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> {
- println!("{}", serde_json::to_string_pretty(&config.config())?);
+ println!("{}", serde_json::to_string_pretty(config)?);
Ok(())
}
}
diff --git a/src/config.rs b/src/config.rs
index 33e08a2..0d4e9de 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -16,78 +16,22 @@ struct TentativeClientConfig {
chunk_size: Option<usize>,
roots: Vec<PathBuf>,
log: Option<PathBuf>,
- encrypt: Option<bool>,
exclude_cache_tag_directories: Option<bool>,
}
#[derive(Debug, Serialize, Clone)]
-pub enum ClientConfig {
- Plain(ClientConfigWithoutPasswords),
- WithPasswords(ClientConfigWithoutPasswords, Passwords),
-}
-
-impl ClientConfig {
- pub fn read_without_passwords(filename: &Path) -> Result<Self, ClientConfigError> {
- let config = ClientConfigWithoutPasswords::read_config(filename)?;
- Ok(ClientConfig::Plain(config))
- }
-
- pub fn read_with_passwords(filename: &Path) -> Result<Self, ClientConfigError> {
- let config = ClientConfigWithoutPasswords::read_config(filename)?;
- if config.encrypt {
- let passwords = Passwords::load(&passwords_filename(filename))
- .map_err(ClientConfigError::PasswordsMissing)?;
- Ok(ClientConfig::WithPasswords(config, passwords))
- } else {
- Ok(ClientConfig::Plain(config))
- }
- }
-
- pub fn config(&self) -> &ClientConfigWithoutPasswords {
- match self {
- Self::Plain(config) => &config,
- Self::WithPasswords(config, _) => &config,
- }
- }
-}
-
-#[derive(Debug, Serialize, Clone)]
-pub struct ClientConfigWithoutPasswords {
+pub struct ClientConfig {
pub filename: PathBuf,
pub server_url: String,
pub verify_tls_cert: bool,
pub chunk_size: usize,
pub roots: Vec<PathBuf>,
pub log: PathBuf,
- pub encrypt: bool,
pub exclude_cache_tag_directories: bool,
}
-#[derive(Debug, thiserror::Error)]
-pub enum ClientConfigError {
- #[error("server_url is empty")]
- ServerUrlIsEmpty,
-
- #[error("No backup roots in config; at least one is needed")]
- NoBackupRoot,
-
- #[error("server URL doesn't use https: {0}")]
- NotHttps(String),
-
- #[error("No passwords are set: you may need to run 'obnam init': {0}")]
- PasswordsMissing(PasswordError),
-
- #[error("failed to read configuration file {0}: {1}")]
- Read(PathBuf, std::io::Error),
-
- #[error("failed to parse configuration file {0} as YAML: {1}")]
- YamlParse(PathBuf, serde_yaml::Error),
-}
-
-pub type ClientConfigResult<T> = Result<T, ClientConfigError>;
-
-impl ClientConfigWithoutPasswords {
- pub fn read_config(filename: &Path) -> ClientConfigResult<Self> {
+impl ClientConfig {
+ pub fn read(filename: &Path) -> ClientConfigResult<Self> {
trace!("read_config: filename={:?}", filename);
let config = std::fs::read_to_string(filename)
.map_err(|err| ClientConfigError::Read(filename.to_path_buf(), err))?;
@@ -102,12 +46,10 @@ impl ClientConfigWithoutPasswords {
.log
.map(|path| expand_tilde(&path))
.unwrap_or_else(|| PathBuf::from(DEVNULL));
- let encrypt = tentative.encrypt.or(Some(false)).unwrap();
let exclude_cache_tag_directories = tentative.exclude_cache_tag_directories.unwrap_or(true);
let config = Self {
chunk_size: tentative.chunk_size.or(Some(DEFAULT_CHUNK_SIZE)).unwrap(),
- encrypt,
filename: filename.to_path_buf(),
roots,
server_url: tentative.server_url,
@@ -132,8 +74,36 @@ impl ClientConfigWithoutPasswords {
}
Ok(())
}
+
+ pub fn passwords(&self) -> Result<Passwords, ClientConfigError> {
+ Passwords::load(&passwords_filename(&self.filename))
+ .map_err(ClientConfigError::PasswordsMissing)
+ }
}
+#[derive(Debug, thiserror::Error)]
+pub enum ClientConfigError {
+ #[error("server_url is empty")]
+ ServerUrlIsEmpty,
+
+ #[error("No backup roots in config; at least one is needed")]
+ NoBackupRoot,
+
+ #[error("server URL doesn't use https: {0}")]
+ NotHttps(String),
+
+ #[error("No passwords are set: you may need to run 'obnam init': {0}")]
+ PasswordsMissing(PasswordError),
+
+ #[error("failed to read configuration file {0}: {1}")]
+ Read(PathBuf, std::io::Error),
+
+ #[error("failed to parse configuration file {0} as YAML: {1}")]
+ YamlParse(PathBuf, serde_yaml::Error),
+}
+
+pub type ClientConfigResult<T> = Result<T, ClientConfigError>;
+
fn expand_tilde(path: &Path) -> PathBuf {
if path.starts_with("~/") {
if let Some(home) = std::env::var_os("HOME") {
diff --git a/subplot/client.py b/subplot/client.py
index be0a6d6..d0beba5 100644
--- a/subplot/client.py
+++ b/subplot/client.py
@@ -16,7 +16,7 @@ def uninstall_obnam(ctx):
runcmd_run(ctx, ["chmod", "-R", "u+rwX", "."])
-def configure_client(ctx, filename=None):
+def configure_client_without_init(ctx, filename=None):
get_file = globals()["get_file"]
assert ctx.get("server_url") is not None
@@ -35,6 +35,15 @@ def configure_client(ctx, filename=None):
yaml.safe_dump(config, stream=f)
+def configure_client_with_init(ctx, filename=None):
+ runcmd_run = globals()["runcmd_run"]
+ runcmd_exit_code_is_zero = globals()["runcmd_exit_code_is_zero"]
+
+ configure_client_without_init(ctx, filename=filename)
+ runcmd_run(ctx, ["obnam", "init", "--insecure-passphrase=hunter2"])
+ runcmd_exit_code_is_zero(ctx)
+
+
def run_obnam_restore(ctx, genid=None, todir=None):
runcmd_run = globals()["runcmd_run"]
diff --git a/subplot/client.yaml b/subplot/client.yaml
index 6de04c9..d660089 100644
--- a/subplot/client.yaml
+++ b/subplot/client.yaml
@@ -3,7 +3,10 @@
cleanup: uninstall_obnam
- given: "a client config based on {filename}"
- function: configure_client
+ function: configure_client_with_init
+
+- given: "a client config, without passphrase, based on {filename}"
+ function: configure_client_without_init
- when: "I invoke obnam restore <{genid}> {todir}"
function: run_obnam_restore