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

Add key listing functionality for workers kv subcommands #462

Merged
merged 8 commits into from
Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 86 additions & 0 deletions src/commands/kv/list_keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
extern crate serde_json;

use cloudflare::endpoints::workerskv::list_namespace_keys::ListNamespaceKeys;
use cloudflare::endpoints::workerskv::list_namespace_keys::ListNamespaceKeysParams;
use cloudflare::endpoints::workerskv::Key;
use cloudflare::framework::apiclient::ApiClient;
use failure::bail;
use serde_json::value::Value as JsonValue;

// Note: this function only prints keys in json form, given that
// the number of entries in each json blob is variable (so csv and tsv
// representation won't make sense)
pub fn list_keys(id: &str, prefix: Option<&str>) -> Result<(), failure::Error> {
let client = super::api_client()?;
let account_id = super::account_id()?;

let params = ListNamespaceKeysParams {
limit: None, // Defaults to 1000 (the maximum)
cursor: None,
prefix: prefix.map(str::to_string),
gabbifish marked this conversation as resolved.
Show resolved Hide resolved
};

let mut request_params = ListNamespaceKeys {
account_identifier: &account_id,
namespace_identifier: id,
params: params,
};

let mut response = client.request(&request_params);

print!("["); // Open json list bracket

// Iterate over all pages until no pages of keys are left.
// This is detected when a returned cursor is an empty string.
loop {
let (result, cursor) = match response {
Ok(success) => (
success.result,
get_cursor_from_result_info(success.result_info.clone()),
),
Err(e) => bail!(e),
};

match cursor {
None => {
// Case where we are done iterating through pages (no cursor returned)
print_page(result, true)?;
print!("]"); // Close json list bracket
break;
}
Some(_) => {
// Case where we still have pages to iterate through (a cursor is returned).
print_page(result, false)?;

// Update cursor in request_params.params, and make another request to Workers KV API.
request_params.params.cursor = cursor;
response = client.request(&request_params);
}
}
}

Ok(())
}

// Returns Some(cursor) if cursor is non-empty, otherwise returns None.
fn get_cursor_from_result_info(result_info: Option<JsonValue>) -> Option<String> {
let result_info = result_info.unwrap();
let returned_cursor_value = &result_info["cursor"];
let returned_cursor = returned_cursor_value.as_str().unwrap().to_string();
if returned_cursor.is_empty() {
None
} else {
Some(returned_cursor)
}
}

fn print_page(keys: Vec<Key>, last_page: bool) -> Result<(), failure::Error> {
for i in 0..keys.len() {
print!("{}", serde_json::to_string(&keys[i])?);
// if last key on last page, don't print final comma.
if !(last_page && i == keys.len() - 1) {
print!(",");
}
}
Ok(())
}
2 changes: 2 additions & 0 deletions src/commands/kv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod create_namespace;
mod delete_bulk;
mod delete_key;
mod delete_namespace;
mod list_keys;
mod list_namespaces;
mod read_key;
mod rename_namespace;
Expand All @@ -22,6 +23,7 @@ pub use create_namespace::create_namespace;
pub use delete_bulk::delete_bulk;
pub use delete_key::delete_key;
pub use delete_namespace::delete_namespace;
pub use list_keys::list_keys;
pub use list_namespaces::list_namespaces;
pub use read_key::read_key;
pub use rename_namespace::rename_namespace;
Expand Down
19 changes: 19 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,20 @@ fn run() -> Result<(), failure::Error> {
Arg::with_name("path")
)
)
.subcommand(
SubCommand::with_name("list-keys")
.arg(
Arg::with_name("id")
)
.arg(
Arg::with_name("prefix")
.short("p")
.long("prefix")
.value_name("STRING")
.takes_value(true)
.help("The prefix to filter listed keys by"),
)
)
)
.subcommand(
SubCommand::with_name("generate")
Expand Down Expand Up @@ -411,6 +425,11 @@ fn run() -> Result<(), failure::Error> {
let path = delete_matches.value_of("path").unwrap();
commands::kv::delete_bulk(id, Path::new(path))?;
}
("list-keys", Some(list_keys_matches)) => {
let id = list_keys_matches.value_of("id").unwrap();
let prefix = list_keys_matches.value_of("prefix");
commands::kv::list_keys(id, prefix)?;
}
("", None) => message::warn("kv expects a subcommand"),
_ => unreachable!(),
}
Expand Down