Merge pull request #85 from NLnetLabs/issue71_cli_improvements

Issue71 cli improvements
This commit is contained in:
Tim Bruijnzeels
2019-09-25 22:13:37 -07:00
committed by GitHub
11 changed files with 795 additions and 545 deletions
+4
View File
@@ -35,3 +35,7 @@ xml-rs = "0.8.0"
[build-dependencies]
ignore = "^0.4"
[features]
default = []
extra-debug = [ "rpki/extra-debug" ]
+7 -2
View File
@@ -1,10 +1,11 @@
use std::io;
use std::{env, io};
use serde::de::DeserializeOwned;
use serde::Serialize;
use rpki::uri;
use crate::cli::options::KRILL_CLI_API_ENV;
use crate::cli::options::{CaCommand, Command, Options, PublishersCommand, Rfc8181Command};
use crate::cli::report::{ApiResponse, ReportError};
use crate::commons::api::{
@@ -43,6 +44,11 @@ impl KrillClient {
server: options.server,
token: options.token,
};
if options.api {
env::set_var(KRILL_CLI_API_ENV, "1") // this is safe here, because the CLI will exit
}
match options.command {
Command::Health => client.health(),
Command::CertAuth(cmd) => client.certauth(cmd),
@@ -79,7 +85,6 @@ impl KrillClient {
httpclient::post_json(&uri, parent, Some(&self.token))?;
Ok(ApiResponse::Empty)
}
CaCommand::AddChild(handle, req) => {
let uri = format!("api/v1/cas/{}/children", handle);
let uri = self.resolve_uri(&uri);
+684 -532
View File
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -296,6 +296,12 @@ pub enum ErrorCode {
#[display(fmt = "Child cannot have resources not held by parent")]
ChildOverclaims,
#[display(fmt = "Parent with name exists")]
DuplicateParent,
#[display(fmt = "Child unknown")]
UnknownChild,
// 3000s General server errors
#[display(fmt = "Cannot update internal state, issue with work_dir?")]
Persistence,
@@ -348,6 +354,8 @@ impl From<usize> for ErrorCode {
2301 => ErrorCode::DuplicateChild,
2302 => ErrorCode::ChildNeedsResources,
2303 => ErrorCode::ChildOverclaims,
2304 => ErrorCode::DuplicateParent,
2305 => ErrorCode::UnknownChild,
// 3000s -> Server issues, bugs or operational issues
3001 => ErrorCode::Persistence,
@@ -391,6 +399,8 @@ impl Into<ErrorResponse> for ErrorCode {
ErrorCode::DuplicateChild => 2301,
ErrorCode::ChildNeedsResources => 2302,
ErrorCode::ChildOverclaims => 2303,
ErrorCode::DuplicateParent => 2304,
ErrorCode::UnknownChild => 2305,
// server errors
ErrorCode::Persistence => 3001,
@@ -438,7 +448,7 @@ mod tests {
test_code(n)
}
for n in 2301..2304 {
for n in 2301..2306 {
test_code(n)
}
+2 -4
View File
@@ -1040,10 +1040,8 @@ mod tests {
let ncc_id_cer = include_bytes!("../../../test-resources/remote/ncc-id.der");
let ncc_id_cer = IdCert::decode(ncc_id_cer.as_ref()).unwrap();
msg.validate_at(
&ncc_id_cer,
Time::utc(2019, 9, 14, 0, 0, 0)
).unwrap();
msg.validate_at(&ncc_id_cer, Time::utc(2019, 9, 27, 0, 0, 0))
.unwrap();
}
#[test]
+78 -3
View File
@@ -1,6 +1,7 @@
//! Some helper functions for HTTP calls
use std::io::Read;
use std::time::Duration;
use std::{env, fmt};
use bytes::Bytes;
use reqwest::header::{HeaderMap, HeaderValue, InvalidHeaderValue, CONTENT_TYPE, USER_AGENT};
@@ -8,14 +9,74 @@ use reqwest::{Client, Response, StatusCode};
use serde::de::DeserializeOwned;
use serde::Serialize;
use crate::cli::options::KRILL_CLI_API_ENV;
use crate::commons::api::{ErrorResponse, Token};
const JSON_CONTENT: &str = "application/json";
fn report_get(uri: &str, content_type: Option<&str>, token: Option<&Token>) {
if env::var(KRILL_CLI_API_ENV).is_ok() {
println!("GET: {}", uri);
if let Some(content_type) = content_type {
println!("Headers: content-type: {}", content_type);
}
if let Some(token) = token {
println!("Headers: Bearer: {}", token);
}
std::process::exit(0);
}
}
enum PostBody<'a> {
String(&'a String),
Bytes(&'a Vec<u8>),
}
impl<'a> fmt::Display for PostBody<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
PostBody::String(string) => write!(f, "{}", string),
PostBody::Bytes(bytes) => {
let base64 = base64::encode(bytes);
write!(f, "<binary content, base64 encoded for display here> {}", base64)
}
}
}
}
fn report_post(uri: &str, content_type: Option<&str>, token: Option<&Token>, body: PostBody) {
if env::var(KRILL_CLI_API_ENV).is_ok() {
println!("POST: {}", uri);
if let Some(content_type) = content_type {
println!("Headers: content-type: {}", content_type);
}
if let Some(token) = token {
println!("Headers: Bearer: {}", token);
}
println!("Body: {}", body);
std::process::exit(0);
}
}
fn report_delete(uri: &str, content_type: Option<&str>, token: Option<&Token>) {
if env::var(KRILL_CLI_API_ENV).is_ok() {
println!("DELETE: {}", uri);
if let Some(content_type) = content_type {
println!("Headers: content-type: {}", content_type);
}
if let Some(token) = token {
println!("Headers: Bearer: {}", token);
}
std::process::exit(0);
}
}
/// Performs a GET request that expects a json response that can be
/// deserialized into the an owned value of the expected type. Returns an error
/// if nothing is returned.
pub fn get_json<T: DeserializeOwned>(uri: &str, token: Option<&Token>) -> Result<T, Error> {
report_get(uri, None, token);
let headers = headers(Some(JSON_CONTENT), token)?;
let res = client(uri)?.get(uri).headers(headers).send()?;
process_json_response(res)
@@ -24,6 +85,8 @@ pub fn get_json<T: DeserializeOwned>(uri: &str, token: Option<&Token>) -> Result
/// Performs a get request and expects a response that can be turned
/// into a string (in particular, not a binary response).
pub fn get_text(uri: &str, content_type: &str, token: Option<&Token>) -> Result<String, Error> {
report_get(uri, Some(content_type), token);
let headers = headers(Some(content_type), token)?;
let res = client(uri)?.get(uri).headers(headers).send()?;
match opt_text_response(res)? {
@@ -35,6 +98,8 @@ pub fn get_text(uri: &str, content_type: &str, token: Option<&Token>) -> Result<
/// Checks that there is a 200 OK response at the given URI. Discards the
/// response body.
pub fn get_ok(uri: &str, token: Option<&Token>) -> Result<(), Error> {
report_get(uri, None, token);
let headers = headers(None, token)?;
let res = client(uri)?.get(uri).headers(headers).send()?;
opt_text_response(res)?; // Will return nice errors with possible body.
@@ -44,8 +109,11 @@ pub fn get_ok(uri: &str, token: Option<&Token>) -> Result<(), Error> {
/// Performs a POST of data that can be serialized into json, and expects
/// a 200 OK response, without a body.
pub fn post_json(uri: &str, data: impl Serialize, token: Option<&Token>) -> Result<(), Error> {
let headers = headers(Some(JSON_CONTENT), token)?;
let body = serde_json::to_string(&data)?;
report_post(uri, None, token, PostBody::String(&body));
let headers = headers(Some(JSON_CONTENT), token)?;
let res = client(uri)?.post(uri).headers(headers).body(body).send()?;
if let Some(res) = opt_text_response(res)? {
Err(Error::UnexpectedResponse(res))
@@ -62,14 +130,18 @@ pub fn post_json_with_response<T: DeserializeOwned>(
data: impl Serialize,
token: Option<&Token>,
) -> Result<T, Error> {
let headers = headers(Some(JSON_CONTENT), token)?;
let body = serde_json::to_string(&data)?;
report_post(uri, None, token, PostBody::String(&body));
let headers = headers(Some(JSON_CONTENT), token)?;
let res = client(uri)?.post(uri).headers(headers).body(body).send()?;
process_json_response(res)
}
/// Performs a POST with no data to the given URI and expects and empty 200 OK response.
pub fn post_empty(uri: &str, token: Option<&Token>) -> Result<(), Error> {
report_post(uri, None, token, PostBody::String(&"<empty>".to_string()));
let headers = headers(Some(JSON_CONTENT), token)?;
let res = client(uri)?.post(uri).headers(headers).send()?;
if let Some(res) = opt_text_response(res)? {
@@ -84,9 +156,10 @@ pub fn post_empty(uri: &str, token: Option<&Token>) -> Result<(), Error> {
/// Note: Bytes may be empty if the post was successful, but the response was
/// empty.
pub fn post_binary(uri: &str, data: &Bytes, content_type: &str) -> Result<Bytes, Error> {
let headers = headers(Some(content_type), None)?;
let body = data.to_vec();
report_post(uri, None, None, PostBody::Bytes(&body));
let headers = headers(Some(content_type), None)?;
let mut res = client(uri)?.post(uri).headers(headers).body(body).send()?;
match res.status() {
@@ -111,6 +184,8 @@ pub fn post_binary(uri: &str, data: &Bytes, content_type: &str) -> Result<Bytes,
/// Sends a delete request to the specified url.
pub fn delete(uri: &str, token: Option<&Token>) -> Result<(), Error> {
report_delete(uri, None, token);
let headers = headers(None, token)?;
client(uri)?.delete(uri).headers(headers).send()?;
Ok(())
+3 -3
View File
@@ -2,6 +2,7 @@ use std::fs::File;
use std::io;
use std::io::Read;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::env;
use std::path::PathBuf;
use std::str::FromStr;
@@ -32,7 +33,7 @@ impl ConfigDefaults {
3000
}
fn use_ta() -> bool {
false
env::var("KRILL_USE_TA").is_ok()
}
fn use_ssl() -> SslChoice {
SslChoice::Test
@@ -59,7 +60,6 @@ impl ConfigDefaults {
PathBuf::from("./krill.log")
}
fn auth_token() -> Token {
use std::env;
match env::var("KRILL_AUTH_TOKEN") {
Ok(token) => Token::from(token),
@@ -229,7 +229,7 @@ impl Config {
let config_file = matches
.value_of("config")
.unwrap_or("./daemon/defaults/krill.conf");
.unwrap_or("./defaults/krill.conf");
let c = Self::read_config(config_file)?;
c.init_logging()?;
+6
View File
@@ -535,6 +535,8 @@ impl ErrorToStatus for ca::ServerError<OpenSslSigner> {
fn status(&self) -> StatusCode {
match self {
ca::ServerError::CertAuth(e) => e.status(),
ca::ServerError::DuplicateCa(_) => StatusCode::BAD_REQUEST,
ca::ServerError::UnknownCa(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
@@ -620,6 +622,8 @@ impl ToErrorCode for ca::ServerError<OpenSslSigner> {
fn code(&self) -> ErrorCode {
match self {
ca::ServerError::CertAuth(e) => e.code(),
ca::ServerError::DuplicateCa(_) => ErrorCode::DuplicateChild,
ca::ServerError::UnknownCa(_) => ErrorCode::UnknownChild,
_ => ErrorCode::CaServerError,
}
}
@@ -629,8 +633,10 @@ impl ToErrorCode for ca::Error {
fn code(&self) -> ErrorCode {
match self {
ca::Error::DuplicateChild(_) => ErrorCode::DuplicateChild,
ca::Error::UnknownChild(_) => ErrorCode::UnknownChild,
ca::Error::MustHaveResources => ErrorCode::ChildNeedsResources,
ca::Error::MissingResources => ErrorCode::ChildOverclaims,
ca::Error::DuplicateParent(_) => ErrorCode::DuplicateParent,
_ => ErrorCode::CaServerError,
}
}
Binary file not shown.