Skip to content

Commit

Permalink
provisional migration to cling
Browse files Browse the repository at this point in the history
This allows us to experiment with cling's design and limitations in practice. There will be further improvements but this is a fully functional migration.
  • Loading branch information
AhmedSoliman authored and MohamedBassem committed Aug 12, 2023
1 parent 7ee65de commit 8e702cd
Show file tree
Hide file tree
Showing 26 changed files with 504 additions and 904 deletions.
43 changes: 43 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cronback-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ admin = ["cronback-client/admin", "cronback-api-model/admin"]
[dependencies]
cronback-client = { workspace = true }
cronback-api-model = { workspace = true, features = ["client", "clap"] }
cling = { git = "https://github.com/AhmedSoliman/cling.git", version = "0.0.0-alpha.2" }

anyhow = { version = "1.0.71" }
async-trait = { workspace = true }
Expand Down
49 changes: 18 additions & 31 deletions cronback-cli/src/admin/api_keys/create.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,32 @@
use anyhow::Result;
use async_trait::async_trait;
use clap::Parser;
use cling::prelude::*;
use cronback_api_model::admin::APIKeyMetaData;

use crate::args::CommonOptions;
use crate::{emitln, Command};

#[derive(Clone, Debug, Parser)]
#[derive(CliRunnable, CliParam, Clone, Debug, Parser)]
#[cling(run = "create")]
pub struct Create {
/// The name of the key to be created
name: String,
}

#[async_trait]
impl Command for Create {
async fn run<
A: tokio::io::AsyncWrite + Send + Sync + Unpin,
B: tokio::io::AsyncWrite + Send + Sync + Unpin,
>(
&self,
out: &mut tokio::io::BufWriter<A>,
_err: &mut tokio::io::BufWriter<B>,
common_options: &CommonOptions,
) -> Result<()> {
let client = common_options.new_client()?;
async fn create(common_options: &CommonOptions, opts: &Create) -> Result<()> {
let client = common_options.new_client()?;

let response = cronback_client::api_keys::gen(
&client,
&self.name,
APIKeyMetaData::default(),
)
.await?;
let response = cronback_client::api_keys::gen(
&client,
&opts.name,
APIKeyMetaData::default(),
)
.await?;

let response = response.into_inner()?;
let response = response.into_inner()?;

emitln!(
out,
"API key with the name '{}' was created successfully.",
self.name
);
emitln!(out, "Secret key: '{}'", response.key);
Ok(())
}
println!(
"API key with the name '{}' was created successfully.",
opts.name
);
println!("Secret key: '{}'", response.key);
Ok(())
}
50 changes: 17 additions & 33 deletions cronback-cli/src/admin/api_keys/list.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,29 @@
use anyhow::Result;
use async_trait::async_trait;
use clap::Parser;
use cling::prelude::*;
use prettytable::{row, Table};

use crate::args::CommonOptions;
use crate::{emitln, Command};

#[derive(Clone, Debug, Parser)]
pub struct List {}
#[derive(CliRunnable, Clone, Debug, Parser)]
#[cling(run = "list")]
pub struct List;

#[async_trait]
impl Command for List {
async fn run<
A: tokio::io::AsyncWrite + Send + Sync + Unpin,
B: tokio::io::AsyncWrite + Send + Sync + Unpin,
>(
&self,
out: &mut tokio::io::BufWriter<A>,
_err: &mut tokio::io::BufWriter<B>,
common_options: &CommonOptions,
) -> Result<()> {
let client = common_options.new_client()?;
async fn list(common_options: &CommonOptions) -> Result<()> {
let client = common_options.new_client()?;

let response = cronback_client::api_keys::list(&client).await?;
let response = cronback_client::api_keys::list(&client).await?;

let response = response.into_inner()?;
// Print Table
if !response.data.is_empty() {
let mut table = Table::new();
table.set_titles(row!["Id", "Name", "Created At"]);
for key in response.data {
table.add_row(row![
key.id,
key.name,
key.created_at.to_rfc2822(),
]);
}

emitln!(out, "{}", table);
let response = response.into_inner()?;
// Print Table
if !response.data.is_empty() {
let mut table = Table::new();
table.set_titles(row!["Id", "Name", "Created At"]);
for key in response.data {
table.add_row(row![key.id, key.name, key.created_at.to_rfc2822(),]);
}

Ok(())
println!("{}", table);
}

Ok(())
}
32 changes: 2 additions & 30 deletions cronback-cli/src/admin/api_keys/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
use anyhow::Result;
use async_trait::async_trait;
use clap::clap_derive::Parser;

use crate::args::CommonOptions;
use crate::Command;
use cling::prelude::*;

mod create;
mod list;
mod revoke;

#[derive(Parser, Debug, Clone)]
#[derive(CliRunnable, Subcommand, Debug, Clone)]
pub enum ApiKeysCommand {
/// List API keys
#[command(visible_alias = "ls")]
Expand All @@ -19,26 +14,3 @@ pub enum ApiKeysCommand {
/// Revokes an API key
Revoke(revoke::Revoke),
}

#[async_trait]
impl Command for ApiKeysCommand {
async fn run<
A: tokio::io::AsyncWrite + Send + Sync + Unpin,
B: tokio::io::AsyncWrite + Send + Sync + Unpin,
>(
&self,
out: &mut tokio::io::BufWriter<A>,
err: &mut tokio::io::BufWriter<B>,
common_options: &CommonOptions,
) -> Result<()> {
match self {
| ApiKeysCommand::List(c) => c.run(out, err, common_options).await,
| ApiKeysCommand::Create(c) => {
c.run(out, err, common_options).await
}
| ApiKeysCommand::Revoke(c) => {
c.run(out, err, common_options).await
}
}
}
}
53 changes: 20 additions & 33 deletions cronback-cli/src/admin/api_keys/revoke.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use anyhow::Result;
use async_trait::async_trait;
use clap::Parser;
use cling::prelude::*;

use crate::args::CommonOptions;
use crate::confirm::confirm_or_abort;
use crate::{emitln, Command};

#[derive(Clone, Debug, Parser)]
#[derive(CliRunnable, CliParam, Clone, Debug, Parser)]
#[cling(run = "revoke")]
pub struct Revoke {
/// The Id of the key to be revoked
id: String,
Expand All @@ -16,33 +15,21 @@ pub struct Revoke {
yes: bool,
}

#[async_trait]
impl Command for Revoke {
async fn run<
A: tokio::io::AsyncWrite + Send + Sync + Unpin,
B: tokio::io::AsyncWrite + Send + Sync + Unpin,
>(
&self,
out: &mut tokio::io::BufWriter<A>,
_err: &mut tokio::io::BufWriter<B>,
common_options: &CommonOptions,
) -> Result<()> {
confirm_or_abort!(
self,
"Are you sure you want to revoke the key '{}'? All API calls with \
this key will start failing.",
self.id
);
let client = common_options.new_client()?;

let response =
cronback_client::api_keys::revoke(&client, &self.id).await?;

// Ensure that the request actually succeeded
response.into_inner()?;

emitln!(out, "Key with id '{}' was revoked!", self.id);

Ok(())
}
async fn revoke(common_options: &CommonOptions, opts: &Revoke) -> Result<()> {
confirm_or_abort!(
opts,
"Are you sure you want to revoke the key '{}'? All API calls with \
this key will start failing.",
opts.id
);
let client = common_options.new_client()?;

let response = cronback_client::api_keys::revoke(&client, &opts.id).await?;

// Ensure that the request actually succeeded
response.into_inner()?;

println!("Key with id '{}' was revoked!", opts.id);

Ok(())
}
44 changes: 6 additions & 38 deletions cronback-cli/src/admin/mod.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,14 @@
use anyhow::Result;
use async_trait::async_trait;
use clap::clap_derive::Parser;

use crate::args::CommonOptions;
use crate::Command;
use cling::prelude::*;

mod api_keys;
mod projects;

#[derive(Parser, Debug, Clone)]
#[derive(CliRunnable, Subcommand, Debug, Clone)]
pub enum AdminCommand {
/// Commands for api key management. This subcommand requires admin
/// privilliages.
ApiKeys {
#[command(subcommand)]
command: api_keys::ApiKeysCommand,
},

Projects {
#[command(subcommand)]
command: projects::ProjectsCommand,
},
}

#[async_trait]
impl Command for AdminCommand {
async fn run<
A: tokio::io::AsyncWrite + Send + Sync + Unpin,
B: tokio::io::AsyncWrite + Send + Sync + Unpin,
>(
&self,
out: &mut tokio::io::BufWriter<A>,
err: &mut tokio::io::BufWriter<B>,
common_options: &CommonOptions,
) -> Result<()> {
match self {
| AdminCommand::ApiKeys { command } => {
command.run(out, err, common_options).await
}
| AdminCommand::Projects { command } => {
command.run(out, err, common_options).await
}
}
}
#[command(subcommand)]
ApiKeys(api_keys::ApiKeysCommand),
#[command(subcommand)]
Projects(projects::ProjectsCommand),
}
Loading

0 comments on commit 8e702cd

Please sign in to comment.