Skip to content

Commit 875d934

Browse files
authored
feat(api-client, cargo-shuttle): json output mode (#2064)
* feat(api-client): wrapper for inner type and raw json * feat(cargo-shuttle): json output mode for commands where it makes sense. breaking: generate output-file arg name * clippy * yeet * nit
1 parent 09831fa commit 875d934

File tree

9 files changed

+429
-178
lines changed

9 files changed

+429
-178
lines changed

admin/src/client.rs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use anyhow::Result;
22
use serde_json::{json, Value};
3-
use shuttle_api_client::{util::ToBodyContent, ShuttleApiClient};
3+
use shuttle_api_client::{
4+
util::{ParsedJson, ToBodyContent},
5+
ShuttleApiClient,
6+
};
47
use shuttle_common::models::{
58
project::{ProjectResponse, ProjectUpdateRequest},
69
team::AddTeamMemberRequest,
@@ -18,11 +21,13 @@ impl Client {
1821
}
1922
}
2023

21-
pub async fn get_old_certificates(&self) -> Result<Vec<(String, String, Option<String>)>> {
24+
pub async fn get_old_certificates(
25+
&self,
26+
) -> Result<ParsedJson<Vec<(String, String, Option<String>)>>> {
2227
self.inner.get_json("/admin/certificates").await
2328
}
2429

25-
pub async fn renew_certificate(&self, cert_id: &str) -> Result<String> {
30+
pub async fn renew_certificate(&self, cert_id: &str) -> Result<ParsedJson<String>> {
2631
self.inner
2732
.put_json(
2833
format!("/admin/certificates/renew/{cert_id}"),
@@ -35,7 +40,7 @@ impl Client {
3540
&self,
3641
project_id: &str,
3742
config: serde_json::Value,
38-
) -> Result<ProjectResponse> {
43+
) -> Result<ParsedJson<ProjectResponse>> {
3944
self.inner
4045
.put_json(
4146
format!("/projects/{project_id}"),
@@ -47,13 +52,13 @@ impl Client {
4752
.await
4853
}
4954

50-
pub async fn get_project_config(&self, project_id: &str) -> Result<Value> {
55+
pub async fn get_project_config(&self, project_id: &str) -> Result<ParsedJson<Value>> {
5156
self.inner
5257
.get_json(format!("/admin/projects/{project_id}/config"))
5358
.await
5459
}
5560

56-
pub async fn upgrade_project_to_lb(&self, project_id: &str) -> Result<Value> {
61+
pub async fn upgrade_project_to_lb(&self, project_id: &str) -> Result<ParsedJson<Value>> {
5762
self.inner
5863
.put_json(
5964
format!("/admin/projects/{project_id}/config"),
@@ -66,7 +71,7 @@ impl Client {
6671
&self,
6772
project_id: &str,
6873
update_config: &Value,
69-
) -> Result<Value> {
74+
) -> Result<ParsedJson<Value>> {
7075
self.inner
7176
.put_json(
7277
format!("/admin/projects/{project_id}/scale"),
@@ -79,7 +84,7 @@ impl Client {
7984
&self,
8085
project_id: &str,
8186
user_id: String,
82-
) -> Result<ProjectResponse> {
87+
) -> Result<ParsedJson<ProjectResponse>> {
8388
self.inner
8489
.put_json(
8590
format!("/projects/{project_id}"),
@@ -91,7 +96,11 @@ impl Client {
9196
.await
9297
}
9398

94-
pub async fn add_team_member(&self, team_user_id: &str, user_id: String) -> Result<String> {
99+
pub async fn add_team_member(
100+
&self,
101+
team_user_id: &str,
102+
user_id: String,
103+
) -> Result<ParsedJson<String>> {
95104
self.inner
96105
.post_json(
97106
format!("/teams/{team_user_id}/members"),
@@ -126,32 +135,32 @@ impl Client {
126135
}
127136
}
128137

129-
pub async fn gc_free_tier(&self, days: u32) -> Result<Vec<String>> {
138+
pub async fn gc_free_tier(&self, days: u32) -> Result<ParsedJson<Vec<String>>> {
130139
let path = format!("/admin/gc/free/{days}");
131140
self.inner.get_json(&path).await
132141
}
133142

134-
pub async fn gc_shuttlings(&self, minutes: u32) -> Result<Vec<String>> {
143+
pub async fn gc_shuttlings(&self, minutes: u32) -> Result<ParsedJson<Vec<String>>> {
135144
let path = format!("/admin/gc/shuttlings/{minutes}");
136145
self.inner.get_json(&path).await
137146
}
138147

139-
pub async fn stop_gc_inactive_project(&self, project_id: &str) -> Result<String> {
148+
pub async fn stop_gc_inactive_project(&self, project_id: &str) -> Result<ParsedJson<String>> {
140149
let path = format!("/admin/gc/stop-inactive-project/{project_id}");
141150
self.inner.put_json(&path, Option::<()>::None).await
142151
}
143152

144-
pub async fn get_user(&self, user_id: &str) -> Result<UserResponse> {
153+
pub async fn get_user(&self, user_id: &str) -> Result<ParsedJson<UserResponse>> {
145154
self.inner.get_json(format!("/admin/users/{user_id}")).await
146155
}
147156

148-
pub async fn get_user_everything(&self, query: &str) -> Result<Value> {
157+
pub async fn get_user_everything(&self, query: &str) -> Result<ParsedJson<Value>> {
149158
self.inner
150159
.get_json_with_body("/admin/users/everything", json!(query))
151160
.await
152161
}
153162

154-
pub async fn delete_user(&self, user_id: &str) -> Result<String> {
163+
pub async fn delete_user(&self, user_id: &str) -> Result<ParsedJson<String>> {
155164
self.inner
156165
.delete_json(format!("/admin/users/{user_id}"))
157166
.await
@@ -168,10 +177,11 @@ impl Client {
168177
.await
169178
}
170179

171-
pub async fn get_expired_protrials(&self) -> Result<Vec<String>> {
180+
pub async fn get_expired_protrials(&self) -> Result<ParsedJson<Vec<String>>> {
172181
self.inner.get_json("/admin/users/protrial-downgrade").await
173182
}
174-
pub async fn downgrade_protrial(&self, user_id: &str) -> Result<String> {
183+
184+
pub async fn downgrade_protrial(&self, user_id: &str) -> Result<ParsedJson<String>> {
175185
self.inner
176186
.put_json(
177187
format!("/admin/users/protrial-downgrade/{user_id}"),
@@ -180,10 +190,10 @@ impl Client {
180190
.await
181191
}
182192

183-
pub async fn get_projects_for_retention_policy(&self) -> Result<Vec<String>> {
193+
pub async fn get_projects_for_retention_policy(&self) -> Result<ParsedJson<Vec<String>>> {
184194
self.inner.get_json("/admin/log-retention").await
185195
}
186-
pub async fn fix_retention_policy(&self, project_id: &str) -> Result<String> {
196+
pub async fn fix_retention_policy(&self, project_id: &str) -> Result<ParsedJson<String>> {
187197
self.inner
188198
.put_json(
189199
format!("/admin/log-retention/{project_id}"),

admin/src/lib.rs

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ pub async fn run(args: Args) {
5757
let res = client
5858
.update_project_owner(&project_id, new_user_id)
5959
.await
60-
.unwrap();
60+
.unwrap()
61+
.into_inner();
6162
println!("{res:?}");
6263
}
6364
Command::AddUserToTeam {
@@ -67,11 +68,12 @@ pub async fn run(args: Args) {
6768
let res = client
6869
.add_team_member(&team_user_id, user_id)
6970
.await
70-
.unwrap();
71+
.unwrap()
72+
.into_inner();
7173
println!("{res}");
7274
}
7375
Command::RenewCerts => {
74-
let certs = client.get_old_certificates().await.unwrap();
76+
let certs = client.get_old_certificates().await.unwrap().into_inner();
7577
eprintln!("Starting renewals of {} certs in 5 seconds...", certs.len());
7678
tokio::time::sleep(tokio::time::Duration::from_millis(5000)).await;
7779
let mut any_error = false;
@@ -135,15 +137,15 @@ pub async fn run(args: Args) {
135137
send_emails,
136138
limit,
137139
} => {
138-
let project_ids = client.gc_free_tier(days).await.unwrap();
140+
let project_ids = client.gc_free_tier(days).await.unwrap().into_inner();
139141
gc(client, project_ids, stop_deployments, send_emails, limit).await;
140142
}
141143
Command::GcShuttlings {
142144
minutes,
143145
stop_deployments,
144146
limit,
145147
} => {
146-
let project_ids = client.gc_shuttlings(minutes).await.unwrap();
148+
let project_ids = client.gc_shuttlings(minutes).await.unwrap().into_inner();
147149
gc(client, project_ids, stop_deployments, false, limit).await;
148150
}
149151
Command::DeleteUser { user_id } => {
@@ -157,11 +159,15 @@ pub async fn run(args: Args) {
157159
println!("Set {user_id} to {tier}");
158160
}
159161
Command::Everything { query } => {
160-
let v = client.get_user_everything(&query).await.unwrap();
162+
let v = client
163+
.get_user_everything(&query)
164+
.await
165+
.unwrap()
166+
.into_inner();
161167
println!("{}", serde_json::to_string_pretty(&v).unwrap());
162168
}
163169
Command::DowngradeProTrials => {
164-
let users = client.get_expired_protrials().await.unwrap();
170+
let users = client.get_expired_protrials().await.unwrap().into_inner();
165171
eprintln!(
166172
"Starting downgrade of {} users in 5 seconds...",
167173
users.len()
@@ -172,9 +178,13 @@ pub async fn run(args: Args) {
172178
println!("{user_id}");
173179
println!(
174180
" {:?}",
175-
client.downgrade_protrial(&user_id).await.inspect_err(|_| {
176-
any_error = true;
177-
})
181+
client
182+
.downgrade_protrial(&user_id)
183+
.await
184+
.map(|r| r.into_inner())
185+
.inspect_err(|_| {
186+
any_error = true;
187+
})
178188
);
179189
// prevent api rate limiting
180190
tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
@@ -184,16 +194,24 @@ pub async fn run(args: Args) {
184194
}
185195
}
186196
Command::FixRetentionPolicies => {
187-
let projects = client.get_projects_for_retention_policy().await.unwrap();
197+
let projects = client
198+
.get_projects_for_retention_policy()
199+
.await
200+
.unwrap()
201+
.into_inner();
188202
eprintln!("Starting fix of {} log retention policies", projects.len());
189203
let mut any_error = false;
190204
for pid in projects {
191205
println!("{pid}");
192206
println!(
193207
" {:?}",
194-
client.fix_retention_policy(&pid).await.inspect_err(|_| {
195-
any_error = true;
196-
})
208+
client
209+
.fix_retention_policy(&pid)
210+
.await
211+
.map(|r| r.into_inner())
212+
.inspect_err(|_| {
213+
any_error = true;
214+
})
197215
);
198216
// prevent api rate limiting
199217
tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
@@ -230,9 +248,16 @@ async fn gc(
230248
for pid in project_ids {
231249
println!("{pid}");
232250
let call = if send_email {
233-
client.stop_gc_inactive_project(&pid).await
251+
client
252+
.stop_gc_inactive_project(&pid)
253+
.await
254+
.map(|r| r.into_inner())
234255
} else {
235-
client.inner.stop_service(&pid).await
256+
client
257+
.inner
258+
.stop_service(&pid)
259+
.await
260+
.map(|r| r.into_inner())
236261
};
237262
println!(
238263
" {:?}",

0 commit comments

Comments
 (0)