2020-08-06 13:46:01 +00:00
|
|
|
use std::convert::TryFrom;
|
2019-11-21 13:53:15 +00:00
|
|
|
use std::fmt;
|
2019-02-14 10:11:39 +00:00
|
|
|
|
2020-04-17 12:11:25 +00:00
|
|
|
use anyhow::{format_err, Error};
|
2019-02-14 10:11:39 +00:00
|
|
|
|
2022-04-14 12:08:48 +00:00
|
|
|
use pbs_api_types::{Authid, Userid, BACKUP_REPO_URL_REGEX, IP_V6_REGEX};
|
2019-11-21 08:36:41 +00:00
|
|
|
|
2019-02-14 10:11:39 +00:00
|
|
|
/// Reference remote backup locations
|
|
|
|
///
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct BackupRepository {
|
|
|
|
/// The user name used for Authentication
|
2020-10-08 13:19:39 +00:00
|
|
|
auth_id: Option<Authid>,
|
2019-02-14 10:11:39 +00:00
|
|
|
/// The host name or IP address
|
2019-03-13 08:47:12 +00:00
|
|
|
host: Option<String>,
|
2020-09-29 14:18:58 +00:00
|
|
|
/// The port
|
|
|
|
port: Option<u16>,
|
2019-02-14 10:11:39 +00:00
|
|
|
/// The name of the datastore
|
2019-03-13 08:47:12 +00:00
|
|
|
store: String,
|
2019-02-14 10:11:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BackupRepository {
|
2022-04-14 12:08:48 +00:00
|
|
|
pub fn new(
|
|
|
|
auth_id: Option<Authid>,
|
|
|
|
host: Option<String>,
|
|
|
|
port: Option<u16>,
|
|
|
|
store: String,
|
|
|
|
) -> Self {
|
2020-09-30 11:23:39 +00:00
|
|
|
let host = match host {
|
2022-04-14 12:08:48 +00:00
|
|
|
Some(host) if (IP_V6_REGEX.regex_obj)().is_match(&host) => Some(format!("[{}]", host)),
|
2020-09-30 11:23:39 +00:00
|
|
|
other => other,
|
|
|
|
};
|
2022-04-14 12:08:48 +00:00
|
|
|
Self {
|
|
|
|
auth_id,
|
|
|
|
host,
|
|
|
|
port,
|
|
|
|
store,
|
|
|
|
}
|
2020-10-08 13:19:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn auth_id(&self) -> &Authid {
|
|
|
|
if let Some(ref auth_id) = self.auth_id {
|
|
|
|
return auth_id;
|
|
|
|
}
|
|
|
|
|
2021-12-30 11:57:37 +00:00
|
|
|
Authid::root_auth_id()
|
2019-12-19 07:44:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 13:46:01 +00:00
|
|
|
pub fn user(&self) -> &Userid {
|
2020-10-08 13:19:39 +00:00
|
|
|
if let Some(auth_id) = &self.auth_id {
|
|
|
|
return auth_id.user();
|
2019-03-13 08:47:12 +00:00
|
|
|
}
|
2020-10-08 13:19:39 +00:00
|
|
|
|
2020-08-06 13:46:01 +00:00
|
|
|
Userid::root_userid()
|
2019-03-13 08:47:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn host(&self) -> &str {
|
|
|
|
if let Some(ref host) = self.host {
|
|
|
|
return host;
|
|
|
|
}
|
|
|
|
"localhost"
|
|
|
|
}
|
|
|
|
|
2020-09-29 14:18:58 +00:00
|
|
|
pub fn port(&self) -> u16 {
|
|
|
|
if let Some(port) = self.port {
|
|
|
|
return port;
|
|
|
|
}
|
|
|
|
8007
|
|
|
|
}
|
|
|
|
|
2019-03-13 08:47:12 +00:00
|
|
|
pub fn store(&self) -> &str {
|
|
|
|
&self.store
|
|
|
|
}
|
2019-03-13 08:57:36 +00:00
|
|
|
}
|
2019-03-13 08:47:12 +00:00
|
|
|
|
2019-03-13 08:57:36 +00:00
|
|
|
impl fmt::Display for BackupRepository {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2020-10-08 13:19:39 +00:00
|
|
|
match (&self.auth_id, &self.host, self.port) {
|
2022-04-14 12:08:48 +00:00
|
|
|
(Some(auth_id), _, _) => write!(
|
|
|
|
f,
|
|
|
|
"{}@{}:{}:{}",
|
|
|
|
auth_id,
|
|
|
|
self.host(),
|
|
|
|
self.port(),
|
|
|
|
self.store
|
|
|
|
),
|
2020-09-29 14:18:58 +00:00
|
|
|
(None, Some(host), None) => write!(f, "{}:{}", host, self.store),
|
|
|
|
(None, _, Some(port)) => write!(f, "{}:{}:{}", self.host(), port, self.store),
|
|
|
|
(None, None, None) => write!(f, "{}", self.store),
|
|
|
|
}
|
2019-03-13 08:47:12 +00:00
|
|
|
}
|
2019-02-14 10:11:39 +00:00
|
|
|
}
|
2019-03-13 09:09:39 +00:00
|
|
|
|
|
|
|
impl std::str::FromStr for BackupRepository {
|
|
|
|
type Err = Error;
|
|
|
|
|
|
|
|
/// Parse a repository URL.
|
|
|
|
///
|
|
|
|
/// This parses strings like `user@host:datastore`. The `user` and
|
|
|
|
/// `host` parts are optional, where `host` defaults to the local
|
|
|
|
/// host, and `user` defaults to `root@pam`.
|
|
|
|
fn from_str(url: &str) -> Result<Self, Self::Err> {
|
2022-04-14 12:08:48 +00:00
|
|
|
let cap = (BACKUP_REPO_URL_REGEX.regex_obj)()
|
|
|
|
.captures(url)
|
2019-03-13 09:09:39 +00:00
|
|
|
.ok_or_else(|| format_err!("unable to parse repository url '{}'", url))?;
|
|
|
|
|
|
|
|
Ok(Self {
|
2022-04-14 12:08:48 +00:00
|
|
|
auth_id: cap
|
|
|
|
.get(1)
|
|
|
|
.map(|m| Authid::try_from(m.as_str().to_owned()))
|
|
|
|
.transpose()?,
|
2019-03-13 09:09:39 +00:00
|
|
|
host: cap.get(2).map(|m| m.as_str().to_owned()),
|
2020-09-29 14:18:58 +00:00
|
|
|
port: cap.get(3).map(|m| m.as_str().parse::<u16>()).transpose()?,
|
|
|
|
store: cap[4].to_owned(),
|
2019-03-13 09:09:39 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|