Add support for sync to AWS (#3723)
This is closely modeled on support for sync to GCP (#3223), but with different authentication options to mirror typical usage of AWS.
This commit is contained in:
committed by
GitHub
parent
ff325bc19e
commit
758ac8f850
@@ -318,6 +318,12 @@ std::string configurationDefaults =
|
||||
"#sync.server.client_id # Client ID for sync to a server\n"
|
||||
"#sync.server.url # URL of the sync server\n"
|
||||
"#sync.local.server_dir # Directory for local sync\n"
|
||||
"#sync.aws.region # region for AWS sync\n"
|
||||
"#sync.aws.bucket # bucket for AWS sync\n"
|
||||
"#sync.aws.access_key_id # access_key_id for AWS sync\n"
|
||||
"#sync.aws.secret_access_key # secret_access_key for AWS sync\n"
|
||||
"#sync.aws.profile # profile name for AWS sync\n"
|
||||
"#sync.aws.default_credentials # use default credentials for AWS sync\n"
|
||||
"#sync.gcp.credential_path # Path to JSON file containing credentials to "
|
||||
"authenticate GCP Sync\n"
|
||||
"#sync.gcp.bucket # Bucket for sync to GCP\n"
|
||||
|
||||
@@ -194,9 +194,15 @@ int CmdShow::execute(std::string& output) {
|
||||
" search.case.sensitive"
|
||||
" sugar"
|
||||
" summary.all.projects"
|
||||
" sync.local.server_dir"
|
||||
" sync.aws.access_key_id"
|
||||
" sync.aws.bucket"
|
||||
" sync.aws.default_credentials"
|
||||
" sync.aws.profile"
|
||||
" sync.aws.region"
|
||||
" sync.aws.secret_access_key"
|
||||
" sync.gcp.credential_path"
|
||||
" sync.gcp.bucket"
|
||||
" sync.local.server_dir"
|
||||
" sync.server.client_id"
|
||||
" sync.encryption_secret"
|
||||
" sync.server.url"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -65,12 +66,11 @@ int CmdSync::execute(std::string& output) {
|
||||
bool avoid_snapshots = false;
|
||||
bool verbose = Context::getContext().verbose("sync");
|
||||
|
||||
// If no server is set up, quit.
|
||||
std::string origin = Context::getContext().config.get("sync.server.origin");
|
||||
std::string url = Context::getContext().config.get("sync.server.url");
|
||||
std::string server_dir = Context::getContext().config.get("sync.local.server_dir");
|
||||
std::string client_id = Context::getContext().config.get("sync.server.client_id");
|
||||
std::string gcp_credential_path = Context::getContext().config.get("sync.gcp.credential_path");
|
||||
std::string aws_bucket = Context::getContext().config.get("sync.aws.bucket");
|
||||
std::string gcp_bucket = Context::getContext().config.get("sync.gcp.bucket");
|
||||
std::string encryption_secret = Context::getContext().config.get("sync.encryption_secret");
|
||||
|
||||
@@ -85,7 +85,55 @@ int CmdSync::execute(std::string& output) {
|
||||
out << format("Syncing with {1}", server_dir) << '\n';
|
||||
}
|
||||
replica->sync_to_local(server_dir, avoid_snapshots);
|
||||
} else if (aws_bucket != "") {
|
||||
std::string aws_region = Context::getContext().config.get("sync.aws.region");
|
||||
std::string aws_profile = Context::getContext().config.get("sync.aws.profile");
|
||||
std::string aws_access_key_id = Context::getContext().config.get("sync.aws.access_key_id");
|
||||
std::string aws_secret_access_key =
|
||||
Context::getContext().config.get("sync.aws.secret_access_key");
|
||||
std::string aws_default_credentials =
|
||||
Context::getContext().config.get("sync.aws.default_credentials");
|
||||
if (aws_region == "") {
|
||||
throw std::string("sync.aws.region is required");
|
||||
}
|
||||
if (encryption_secret == "") {
|
||||
throw std::string("sync.encryption_secret is required");
|
||||
}
|
||||
|
||||
bool using_profile = false;
|
||||
bool using_creds = false;
|
||||
bool using_default = false;
|
||||
if (aws_profile != "") {
|
||||
using_profile = true;
|
||||
}
|
||||
if (aws_access_key_id != "" || aws_secret_access_key != "") {
|
||||
using_creds = true;
|
||||
}
|
||||
if (aws_default_credentials != "") {
|
||||
using_default = true;
|
||||
}
|
||||
|
||||
if (using_profile + using_creds + using_default != 1) {
|
||||
throw std::string("exactly one method of specifying AWS credentials is required");
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
out << format("Syncing with AWS bucket {1}", aws_bucket) << '\n';
|
||||
}
|
||||
|
||||
if (using_profile) {
|
||||
replica->sync_to_aws_with_profile(aws_region, aws_bucket, aws_profile, encryption_secret,
|
||||
avoid_snapshots);
|
||||
} else if (using_creds) {
|
||||
replica->sync_to_aws_with_access_key(aws_region, aws_bucket, aws_access_key_id,
|
||||
aws_secret_access_key, encryption_secret,
|
||||
avoid_snapshots);
|
||||
} else {
|
||||
replica->sync_to_aws_with_default_creds(aws_region, aws_bucket, encryption_secret,
|
||||
avoid_snapshots);
|
||||
}
|
||||
} else if (gcp_bucket != "") {
|
||||
std::string gcp_credential_path = Context::getContext().config.get("sync.gcp.credential_path");
|
||||
if (encryption_secret == "") {
|
||||
throw std::string("sync.encryption_secret is required");
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ rust-version = "1.78.0" # MSRV
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
taskchampion = "1.0.0"
|
||||
taskchampion = "=1.0.2"
|
||||
cxx = "1.0.133"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -164,6 +164,36 @@ mod ffi {
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Sync with a server created from `ServerConfig::Aws` using `AwsCredentials::Profile`.
|
||||
fn sync_to_aws_with_profile(
|
||||
&mut self,
|
||||
region: String,
|
||||
bucket: String,
|
||||
profile_name: String,
|
||||
encryption_secret: &CxxString,
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Sync with a server created from `ServerConfig::Aws` using `AwsCredentials::AccessKey`.
|
||||
fn sync_to_aws_with_access_key(
|
||||
&mut self,
|
||||
region: String,
|
||||
bucket: String,
|
||||
access_key_id: String,
|
||||
secret_access_key: String,
|
||||
encryption_secret: &CxxString,
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Sync with a server created from `ServerConfig::Aws` using `AwsCredentials::Default`.
|
||||
fn sync_to_aws_with_default_creds(
|
||||
&mut self,
|
||||
region: String,
|
||||
bucket: String,
|
||||
encryption_secret: &CxxString,
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Sync with a server created from `ServerConfig::Gcp`.
|
||||
///
|
||||
/// An empty value for `credential_path` is converted to `Option::None`.
|
||||
@@ -580,6 +610,63 @@ impl Replica {
|
||||
Ok(self.0.sync(&mut server, avoid_snapshots)?)
|
||||
}
|
||||
|
||||
fn sync_to_aws_with_profile(
|
||||
&mut self,
|
||||
region: String,
|
||||
bucket: String,
|
||||
profile_name: String,
|
||||
encryption_secret: &CxxString,
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<(), CppError> {
|
||||
let mut server = tc::server::ServerConfig::Aws {
|
||||
region,
|
||||
bucket,
|
||||
credentials: tc::server::AwsCredentials::Profile { profile_name },
|
||||
encryption_secret: encryption_secret.as_bytes().to_vec(),
|
||||
}
|
||||
.into_server()?;
|
||||
Ok(self.0.sync(&mut server, avoid_snapshots)?)
|
||||
}
|
||||
|
||||
fn sync_to_aws_with_access_key(
|
||||
&mut self,
|
||||
region: String,
|
||||
bucket: String,
|
||||
access_key_id: String,
|
||||
secret_access_key: String,
|
||||
encryption_secret: &CxxString,
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<(), CppError> {
|
||||
let mut server = tc::server::ServerConfig::Aws {
|
||||
region,
|
||||
bucket,
|
||||
credentials: tc::server::AwsCredentials::AccessKey {
|
||||
access_key_id,
|
||||
secret_access_key,
|
||||
},
|
||||
encryption_secret: encryption_secret.as_bytes().to_vec(),
|
||||
}
|
||||
.into_server()?;
|
||||
Ok(self.0.sync(&mut server, avoid_snapshots)?)
|
||||
}
|
||||
|
||||
fn sync_to_aws_with_default_creds(
|
||||
&mut self,
|
||||
region: String,
|
||||
bucket: String,
|
||||
encryption_secret: &CxxString,
|
||||
avoid_snapshots: bool,
|
||||
) -> Result<(), CppError> {
|
||||
let mut server = tc::server::ServerConfig::Aws {
|
||||
region,
|
||||
bucket,
|
||||
credentials: tc::server::AwsCredentials::Default,
|
||||
encryption_secret: encryption_secret.as_bytes().to_vec(),
|
||||
}
|
||||
.into_server()?;
|
||||
Ok(self.0.sync(&mut server, avoid_snapshots)?)
|
||||
}
|
||||
|
||||
fn sync_to_gcp(
|
||||
&mut self,
|
||||
bucket: String,
|
||||
|
||||
Reference in New Issue
Block a user