Skip to content

Commit

Permalink
Merge pull request #4960 from wasmerio/list-regions
Browse files Browse the repository at this point in the history
Add `regions` subcommand to `app` subcommand
  • Loading branch information
xdoardo authored Jul 26, 2024
2 parents b63dfe4 + 3a272c8 commit 94edff8
Show file tree
Hide file tree
Showing 8 changed files with 592 additions and 344 deletions.
722 changes: 378 additions & 344 deletions lib/backend-api/schema.graphql

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions lib/backend-api/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,57 @@ pub async fn get_all_app_secrets_filtered(
Ok(all_secrets)
}

/// Load all available regions.
///
/// Will paginate through all versions and return them in a single list.
pub async fn get_all_app_regions(client: &WasmerClient) -> Result<Vec<AppRegion>, anyhow::Error> {
let mut vars = GetAllAppRegionsVariables {
after: None,
before: None,
first: None,
last: None,
offset: None,
};

let mut all_regions = Vec::<AppRegion>::new();

loop {
let page = get_regions(client, vars.clone()).await?;
if page.edges.is_empty() {
break;
}

for edge in page.edges {
let edge = match edge {
Some(edge) => edge,
None => continue,
};
let version = match edge.node {
Some(item) => item,
None => continue,
};

all_regions.push(version);

// Update pagination.
vars.after = Some(edge.cursor);
}
}

Ok(all_regions)
}

/// Retrieve regions.
pub async fn get_regions(
client: &WasmerClient,
vars: GetAllAppRegionsVariables,
) -> Result<AppRegionConnection, anyhow::Error> {
let res = client
.run_graphql_strict(types::GetAllAppRegions::build(vars))
.await?;
Ok(res.get_app_regions)
}

/// Load all secrets of an app.
///
/// Will paginate through all versions and return them in a single list.
Expand Down
37 changes: 37 additions & 0 deletions lib/backend-api/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,43 @@ mod queries {
pub updated_at: DateTime,
}

#[derive(cynic::QueryVariables, Debug, Clone)]
pub struct GetAllAppRegionsVariables {
pub after: Option<String>,
pub before: Option<String>,
pub first: Option<i32>,
pub last: Option<i32>,
pub offset: Option<i32>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "GetAllAppRegionsVariables")]
pub struct GetAllAppRegions {
#[arguments(after: $after, offset: $offset, before: $before, first: $first, last: $last)]
pub get_app_regions: AppRegionConnection,
}

#[derive(cynic::QueryFragment, Debug)]
pub struct AppRegionConnection {
pub edges: Vec<Option<AppRegionEdge>>,
pub page_info: PageInfo,
pub total_count: Option<i32>,
}

#[derive(cynic::QueryFragment, Debug)]
pub struct AppRegionEdge {
pub cursor: String,
pub node: Option<AppRegion>,
}

#[derive(cynic::QueryFragment, Debug, Serialize)]
pub struct AppRegion {
pub city: String,
pub country: String,
pub id: cynic::Id,
pub name: String,
}

#[derive(cynic::QueryFragment, Debug, Clone, Serialize)]
#[cynic(graphql_type = "TXTRecord")]
pub struct TxtRecord {
Expand Down
4 changes: 4 additions & 0 deletions lib/cli/src/commands/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod info;
pub mod list;
pub mod logs;
pub mod purge_cache;
pub mod regions;
pub mod secrets;
pub mod version;

Expand All @@ -30,6 +31,8 @@ pub enum CmdApp {
Version(version::CmdAppVersion),
#[clap(subcommand, alias = "secrets")]
Secret(secrets::CmdAppSecrets),
#[clap(subcommand, alias = "regions")]
Region(regions::CmdAppRegions),
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -57,6 +60,7 @@ impl AsyncCliCommand for CmdApp {
Self::Deploy(cmd) => cmd.run_async().await,
Self::PurgeCache(cmd) => cmd.run_async().await,
Self::Secret(cmd) => cmd.run_async().await,
Self::Region(cmd) => cmd.run_async().await,
}
}
}
42 changes: 42 additions & 0 deletions lib/cli/src/commands/app/regions/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use crate::{
commands::AsyncCliCommand,
opts::{ApiOpts, ListFormatOpts, WasmerEnv},
};
use is_terminal::IsTerminal;

/// List available Edge regions.
#[derive(clap::Parser, Debug)]
pub struct CmdAppRegionsList {
/* --- Common flags --- */
#[clap(flatten)]
#[allow(missing_docs)]
pub api: ApiOpts,

#[clap(flatten)]
pub env: WasmerEnv,

/// Don't print any message.
#[clap(long)]
pub quiet: bool,

/// Do not prompt for user input.
#[clap(long, default_value_t = !std::io::stdin().is_terminal())]
pub non_interactive: bool,

#[clap(flatten)]
pub fmt: ListFormatOpts,
}

#[async_trait::async_trait]
impl AsyncCliCommand for CmdAppRegionsList {
type Output = ();

async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
let client = self.api.client()?;
let regions = wasmer_api::query::get_all_app_regions(&client).await?;

println!("{}", self.fmt.format.render(regions.as_slice()));

Ok(())
}
}
24 changes: 24 additions & 0 deletions lib/cli/src/commands/app/regions/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::commands::AsyncCliCommand;

pub mod list;
mod utils;

/// Informations about available Edge regioins.
#[derive(Debug, clap::Parser)]
pub enum CmdAppRegions {
List(list::CmdAppRegionsList),
}

#[async_trait::async_trait]
impl AsyncCliCommand for CmdAppRegions {
type Output = ();

async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
match self {
Self::List(c) => {
c.run_async().await?;
Ok(())
}
}
}
}
1 change: 1 addition & 0 deletions lib/cli/src/commands/app/regions/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub(crate) mod render;
55 changes: 55 additions & 0 deletions lib/cli/src/commands/app/regions/utils/render.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::utils::render::CliRender;
use comfy_table::{Cell, Table};
use wasmer_api::types::AppRegion;

impl CliRender for AppRegion {
fn render_item_table(&self) -> String {
let mut table = Table::new();
let AppRegion {
name,
city,
country,
..
}: &AppRegion = self;

table.load_preset(comfy_table::presets::NOTHING);
table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);

table.add_rows([
vec![
Cell::new("Name".to_string()).add_attribute(comfy_table::Attribute::Bold),
Cell::new("City".to_string()).add_attribute(comfy_table::Attribute::Bold),
Cell::new("Country code".to_string()).add_attribute(comfy_table::Attribute::Bold),
],
vec![
Cell::new(name.to_string()).add_attribute(comfy_table::Attribute::Bold),
Cell::new(city.to_string()),
Cell::new(country.to_string()),
],
]);
table.to_string()
}

fn render_list_table(items: &[Self]) -> String {
if items.is_empty() {
return String::new();
}
let mut table = Table::new();
table.load_preset(comfy_table::presets::NOTHING);
//table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);

table.set_header(vec![
Cell::new("Name".to_string()).add_attribute(comfy_table::Attribute::Bold),
Cell::new("City".to_string()).add_attribute(comfy_table::Attribute::Bold),
Cell::new("Country code".to_string()).add_attribute(comfy_table::Attribute::Bold),
]);
table.add_rows(items.iter().map(|s| {
vec![
Cell::new(s.name.to_string()).add_attribute(comfy_table::Attribute::Bold),
Cell::new(s.city.to_string()),
Cell::new(s.country.to_string()),
]
}));
table.to_string()
}
}

0 comments on commit 94edff8

Please sign in to comment.