diff --git a/lib/cli/src/commands/app/mod.rs b/lib/cli/src/commands/app/mod.rs index cc3ad250055..7a461a06c83 100644 --- a/lib/cli/src/commands/app/mod.rs +++ b/lib/cli/src/commands/app/mod.rs @@ -11,6 +11,7 @@ pub mod purge_cache; pub mod regions; pub mod secrets; pub mod version; +pub mod volumes; mod util; @@ -33,6 +34,8 @@ pub enum CmdApp { Secret(secrets::CmdAppSecrets), #[clap(subcommand, alias = "regions")] Region(regions::CmdAppRegions), + #[clap(subcommand, alias = "volumes")] + Volume(volumes::CmdAppVolumes), } #[async_trait::async_trait] @@ -61,6 +64,7 @@ impl AsyncCliCommand for CmdApp { Self::PurgeCache(cmd) => cmd.run_async().await, Self::Secret(cmd) => cmd.run_async().await, Self::Region(cmd) => cmd.run_async().await, + Self::Volume(cmd) => cmd.run_async().await, } } } diff --git a/lib/cli/src/commands/app/volumes/list.rs b/lib/cli/src/commands/app/volumes/list.rs new file mode 100644 index 00000000000..a48d4910162 --- /dev/null +++ b/lib/cli/src/commands/app/volumes/list.rs @@ -0,0 +1,38 @@ +//! List Edge apps. + +use super::super::util::AppIdentOpts; +use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ListFormatOpts}; + +/// List the volumes of an app. +#[derive(clap::Parser, Debug)] +pub struct CmdAppVolumesList { + #[clap(flatten)] + fmt: ListFormatOpts, + + #[clap(flatten)] + env: WasmerEnv, + + #[clap(flatten)] + ident: AppIdentOpts, +} + +#[async_trait::async_trait] +impl AsyncCliCommand for CmdAppVolumesList { + type Output = (); + + async fn run_async(self) -> Result<(), anyhow::Error> { + let client = self.env.client()?; + + let (_ident, app) = self.ident.load_app(&client).await?; + let volumes = + wasmer_api::query::get_app_volumes(&client, &app.owner.global_name, &app.name).await?; + + if volumes.is_empty() { + eprintln!("App {} has no volumes!", app.name); + } else { + println!("{}", self.fmt.format.render(volumes.as_slice())); + } + + Ok(()) + } +} diff --git a/lib/cli/src/commands/app/volumes/mod.rs b/lib/cli/src/commands/app/volumes/mod.rs new file mode 100644 index 00000000000..d41414da768 --- /dev/null +++ b/lib/cli/src/commands/app/volumes/mod.rs @@ -0,0 +1,29 @@ +use crate::commands::AsyncCliCommand; + +pub mod list; +pub mod s3_credentials; + +/// App volume management. +#[derive(Debug, clap::Parser)] +pub enum CmdAppVolumes { + S3Credentials(s3_credentials::CmdAppS3Credentials), + List(list::CmdAppVolumesList), +} + +#[async_trait::async_trait] +impl AsyncCliCommand for CmdAppVolumes { + type Output = (); + + async fn run_async(self) -> Result { + match self { + Self::S3Credentials(c) => { + c.run_async().await?; + Ok(()) + } + Self::List(c) => { + c.run_async().await?; + Ok(()) + } + } + } +} diff --git a/lib/cli/src/commands/app/volumes/s3_credentials.rs b/lib/cli/src/commands/app/volumes/s3_credentials.rs new file mode 100644 index 00000000000..0949902ddd9 --- /dev/null +++ b/lib/cli/src/commands/app/volumes/s3_credentials.rs @@ -0,0 +1,42 @@ +//! Get information about an edge app. + +use wasmer_api::types::DeployApp; + +use super::super::util::AppIdentOpts; + +use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ItemFormatOpts}; + +/// Retrieve S3 access credentials for the volumes of an app. +#[derive(clap::Parser, Debug)] +pub struct CmdAppS3Credentials { + #[clap(flatten)] + pub env: WasmerEnv, + + #[clap(flatten)] + pub fmt: ItemFormatOpts, + + #[clap(flatten)] + pub ident: AppIdentOpts, +} + +#[async_trait::async_trait] +impl AsyncCliCommand for CmdAppS3Credentials { + type Output = DeployApp; + + async fn run_async(self) -> Result { + let client = self.env.client()?; + let (_ident, app) = self.ident.load_app(&client).await?; + + let creds = + wasmer_api::query::get_app_s3_credentials(&client, app.id.clone().into_inner()).await?; + + println!("S3 credentials for app {}:\n", app.name); + println!(" S3 URL: https://{}", creds.domain); + println!(" Access key: {}", creds.access_key); + println!(" Secret key: {}", creds.secret_key); + println!(); + println!("Consult the app volumes documentation for more information."); + + Ok(app) + } +} diff --git a/lib/cli/src/types.rs b/lib/cli/src/types.rs index 68897ca7468..27fc3349ff3 100644 --- a/lib/cli/src/types.rs +++ b/lib/cli/src/types.rs @@ -156,3 +156,36 @@ impl CliRender for DeployAppVersion { table.to_string() } } + +impl CliRender for wasmer_api::types::AppVersionVolume { + fn render_item_table(&self) -> String { + let mut table = Table::new(); + table.add_rows([ + vec!["Name".to_string(), self.name.clone()], + vec![ + "Used size".to_string(), + format_disk_size_opt(self.used_size), + ], + ]); + table.to_string() + } + + fn render_list_table(items: &[Self]) -> String { + let mut table = Table::new(); + table.set_header(vec!["Name".to_string(), "Used size".to_string()]); + table.add_rows( + items + .iter() + .map(|vol| vec![vol.name.clone(), format_disk_size_opt(vol.used_size)]), + ); + table.to_string() + } +} + +fn format_disk_size_opt(value: Option) -> String { + if let Some(v) = value { + format!("{}Mb", v) + } else { + "n/a".to_string() + } +}