Skip to content

Commit 6f62944

Browse files
authored
fix: paid tunnels cli errors (#102)
1 parent 3c2005e commit 6f62944

File tree

3 files changed

+50
-36
lines changed

3 files changed

+50
-36
lines changed

linkup-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "linkup-cli"
3-
version = "1.0.3"
3+
version = "1.0.4"
44
edition = "2021"
55

66
[[bin]]

linkup-cli/src/main.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ pub enum CliError {
120120
RebootDNSMasq(String),
121121
#[error("--no-tunnel does not work without `local-dns`")]
122122
NoTunnelWithoutLocalDns,
123+
#[error("could not get env var: {0}")]
124+
GetEnvVar(String),
125+
#[error("HTTP error: {0}")]
126+
HttpErr(String),
127+
#[error("could not parse: {0}. {1}")]
128+
ParseErr(String, String),
129+
#[error("{0}: {1}")]
130+
FileErr(String, String),
123131
}
124132

125133
#[derive(Error, Debug)]

linkup-cli/src/paid_tunnel.rs

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ fn prepare_client_and_headers(
6969
headers.insert(
7070
AUTHORIZATION,
7171
HeaderValue::from_str(&format!("Bearer {}", bearer_token))
72-
.map_err(|err| CliError::StatusErr(err.to_string()))?,
72+
.map_err(|_| CliError::GetEnvVar("LINKUP_CF_API_TOKEN".to_string()))?,
7373
);
7474

7575
Ok((client, headers))
@@ -86,7 +86,12 @@ fn send_request<T: for<'de> serde::Deserialize<'de>>(
8686
let builder = match method {
8787
"GET" => client.get(url),
8888
"POST" => client.post(url),
89-
_ => return Err(CliError::StatusErr("Unsupported HTTP method".to_string())),
89+
_ => {
90+
return Err(CliError::HttpErr(format!(
91+
"Unsupported HTTP method: {}",
92+
method
93+
)))
94+
}
9095
};
9196

9297
let builder = builder.headers(headers);
@@ -96,25 +101,18 @@ fn send_request<T: for<'de> serde::Deserialize<'de>>(
96101
builder
97102
};
98103

99-
let response = builder.send().map_err(|err| {
100-
CliError::StatusErr(format!("Failed to send request, {}", err).to_string())
101-
})?;
104+
let response = builder
105+
.send()
106+
.map_err(|err| CliError::HttpErr(format!("Failed to send request, {}", err).to_string()))?;
102107

103108
if response.status().is_success() {
104109
let response_body = response.text().map_err(|err| {
105-
CliError::StatusErr(format!("Could not read response body, {}", err).to_string())
110+
CliError::HttpErr(format!("Could not read response body, {}", err).to_string())
106111
})?;
107-
serde_json::from_str(&response_body).map_err(|err| {
108-
CliError::StatusErr(
109-
format!(
110-
"Could not parse JSON, {}. Response body: {}",
111-
err, response_body
112-
)
113-
.to_string(),
114-
)
115-
})
112+
serde_json::from_str(&response_body)
113+
.map_err(|err| CliError::ParseErr("from str to JSON".to_string(), err.to_string()))
116114
} else {
117-
Err(CliError::StatusErr(format!(
115+
Err(CliError::HttpErr(format!(
118116
"Failed to get a successful response: {}",
119117
response.status()
120118
)))
@@ -133,7 +131,7 @@ pub struct RealPaidTunnelManager;
133131
impl PaidTunnelManager for RealPaidTunnelManager {
134132
fn get_tunnel_id(&self, tunnel_name: &str) -> Result<Option<String>, CliError> {
135133
let account_id = env::var("LINKUP_CLOUDFLARE_ACCOUNT_ID")
136-
.map_err(|err| CliError::BadConfig(err.to_string()))?;
134+
.map_err(|_| CliError::GetEnvVar("LINKUP_CLOUDFLARE_ACCOUNT_ID".to_string()))?;
137135
let url = format!(
138136
"https://api.cloudflare.com/client/v4/accounts/{}/cfd_tunnel",
139137
account_id
@@ -160,7 +158,7 @@ impl PaidTunnelManager for RealPaidTunnelManager {
160158
fn create_tunnel(&self, tunnel_name: &str) -> Result<String, CliError> {
161159
let tunnel_secret = generate_tunnel_secret();
162160
let account_id = env::var("LINKUP_CLOUDFLARE_ACCOUNT_ID")
163-
.map_err(|err| CliError::BadConfig(err.to_string()))?;
161+
.map_err(|_| CliError::GetEnvVar("LINKUP_CLOUDFLARE_ACCOUNT_ID".to_string()))?;
164162
let url = format!(
165163
"https://api.cloudflare.com/client/v4/accounts/{}/cfd_tunnel",
166164
account_id,
@@ -170,21 +168,26 @@ impl PaidTunnelManager for RealPaidTunnelManager {
170168
name: tunnel_name.to_string(),
171169
tunnel_secret: tunnel_secret.clone(),
172170
})
173-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
171+
.map_err(|err| CliError::ParseErr("from JSON to String".to_string(), err.to_string()))?;
174172

175173
let parsed: CreateTunnelResponse =
176174
send_request(&client, &url, headers, Some(body), "POST")?;
177-
save_tunnel_credentials(&RealSystem, &parsed.result.id, &tunnel_secret)
178-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
179-
create_config_yml(&RealSystem, &parsed.result.id)
180-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
175+
save_tunnel_credentials(&RealSystem, &parsed.result.id, &tunnel_secret).map_err(|err| {
176+
CliError::FileErr(
177+
"Failed to save tunnel credentials".to_string(),
178+
err.to_string(),
179+
)
180+
})?;
181+
create_config_yml(&RealSystem, &parsed.result.id).map_err(|err| {
182+
CliError::FileErr("Failed to create config YML".to_string(), err.to_string())
183+
})?;
181184

182185
Ok(parsed.result.id)
183186
}
184187

185188
fn create_dns_record(&self, tunnel_id: &str, tunnel_name: &str) -> Result<(), CliError> {
186189
let zone_id = env::var("LINKUP_CLOUDFLARE_ZONE_ID")
187-
.map_err(|err| CliError::BadConfig(err.to_string()))?;
190+
.map_err(|_| CliError::GetEnvVar("LINKUP_CLOUDFLARE_ZONE_ID".to_string()))?;
188191
let url = format!(
189192
"https://api.cloudflare.com/client/v4/zones/{}/dns_records",
190193
zone_id
@@ -196,7 +199,7 @@ impl PaidTunnelManager for RealPaidTunnelManager {
196199
r#type: "CNAME".to_string(),
197200
proxied: true,
198201
})
199-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
202+
.map_err(|err| CliError::ParseErr("from JSON to String".to_string(), err.to_string()))?;
200203

201204
let _parsed: CreateDNSRecordResponse =
202205
send_request(&client, &url, headers, Some(body), "POST")?;
@@ -217,7 +220,7 @@ fn save_tunnel_credentials(
217220
) -> Result<(), CliError> {
218221
let account_id = sys
219222
.get_env("LINKUP_CLOUDFLARE_ACCOUNT_ID")
220-
.map_err(|err| CliError::BadConfig(err.to_string()))?;
223+
.map_err(|_| CliError::GetEnvVar("LINKUP_CLOUDFLARE_ACCOUNT_ID".to_string()))?;
221224
let data = serde_json::json!({
222225
"AccountTag": account_id,
223226
"TunnelID": tunnel_id,
@@ -227,12 +230,14 @@ fn save_tunnel_credentials(
227230
// Determine the directory path
228231
let home_dir = sys
229232
.get_env("HOME")
230-
.map_err(|err| CliError::BadConfig(err.to_string()))?;
233+
.map_err(|_| CliError::GetEnvVar("HOME".to_string()))?;
231234
let dir_path = Path::new(&home_dir).join(".cloudflared");
232235

233236
// Create the directory if it does not exist
234237
if !dir_path.exists() {
235-
fs::create_dir_all(&dir_path).map_err(|err| CliError::StatusErr(err.to_string()))?;
238+
fs::create_dir_all(&dir_path).map_err(|err| {
239+
CliError::FileErr("Could not create directory".to_string(), err.to_string())
240+
})?
236241
}
237242

238243
// Define the file path
@@ -241,10 +246,10 @@ fn save_tunnel_credentials(
241246
// Create and write to the file
242247
let mut file: Box<dyn FileLike> = sys
243248
.create_file(file_path)
244-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
249+
.map_err(|err| CliError::FileErr("Could not create file".to_string(), err.to_string()))?;
245250
let data_string = data.to_string();
246251
sys.write_file(&mut file, &data_string)
247-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
252+
.map_err(|err| CliError::FileErr("Could not write to file".to_string(), err.to_string()))?;
248253

249254
Ok(())
250255
}
@@ -253,14 +258,15 @@ fn create_config_yml(sys: &dyn System, tunnel_id: &str) -> Result<(), CliError>
253258
// Determine the directory path
254259
let home_dir = sys
255260
.get_env("HOME")
256-
.map_err(|err| CliError::BadConfig(err.to_string()))?;
261+
.map_err(|_| CliError::GetEnvVar("HOME".to_string()))?;
257262
let dir_path = Path::new(&home_dir).join(".cloudflared");
258263

259264
// Create the directory if it does not exist
260265
if !sys.file_exists(dir_path.as_path()) {
261266
log::info!("Creating directory: {:?}", dir_path);
262-
sys.create_dir_all(&dir_path)
263-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
267+
sys.create_dir_all(&dir_path).map_err(|err| {
268+
CliError::FileErr("Could not create directory".to_string(), err.to_string())
269+
})?;
264270
}
265271

266272
// Define the file path
@@ -277,9 +283,9 @@ fn create_config_yml(sys: &dyn System, tunnel_id: &str) -> Result<(), CliError>
277283

278284
let mut file: Box<dyn FileLike> = sys
279285
.create_file(dir_path.join("config.yml"))
280-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
286+
.map_err(|err| CliError::FileErr("Could not create file".to_string(), err.to_string()))?;
281287
sys.write_file(&mut file, &serialized)
282-
.map_err(|err| CliError::StatusErr(err.to_string()))?;
288+
.map_err(|err| CliError::FileErr("Could not write to file".to_string(), err.to_string()))?;
283289
Ok(())
284290
}
285291

0 commit comments

Comments
 (0)