Skip to content

Commit

Permalink
feat(cli): Implement app deployment commands
Browse files Browse the repository at this point in the history
* list
* get
* logs
  • Loading branch information
theduke committed Oct 22, 2024
1 parent 404f6e9 commit 22a6f70
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 0 deletions.
37 changes: 37 additions & 0 deletions lib/cli/src/commands/app/deployments/get.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Get deployments for an app.
use crate::{
commands::AsyncCliCommand, config::WasmerEnv, opts::ItemFormatOpts, utils::render::ItemFormat,
};

/// Get the volumes of an app.
#[derive(clap::Parser, Debug)]
pub struct CmdAppDeploymentGet {
#[clap(flatten)]
fmt: ItemFormatOpts,

#[clap(flatten)]
env: WasmerEnv,

/// ID of the deployment.
id: String,
}

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

async fn run_async(mut self) -> Result<(), anyhow::Error> {
let client = self.env.client()?;
let item = wasmer_api::query::app_deployment(&client, self.id).await?;

// The below is a bit hacky - the default is YAML, but this is not a good
// default for deployments, so we switch to table.
if self.fmt.format == ItemFormat::Yaml {
self.fmt.format = ItemFormat::Table;
}

println!("{}", self.fmt.format.render(&item));
Ok(())
}
}
50 changes: 50 additions & 0 deletions lib/cli/src/commands/app/deployments/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//! List volumes tied to an edge app.
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 CmdAppDeploymentList {
#[clap(flatten)]
fmt: ListFormatOpts,

#[clap(flatten)]
env: WasmerEnv,

#[clap(flatten)]
ident: AppIdentOpts,

#[clap(long)]
offset: Option<u32>,

#[clap(long)]
limit: Option<u32>,
}

#[async_trait::async_trait]
impl AsyncCliCommand for CmdAppDeploymentList {
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 vars = wasmer_api::types::GetAppDeploymentsVariables {
after: None,
first: self.limit.map(|x| x as i32),
name: app.name.clone(),
offset: self.offset.map(|x| x as i32),
owner: app.owner.global_name,
};
let items = wasmer_api::query::app_deployments(&client, vars).await?;

if items.is_empty() {
eprintln!("App {} has no deployments!", app.name);
} else {
println!("{}", self.fmt.format.render(&items));
}

Ok(())
}
}
51 changes: 51 additions & 0 deletions lib/cli/src/commands/app/deployments/logs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! Get logs for an app deployment.
use std::io::Write;

use anyhow::Context;
use futures::stream::TryStreamExt;

use crate::{commands::AsyncCliCommand, config::WasmerEnv, opts::ItemFormatOpts};

/// Get logs for an app deployment.
#[derive(clap::Parser, Debug)]
pub struct CmdAppDeploymentLogs {
#[clap(flatten)]
fmt: ItemFormatOpts,

#[clap(flatten)]
env: WasmerEnv,

/// ID of the deployment.
id: String,
}

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

async fn run_async(mut self) -> Result<(), anyhow::Error> {
let client = self.env.client()?;
let item = wasmer_api::query::app_deployment(&client, self.id).await?;

let url = item
.log_url
.context("This deployment does not have logs available")?;

let mut writer = std::io::BufWriter::new(std::io::stdout());

let mut stream = reqwest::Client::new()
.get(url)
.send()
.await?
.error_for_status()?
.bytes_stream();

while let Some(chunk) = stream.try_next().await? {
writer.write_all(&chunk)?;
writer.flush()?;
}

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

pub mod get;
pub mod list;
pub mod logs;

/// App volume management.
#[derive(Debug, clap::Parser)]
pub enum CmdAppDeployment {
List(list::CmdAppDeploymentList),
Get(get::CmdAppDeploymentGet),
Logs(logs::CmdAppDeploymentLogs),
}

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

async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
match self {
Self::List(c) => c.run_async().await,
Self::Get(c) => c.run_async().await,
Self::Logs(c) => c.run_async().await,
}
}
}
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 @@ -3,6 +3,7 @@
pub mod create;
pub mod delete;
pub mod deploy;
mod deployments;
pub mod get;
pub mod info;
pub mod list;
Expand Down Expand Up @@ -36,6 +37,8 @@ pub enum CmdApp {
Region(regions::CmdAppRegions),
#[clap(subcommand, alias = "volumes")]
Volume(volumes::CmdAppVolumes),
#[clap(subcommand, alias = "deployments")]
Deployment(deployments::CmdAppDeployment),
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -65,6 +68,7 @@ impl AsyncCliCommand for CmdApp {
Self::Secret(cmd) => cmd.run_async().await,
Self::Region(cmd) => cmd.run_async().await,
Self::Volume(cmd) => cmd.run_async().await,
Self::Deployment(cmd) => cmd.run_async().await,
}
}
}
29 changes: 29 additions & 0 deletions lib/cli/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,32 @@ fn format_disk_size_opt(value: Option<wasmer_api::types::BigInt>) -> String {
"n/a".to_string()
}
}

impl CliRender for wasmer_api::types::AutobuildRepository {
fn render_item_table(&self) -> String {
let mut table = Table::new();
table.add_rows([
vec!["Id".to_string(), self.id.clone().into_inner()],
vec!["Status".to_string(), self.status.as_str().to_string()],
vec!["Created at".to_string(), self.created_at.0.clone()],
]);
table.to_string()
}

fn render_list_table(items: &[Self]) -> String {
let mut table = Table::new();
table.set_header(vec![
"Id".to_string(),
"Status".to_string(),
"Created at".to_string(),
]);
table.add_rows(items.iter().map(|item| {
vec![
item.id.clone().into_inner(),
item.status.as_str().to_string(),
item.created_at.0.clone(),
]
}));
table.to_string()
}
}

0 comments on commit 22a6f70

Please sign in to comment.