Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement xlinectl snapshot and auth commands #425

Merged
merged 2 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions xlinectl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,30 @@ keep_alive [options] <leaseId>
## Cluster maintenance commands

### SNAPSHOT
Get snapshots of xline nodes

### SNAPSHOT SAVE
Save snapshot to file

#### Usage

```bash
snapshot save <filename>
```

#### Output

```
snapshot saved to: <filename>
```

#### Examples

```bash
# Save snapshot to /tmp/foo
./xlinectl snapshot save /tmp/foo.snapshot
snapshot saved to: /tmp/foo.snapshot
```

## Concurrency commands

Expand All @@ -348,6 +372,68 @@ keep_alive [options] <leaseId>
## Authentication commands

### AUTH
Manage authentication

### AUTH ENABLE
Enable authentication

#### Usage

```bash
auth enable
```

#### Output

```
Authentication enabled
```

#### Examples
```bash
./xlinectl user add root rootpw
./xlienctl user grant-role root root
# Enable authentication
./xlinectl auth enable
Authentication enabled
```

### AUTH DISABLE
Disable authentication

#### Usage

```bash
auth disable
```

#### Output

```
Authentication disabled
```

#### Examples
```bash
# Disable authentication
./xlinectl --user root:root auth disable
Authentication disabled
```

### AUTH STATUS
Status of authentication

#### Usage

```bash
auth status
```

#### Examples
```bash
# Check the status of authentication
./xlinectl auth status
```

### ROLE

Expand Down
17 changes: 17 additions & 0 deletions xlinectl/src/command/auth/disable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use clap::{ArgMatches, Command};
use xline_client::{error::Result, Client};

use crate::utils::printer::Printer;

/// Definition of `disable` command
pub(super) fn command() -> Command {
Command::new("disable").about("disable authentication")
}

/// Execute the command
pub(super) async fn execute(client: &mut Client, _matches: &ArgMatches) -> Result<()> {
let resp = client.auth_client().auth_disable().await?;
resp.print();

Ok(())
}
17 changes: 17 additions & 0 deletions xlinectl/src/command/auth/enable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use clap::{ArgMatches, Command};
use xline_client::{error::Result, Client};

use crate::utils::printer::Printer;

/// Definition of `enable` command
pub(super) fn command() -> Command {
Command::new("enable").about("Enable authentication")
}

/// Execute the command
pub(super) async fn execute(client: &mut Client, _matches: &ArgMatches) -> Result<()> {
let resp = client.auth_client().auth_enable().await?;
resp.print();

Ok(())
}
27 changes: 27 additions & 0 deletions xlinectl/src/command/auth/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use clap::{ArgMatches, Command};
use xline_client::{error::Result, Client};

use crate::handle_matches;

/// Auth disable command
mod disable;
/// Auth enable command
mod enable;
/// Auth status command
mod status;

/// Definition of `auth` command
pub(crate) fn command() -> Command {
Command::new("auth")
.about("Manage authentication")
.subcommand(enable::command())
.subcommand(disable::command())
.subcommand(status::command())
}

/// Execute the command
pub(crate) async fn execute(mut client: &mut Client, matches: &ArgMatches) -> Result<()> {
handle_matches!(matches, client, {enable, disable, status});

Ok(())
}
17 changes: 17 additions & 0 deletions xlinectl/src/command/auth/status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use clap::{ArgMatches, Command};
use xline_client::{error::Result, Client};

use crate::utils::printer::Printer;

/// Definition of `status` command
pub(super) fn command() -> Command {
Command::new("status").about("Status of authentication")
}

/// Execute the command
pub(super) async fn execute(client: &mut Client, _matches: &ArgMatches) -> Result<()> {
let resp = client.auth_client().auth_status().await?;
resp.print();

Ok(())
}
4 changes: 4 additions & 0 deletions xlinectl/src/command/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/// Auth command
pub(crate) mod auth;
/// Delete command
pub(crate) mod delete;
/// Get command
Expand All @@ -6,3 +8,5 @@ pub(crate) mod get;
pub(crate) mod lease;
/// Put command
pub(crate) mod put;
/// Snapshot command
pub(crate) mod snapshot;
42 changes: 42 additions & 0 deletions xlinectl/src/command/snapshot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::{fs::File, io::Write, path::PathBuf};

use clap::{arg, ArgMatches, Command};
use xline_client::{error::Result, Client};

/// Definition of `snapshot` command
pub(crate) fn command() -> Command {
Command::new("snapshot")
.about("get snapshots of xline nodes")
.subcommand(
Command::new("save")
.about("save snapshot")
.arg(arg!(<filename> "save snapshot to the give filename")),
)
}

/// Execute the command
pub(crate) async fn execute(client: &mut Client, matches: &ArgMatches) -> Result<()> {
if let Some(("save", sub_matches)) = matches.subcommand() {
let filename = sub_matches.get_one::<String>("filename").expect("required");
let path = PathBuf::from(filename);
let mut resp = client.maintenance_client().snapshot().await?;

if path.exists() || path.is_dir() {
eprintln!("file exist: {filename}");
return Ok(());
}

let mut file = File::create(path)?;

let mut all = Vec::new();
while let Some(data) = resp.message().await? {
all.extend_from_slice(&data.blob);
}

file.write_all(&all)?;

println!("snapshot saved to: {filename}");
}

Ok(())
}
6 changes: 4 additions & 2 deletions xlinectl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ use ext_utils::config::ClientConfig;
use xline_client::{Client, ClientOptions};

use crate::{
command::{delete, get, lease, put},
command::{auth, delete, get, lease, put, snapshot},
utils::{
parser::parse_user,
printer::{set_printer_type, PrinterType},
Expand Down Expand Up @@ -229,6 +229,8 @@ fn cli() -> Command {
.subcommand(put::command())
.subcommand(delete::command())
.subcommand(lease::command())
.subcommand(snapshot::command())
.subcommand(auth::command())
}

#[tokio::main]
Expand All @@ -255,6 +257,6 @@ async fn main() -> Result<()> {
set_printer_type(printer_type);

let mut client = Client::connect(endpoints, options).await?;
handle_matches!(matches, client, { get, put, delete, lease });
handle_matches!(matches, client, { get, put, delete, lease, snapshot, auth });
Ok(())
}
44 changes: 42 additions & 2 deletions xlinectl/src/utils/printer.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::sync::OnceLock;

use xlineapi::{
DeleteRangeResponse, KeyValue, LeaseGrantResponse, LeaseKeepAliveResponse, LeaseLeasesResponse,
LeaseRevokeResponse, LeaseTimeToLiveResponse, PutResponse, RangeResponse, ResponseHeader,
AuthDisableResponse, AuthEnableResponse, AuthStatusResponse, DeleteRangeResponse, KeyValue,
LeaseGrantResponse, LeaseKeepAliveResponse, LeaseLeasesResponse, LeaseRevokeResponse,
LeaseTimeToLiveResponse, PutResponse, RangeResponse, ResponseHeader,
};

/// The global printer type config
Expand Down Expand Up @@ -155,6 +156,45 @@ impl Printer for LeaseTimeToLiveResponse {
}
}

impl Printer for AuthEnableResponse {
fn simple(&self) {
println!("Authentication enabled");
}

fn field(&self) {
FieldPrinter::header(self.header.as_ref());
println!("Authentication enabled");
}
}

impl Printer for AuthDisableResponse {
fn simple(&self) {
println!("Authentication disabled");
}

fn field(&self) {
FieldPrinter::header(self.header.as_ref());
println!("Authentication disabled");
}
}

impl Printer for AuthStatusResponse {
fn simple(&self) {
println!(
"enabled: {}, revision: {}",
self.enabled, self.auth_revision
);
}

fn field(&self) {
FieldPrinter::header(self.header.as_ref());
println!(
"enabled: {}, revision: {}",
self.enabled, self.auth_revision
);
}
}

/// Simple Printer of common response types
struct SimplePrinter;

Expand Down
Loading