Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

Upload "draft" worker if secret is created before initial worker script has been uploaded #1087

Merged
merged 8 commits into from
Feb 19, 2020
84 changes: 72 additions & 12 deletions src/commands/secret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::http;
use crate::settings::global_user::GlobalUser;
use crate::settings::toml::Target;
use crate::terminal::{emoji, interactive, message};
use crate::upload;

fn format_error(e: ApiFailure) -> String {
http::format_error(e, Some(&secret_errors))
Expand Down Expand Up @@ -35,25 +36,50 @@ fn validate_target(target: &Target) -> Result<(), failure::Error> {
fn secret_errors(error_code: u16) -> &'static str {
match error_code {
7003 | 7000 => {
"Your wrangler.toml is likely missing the field \"account_id\", which is required to write to Workers KV."
"Your wrangler.toml is likely missing the field \"account_id\", which is required to create a secret."
}
gabbifish marked this conversation as resolved.
Show resolved Hide resolved
10053 => "There is already another binding with a different type by this name. Check your wrangler.toml or your Cloudflare dashboard for conflicting bindings",
10054 => "Your secret is too large, bindings must be 1kB or less",
10054 => "Your secret is too large, it must be 1kB or less",
10055 => "You have exceeded the limit of 32 text bindings for this worker. Run `wrangler secret list` or go to your Cloudflare dashboard to clean up unused text/secret variables",
_ => "",
}
}

// upload_draft_worker will attempt to upload a "draft" version of a worker script if it does not
// already exist in the API (API error code 10007 is returned). The function returns None if this draft
// script was uploaded, or else returns Some (with a Result type so we can return a potential script upload error
// up the call chain).
pub fn upload_draft_worker(
gabbifish marked this conversation as resolved.
Show resolved Hide resolved
e: &ApiFailure,
user: &GlobalUser,
target: &Target,
) -> Option<Result<(), failure::Error>> {
match e {
ApiFailure::Error(_, api_errors) => {
for error in &api_errors.errors {
if error.code == 10007 {
message::working("This worker doesn't exist in the API yet. Uploading worker script so we can create new secret.");
gabbifish marked this conversation as resolved.
Show resolved Hide resolved
return Some(upload::script(user, target, None));
} else {
return None;
}
}
return None;
}
ApiFailure::Invalid(_) => None,
}
}

pub fn create_secret(name: &str, user: &GlobalUser, target: &Target) -> Result<(), failure::Error> {
validate_target(target)?;

let secret_value = interactive::get_user_input(&format!(
"Enter the secret text you'd like assigned to the variable {} on the script named {}",
"Enter the secret text you'd like assigned to the variable {} on the script named {}:",
name, target.name
));

if secret_value.is_empty() {
failure::bail!("Your secret cannot be empty")
failure::bail!("Your secret cannot be empty.")
}

message::working(&format!(
Expand All @@ -72,12 +98,29 @@ pub fn create_secret(name: &str, user: &GlobalUser, target: &Target) -> Result<(
let response = client.request(&CreateSecret {
account_identifier: &target.account_id,
script_name: &target.name,
params,
params: params.clone(),
});

match response {
Ok(_) => message::success(&format!("Success! You've uploaded secret {}.", name)),
Err(e) => failure::bail!(format_error(e)),
Ok(_) => message::success(&format!("Success! Uploaded secret {}.", name)),
Err(e) => match upload_draft_worker(&e, user, target) {
None => failure::bail!(format_error(e)),
Some(draft_upload_response) => match draft_upload_response {
Ok(_) => {
let retry_response = client.request(&CreateSecret {
account_identifier: &target.account_id,
script_name: &target.name,
params,
});

match retry_response {
Ok(_) => message::success(&format!("Success! Uploaded secret {}.", name)),
Err(e) => failure::bail!(format_error(e)),
}
}
Err(e) => failure::bail!(e),
},
},
}

Ok(())
Expand All @@ -87,12 +130,12 @@ pub fn delete_secret(name: &str, user: &GlobalUser, target: &Target) -> Result<(
validate_target(target)?;

match interactive::delete(&format!(
"Are you sure you want to permanently delete the variable {} on the script named {}",
"Are you sure you want to permanently delete the variable {} on the script named {}?",
name, target.name
)) {
Ok(true) => (),
Ok(false) => {
message::info(&format!("Not deleting secret {}", name));
message::info(&format!("Not deleting secret {}.", name));
return Ok(());
}
Err(e) => failure::bail!(e),
Expand All @@ -108,12 +151,29 @@ pub fn delete_secret(name: &str, user: &GlobalUser, target: &Target) -> Result<(
let response = client.request(&DeleteSecret {
account_identifier: &target.account_id,
script_name: &target.name,
secret_name: name,
secret_name: name.clone(),
});

match response {
Ok(_) => message::success(&format!("You've deleted the secret {}.", name)),
Err(e) => failure::bail!(format_error(e)),
Ok(_) => message::success(&format!("Success! Deleted secret {}.", name)),
Err(e) => match upload_draft_worker(&e, user, target) {
gabbifish marked this conversation as resolved.
Show resolved Hide resolved
None => failure::bail!(format_error(e)),
Some(draft_upload_response) => match draft_upload_response {
Ok(_) => {
let retry_response = client.request(&DeleteSecret {
account_identifier: &target.account_id,
script_name: &target.name,
secret_name: name,
});

match retry_response {
Ok(_) => message::success(&format!("Success! Deleted secret {}.", name)),
Err(e) => failure::bail!(format_error(e)),
}
}
Err(e) => failure::bail!(e),
},
},
}

Ok(())
Expand Down