Skip to content

Commit

Permalink
feat: create subcommand to list all projects of calling account
Browse files Browse the repository at this point in the history
  • Loading branch information
emmakuen committed Dec 28, 2022
1 parent 998fff7 commit bb078e8
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cargo-shuttle/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ pub enum DeploymentCommand {
pub enum ProjectCommand {
/// create an environment for this project on shuttle
New,
/// list all projects belonging to the calling account
List,
/// remove this project environment from shuttle
Rm,
/// show the status of this project's environment on shuttle
Expand Down
6 changes: 6 additions & 0 deletions cargo-shuttle/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ impl Client {
self.get(path).await
}

pub async fn get_projects_list(&self) -> Result<Vec<project::Response>> {
let path = "/projects".to_string();

self.get(path).await
}

pub async fn delete_project(&self, project: &ProjectName) -> Result<project::Response> {
let path = format!("/projects/{}", project.as_str());

Expand Down
10 changes: 10 additions & 0 deletions cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl Shuttle {
Command::Project(ProjectCommand::Status { follow }) => {
self.project_status(&client, follow).await
}
Command::Project(ProjectCommand::List) => self.projects_list(&client).await,
Command::Project(ProjectCommand::Rm) => self.project_delete(&client).await,
_ => {
unreachable!("commands that don't need a client have already been matched")
Expand Down Expand Up @@ -521,6 +522,15 @@ impl Shuttle {
Ok(())
}

async fn projects_list(&self, client: &Client) -> Result<()> {
let projects = client.get_projects_list().await?;
let projects_table = project::get_table(&projects);

println!("{projects_table}");

Ok(())
}

async fn project_status(&self, client: &Client, follow: bool) -> Result<()> {
match follow {
true => {
Expand Down
41 changes: 40 additions & 1 deletion common/src/models/project.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use comfy_table::Color;
use comfy_table::{
modifiers::UTF8_ROUND_CORNERS, presets::UTF8_FULL, Cell, CellAlignment, Color,
ContentArrangement, Table,
};
use crossterm::style::Stylize;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
Expand Down Expand Up @@ -52,3 +55,39 @@ pub struct AdminResponse {
pub project_name: String,
pub account_name: String,
}

pub fn get_table(projects: &Vec<Response>) -> String {
if projects.is_empty() {
format!(
"{}\n",
"No projects are linked to this account".yellow().bold()
)
} else {
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS)
.set_content_arrangement(ContentArrangement::DynamicFullWidth)
.set_header(vec![
Cell::new("Project Name").set_alignment(CellAlignment::Center),
Cell::new("Status").set_alignment(CellAlignment::Center),
]);

for project in projects.iter() {
table.add_row(vec![
Cell::new(&project.name),
Cell::new(&project.state)
.fg(project.state.get_color())
.set_alignment(CellAlignment::Center),
]);
}

format!(
r#"
These projects are linked to this account
{}
"#,
table,
)
}
}
18 changes: 18 additions & 0 deletions gateway/src/api/latest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ async fn get_project(
Ok(AxumJson(response))
}

async fn get_projects_list(
State(RouterState { service, .. }): State<RouterState>,
_: User,
) -> Result<AxumJson<Vec<project::Response>>, Error> {
let projects = service
.iter_projects_list()
.await?
.into_iter()
.map(|project| project::Response {
name: project.0.to_string(),
state: project.1.into(),
})
.collect();

Ok(AxumJson(projects))
}

#[instrument(skip_all, fields(%project))]
async fn post_project(
State(RouterState {
Expand Down Expand Up @@ -457,6 +474,7 @@ impl ApiBuilder {
self.router = self
.router
.route("/", get(get_status))
.route("/projects", get(get_projects_list))
.route(
"/projects/:project_name",
get(get_project).delete(delete_project).post(post_project),
Expand Down
16 changes: 16 additions & 0 deletions gateway/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,22 @@ impl GatewayService {
.ok_or_else(|| Error::from_kind(ErrorKind::ProjectNotFound))
}

pub async fn iter_projects_list(
&self,
) -> Result<impl Iterator<Item = (ProjectName, Project)>, Error> {
let iter = query("SELECT project_name, project_state FROM projects")
.fetch_all(&self.db)
.await?
.into_iter()
.map(|row| {
(
row.get("project_name"),
row.get::<SqlxJson<Project>, _>("project_state").0,
)
});
Ok(iter)
}

pub async fn update_project(
&self,
project_name: &ProjectName,
Expand Down

0 comments on commit bb078e8

Please sign in to comment.