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

Commit

Permalink
Merge pull request #1360 from cloudflare/avery/kv-preview
Browse files Browse the repository at this point in the history
add --preview to kv:key, kv:bulk + kv:namespace
  • Loading branch information
EverlastingBugstopper authored Jun 10, 2020
2 parents 2aec250 + faecacc commit 16a14b1
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 38 deletions.
254 changes: 225 additions & 29 deletions src/commands/kv/namespace/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,43 @@ use crate::commands::kv;
use crate::http;
use crate::kv::namespace::create;
use crate::settings::global_user::GlobalUser;
use crate::settings::toml::Target;
use crate::settings::toml::{ConfigKvNamespace, KvNamespace, Manifest};
use crate::terminal::message;

pub fn run(
target: &Target,
manifest: &Manifest,
is_preview: bool,
env: Option<&str>,
user: &GlobalUser,
binding: &str,
) -> Result<(), failure::Error> {
kv::validate_target(target)?;
let target = manifest.get_target(env, is_preview)?;
kv::validate_target(&target)?;
validate_binding(binding)?;

let title = format!("{}-{}", target.name, binding);
let msg = format!("Creating namespace with title \"{}\"", title);
message::working(&msg);

let client = http::cf_v4_client(user)?;
let result = create(&client, target, &title);
let result = create(&client, &target, &title);

match result {
Ok(success) => {
let namespace = success.result;
message::success(&format!("Success: {:#?}", namespace));
if target.kv_namespaces.is_empty() {
match env {
Some(env) => message::success(&format!(
"Add the following to your wrangler.toml under [env.{}]:",
env
)),
None => message::success("Add the following to your wrangler.toml:"),
};
println!(
"kv-namespaces = [ \n\
\t {{ binding = \"{}\", id = \"{}\" }} \n\
]",
binding, namespace.id
);
} else {
match env {
Some(env) => message::success(&format!(
"Add the following to your wrangler.toml's \"kv-namespaces\" array in [env.{}]:",
env
)),
None => message::success("Add the following to your wrangler.toml's \"kv-namespaces\" array:"),
};
println!("{{ binding = \"{}\", id = \"{}\" }}", binding, namespace.id);
}
message::success("Success!");
println!(
"{}",
toml_modification_instructions(
KvNamespace {
binding: binding.to_string(),
id: namespace.id,
},
manifest.kv_namespaces.as_ref(),
env,
is_preview,
)
);
}
Err(e) => print!("{}", kv::format_error(e)),
}
Expand All @@ -68,10 +58,216 @@ fn validate_binding(binding: &str) -> Result<(), failure::Error> {
Ok(())
}

fn toml_modification_instructions(
new_namespace: KvNamespace,
all_namespaces: Option<&Vec<ConfigKvNamespace>>,
env: Option<&str>,
is_preview: bool,
) -> String {
let mut msg = "Add the following to your wrangler.toml".to_string();

if all_namespaces.is_some() {
msg.push_str(" in your kv_namespaces array");
}

if let Some(env) = env {
msg.push_str(&format!(" under [env.{}]", env));
}

msg.push_str(":\n");

let existing_namespace = if let Some(all_namespaces) = all_namespaces {
all_namespaces
.iter()
.find(|namespace| namespace.binding == new_namespace.binding)
} else {
None
};

let mut inline_msg = format!("{{ binding = \"{}\", ", &new_namespace.binding);
if let Some(existing_namespace) = existing_namespace {
if is_preview {
inline_msg.push_str(&format!("preview_id = \"{}\"", new_namespace.id));
if let Some(existing_namespace_id) = &existing_namespace.id {
inline_msg.push_str(&format!(", id = \"{}\"", existing_namespace_id));
}
} else {
inline_msg.push_str(&format!("id = \"{}\"", new_namespace.id));
if let Some(existing_namespace_preview_id) = &existing_namespace.preview_id {
inline_msg.push_str(&format!(
", preview_id = \"{}\"",
existing_namespace_preview_id
));
}
}
} else {
if is_preview {
inline_msg.push_str("preview_id");
} else {
inline_msg.push_str("id")
}
inline_msg.push_str(" = \"");
inline_msg.push_str(&new_namespace.id);
inline_msg.push_str("\"");
};
inline_msg.push_str(" }");

if all_namespaces.is_some() {
msg.push_str(&inline_msg);
} else {
msg.push_str(&format!("kv_namespaces = [ \n\t {}\n]", &inline_msg));
}

msg
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_messages_about_env() {
let new_namespace = KvNamespace {
id: "new_preview_id".to_string(),
binding: "FOO".to_string(),
};

let all_namespaces = Some(vec![ConfigKvNamespace {
binding: "BAR".to_string(),
id: Some("production_id".to_string()),
preview_id: None,
}]);

let env = Some("my_env");

let is_preview = true;

let msg =
toml_modification_instructions(new_namespace, all_namespaces.as_ref(), env, is_preview);
assert!(msg.contains("[env.my_env]"));
}

#[test]
fn it_messages_about_preview() {
let new_namespace = KvNamespace {
id: "new_preview_id".to_string(),
binding: "FOO".to_string(),
};

let all_namespaces = Some(vec![ConfigKvNamespace {
binding: "FOO".to_string(),
id: Some("existing_production_id".to_string()),
preview_id: None,
}]);

let env = None;

let is_preview = true;

let msg =
toml_modification_instructions(new_namespace, all_namespaces.as_ref(), env, is_preview);
assert!(msg.contains("{ binding = \"FOO\", preview_id = \"new_preview_id\", id = \"existing_production_id\" }"));
assert!(!msg.contains("kv_namespaces = ["));
}

#[test]
fn it_messages_about_namespaces() {
let new_namespace = KvNamespace {
id: "new_id".to_string(),
binding: "FOO".to_string(),
};

let all_namespaces = None;

let env = None;

let is_preview = false;

let msg =
toml_modification_instructions(new_namespace, all_namespaces.as_ref(), env, is_preview);
assert!(msg.contains("{ binding = \"FOO\", id = \"new_id\" }"));
assert!(msg.contains("kv_namespaces = ["));
}

#[test]
fn it_doesnt_message_about_namespaces() {
let new_namespace = KvNamespace {
id: "new_id".to_string(),
binding: "FOO".to_string(),
};

let all_namespaces = Some(vec![]);

let env = None;

let is_preview = false;

let msg =
toml_modification_instructions(new_namespace, all_namespaces.as_ref(), env, is_preview);
assert!(msg.contains("{ binding = \"FOO\", id = \"new_id\" }"));
assert!(!msg.contains("kv_namespaces = ["));
}

#[test]
fn it_messages_about_overridden_namespaces() {
let new_namespace = KvNamespace {
id: "new_preview_id".to_string(),
binding: "FOO".to_string(),
};

let all_namespaces = Some(vec![
ConfigKvNamespace {
binding: "FOO".to_string(),
id: Some("existing_production_id".to_string()),
preview_id: Some("existing_preview_id".to_string()),
},
ConfigKvNamespace {
binding: "BAR".to_string(),
id: Some("some_prod_id".to_string()),
preview_id: None,
},
]);

let env = None;

let is_preview = true;

let msg =
toml_modification_instructions(new_namespace, all_namespaces.as_ref(), env, is_preview);
assert!(msg.contains("{ binding = \"FOO\", preview_id = \"new_preview_id\", id = \"existing_production_id\" }"));
assert!(!msg.contains("kv_namespaces = ["));
}

#[test]
fn it_messages_when_no_existing_id() {
let new_namespace = KvNamespace {
id: "new_preview_id".to_string(),
binding: "FOO".to_string(),
};

let all_namespaces = Some(vec![
ConfigKvNamespace {
binding: "FOO".to_string(),
id: None,
preview_id: None,
},
ConfigKvNamespace {
binding: "BAR".to_string(),
id: Some("some_prod_id".to_string()),
preview_id: None,
},
]);

let env = None;

let is_preview = true;

let msg =
toml_modification_instructions(new_namespace, all_namespaces.as_ref(), env, is_preview);
assert!(msg.contains("{ binding = \"FOO\", preview_id = \"new_preview_id\" }"));
assert!(!msg.contains("kv_namespaces = ["));
}

#[test]
fn it_can_detect_invalid_binding() {
let invalid_bindings = vec!["hi there", "1234"];
Expand Down
20 changes: 17 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ fn run() -> Result<(), failure::Error> {
let kv_namespace_specifier_group = ArgGroup::with_name("namespace-specifier")
.args(&["binding", "namespace-id"])
.required(true);
let kv_preview_arg = Arg::with_name("preview")
.help("applies the command to the preview namespace when combined with --binding")
.long("preview")
.takes_value(false);

// This arg is for any action that uses environments (e.g. KV subcommands, publish)
let environment_arg = Arg::with_name("env")
Expand Down Expand Up @@ -122,13 +126,15 @@ fn run() -> Result<(), failure::Error> {
.required(true)
.index(1)
)
.arg(kv_preview_arg.clone())
.arg(silent_verbose_arg.clone())
)
.subcommand(
SubCommand::with_name("delete")
.about("Delete namespace")
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.arg(kv_preview_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(environment_arg.clone())
.arg(silent_verbose_arg.clone())
Expand All @@ -153,6 +159,7 @@ fn run() -> Result<(), failure::Error> {
.about("Put a key-value pair into a namespace")
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.arg(kv_preview_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(environment_arg.clone())
.arg(
Expand Down Expand Up @@ -197,6 +204,7 @@ fn run() -> Result<(), failure::Error> {
.about("Get a key's value from a namespace")
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.arg(kv_preview_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(environment_arg.clone())
.arg(
Expand All @@ -212,6 +220,7 @@ fn run() -> Result<(), failure::Error> {
.about("Delete a key and its value from a namespace")
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.arg(kv_preview_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(environment_arg.clone())
.arg(
Expand All @@ -227,6 +236,7 @@ fn run() -> Result<(), failure::Error> {
.about("List all keys in a namespace. Produces JSON output")
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.arg(kv_preview_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(environment_arg.clone())
.arg(
Expand All @@ -253,6 +263,7 @@ fn run() -> Result<(), failure::Error> {
.about("Upload multiple key-value pairs to a namespace")
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.arg(kv_preview_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(environment_arg.clone())
.arg(
Expand All @@ -268,6 +279,7 @@ fn run() -> Result<(), failure::Error> {
.arg(kv_binding_arg.clone())
.arg(kv_namespace_id_arg.clone())
.group(kv_namespace_specifier_group.clone())
.arg(kv_preview_arg.clone())
.arg(environment_arg.clone())
.about("Delete multiple keys and their values from a namespace")
.arg(
Expand Down Expand Up @@ -830,15 +842,15 @@ fn run() -> Result<(), failure::Error> {
} else if let Some(kv_matches) = matches.subcommand_matches("kv:namespace") {
let manifest = settings::toml::Manifest::new(config_path)?;
let user = settings::global_user::GlobalUser::new()?;

match kv_matches.subcommand() {
("create", Some(create_matches)) => {
is_preview = create_matches.is_present("preview");
let env = create_matches.value_of("env");
let target = manifest.get_target(env, is_preview)?;
let binding = create_matches.value_of("binding").unwrap();
commands::kv::namespace::create(&target, env, &user, binding)?;
commands::kv::namespace::create(&manifest, is_preview, env, &user, binding)?;
}
("delete", Some(delete_matches)) => {
is_preview = delete_matches.is_present("preview");
let env = delete_matches.value_of("env");
let target = manifest.get_target(env, is_preview)?;
let namespace_id = match delete_matches.value_of("binding") {
Expand Down Expand Up @@ -868,6 +880,7 @@ fn run() -> Result<(), failure::Error> {
let (subcommand, subcommand_matches) = kv_matches.subcommand();
let (target, namespace_id) = match subcommand_matches {
Some(subcommand_matches) => {
is_preview = subcommand_matches.is_present("preview");
let env = subcommand_matches.value_of("env");
let target = manifest.get_target(env, is_preview)?;
let namespace_id = match subcommand_matches.value_of("binding") {
Expand Down Expand Up @@ -931,6 +944,7 @@ fn run() -> Result<(), failure::Error> {
let (subcommand, subcommand_matches) = kv_matches.subcommand();
let (target, namespace_id) = match subcommand_matches {
Some(subcommand_matches) => {
is_preview = subcommand_matches.is_present("preview");
let env = subcommand_matches.value_of("env");
let target = manifest.get_target(env, is_preview)?;
let namespace_id = match subcommand_matches.value_of("binding") {
Expand Down
Loading

0 comments on commit 16a14b1

Please sign in to comment.