-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial parsec-tool implementation
Signed-off-by: Joe Ellis <[email protected]>
- Loading branch information
Joe Ellis
committed
Aug 5, 2020
1 parent
a3f8a55
commit a0a9ebd
Showing
16 changed files
with
1,575 additions
and
32 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
"ionut-arm", | ||
"justincormack", | ||
"paulhowardarm", | ||
"joechrisellis", | ||
] | ||
|
||
[people] | ||
|
@@ -43,3 +44,7 @@ | |
Email = "[email protected]" | ||
GitHub = "paulhowardarm" | ||
|
||
[people.joechrisellis] | ||
Name = "Joe Ellis" | ||
Email = "[email protected]" | ||
GitHub = "joechrisellis" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Base CLI implementation. | ||
use crate::common::{PROJECT_AUTHOR, PROJECT_DESC, PROJECT_NAME, PROJECT_VERSION}; | ||
use crate::error::ParsecToolError; | ||
use crate::subcommands::{ParsecToolSubcommand, Subcommand}; | ||
use parsec_client::auth::AuthenticationData; | ||
use structopt::StructOpt; | ||
|
||
/// Struct representing the command-line interface of parsec-tool. | ||
#[derive(Debug, StructOpt)] | ||
#[structopt(name=PROJECT_NAME, about=PROJECT_DESC, author=PROJECT_AUTHOR, version=PROJECT_VERSION)] | ||
pub struct ParsecToolApp { | ||
/// How verbose should we be? | ||
#[structopt(short = "v", multiple = true, default_value = "0")] | ||
pub verbosity: u8, | ||
|
||
/// Sets the authentication secret -- will default to no authentication if unspecified. | ||
#[structopt(short = "a", long = "auth-secret")] | ||
pub auth_secret: Option<String>, | ||
|
||
/// The subcommand -- e.g., ping. | ||
#[structopt(subcommand)] | ||
pub subcommand: Subcommand, | ||
} | ||
|
||
impl ParsecToolApp { | ||
/// Run the requested subcommand. | ||
pub fn dispatch_subcommand(&self) -> Result<(), ParsecToolError> { | ||
match &self.subcommand { | ||
Subcommand::Ping(cmd) => cmd.run(self), | ||
Subcommand::ListProviders(cmd) => cmd.run(self), | ||
Subcommand::ListOpcodes(cmd) => cmd.run(self), | ||
} | ||
} | ||
|
||
/// Given an optional string, generate the corresponding AuthenticationData instance. This is | ||
/// effectively a `FromStr` implementation for AuthenticationData. Passing in `None` will return | ||
/// AuthenticationData::None. Passing in `Some(s)` will give you an app identity whose secret is | ||
/// built from the string `s`. | ||
pub fn authentication_data(&self) -> AuthenticationData { | ||
match &self.auth_secret { | ||
None => AuthenticationData::None, | ||
Some(s) => AuthenticationData::AppIdentity(secrecy::Secret::new(s.into())), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Common variables. | ||
/// The project name from Cargo. | ||
pub const PROJECT_NAME: &str = env!("CARGO_PKG_NAME"); | ||
|
||
/// The project description from Cargo. | ||
pub const PROJECT_DESC: &str = env!("CARGO_PKG_DESCRIPTION"); | ||
|
||
/// The project author from Cargo. | ||
pub const PROJECT_AUTHOR: &str = env!("CARGO_PKG_AUTHORS"); | ||
|
||
/// The project version from Cargo. | ||
pub const PROJECT_VERSION: &str = env!("CARGO_PKG_VERSION"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Error definitions/handling. | ||
use parsec_interface::operations::NativeResult; | ||
use thiserror::Error; | ||
|
||
/// Errors in parsec-tool. | ||
#[derive(Error, Debug)] | ||
pub enum ParsecToolError { | ||
/// Error emanating from the parsec_client crate. | ||
#[error(transparent)] | ||
ParsecClientError(#[from] parsec_client::error::Error), | ||
|
||
/// Error emanating from the parsec_interface crate. | ||
#[error(transparent)] | ||
ParsecInterfaceError(#[from] parsec_interface::requests::ResponseStatus), | ||
|
||
/// Unexpected native result error, for when we expected a particular type of result but get | ||
/// something else. | ||
#[error("Got an unexpected native result: {0:?}")] | ||
UnexpectedNativeResult(NativeResult), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Source code for the `parsec-tool` project. This is a command-line interface for interacting | ||
//! with the Parsec service. | ||
#![deny( | ||
nonstandard_style, | ||
const_err, | ||
dead_code, | ||
improper_ctypes, | ||
non_shorthand_field_patterns, | ||
no_mangle_generic_items, | ||
overflowing_literals, | ||
path_statements, | ||
patterns_in_fns_without_body, | ||
private_in_public, | ||
unconditional_recursion, | ||
unused, | ||
unused_allocation, | ||
unused_comparisons, | ||
unused_parens, | ||
while_true, | ||
missing_debug_implementations, | ||
missing_docs, | ||
trivial_casts, | ||
trivial_numeric_casts, | ||
unused_extern_crates, | ||
unused_import_braces, | ||
unused_qualifications, | ||
unused_results, | ||
missing_copy_implementations | ||
)] | ||
// This one is hard to avoid. | ||
#![allow(clippy::multiple_crate_versions)] | ||
|
||
#[macro_use] | ||
pub mod util; | ||
|
||
pub mod cli; | ||
pub mod common; | ||
pub mod error; | ||
pub mod subcommands; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,26 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#![deny( | ||
nonstandard_style, | ||
const_err, | ||
dead_code, | ||
improper_ctypes, | ||
non_shorthand_field_patterns, | ||
no_mangle_generic_items, | ||
overflowing_literals, | ||
path_statements, | ||
patterns_in_fns_without_body, | ||
private_in_public, | ||
unconditional_recursion, | ||
unused, | ||
unused_allocation, | ||
unused_comparisons, | ||
unused_parens, | ||
while_true, | ||
missing_debug_implementations, | ||
missing_docs, | ||
trivial_casts, | ||
trivial_numeric_casts, | ||
unused_extern_crates, | ||
unused_import_braces, | ||
unused_qualifications, | ||
unused_results, | ||
missing_copy_implementations | ||
)] | ||
// This one is hard to avoid. | ||
#![allow(clippy::multiple_crate_versions)] | ||
//! parsec-tool: a tool for interfacing with the Parsec service from the command-line. | ||
//! Parsec Tool: a tool to communicate with Parsec from the command-line | ||
use parsec_tool::err; | ||
|
||
use anyhow::Context; | ||
use anyhow::Result; | ||
use parsec_tool::cli; | ||
use structopt::StructOpt; | ||
|
||
fn run() -> Result<()> { | ||
let matches = cli::ParsecToolApp::from_args(); | ||
matches | ||
.dispatch_subcommand() | ||
.context("Executing subcommand failed.")?; | ||
Ok(()) | ||
} | ||
|
||
fn main() { | ||
println!("Hello, Parsec!"); | ||
if let Err(err) = run() { | ||
err!("{:?}", err); | ||
std::process::exit(1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Common facilities and options for subcommands. | ||
use structopt::StructOpt; | ||
|
||
/// Options for specifying a provider. Most, but not all subcommands require the user to do this, | ||
/// so it's useful to have these options shared. | ||
#[derive(Copy, Clone, Debug, StructOpt)] | ||
pub struct ProviderOpts { | ||
/// The provider to list opcodes for. | ||
#[structopt(short = "p", long = "provider", default_value = "0")] | ||
pub provider: u8, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Lists the supported opcodes for a given provider. | ||
use crate::cli::ParsecToolApp; | ||
use crate::error::ParsecToolError; | ||
use crate::subcommands::common::ProviderOpts; | ||
use crate::subcommands::ParsecToolSubcommand; | ||
use parsec_client::core::interface::requests::ProviderID; | ||
use parsec_client::core::operation_client::OperationClient; | ||
use parsec_interface::operations::list_opcodes; | ||
use parsec_interface::operations::{NativeOperation, NativeResult}; | ||
use std::convert::TryFrom; | ||
use structopt::StructOpt; | ||
|
||
/// Lists the supported opcodes for a given provider. | ||
#[derive(Copy, Clone, Debug, StructOpt)] | ||
#[structopt(name = "list_opcodes")] | ||
pub struct ListOpcodesSubcommand { | ||
#[structopt(flatten)] | ||
provider_opts: ProviderOpts, | ||
} | ||
|
||
impl TryFrom<ListOpcodesSubcommand> for NativeOperation { | ||
type Error = ParsecToolError; | ||
|
||
fn try_from(list_opcodes_subcommand: ListOpcodesSubcommand) -> Result<Self, Self::Error> { | ||
// Trivially converted to a `NativeOperation`. | ||
Ok(NativeOperation::ListOpcodes(list_opcodes::Operation { | ||
provider_id: ProviderID::try_from(list_opcodes_subcommand.provider_opts.provider)?, | ||
})) | ||
} | ||
} | ||
|
||
impl ParsecToolSubcommand for ListOpcodesSubcommand { | ||
/// Lists the supported opcodes for a given provider. | ||
fn run(&self, matches: &ParsecToolApp) -> Result<(), ParsecToolError> { | ||
let client = OperationClient::new(); | ||
let native_result = client.process_operation( | ||
NativeOperation::try_from(*self)?, | ||
// We still use the core provider beacuse listing opcodes is a core operation. Note the | ||
// distinction between the provider we're _using_ and the provider we're querying. | ||
ProviderID::Core, | ||
&matches.authentication_data(), | ||
)?; | ||
|
||
if let NativeResult::ListOpcodes(result) = native_result { | ||
info!( | ||
"Available opcodes for provider {:?}:", | ||
ProviderID::try_from(self.provider_opts.provider)? | ||
); | ||
for provider_opcode in result.opcodes { | ||
eprint_colored!(Blue, "*"); | ||
eprintln!(" {:?}", provider_opcode); | ||
} | ||
Ok(()) | ||
} else { | ||
Err(ParsecToolError::UnexpectedNativeResult(native_result)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Lists the available providers supported by the Parsec service. | ||
pub use crate::cli::ParsecToolApp; | ||
use crate::error::ParsecToolError; | ||
use crate::subcommands::ParsecToolSubcommand; | ||
use parsec_client::core::interface::requests::ProviderID; | ||
use parsec_client::core::operation_client::OperationClient; | ||
use parsec_interface::operations::list_providers; | ||
use parsec_interface::operations::{NativeOperation, NativeResult}; | ||
use std::convert::TryFrom; | ||
use structopt::StructOpt; | ||
|
||
/// Lists the available providers supported by the Parsec service. | ||
#[derive(Copy, Clone, Debug, StructOpt)] | ||
#[structopt(name = "list_providers")] | ||
pub struct ListProvidersSubcommand {} | ||
|
||
impl TryFrom<ListProvidersSubcommand> for NativeOperation { | ||
type Error = ParsecToolError; | ||
|
||
fn try_from(_list_providers_subcommand: ListProvidersSubcommand) -> Result<Self, Self::Error> { | ||
// Trivially converted to a `NativeOperation`. | ||
Ok(NativeOperation::ListProviders(list_providers::Operation {})) | ||
} | ||
} | ||
|
||
impl ParsecToolSubcommand for ListProvidersSubcommand { | ||
/// Lists the available providers supported by the Parsec service. | ||
fn run(&self, matches: &ParsecToolApp) -> Result<(), ParsecToolError> { | ||
let client = OperationClient::new(); | ||
let native_result = client.process_operation( | ||
NativeOperation::try_from(*self)?, | ||
ProviderID::Core, | ||
&matches.authentication_data(), | ||
)?; | ||
|
||
if let NativeResult::ListProviders(result) = native_result { | ||
info!("Available providers:"); | ||
for provider in result.providers { | ||
title!("0x{:02x} ({})", provider.id as u32, provider.id); | ||
field!("Description", "{}", provider.description); | ||
field!( | ||
"Version", | ||
"{}.{}.{}", | ||
provider.version_maj, | ||
provider.version_min, | ||
provider.version_rev | ||
); | ||
field!( | ||
"Vendor", | ||
"{}", | ||
if !provider.vendor.is_empty() { | ||
provider.vendor | ||
} else { | ||
"Unspecified".to_string() | ||
}, | ||
); | ||
field!("Vendor", "{}", provider.uuid); | ||
println!(); | ||
} | ||
Ok(()) | ||
} else { | ||
Err(ParsecToolError::UnexpectedNativeResult(native_result)) | ||
} | ||
} | ||
} |
Oops, something went wrong.