aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2020-04-19 17:15:48 +0200
committerAlex Auvolat <alex@adnab.me>2020-04-19 17:15:48 +0200
commita6129d8626f5b87462b70eadbce2db08c9761cfd (patch)
tree7e0e0d348bc8f8672db57680f8aeedf9c6c03523 /src/main.rs
parent302502f4c10b4c1cd03d3b098b3e55a3f70054f2 (diff)
downloadgarage-a6129d8626f5b87462b70eadbce2db08c9761cfd.tar.gz
garage-a6129d8626f5b87462b70eadbce2db08c9761cfd.zip
Begin implement bucket management & admin commands
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs139
1 files changed, 124 insertions, 15 deletions
diff --git a/src/main.rs b/src/main.rs
index 89953223..08f37dd5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,9 +10,11 @@ mod table_sync;
mod block;
mod block_ref_table;
+mod bucket_table;
mod object_table;
mod version_table;
+mod admin_rpc;
mod api_server;
mod http_util;
mod rpc_client;
@@ -20,6 +22,7 @@ mod rpc_server;
mod server;
mod tls_util;
+use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::net::SocketAddr;
use std::path::PathBuf;
@@ -32,6 +35,8 @@ use membership::*;
use rpc_client::*;
use server::TlsConfig;
+use admin_rpc::*;
+
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
#[derive(StructOpt, Debug)]
@@ -62,13 +67,13 @@ pub enum Command {
#[structopt(name = "status")]
Status,
- /// Configure Garage node
- #[structopt(name = "configure")]
- Configure(ConfigureOpt),
+ /// Garage node operations
+ #[structopt(name = "node")]
+ Node(NodeOperation),
- /// Remove Garage node from cluster
- #[structopt(name = "remove")]
- Remove(RemoveOpt),
+ /// Bucket operations
+ #[structopt(name = "bucket")]
+ Bucket(BucketOperation),
}
#[derive(StructOpt, Debug)]
@@ -79,7 +84,18 @@ pub struct ServerOpt {
}
#[derive(StructOpt, Debug)]
-pub struct ConfigureOpt {
+pub enum NodeOperation {
+ /// Configure Garage node
+ #[structopt(name = "configure")]
+ Configure(ConfigureNodeOpt),
+
+ /// Remove Garage node from cluster
+ #[structopt(name = "remove")]
+ Remove(RemoveNodeOpt),
+}
+
+#[derive(StructOpt, Debug)]
+pub struct ConfigureNodeOpt {
/// Node to configure (prefix of hexadecimal node id)
node_id: String,
@@ -91,7 +107,7 @@ pub struct ConfigureOpt {
}
#[derive(StructOpt, Debug)]
-pub struct RemoveOpt {
+pub struct RemoveNodeOpt {
/// Node to configure (prefix of hexadecimal node id)
node_id: String,
@@ -100,6 +116,67 @@ pub struct RemoveOpt {
yes: bool,
}
+#[derive(Serialize, Deserialize, StructOpt, Debug)]
+pub enum BucketOperation {
+ /// List buckets
+ #[structopt(name = "list")]
+ List,
+
+ /// Get bucket info
+ #[structopt(name = "info")]
+ Info(BucketOpt),
+
+ /// Create bucket
+ #[structopt(name = "create")]
+ Create(BucketOpt),
+
+ /// Delete bucket
+ #[structopt(name = "delete")]
+ Delete(DeleteBucketOpt),
+
+ /// Allow key to read or write to bucket
+ #[structopt(name = "allow")]
+ Allow(PermBucketOpt),
+
+ /// Allow key to read or write to bucket
+ #[structopt(name = "deny")]
+ Deny(PermBucketOpt),
+}
+
+#[derive(Serialize, Deserialize, StructOpt, Debug)]
+pub struct BucketOpt {
+ /// Bucket name
+ pub name: String,
+}
+
+#[derive(Serialize, Deserialize, StructOpt, Debug)]
+pub struct DeleteBucketOpt {
+ /// Bucket name
+ pub name: String,
+
+ /// If this flag is not given, the bucket won't be deleted
+ #[structopt(long = "yes")]
+ pub yes: bool,
+}
+
+#[derive(Serialize, Deserialize, StructOpt, Debug)]
+pub struct PermBucketOpt {
+ /// Access key ID
+ #[structopt(long = "key")]
+ pub key: String,
+
+ /// Allow/deny read operations
+ #[structopt(long = "read")]
+ pub read: bool,
+
+ /// Allow/deny write operations
+ #[structopt(long = "write")]
+ pub write: bool,
+
+ /// Bucket name
+ pub bucket: String,
+}
+
#[tokio::main]
async fn main() {
let opt = Opt::from_args();
@@ -119,7 +196,9 @@ async fn main() {
let rpc_http_cli =
Arc::new(RpcHttpClient::new(&tls_config).expect("Could not create RPC client"));
- let rpc_cli = RpcAddrClient::new(rpc_http_cli, "_membership".into());
+ let membership_rpc_cli =
+ RpcAddrClient::new(rpc_http_cli.clone(), MEMBERSHIP_RPC_PATH.to_string());
+ let admin_rpc_cli = RpcAddrClient::new(rpc_http_cli.clone(), ADMIN_RPC_PATH.to_string());
let resp = match opt.cmd {
Command::Server(server_opt) => {
@@ -131,11 +210,16 @@ async fn main() {
server::run_server(server_opt.config_file).await
}
- Command::Status => cmd_status(rpc_cli, opt.rpc_host).await,
- Command::Configure(configure_opt) => {
- cmd_configure(rpc_cli, opt.rpc_host, configure_opt).await
+ Command::Status => cmd_status(membership_rpc_cli, opt.rpc_host).await,
+ Command::Node(NodeOperation::Configure(configure_opt)) => {
+ cmd_configure(membership_rpc_cli, opt.rpc_host, configure_opt).await
+ }
+ Command::Node(NodeOperation::Remove(remove_opt)) => {
+ cmd_remove(membership_rpc_cli, opt.rpc_host, remove_opt).await
+ }
+ Command::Bucket(bo) => {
+ cmd_admin(admin_rpc_cli, opt.rpc_host, AdminRPC::BucketOperation(bo)).await
}
- Command::Remove(remove_opt) => cmd_remove(rpc_cli, opt.rpc_host, remove_opt).await,
};
if let Err(e) = resp {
@@ -201,7 +285,7 @@ async fn cmd_status(rpc_cli: RpcAddrClient<Message>, rpc_host: SocketAddr) -> Re
async fn cmd_configure(
rpc_cli: RpcAddrClient<Message>,
rpc_host: SocketAddr,
- args: ConfigureOpt,
+ args: ConfigureNodeOpt,
) -> Result<(), Error> {
let status = match rpc_cli
.call(&rpc_host, &Message::PullStatus, DEFAULT_TIMEOUT)
@@ -254,7 +338,7 @@ async fn cmd_configure(
async fn cmd_remove(
rpc_cli: RpcAddrClient<Message>,
rpc_host: SocketAddr,
- args: RemoveOpt,
+ args: RemoveNodeOpt,
) -> Result<(), Error> {
let mut config = match rpc_cli
.call(&rpc_host, &Message::PullConfig, DEFAULT_TIMEOUT)
@@ -296,3 +380,28 @@ async fn cmd_remove(
.await?;
Ok(())
}
+
+async fn cmd_admin(
+ rpc_cli: RpcAddrClient<AdminRPC>,
+ rpc_host: SocketAddr,
+ args: AdminRPC,
+) -> Result<(), Error> {
+ match rpc_cli.call(&rpc_host, args, DEFAULT_TIMEOUT).await? {
+ AdminRPC::Ok => {
+ println!("Ok.");
+ }
+ AdminRPC::BucketList(bl) => {
+ println!("List of buckets:");
+ for bucket in bl {
+ println!("{}", bucket);
+ }
+ }
+ AdminRPC::BucketInfo(bucket) => {
+ println!("{:?}", bucket);
+ }
+ r => {
+ eprintln!("Unexpected response: {:?}", r);
+ }
+ }
+ Ok(())
+}