Skip to content

Commit

Permalink
feat(cargo-shuttle): beta flag, remove project list pagination logic (#…
Browse files Browse the repository at this point in the history
…1732)

* feat(cargo-shuttle): beta flag

* nit: client name

* fix: delete beta endpoint
  • Loading branch information
jonaro00 authored and iulianbarbu committed Apr 11, 2024
1 parent 553ad8a commit 88198a9
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 122 deletions.
6 changes: 3 additions & 3 deletions cargo-shuttle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.43.0"
edition.workspace = true
license.workspace = true
repository.workspace = true
description = "A cargo command for the shuttle platform (https://www.shuttle.rs/)"
description = "A cargo command for the Shuttle platform (https://www.shuttle.rs/)"
homepage = "https://www.shuttle.rs"

[dependencies]
Expand Down Expand Up @@ -32,10 +32,10 @@ gix = { version = "0.55.2", default-features = false, features = [
"worktree-mutation",
] }
globset = "0.4.13"
home = { workspace = true }
headers = { workspace = true }
indicatif = "0.17.3"
home = { workspace = true }
ignore = "0.4.20"
indicatif = "0.17.3"
indoc = "2.0.1"
percent-encoding = { workspace = true }
portpicker = { workspace = true }
Expand Down
9 changes: 6 additions & 3 deletions cargo-shuttle/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ pub struct ShuttleArgs {
/// Turn on tracing output for cargo-shuttle and shuttle libraries.
#[arg(long, env = "SHUTTLE_DEBUG")]
pub debug: bool,
/// Target Shuttle's development environment
#[arg(long, env = "SHUTTLE_BETA")]
pub beta: bool,

#[command(subcommand)]
pub cmd: Command,
Expand Down Expand Up @@ -158,7 +161,7 @@ pub enum DeploymentCommand {
limit: u32,

#[arg(long, default_value_t = false)]
/// Output table in `raw` format
/// Output table without borders
raw: bool,
},
/// View status of a deployment
Expand All @@ -173,7 +176,7 @@ pub enum ResourceCommand {
/// List all the resources for a project
List {
#[arg(long, default_value_t = false)]
/// Output table in `raw` format
/// Output table without borders
raw: bool,

#[arg(
Expand Down Expand Up @@ -219,7 +222,7 @@ pub enum ProjectCommand {
limit: u32,

#[arg(long, default_value_t = false)]
/// Output table in `raw` format
/// Output table without borders
raw: bool,
},
/// Delete a project and all linked data
Expand Down
76 changes: 40 additions & 36 deletions cargo-shuttle/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,25 @@ use serde::{Deserialize, Serialize};
use shuttle_common::constants::headers::X_CARGO_SHUTTLE_VERSION;
use shuttle_common::models::deployment::DeploymentRequest;
use shuttle_common::models::{deployment, project, service, ToJson};
use shuttle_common::secrets::Secret;
use shuttle_common::{resource, ApiKey, ApiUrl, LogItem, VersionInfo};
use shuttle_common::{resource, ApiKey, LogItem, VersionInfo};
use tokio::net::TcpStream;
use tokio_tungstenite::tungstenite::client::IntoClientRequest;
use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
use tracing::error;
use uuid::Uuid;

#[derive(Clone)]
pub struct Client {
api_url: ApiUrl,
api_key: Option<Secret<ApiKey>>,
pub struct ShuttleApiClient {
client: reqwest::Client,
api_url: String,
api_key: Option<ApiKey>,
/// alter behaviour to interact with the new platform
beta: bool,
}

impl Client {
pub fn new(api_url: ApiUrl) -> Self {
impl ShuttleApiClient {
pub fn new(api_url: String, api_key: Option<ApiKey>, beta: bool) -> Self {
Self {
api_url,
api_key: None,
client: reqwest::Client::builder()
.default_headers(
HeaderMap::try_from(&HashMap::from([(
Expand All @@ -42,11 +41,22 @@ impl Client {
.timeout(Duration::from_secs(60))
.build()
.unwrap(),
api_url,
api_key,
beta,
}
}

pub fn set_api_key(&mut self, api_key: ApiKey) {
self.api_key = Some(Secret::new(api_key));
self.api_key = Some(api_key);
}

fn set_auth_bearer(&self, builder: RequestBuilder) -> RequestBuilder {
if let Some(ref api_key) = self.api_key {
builder.bearer_auth(api_key.as_ref())
} else {
builder
}
}

pub async fn get_api_versions(&self) -> Result<VersionInfo> {
Expand Down Expand Up @@ -79,13 +89,17 @@ impl Client {
project: &str,
deployment_req: DeploymentRequest,
) -> Result<deployment::Response> {
let path = format!("/projects/{project}/services/{project}");
let path = if self.beta {
format!("/projects/{project}")
} else {
format!("/projects/{project}/services/{project}")
};
let deployment_req = rmp_serde::to_vec(&deployment_req)
.context("serialize DeploymentRequest as a MessagePack byte vector")?;

let url = format!("{}{}", self.api_url, path);
let mut builder = self.client.post(url);
builder = self.set_builder_auth(builder);
builder = self.set_auth_bearer(builder);

builder
.header("Transfer-Encoding", "chunked")
Expand Down Expand Up @@ -161,10 +175,8 @@ impl Client {
self.get(path).await
}

pub async fn get_projects_list(&self, page: u32, limit: u32) -> Result<Vec<project::Response>> {
let path = format!("/projects?page={}&limit={}", page.saturating_sub(1), limit);

self.get(path).await
pub async fn get_projects_list(&self) -> Result<Vec<project::Response>> {
self.get("/projects".to_owned()).await
}

pub async fn stop_project(&self, project: &str) -> Result<project::Response> {
Expand All @@ -174,7 +186,11 @@ impl Client {
}

pub async fn delete_project(&self, project: &str) -> Result<String> {
let path = format!("/projects/{project}/delete");
let path = if self.beta {
format!("/projects/{project}")
} else {
format!("/projects/{project}/delete")
};

self.delete(path).await
}
Expand Down Expand Up @@ -228,12 +244,12 @@ impl Client {
}

async fn ws_get(&self, path: String) -> Result<WebSocketStream<MaybeTlsStream<TcpStream>>> {
let ws_scheme = self.api_url.clone().replace("http", "ws");
let url = format!("{ws_scheme}{path}");
let ws_url = self.api_url.clone().replace("http", "ws");
let url = format!("{ws_url}{path}");
let mut request = url.into_client_request()?;

if let Some(ref api_key) = self.api_key {
let auth_header = Authorization::bearer(api_key.expose().as_ref())?;
let auth_header = Authorization::bearer(api_key.as_ref())?;
request.headers_mut().typed_insert(auth_header);
}

Expand All @@ -252,8 +268,7 @@ impl Client {
let url = format!("{}{}", self.api_url, path);

let mut builder = self.client.get(url);

builder = self.set_builder_auth(builder);
builder = self.set_auth_bearer(builder);

builder
.send()
Expand All @@ -267,8 +282,7 @@ impl Client {
let url = format!("{}{}", self.api_url, path);

let mut builder = self.client.post(url);

builder = self.set_builder_auth(builder);
builder = self.set_auth_bearer(builder);

if let Some(body) = body {
let body = serde_json::to_string(&body)?;
Expand All @@ -283,8 +297,7 @@ impl Client {
let url = format!("{}{}", self.api_url, path);

let mut builder = self.client.put(url);

builder = self.set_builder_auth(builder);
builder = self.set_auth_bearer(builder);

if let Some(body) = body {
let body = serde_json::to_string(&body)?;
Expand All @@ -302,8 +315,7 @@ impl Client {
let url = format!("{}{}", self.api_url, path);

let mut builder = self.client.delete(url);

builder = self.set_builder_auth(builder);
builder = self.set_auth_bearer(builder);

builder
.send()
Expand All @@ -312,12 +324,4 @@ impl Client {
.to_json()
.await
}

fn set_builder_auth(&self, builder: RequestBuilder) -> RequestBuilder {
if let Some(ref api_key) = self.api_key {
builder.bearer_auth(api_key.expose().as_ref())
} else {
builder
}
}
}
8 changes: 4 additions & 4 deletions cargo-shuttle/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use shuttle_common::{constants::API_URL_DEFAULT, ApiKey, ApiUrl};
use shuttle_common::{constants::API_URL_DEFAULT, ApiKey};
use tracing::trace;

use crate::args::ProjectArgs;
Expand Down Expand Up @@ -122,7 +122,7 @@ impl ConfigManager for LocalConfigManager {
#[derive(Deserialize, Serialize, Default)]
pub struct GlobalConfig {
api_key: Option<String>,
pub api_url: Option<ApiUrl>,
pub api_url: Option<String>,
}

impl GlobalConfig {
Expand All @@ -138,7 +138,7 @@ impl GlobalConfig {
self.api_key = None;
}

pub fn api_url(&self) -> Option<ApiUrl> {
pub fn api_url(&self) -> Option<String> {
self.api_url.clone()
}
}
Expand Down Expand Up @@ -315,7 +315,7 @@ impl RequestContext {
self.api_url = api_url;
}

pub fn api_url(&self) -> ApiUrl {
pub fn api_url(&self) -> String {
if let Some(api_url) = self.api_url.clone() {
api_url
} else if let Some(api_url) = self.global.as_ref().unwrap().api_url() {
Expand Down
Loading

0 comments on commit 88198a9

Please sign in to comment.