mirror of
https://github.com/OMGeeky/google-apis-rs.git
synced 2026-02-23 15:49:49 +01:00
prepare release of version 2.0, regen all APIs
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
[package]
|
||||
|
||||
name = "google-remotebuildexecution2-cli"
|
||||
version = "1.0.14+20200702"
|
||||
version = "2.0.0+20210329"
|
||||
authors = ["Sebastian Thiel <byronimo@gmail.com>"]
|
||||
description = "A complete library to interact with Remote Build Execution (protocol v2)"
|
||||
repository = "https://github.com/Byron/google-apis-rs/tree/master/gen/remotebuildexecution2-cli"
|
||||
@@ -13,33 +13,28 @@ documentation = "http://byron.github.io/google-apis-rs/google_remotebuildexecuti
|
||||
license = "MIT"
|
||||
keywords = ["remotebuildexecution", "google", "cli"]
|
||||
autobins = false
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "remotebuildexecution2"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
hyper-rustls = "^0.6"
|
||||
|
||||
[dependencies]
|
||||
hyper = "^ 0.10"
|
||||
hyper-rustls = "^0.22"
|
||||
mime = "^ 0.2.0"
|
||||
serde = "^ 1.0"
|
||||
serde_json = "^ 1.0"
|
||||
serde_derive = "^ 1.0"
|
||||
yup-oauth2 = { version = "^ 1.0", default-features = false }
|
||||
yup-oauth2 = "^ 5.0"
|
||||
itertools = "^ 0.10"
|
||||
strsim = "^0.5"
|
||||
hyper-rustls = "^0.6"
|
||||
yup-hyper-mock = "^2.0"
|
||||
clap = "^2.0"
|
||||
hyper = { version = "0.14", features = ["full"] }
|
||||
tokio = { version = "^ 1.0", features = ["full"] }
|
||||
|
||||
[features]
|
||||
default = ["openssl"]
|
||||
openssl = ["yup-oauth2/default"]
|
||||
rustls = ["yup-oauth2/no-openssl"]
|
||||
|
||||
|
||||
|
||||
[dependencies.google-remotebuildexecution2]
|
||||
path = "../remotebuildexecution2"
|
||||
version = "1.0.14+20200702"
|
||||
version = "2.0.0+20210329"
|
||||
|
||||
@@ -25,7 +25,7 @@ Find the source code [on github](https://github.com/Byron/google-apis-rs/tree/ma
|
||||
|
||||
# Usage
|
||||
|
||||
This documentation was generated from the *Remote Build Execution* API at revision *20200702*. The CLI is at version *1.0.14*.
|
||||
This documentation was generated from the *Remote Build Execution* API at revision *20210329*. The CLI is at version *2.0.0*.
|
||||
|
||||
```bash
|
||||
remotebuildexecution2 [options]
|
||||
@@ -54,12 +54,6 @@ Configuration:
|
||||
A directory into which we will store our persistent data. Defaults to
|
||||
a user-writable directory that we will create during the first invocation.
|
||||
[default: ~/.google-service-cli]
|
||||
--debug
|
||||
Output all server communication to standard error. `tx` and `rx` are placed
|
||||
into the same stream.
|
||||
--debug-auth
|
||||
Output all communication related to authentication to standard error. `tx`
|
||||
and `rx` are placed into the same stream.
|
||||
|
||||
```
|
||||
|
||||
@@ -112,10 +106,7 @@ Even though the CLI does its best to provide usable error messages, sometimes it
|
||||
what exactly led to a particular issue. This is done by allowing all client-server communication to be
|
||||
output to standard error *as-is*.
|
||||
|
||||
The `--debug` flag will print all client-server communication to standard error, whereas the `--debug-auth` flag
|
||||
will cause all communication related to authentication to standard error.
|
||||
If the `--debug` flag is set, error-results will be debug-printed, possibly yielding more information about the
|
||||
issue at hand.
|
||||
The `--debug` flag will print errors using the `Debug` representation to standard error.
|
||||
|
||||
You may consider redirecting standard error into a file for ease of use, e.g. `remotebuildexecution2 --debug <resource> <method> [options] 2>debug.txt`.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
site_name: Remote Build Execution v1.0.14+20200702
|
||||
site_name: Remote Build Execution v2.0.0+20210329
|
||||
site_url: http://byron.github.io/google-apis-rs/google-remotebuildexecution2-cli
|
||||
site_description: A complete library to interact with Remote Build Execution (protocol v2)
|
||||
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
// COPY OF 'src/rust/cli/cmn.rs'
|
||||
// COPY OF 'src/rust/cli/client.rs'
|
||||
// DO NOT EDIT
|
||||
use oauth2::{ApplicationSecret, ConsoleApplicationSecret, TokenStorage, Token};
|
||||
use clap::{App, SubCommand};
|
||||
use mime::Mime;
|
||||
use oauth2::{ApplicationSecret, ConsoleApplicationSecret};
|
||||
use serde_json as json;
|
||||
use serde_json::value::Value;
|
||||
use mime::Mime;
|
||||
use clap::{App, SubCommand};
|
||||
use strsim;
|
||||
|
||||
use std::fs;
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::{stdout, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use std::io::{Write, Read, stdout};
|
||||
|
||||
use std::default::Default;
|
||||
|
||||
const FIELD_SEP: char = '.';
|
||||
|
||||
|
||||
pub enum ComplexType {
|
||||
Pod,
|
||||
Vec,
|
||||
@@ -83,12 +82,11 @@ pub fn remove_json_null_values(value: &mut Value) {
|
||||
}
|
||||
|
||||
fn did_you_mean<'a>(v: &str, possible_values: &[&'a str]) -> Option<&'a str> {
|
||||
|
||||
let mut candidate: Option<(f64, &str)> = None;
|
||||
for pv in possible_values {
|
||||
let confidence = strsim::jaro_winkler(v, pv);
|
||||
if confidence > 0.8 &&
|
||||
(candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence)) {
|
||||
if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
|
||||
{
|
||||
candidate = Some((confidence, pv));
|
||||
}
|
||||
}
|
||||
@@ -103,10 +101,10 @@ pub enum CallType {
|
||||
Standard,
|
||||
}
|
||||
|
||||
arg_enum!{
|
||||
arg_enum! {
|
||||
pub enum UploadProtocol {
|
||||
Simple,
|
||||
Resumable
|
||||
// Resumable // This seems to be lost during the async conversion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +112,7 @@ impl AsRef<str> for UploadProtocol {
|
||||
fn as_ref(&self) -> &str {
|
||||
match *self {
|
||||
UploadProtocol::Simple => "simple",
|
||||
UploadProtocol::Resumable => "resumable",
|
||||
// UploadProtocol::Resumable => "resumable",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,7 +129,7 @@ impl AsRef<str> for CallType {
|
||||
#[derive(Clone, Default)]
|
||||
pub struct FieldCursor(Vec<String>);
|
||||
|
||||
impl ToString for FieldCursor {
|
||||
impl ToString for FieldCursor {
|
||||
fn to_string(&self) -> String {
|
||||
self.0.join(".")
|
||||
}
|
||||
@@ -208,7 +206,9 @@ impl FieldCursor {
|
||||
fields.truncate(0);
|
||||
}
|
||||
if char_count > 1 && num_conscutive_field_seps == 1 {
|
||||
return Err(CLIError::Field(FieldError::TrailingFieldSep(value.to_string())));
|
||||
return Err(CLIError::Field(FieldError::TrailingFieldSep(
|
||||
value.to_string(),
|
||||
)));
|
||||
}
|
||||
|
||||
self.0 = fields;
|
||||
@@ -257,20 +257,20 @@ impl FieldCursor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_json_value(&self,
|
||||
mut object: &mut Value,
|
||||
value: &str,
|
||||
type_info: JsonTypeInfo,
|
||||
err: &mut InvalidOptionsError,
|
||||
orig_cursor: &FieldCursor) {
|
||||
pub fn set_json_value(
|
||||
&self,
|
||||
mut object: &mut Value,
|
||||
value: &str,
|
||||
type_info: JsonTypeInfo,
|
||||
err: &mut InvalidOptionsError,
|
||||
orig_cursor: &FieldCursor,
|
||||
) {
|
||||
assert!(self.0.len() > 0);
|
||||
|
||||
for field in &self.0[..self.0.len() - 1] {
|
||||
let tmp = object;
|
||||
object = match *tmp {
|
||||
Value::Object(ref mut mapping) => {
|
||||
assure_entry(mapping, &field)
|
||||
}
|
||||
Value::Object(ref mut mapping) => assure_entry(mapping, &field),
|
||||
_ => panic!("We don't expect non-object Values here ..."),
|
||||
};
|
||||
}
|
||||
@@ -278,58 +278,55 @@ impl FieldCursor {
|
||||
match *object {
|
||||
Value::Object(ref mut mapping) => {
|
||||
let field = &self.0[self.0.len() - 1];
|
||||
let to_jval = |value: &str,
|
||||
jtype: JsonType,
|
||||
err: &mut InvalidOptionsError|
|
||||
-> Value {
|
||||
match jtype {
|
||||
JsonType::Boolean =>
|
||||
Value::Bool(arg_from_str(value, err, &field, "boolean")),
|
||||
JsonType::Int =>
|
||||
Value::Number(json::Number::from_f64(arg_from_str(value,
|
||||
err,
|
||||
&field,
|
||||
"int"))
|
||||
.expect("valid f64")),
|
||||
JsonType::Uint =>
|
||||
Value::Number(json::Number::from_f64(arg_from_str(value,
|
||||
err,
|
||||
&field,
|
||||
"uint"))
|
||||
.expect("valid f64")),
|
||||
JsonType::Float =>
|
||||
Value::Number(json::Number::from_f64(arg_from_str(value,
|
||||
err,
|
||||
&field,
|
||||
"float"))
|
||||
.expect("valid f64")),
|
||||
JsonType::String => Value::String(value.to_owned()),
|
||||
}
|
||||
};
|
||||
let to_jval =
|
||||
|value: &str, jtype: JsonType, err: &mut InvalidOptionsError| -> Value {
|
||||
match jtype {
|
||||
JsonType::Boolean => {
|
||||
Value::Bool(arg_from_str(value, err, &field, "boolean"))
|
||||
}
|
||||
JsonType::Int => Value::Number(
|
||||
json::Number::from_f64(arg_from_str(value, err, &field, "int"))
|
||||
.expect("valid f64"),
|
||||
),
|
||||
JsonType::Uint => Value::Number(
|
||||
json::Number::from_f64(arg_from_str(value, err, &field, "uint"))
|
||||
.expect("valid f64"),
|
||||
),
|
||||
JsonType::Float => Value::Number(
|
||||
json::Number::from_f64(arg_from_str(value, err, &field, "float"))
|
||||
.expect("valid f64"),
|
||||
),
|
||||
JsonType::String => Value::String(value.to_owned()),
|
||||
}
|
||||
};
|
||||
|
||||
match type_info.ctype {
|
||||
ComplexType::Pod => {
|
||||
if mapping.insert(field.to_owned(), to_jval(value, type_info.jtype, err))
|
||||
.is_some() {
|
||||
err.issues.push(CLIError::Field(FieldError::Duplicate(orig_cursor.to_string())));
|
||||
if mapping
|
||||
.insert(field.to_owned(), to_jval(value, type_info.jtype, err))
|
||||
.is_some()
|
||||
{
|
||||
err.issues.push(CLIError::Field(FieldError::Duplicate(
|
||||
orig_cursor.to_string(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
ComplexType::Vec => {
|
||||
match *assure_entry(mapping, field) {
|
||||
Value::Array(ref mut values) =>
|
||||
values.push(to_jval(value, type_info.jtype, err)),
|
||||
_ => unreachable!(),
|
||||
ComplexType::Vec => match *assure_entry(mapping, field) {
|
||||
Value::Array(ref mut values) => {
|
||||
values.push(to_jval(value, type_info.jtype, err))
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
ComplexType::Map => {
|
||||
let (key, value) = parse_kv_arg(value, err, true);
|
||||
let jval = to_jval(value.unwrap_or(""), type_info.jtype, err);
|
||||
|
||||
match *assure_entry(mapping, &field) {
|
||||
|
||||
Value::Object(ref mut value_map) => {
|
||||
if value_map.insert(key.to_owned(), jval).is_some() {
|
||||
err.issues.push(CLIError::Field(FieldError::Duplicate(orig_cursor.to_string())));
|
||||
err.issues.push(CLIError::Field(FieldError::Duplicate(
|
||||
orig_cursor.to_string(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -346,12 +343,14 @@ impl FieldCursor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_kv_arg<'a>(kv: &'a str,
|
||||
err: &mut InvalidOptionsError,
|
||||
for_hashmap: bool)
|
||||
-> (&'a str, Option<&'a str>) {
|
||||
pub fn parse_kv_arg<'a>(
|
||||
kv: &'a str,
|
||||
err: &mut InvalidOptionsError,
|
||||
for_hashmap: bool,
|
||||
) -> (&'a str, Option<&'a str>) {
|
||||
let mut add_err = || {
|
||||
err.issues.push(CLIError::InvalidKeyValueSyntax(kv.to_string(), for_hashmap))
|
||||
err.issues
|
||||
.push(CLIError::InvalidKeyValueSyntax(kv.to_string(), for_hashmap))
|
||||
};
|
||||
match kv.find('=') {
|
||||
None => {
|
||||
@@ -369,14 +368,18 @@ pub fn parse_kv_arg<'a>(kv: &'a str,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn calltype_from_str(name: &str,
|
||||
valid_protocols: Vec<String>,
|
||||
err: &mut InvalidOptionsError)
|
||||
-> CallType {
|
||||
pub fn calltype_from_str(
|
||||
name: &str,
|
||||
valid_protocols: Vec<String>,
|
||||
err: &mut InvalidOptionsError,
|
||||
) -> CallType {
|
||||
CallType::Upload(match UploadProtocol::from_str(name) {
|
||||
Ok(up) => up,
|
||||
Err(msg) => {
|
||||
err.issues.push(CLIError::InvalidUploadProtocol(name.to_string(), valid_protocols));
|
||||
err.issues.push(CLIError::InvalidUploadProtocol(
|
||||
name.to_string(),
|
||||
valid_protocols,
|
||||
));
|
||||
UploadProtocol::Simple
|
||||
}
|
||||
})
|
||||
@@ -386,7 +389,10 @@ pub fn input_file_from_opts(file_path: &str, err: &mut InvalidOptionsError) -> O
|
||||
match fs::File::open(file_path) {
|
||||
Ok(f) => Some(f),
|
||||
Err(io_err) => {
|
||||
err.issues.push(CLIError::Input(InputError::Io((file_path.to_string(), io_err))));
|
||||
err.issues.push(CLIError::Input(InputError::Io((
|
||||
file_path.to_string(),
|
||||
io_err,
|
||||
))));
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -396,7 +402,8 @@ pub fn input_mime_from_opts(mime: &str, err: &mut InvalidOptionsError) -> Option
|
||||
match mime.parse() {
|
||||
Ok(m) => Some(m),
|
||||
Err(_) => {
|
||||
err.issues.push(CLIError::Input(InputError::Mime(mime.to_string())));
|
||||
err.issues
|
||||
.push(CLIError::Input(InputError::Mime(mime.to_string())));
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -406,120 +413,42 @@ pub fn writer_from_opts(arg: Option<&str>) -> Result<Box<dyn Write>, io::Error>
|
||||
let f = arg.unwrap_or("-");
|
||||
match f {
|
||||
"-" => Ok(Box::new(stdout())),
|
||||
_ => match fs::OpenOptions::new().create(true).truncate(true).write(true).open(f) {
|
||||
_ => match fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.write(true)
|
||||
.open(f)
|
||||
{
|
||||
Ok(f) => Ok(Box::new(f)),
|
||||
Err(io_err) => Err(io_err),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn arg_from_str<'a, T>(arg: &str,
|
||||
err: &mut InvalidOptionsError,
|
||||
arg_name: &'a str,
|
||||
arg_type: &'a str)
|
||||
-> T
|
||||
where T: FromStr + Default,
|
||||
<T as FromStr>::Err: fmt::Display
|
||||
pub fn arg_from_str<'a, T>(
|
||||
arg: &str,
|
||||
err: &mut InvalidOptionsError,
|
||||
arg_name: &'a str,
|
||||
arg_type: &'a str,
|
||||
) -> T
|
||||
where
|
||||
T: FromStr + Default,
|
||||
<T as FromStr>::Err: fmt::Display,
|
||||
{
|
||||
match FromStr::from_str(arg) {
|
||||
Err(perr) => {
|
||||
err.issues.push(CLIError::ParseError(arg_name.to_owned(),
|
||||
arg_type.to_owned(),
|
||||
arg.to_string(),
|
||||
format!("{}", perr)));
|
||||
err.issues.push(CLIError::ParseError(
|
||||
arg_name.to_owned(),
|
||||
arg_type.to_owned(),
|
||||
arg.to_string(),
|
||||
format!("{}", perr),
|
||||
));
|
||||
Default::default()
|
||||
}
|
||||
Ok(v) => v,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct JsonTokenStorage {
|
||||
pub program_name: &'static str,
|
||||
pub db_dir: String,
|
||||
}
|
||||
|
||||
impl JsonTokenStorage {
|
||||
fn path(&self, scope_hash: u64) -> PathBuf {
|
||||
Path::new(&self.db_dir).join(&format!("{}-token-{}.json", self.program_name, scope_hash))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TokenStorageError {
|
||||
Json(json::Error),
|
||||
Io(io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for TokenStorageError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
TokenStorageError::Json(ref err) => writeln!(f, "Could not serialize secrets: {}", err),
|
||||
TokenStorageError::Io(ref err) => writeln!(f, "Failed to write secret token: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for TokenStorageError {
|
||||
fn description(&self) -> &str {
|
||||
"Failure when getting or setting the token storage"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl TokenStorage for JsonTokenStorage {
|
||||
type Error = TokenStorageError;
|
||||
|
||||
// NOTE: logging might be interesting, currently we swallow all errors
|
||||
fn set(&mut self,
|
||||
scope_hash: u64,
|
||||
_: &Vec<&str>,
|
||||
token: Option<Token>)
|
||||
-> Result<(), TokenStorageError> {
|
||||
match token {
|
||||
None => {
|
||||
match fs::remove_file(self.path(scope_hash)) {
|
||||
Err(err) => match err.kind() {
|
||||
io::ErrorKind::NotFound => Ok(()),
|
||||
_ => Err(TokenStorageError::Io(err)),
|
||||
},
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
Some(token) => {
|
||||
match fs::OpenOptions::new().create(true).write(true).truncate(true).open(&self.path(scope_hash)) {
|
||||
Ok(mut f) => {
|
||||
match json::to_writer_pretty(&mut f, &token) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(serde_err) => Err(TokenStorageError::Json(serde_err)),
|
||||
}
|
||||
}
|
||||
Err(io_err) => Err(TokenStorageError::Io(io_err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, scope_hash: u64, _: &Vec<&str>) -> Result<Option<Token>, TokenStorageError> {
|
||||
match fs::File::open(&self.path(scope_hash)) {
|
||||
Ok(f) => {
|
||||
match json::de::from_reader(f) {
|
||||
Ok(token) => Ok(Some(token)),
|
||||
Err(err) => Err(TokenStorageError::Json(err)),
|
||||
}
|
||||
}
|
||||
Err(io_err) => {
|
||||
match io_err.kind() {
|
||||
io::ErrorKind::NotFound => Ok(None),
|
||||
_ => Err(TokenStorageError::Io(io_err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ApplicationSecretError {
|
||||
DecoderError((String, json::Error)),
|
||||
@@ -529,15 +458,16 @@ pub enum ApplicationSecretError {
|
||||
impl fmt::Display for ApplicationSecretError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
ApplicationSecretError::DecoderError((ref path, ref err)) =>
|
||||
writeln!(f,
|
||||
"Could not decode file at '{}' with error: {}.",
|
||||
path,
|
||||
err),
|
||||
ApplicationSecretError::FormatError(ref path) =>
|
||||
writeln!(f,
|
||||
"'installed' field is unset in secret file at '{}'.",
|
||||
path),
|
||||
ApplicationSecretError::DecoderError((ref path, ref err)) => writeln!(
|
||||
f,
|
||||
"Could not decode file at '{}' with error: {}.",
|
||||
path, err
|
||||
),
|
||||
ApplicationSecretError::FormatError(ref path) => writeln!(
|
||||
f,
|
||||
"'installed' field is unset in secret file at '{}'.",
|
||||
path
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -554,22 +484,23 @@ pub enum ConfigurationError {
|
||||
impl fmt::Display for ConfigurationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) =>
|
||||
writeln!(f,
|
||||
"Directory '{}' could not be created with error: {}.",
|
||||
dir,
|
||||
err),
|
||||
ConfigurationError::DirectoryCreationFailed((ref dir, ref err)) => writeln!(
|
||||
f,
|
||||
"Directory '{}' could not be created with error: {}.",
|
||||
dir, err
|
||||
),
|
||||
ConfigurationError::DirectoryUnset => writeln!(f, "--config-dir was unset or empty."),
|
||||
ConfigurationError::HomeExpansionFailed(ref dir) =>
|
||||
writeln!(f,
|
||||
"Couldn't find HOME directory of current user, failed to expand '{}'.",
|
||||
dir),
|
||||
ConfigurationError::HomeExpansionFailed(ref dir) => writeln!(
|
||||
f,
|
||||
"Couldn't find HOME directory of current user, failed to expand '{}'.",
|
||||
dir
|
||||
),
|
||||
ConfigurationError::Secret(ref err) => writeln!(f, "Secret -> {}", err),
|
||||
ConfigurationError::Io((ref path, ref err)) =>
|
||||
writeln!(f,
|
||||
"IO operation failed on path '{}' with error: {}.",
|
||||
path,
|
||||
err),
|
||||
ConfigurationError::Io((ref path, ref err)) => writeln!(
|
||||
f,
|
||||
"IO operation failed on path '{}' with error: {}.",
|
||||
path, err
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -583,11 +514,11 @@ pub enum InputError {
|
||||
impl fmt::Display for InputError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
InputError::Io((ref file_path, ref io_err)) =>
|
||||
writeln!(f,
|
||||
"Failed to open '{}' for reading with error: {}.",
|
||||
file_path,
|
||||
io_err),
|
||||
InputError::Io((ref file_path, ref io_err)) => writeln!(
|
||||
f,
|
||||
"Failed to open '{}' for reading with error: {}.",
|
||||
file_path, io_err
|
||||
),
|
||||
InputError::Mime(ref mime) => writeln!(f, "'{}' is not a known mime-type.", mime),
|
||||
}
|
||||
}
|
||||
@@ -602,16 +533,17 @@ pub enum FieldError {
|
||||
Empty,
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Display for FieldError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
match *self {
|
||||
FieldError::PopOnEmpty(ref field) =>
|
||||
writeln!(f, "'{}': Cannot move up on empty field cursor.", field),
|
||||
FieldError::TrailingFieldSep(ref field) =>
|
||||
writeln!(f,
|
||||
"'{}': Single field separator may not be last character.",
|
||||
field),
|
||||
FieldError::PopOnEmpty(ref field) => {
|
||||
writeln!(f, "'{}': Cannot move up on empty field cursor.", field)
|
||||
}
|
||||
FieldError::TrailingFieldSep(ref field) => writeln!(
|
||||
f,
|
||||
"'{}': Single field separator may not be last character.",
|
||||
field
|
||||
),
|
||||
FieldError::Unknown(ref field, ref suggestion, ref value) => {
|
||||
let suffix = match *suggestion {
|
||||
Some(ref s) => {
|
||||
@@ -625,14 +557,14 @@ impl fmt::Display for FieldError {
|
||||
};
|
||||
writeln!(f, "Field '{}' does not exist.{}", field, suffix)
|
||||
}
|
||||
FieldError::Duplicate(ref cursor) =>
|
||||
writeln!(f, "Value at '{}' was already set", cursor),
|
||||
FieldError::Duplicate(ref cursor) => {
|
||||
writeln!(f, "Value at '{}' was already set", cursor)
|
||||
}
|
||||
FieldError::Empty => writeln!(f, "Field names must not be empty."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CLIError {
|
||||
Configuration(ConfigurationError),
|
||||
@@ -652,18 +584,17 @@ impl fmt::Display for CLIError {
|
||||
CLIError::Configuration(ref err) => write!(f, "Configuration -> {}", err),
|
||||
CLIError::Input(ref err) => write!(f, "Input -> {}", err),
|
||||
CLIError::Field(ref err) => write!(f, "Field -> {}", err),
|
||||
CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) =>
|
||||
writeln!(f,
|
||||
"'{}' is not a valid upload protocol. Choose from one of {}.",
|
||||
proto_name,
|
||||
valid_names.join(", ")),
|
||||
CLIError::ParseError(ref arg_name, ref type_name, ref value, ref err_desc) =>
|
||||
writeln!(f,
|
||||
"Failed to parse argument '{}' with value '{}' as {} with error: {}.",
|
||||
arg_name,
|
||||
value,
|
||||
type_name,
|
||||
err_desc),
|
||||
CLIError::InvalidUploadProtocol(ref proto_name, ref valid_names) => writeln!(
|
||||
f,
|
||||
"'{}' is not a valid upload protocol. Choose from one of {}.",
|
||||
proto_name,
|
||||
valid_names.join(", ")
|
||||
),
|
||||
CLIError::ParseError(ref arg_name, ref type_name, ref value, ref err_desc) => writeln!(
|
||||
f,
|
||||
"Failed to parse argument '{}' with value '{}' as {} with error: {}.",
|
||||
arg_name, value, type_name, err_desc
|
||||
),
|
||||
CLIError::UnknownParameter(ref param_name, ref possible_values) => {
|
||||
let suffix = match did_you_mean(param_name, &possible_values) {
|
||||
Some(v) => format!(" Did you mean '{}' ?", v),
|
||||
@@ -672,21 +603,19 @@ impl fmt::Display for CLIError {
|
||||
write!(f, "Parameter '{}' is unknown.{}\n", param_name, suffix)
|
||||
}
|
||||
CLIError::InvalidKeyValueSyntax(ref kv, is_hashmap) => {
|
||||
let hashmap_info = if is_hashmap {
|
||||
"hashmap "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
writeln!(f,
|
||||
"'{}' does not match {}pattern <key>=<value>.",
|
||||
kv,
|
||||
hashmap_info)
|
||||
let hashmap_info = if is_hashmap { "hashmap " } else { "" };
|
||||
writeln!(
|
||||
f,
|
||||
"'{}' does not match {}pattern <key>=<value>.",
|
||||
kv, hashmap_info
|
||||
)
|
||||
}
|
||||
CLIError::MissingCommandError => writeln!(f, "Please specify the main sub-command."),
|
||||
CLIError::MissingMethodError(ref cmd) =>
|
||||
writeln!(f,
|
||||
"Please specify the method to call on the '{}' command.",
|
||||
cmd),
|
||||
CLIError::MissingMethodError(ref cmd) => writeln!(
|
||||
f,
|
||||
"Please specify the method to call on the '{}' command.",
|
||||
cmd
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -730,7 +659,11 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> {
|
||||
|
||||
let expanded_config_dir = if trdir.as_bytes()[0] == b'~' {
|
||||
match env::var("HOME").ok().or(env::var("UserProfile").ok()) {
|
||||
None => return Err(CLIError::Configuration(ConfigurationError::HomeExpansionFailed(trdir.to_string()))),
|
||||
None => {
|
||||
return Err(CLIError::Configuration(
|
||||
ConfigurationError::HomeExpansionFailed(trdir.to_string()),
|
||||
))
|
||||
}
|
||||
Some(mut user) => {
|
||||
user.push_str(&trdir[1..]);
|
||||
user
|
||||
@@ -743,21 +676,26 @@ pub fn assure_config_dir_exists(dir: &str) -> Result<String, CLIError> {
|
||||
if let Err(err) = fs::create_dir(&expanded_config_dir) {
|
||||
if err.kind() != io::ErrorKind::AlreadyExists {
|
||||
return Err(CLIError::Configuration(
|
||||
ConfigurationError::DirectoryCreationFailed((expanded_config_dir, err))));
|
||||
ConfigurationError::DirectoryCreationFailed((expanded_config_dir, err)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(expanded_config_dir)
|
||||
}
|
||||
|
||||
pub fn application_secret_from_directory(dir: &str,
|
||||
secret_basename: &str,
|
||||
json_console_secret: &str)
|
||||
-> Result<ApplicationSecret, CLIError> {
|
||||
pub fn application_secret_from_directory(
|
||||
dir: &str,
|
||||
secret_basename: &str,
|
||||
json_console_secret: &str,
|
||||
) -> Result<ApplicationSecret, CLIError> {
|
||||
let secret_path = Path::new(dir).join(secret_basename);
|
||||
let secret_str = || secret_path.as_path().to_str().unwrap().to_string();
|
||||
let secret_io_error = |io_err: io::Error| {
|
||||
Err(CLIError::Configuration(ConfigurationError::Io((secret_str(), io_err))))
|
||||
Err(CLIError::Configuration(ConfigurationError::Io((
|
||||
secret_str(),
|
||||
io_err,
|
||||
))))
|
||||
};
|
||||
|
||||
for _ in 0..2 {
|
||||
@@ -767,18 +705,20 @@ pub fn application_secret_from_directory(dir: &str,
|
||||
// Write our built-in one - user may adjust the written file at will
|
||||
|
||||
err = match fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(&secret_path) {
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(&secret_path)
|
||||
{
|
||||
Err(cfe) => cfe,
|
||||
Ok(mut f) => {
|
||||
// Assure we convert 'ugly' json string into pretty one
|
||||
let console_secret: ConsoleApplicationSecret =
|
||||
json::from_str(json_console_secret).unwrap();
|
||||
match json::to_writer_pretty(&mut f, &console_secret) {
|
||||
Err(serde_err) =>
|
||||
panic!("Unexpected serde error: {:#?}", serde_err),
|
||||
Err(serde_err) => {
|
||||
panic!("Unexpected serde error: {:#?}", serde_err)
|
||||
}
|
||||
Ok(_) => continue,
|
||||
}
|
||||
}
|
||||
@@ -787,24 +727,21 @@ pub fn application_secret_from_directory(dir: &str,
|
||||
}
|
||||
return secret_io_error(err);
|
||||
}
|
||||
Ok(f) => {
|
||||
match json::de::from_reader::<_, ConsoleApplicationSecret>(f) {
|
||||
Err(json_err) =>
|
||||
return Err(CLIError::Configuration(
|
||||
ConfigurationError::Secret(
|
||||
ApplicationSecretError::DecoderError(
|
||||
(secret_str(), json_err)
|
||||
)))),
|
||||
Ok(console_secret) => match console_secret.installed {
|
||||
Some(secret) => return Ok(secret),
|
||||
None => return Err(
|
||||
CLIError::Configuration(
|
||||
ConfigurationError::Secret(
|
||||
ApplicationSecretError::FormatError(secret_str())
|
||||
))),
|
||||
},
|
||||
Ok(f) => match json::de::from_reader::<_, ConsoleApplicationSecret>(f) {
|
||||
Err(json_err) => {
|
||||
return Err(CLIError::Configuration(ConfigurationError::Secret(
|
||||
ApplicationSecretError::DecoderError((secret_str(), json_err)),
|
||||
)))
|
||||
}
|
||||
}
|
||||
Ok(console_secret) => match console_secret.installed {
|
||||
Some(secret) => return Ok(secret),
|
||||
None => {
|
||||
return Err(CLIError::Configuration(ConfigurationError::Secret(
|
||||
ApplicationSecretError::FormatError(secret_str()),
|
||||
)))
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
unreachable!();
|
||||
@@ -3,50 +3,46 @@
|
||||
// DO NOT EDIT !
|
||||
#![allow(unused_variables, unused_imports, dead_code, unused_mut)]
|
||||
|
||||
extern crate tokio;
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
extern crate yup_oauth2 as oauth2;
|
||||
extern crate yup_hyper_mock as mock;
|
||||
extern crate hyper_rustls;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate hyper;
|
||||
extern crate mime;
|
||||
extern crate strsim;
|
||||
extern crate google_remotebuildexecution2 as api;
|
||||
|
||||
use std::env;
|
||||
use std::io::{self, Write};
|
||||
use clap::{App, SubCommand, Arg};
|
||||
|
||||
mod cmn;
|
||||
use google_remotebuildexecution2::{api, Error};
|
||||
|
||||
use cmn::{InvalidOptionsError, CLIError, JsonTokenStorage, arg_from_str, writer_from_opts, parse_kv_arg,
|
||||
mod client;
|
||||
|
||||
use client::{InvalidOptionsError, CLIError, arg_from_str, writer_from_opts, parse_kv_arg,
|
||||
input_file_from_opts, input_mime_from_opts, FieldCursor, FieldError, CallType, UploadProtocol,
|
||||
calltype_from_str, remove_json_null_values, ComplexType, JsonType, JsonTypeInfo};
|
||||
|
||||
use std::default::Default;
|
||||
use std::str::FromStr;
|
||||
|
||||
use oauth2::{Authenticator, DefaultAuthenticatorDelegate, FlowType};
|
||||
use serde_json as json;
|
||||
use clap::ArgMatches;
|
||||
|
||||
enum DoitError {
|
||||
IoError(String, io::Error),
|
||||
ApiError(api::Error),
|
||||
ApiError(Error),
|
||||
}
|
||||
|
||||
struct Engine<'n> {
|
||||
opt: ArgMatches<'n>,
|
||||
hub: api::RemoteBuildExecution<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>,
|
||||
hub: api::RemoteBuildExecution<hyper::Client<hyper_rustls::HttpsConnector<hyper::client::connect::HttpConnector>, hyper::body::Body>
|
||||
>,
|
||||
gp: Vec<&'static str>,
|
||||
gpm: Vec<(&'static str, &'static str)>,
|
||||
}
|
||||
|
||||
|
||||
impl<'n> Engine<'n> {
|
||||
fn _action_results_get(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _action_results_get(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
let mut call = self.hub.action_results().get(opt.value_of("instance-name").unwrap_or(""), opt.value_of("hash").unwrap_or(""), opt.value_of("size-bytes").unwrap_or(""));
|
||||
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
|
||||
@@ -74,7 +70,7 @@ impl<'n> Engine<'n> {
|
||||
err.issues.push(CLIError::UnknownParameter(key.to_string(),
|
||||
{let mut v = Vec::new();
|
||||
v.extend(self.gp.iter().map(|v|*v));
|
||||
v.extend(["inline-output-files", "inline-stderr", "inline-stdout"].iter().map(|v|*v));
|
||||
v.extend(["inline-stdout", "inline-output-files", "inline-stderr"].iter().map(|v|*v));
|
||||
v } ));
|
||||
}
|
||||
}
|
||||
@@ -93,7 +89,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -108,7 +104,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _action_results_update(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _action_results_update(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
@@ -131,23 +127,23 @@ impl<'n> Engine<'n> {
|
||||
|
||||
let type_info: Option<(&'static str, JsonTypeInfo)> =
|
||||
match &temp_cursor.to_string()[..] {
|
||||
"execution-metadata.execution-completed-timestamp" => Some(("executionMetadata.executionCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.execution-start-timestamp" => Some(("executionMetadata.executionStartTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.input-fetch-completed-timestamp" => Some(("executionMetadata.inputFetchCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.input-fetch-start-timestamp" => Some(("executionMetadata.inputFetchStartTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.output-upload-completed-timestamp" => Some(("executionMetadata.outputUploadCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.output-upload-start-timestamp" => Some(("executionMetadata.outputUploadStartTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.worker-completed-timestamp" => Some(("executionMetadata.workerCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.queued-timestamp" => Some(("executionMetadata.queuedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.worker" => Some(("executionMetadata.worker", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.execution-start-timestamp" => Some(("executionMetadata.executionStartTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.input-fetch-start-timestamp" => Some(("executionMetadata.inputFetchStartTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.worker-completed-timestamp" => Some(("executionMetadata.workerCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.worker-start-timestamp" => Some(("executionMetadata.workerStartTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.output-upload-completed-timestamp" => Some(("executionMetadata.outputUploadCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.execution-completed-timestamp" => Some(("executionMetadata.executionCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-metadata.input-fetch-completed-timestamp" => Some(("executionMetadata.inputFetchCompletedTimestamp", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stderr-digest.size-bytes" => Some(("stderrDigest.sizeBytes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stderr-digest.hash" => Some(("stderrDigest.hash", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stdout-raw" => Some(("stdoutRaw", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stderr-raw" => Some(("stderrRaw", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stdout-digest.size-bytes" => Some(("stdoutDigest.sizeBytes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stdout-digest.hash" => Some(("stdoutDigest.hash", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"exit-code" => Some(("exitCode", JsonTypeInfo { jtype: JsonType::Int, ctype: ComplexType::Pod })),
|
||||
"stderr-digest.hash" => Some(("stderrDigest.hash", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stderr-digest.size-bytes" => Some(("stderrDigest.sizeBytes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stderr-raw" => Some(("stderrRaw", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stdout-digest.hash" => Some(("stdoutDigest.hash", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stdout-digest.size-bytes" => Some(("stdoutDigest.sizeBytes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"stdout-raw" => Some(("stdoutRaw", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
_ => {
|
||||
let suggestion = FieldCursor::did_you_mean(key, &vec!["execution-completed-timestamp", "execution-metadata", "execution-start-timestamp", "exit-code", "hash", "input-fetch-completed-timestamp", "input-fetch-start-timestamp", "output-upload-completed-timestamp", "output-upload-start-timestamp", "queued-timestamp", "size-bytes", "stderr-digest", "stderr-raw", "stdout-digest", "stdout-raw", "worker", "worker-completed-timestamp", "worker-start-timestamp"]);
|
||||
err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string()))));
|
||||
@@ -198,7 +194,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -213,7 +209,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _actions_execute(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _actions_execute(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
@@ -236,11 +232,11 @@ impl<'n> Engine<'n> {
|
||||
|
||||
let type_info: Option<(&'static str, JsonTypeInfo)> =
|
||||
match &temp_cursor.to_string()[..] {
|
||||
"action-digest.hash" => Some(("actionDigest.hash", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"action-digest.size-bytes" => Some(("actionDigest.sizeBytes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-policy.priority" => Some(("executionPolicy.priority", JsonTypeInfo { jtype: JsonType::Int, ctype: ComplexType::Pod })),
|
||||
"results-cache-policy.priority" => Some(("resultsCachePolicy.priority", JsonTypeInfo { jtype: JsonType::Int, ctype: ComplexType::Pod })),
|
||||
"skip-cache-lookup" => Some(("skipCacheLookup", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
|
||||
"action-digest.size-bytes" => Some(("actionDigest.sizeBytes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"action-digest.hash" => Some(("actionDigest.hash", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
|
||||
"execution-policy.priority" => Some(("executionPolicy.priority", JsonTypeInfo { jtype: JsonType::Int, ctype: ComplexType::Pod })),
|
||||
_ => {
|
||||
let suggestion = FieldCursor::did_you_mean(key, &vec!["action-digest", "execution-policy", "hash", "priority", "results-cache-policy", "size-bytes", "skip-cache-lookup"]);
|
||||
err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string()))));
|
||||
@@ -287,7 +283,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -302,7 +298,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _blobs_batch_read(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _blobs_batch_read(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
@@ -371,7 +367,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -386,7 +382,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _blobs_batch_update(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _blobs_batch_update(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
@@ -455,7 +451,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -470,7 +466,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _blobs_find_missing(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _blobs_find_missing(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
@@ -539,7 +535,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -554,7 +550,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _blobs_get_tree(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _blobs_get_tree(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
let mut call = self.hub.blobs().get_tree(opt.value_of("instance-name").unwrap_or(""), opt.value_of("hash").unwrap_or(""), opt.value_of("size-bytes").unwrap_or(""));
|
||||
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
|
||||
@@ -579,7 +575,7 @@ impl<'n> Engine<'n> {
|
||||
err.issues.push(CLIError::UnknownParameter(key.to_string(),
|
||||
{let mut v = Vec::new();
|
||||
v.extend(self.gp.iter().map(|v|*v));
|
||||
v.extend(["page-token", "page-size"].iter().map(|v|*v));
|
||||
v.extend(["page-size", "page-token"].iter().map(|v|*v));
|
||||
v } ));
|
||||
}
|
||||
}
|
||||
@@ -598,7 +594,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -613,7 +609,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _methods_get_capabilities(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _methods_get_capabilities(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
let mut call = self.hub.methods().get_capabilities(opt.value_of("instance-name").unwrap_or(""));
|
||||
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
|
||||
@@ -650,7 +646,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -665,7 +661,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _operations_wait_execution(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
async fn _operations_wait_execution(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
|
||||
-> Result<(), DoitError> {
|
||||
|
||||
let mut field_cursor = FieldCursor::default();
|
||||
@@ -734,7 +730,7 @@ impl<'n> Engine<'n> {
|
||||
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
|
||||
};
|
||||
match match protocol {
|
||||
CallType::Standard => call.doit(),
|
||||
CallType::Standard => call.doit().await,
|
||||
_ => unreachable!()
|
||||
} {
|
||||
Err(api_err) => Err(DoitError::ApiError(api_err)),
|
||||
@@ -749,7 +745,7 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
}
|
||||
|
||||
fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> {
|
||||
async fn _doit(&self, dry_run: bool) -> Result<Result<(), DoitError>, Option<InvalidOptionsError>> {
|
||||
let mut err = InvalidOptionsError::new();
|
||||
let mut call_result: Result<(), DoitError> = Ok(());
|
||||
let mut err_opt: Option<InvalidOptionsError> = None;
|
||||
@@ -757,10 +753,10 @@ impl<'n> Engine<'n> {
|
||||
("action-results", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
("get", Some(opt)) => {
|
||||
call_result = self._action_results_get(opt, dry_run, &mut err);
|
||||
call_result = self._action_results_get(opt, dry_run, &mut err).await;
|
||||
},
|
||||
("update", Some(opt)) => {
|
||||
call_result = self._action_results_update(opt, dry_run, &mut err);
|
||||
call_result = self._action_results_update(opt, dry_run, &mut err).await;
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("action-results".to_string()));
|
||||
@@ -771,7 +767,7 @@ impl<'n> Engine<'n> {
|
||||
("actions", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
("execute", Some(opt)) => {
|
||||
call_result = self._actions_execute(opt, dry_run, &mut err);
|
||||
call_result = self._actions_execute(opt, dry_run, &mut err).await;
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("actions".to_string()));
|
||||
@@ -782,16 +778,16 @@ impl<'n> Engine<'n> {
|
||||
("blobs", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
("batch-read", Some(opt)) => {
|
||||
call_result = self._blobs_batch_read(opt, dry_run, &mut err);
|
||||
call_result = self._blobs_batch_read(opt, dry_run, &mut err).await;
|
||||
},
|
||||
("batch-update", Some(opt)) => {
|
||||
call_result = self._blobs_batch_update(opt, dry_run, &mut err);
|
||||
call_result = self._blobs_batch_update(opt, dry_run, &mut err).await;
|
||||
},
|
||||
("find-missing", Some(opt)) => {
|
||||
call_result = self._blobs_find_missing(opt, dry_run, &mut err);
|
||||
call_result = self._blobs_find_missing(opt, dry_run, &mut err).await;
|
||||
},
|
||||
("get-tree", Some(opt)) => {
|
||||
call_result = self._blobs_get_tree(opt, dry_run, &mut err);
|
||||
call_result = self._blobs_get_tree(opt, dry_run, &mut err).await;
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("blobs".to_string()));
|
||||
@@ -802,7 +798,7 @@ impl<'n> Engine<'n> {
|
||||
("methods", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
("get-capabilities", Some(opt)) => {
|
||||
call_result = self._methods_get_capabilities(opt, dry_run, &mut err);
|
||||
call_result = self._methods_get_capabilities(opt, dry_run, &mut err).await;
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("methods".to_string()));
|
||||
@@ -813,7 +809,7 @@ impl<'n> Engine<'n> {
|
||||
("operations", Some(opt)) => {
|
||||
match opt.subcommand() {
|
||||
("wait-execution", Some(opt)) => {
|
||||
call_result = self._operations_wait_execution(opt, dry_run, &mut err);
|
||||
call_result = self._operations_wait_execution(opt, dry_run, &mut err).await;
|
||||
},
|
||||
_ => {
|
||||
err.issues.push(CLIError::MissingMethodError("operations".to_string()));
|
||||
@@ -838,41 +834,26 @@ impl<'n> Engine<'n> {
|
||||
}
|
||||
|
||||
// Please note that this call will fail if any part of the opt can't be handled
|
||||
fn new(opt: ArgMatches<'n>) -> Result<Engine<'n>, InvalidOptionsError> {
|
||||
async fn new(opt: ArgMatches<'n>) -> Result<Engine<'n>, InvalidOptionsError> {
|
||||
let (config_dir, secret) = {
|
||||
let config_dir = match cmn::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) {
|
||||
let config_dir = match client::assure_config_dir_exists(opt.value_of("folder").unwrap_or("~/.google-service-cli")) {
|
||||
Err(e) => return Err(InvalidOptionsError::single(e, 3)),
|
||||
Ok(p) => p,
|
||||
};
|
||||
|
||||
match cmn::application_secret_from_directory(&config_dir, "remotebuildexecution2-secret.json",
|
||||
match client::application_secret_from_directory(&config_dir, "remotebuildexecution2-secret.json",
|
||||
"{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\"client_secret\":\"hCsslbCUyfehWMmbkG8vTYxG\",\"token_uri\":\"https://accounts.google.com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\"620010449518-9ngf7o4dhs0dka470npqvor6dc5lqb9b.apps.googleusercontent.com\",\"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}") {
|
||||
Ok(secret) => (config_dir, secret),
|
||||
Err(e) => return Err(InvalidOptionsError::single(e, 4))
|
||||
}
|
||||
};
|
||||
|
||||
let auth = Authenticator::new( &secret, DefaultAuthenticatorDelegate,
|
||||
if opt.is_present("debug-auth") {
|
||||
hyper::Client::with_connector(mock::TeeConnector {
|
||||
connector: hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
|
||||
})
|
||||
} else {
|
||||
hyper::Client::with_connector(hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new()))
|
||||
},
|
||||
JsonTokenStorage {
|
||||
program_name: "remotebuildexecution2",
|
||||
db_dir: config_dir.clone(),
|
||||
}, Some(FlowType::InstalledRedirect(54324)));
|
||||
let auth = yup_oauth2::InstalledFlowAuthenticator::builder(
|
||||
secret,
|
||||
yup_oauth2::InstalledFlowReturnMethod::HTTPRedirect,
|
||||
).persist_tokens_to_disk(format!("{}/remotebuildexecution2", config_dir)).build().await.unwrap();
|
||||
|
||||
let client =
|
||||
if opt.is_present("debug") {
|
||||
hyper::Client::with_connector(mock::TeeConnector {
|
||||
connector: hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
|
||||
})
|
||||
} else {
|
||||
hyper::Client::with_connector(hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new()))
|
||||
};
|
||||
let client = hyper::Client::builder().build(hyper_rustls::HttpsConnector::with_native_roots());
|
||||
let engine = Engine {
|
||||
opt: opt,
|
||||
hub: api::RemoteBuildExecution::new(client, auth),
|
||||
@@ -888,54 +869,39 @@ impl<'n> Engine<'n> {
|
||||
]
|
||||
};
|
||||
|
||||
match engine._doit(true) {
|
||||
match engine._doit(true).await {
|
||||
Err(Some(err)) => Err(err),
|
||||
Err(None) => Ok(engine),
|
||||
Ok(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn doit(&self) -> Result<(), DoitError> {
|
||||
match self._doit(false) {
|
||||
async fn doit(&self) -> Result<(), DoitError> {
|
||||
match self._doit(false).await {
|
||||
Ok(res) => res,
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let mut exit_status = 0i32;
|
||||
let arg_data = [
|
||||
("action-results", "methods: 'get' and 'update'", vec![
|
||||
("get",
|
||||
Some(r##"Retrieve a cached execution result.
|
||||
|
||||
Implementations SHOULD ensure that any blobs referenced from the
|
||||
ContentAddressableStorage
|
||||
are available at the time of returning the
|
||||
ActionResult and will be
|
||||
for some period of time afterwards. The TTLs of the referenced blobs SHOULD be increased
|
||||
if necessary and applicable.
|
||||
|
||||
Errors:
|
||||
|
||||
* `NOT_FOUND`: The requested `ActionResult` is not in the cache."##),
|
||||
Some(r##"Retrieve a cached execution result. Implementations SHOULD ensure that any blobs referenced from the ContentAddressableStorage are available at the time of returning the ActionResult and will be for some period of time afterwards. The lifetimes of the referenced blobs SHOULD be increased if necessary and applicable. Errors: * `NOT_FOUND`: The requested `ActionResult` is not in the cache."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/action-results_get",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
(Some(r##"hash"##),
|
||||
None,
|
||||
Some(r##"The hash. In the case of SHA-256, it will always be a lowercase hex string
|
||||
exactly 64 characters long."##),
|
||||
Some(r##"The hash. In the case of SHA-256, it will always be a lowercase hex string exactly 64 characters long."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -958,38 +924,18 @@ fn main() {
|
||||
Some(false)),
|
||||
]),
|
||||
("update",
|
||||
Some(r##"Upload a new execution result.
|
||||
|
||||
In order to allow the server to perform access control based on the type of
|
||||
action, and to assist with client debugging, the client MUST first upload
|
||||
the Action that produced the
|
||||
result, along with its
|
||||
Command, into the
|
||||
`ContentAddressableStorage`.
|
||||
|
||||
Errors:
|
||||
|
||||
* `INVALID_ARGUMENT`: One or more arguments are invalid.
|
||||
* `FAILED_PRECONDITION`: One or more errors occurred in updating the
|
||||
action result, such as a missing command or action.
|
||||
* `RESOURCE_EXHAUSTED`: There is insufficient storage space to add the
|
||||
entry to the cache."##),
|
||||
Some(r##"Upload a new execution result. In order to allow the server to perform access control based on the type of action, and to assist with client debugging, the client MUST first upload the Action that produced the result, along with its Command, into the `ContentAddressableStorage`. Server implementations MAY modify the `UpdateActionResultRequest.action_result` and return an equivalent value. Errors: * `INVALID_ARGUMENT`: One or more arguments are invalid. * `FAILED_PRECONDITION`: One or more errors occurred in updating the action result, such as a missing command or action. * `RESOURCE_EXHAUSTED`: There is insufficient storage space to add the entry to the cache."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/action-results_update",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
(Some(r##"hash"##),
|
||||
None,
|
||||
Some(r##"The hash. In the case of SHA-256, it will always be a lowercase hex string
|
||||
exactly 64 characters long."##),
|
||||
Some(r##"The hash. In the case of SHA-256, it will always be a lowercase hex string exactly 64 characters long."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1021,78 +967,12 @@ fn main() {
|
||||
|
||||
("actions", "methods: 'execute'", vec![
|
||||
("execute",
|
||||
Some(r##"Execute an action remotely.
|
||||
|
||||
In order to execute an action, the client must first upload all of the
|
||||
inputs, the
|
||||
Command to run, and the
|
||||
Action into the
|
||||
ContentAddressableStorage.
|
||||
It then calls `Execute` with an `action_digest` referring to them. The
|
||||
server will run the action and eventually return the result.
|
||||
|
||||
The input `Action`'s fields MUST meet the various canonicalization
|
||||
requirements specified in the documentation for their types so that it has
|
||||
the same digest as other logically equivalent `Action`s. The server MAY
|
||||
enforce the requirements and return errors if a non-canonical input is
|
||||
received. It MAY also proceed without verifying some or all of the
|
||||
requirements, such as for performance reasons. If the server does not
|
||||
verify the requirement, then it will treat the `Action` as distinct from
|
||||
another logically equivalent action if they hash differently.
|
||||
|
||||
Returns a stream of
|
||||
google.longrunning.Operation messages
|
||||
describing the resulting execution, with eventual `response`
|
||||
ExecuteResponse. The
|
||||
`metadata` on the operation is of type
|
||||
ExecuteOperationMetadata.
|
||||
|
||||
If the client remains connected after the first response is returned after
|
||||
the server, then updates are streamed as if the client had called
|
||||
WaitExecution
|
||||
until the execution completes or the request reaches an error. The
|
||||
operation can also be queried using Operations
|
||||
API.
|
||||
|
||||
The server NEED NOT implement other methods or functionality of the
|
||||
Operations API.
|
||||
|
||||
Errors discovered during creation of the `Operation` will be reported
|
||||
as gRPC Status errors, while errors that occurred while running the
|
||||
action will be reported in the `status` field of the `ExecuteResponse`. The
|
||||
server MUST NOT set the `error` field of the `Operation` proto.
|
||||
The possible errors include:
|
||||
|
||||
* `INVALID_ARGUMENT`: One or more arguments are invalid.
|
||||
* `FAILED_PRECONDITION`: One or more errors occurred in setting up the
|
||||
action requested, such as a missing input or command or no worker being
|
||||
available. The client may be able to fix the errors and retry.
|
||||
* `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to run
|
||||
the action.
|
||||
* `UNAVAILABLE`: Due to a transient condition, such as all workers being
|
||||
occupied (and the server does not support a queue), the action could not
|
||||
be started. The client should retry.
|
||||
* `INTERNAL`: An internal error occurred in the execution engine or the
|
||||
worker.
|
||||
* `DEADLINE_EXCEEDED`: The execution timed out.
|
||||
* `CANCELLED`: The operation was cancelled by the client. This status is
|
||||
only possible if the server implements the Operations API CancelOperation
|
||||
method, and it was called for the current execution.
|
||||
|
||||
In the case of a missing input or command, the server SHOULD additionally
|
||||
send a PreconditionFailure error detail
|
||||
where, for each requested blob not present in the CAS, there is a
|
||||
`Violation` with a `type` of `MISSING` and a `subject` of
|
||||
`"blobs/{hash}/{size}"` indicating the digest of the missing blob."##),
|
||||
Some(r##"Execute an action remotely. In order to execute an action, the client must first upload all of the inputs, the Command to run, and the Action into the ContentAddressableStorage. It then calls `Execute` with an `action_digest` referring to them. The server will run the action and eventually return the result. The input `Action`'s fields MUST meet the various canonicalization requirements specified in the documentation for their types so that it has the same digest as other logically equivalent `Action`s. The server MAY enforce the requirements and return errors if a non-canonical input is received. It MAY also proceed without verifying some or all of the requirements, such as for performance reasons. If the server does not verify the requirement, then it will treat the `Action` as distinct from another logically equivalent action if they hash differently. Returns a stream of google.longrunning.Operation messages describing the resulting execution, with eventual `response` ExecuteResponse. The `metadata` on the operation is of type ExecuteOperationMetadata. If the client remains connected after the first response is returned after the server, then updates are streamed as if the client had called WaitExecution until the execution completes or the request reaches an error. The operation can also be queried using Operations API. The server NEED NOT implement other methods or functionality of the Operations API. Errors discovered during creation of the `Operation` will be reported as gRPC Status errors, while errors that occurred while running the action will be reported in the `status` field of the `ExecuteResponse`. The server MUST NOT set the `error` field of the `Operation` proto. The possible errors include: * `INVALID_ARGUMENT`: One or more arguments are invalid. * `FAILED_PRECONDITION`: One or more errors occurred in setting up the action requested, such as a missing input or command or no worker being available. The client may be able to fix the errors and retry. * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to run the action. * `UNAVAILABLE`: Due to a transient condition, such as all workers being occupied (and the server does not support a queue), the action could not be started. The client should retry. * `INTERNAL`: An internal error occurred in the execution engine or the worker. * `DEADLINE_EXCEEDED`: The execution timed out. * `CANCELLED`: The operation was cancelled by the client. This status is only possible if the server implements the Operations API CancelOperation method, and it was called for the current execution. In the case of a missing input or command, the server SHOULD additionally send a PreconditionFailure error detail where, for each requested blob not present in the CAS, there is a `Violation` with a `type` of `MISSING` and a `subject` of `"blobs/{hash}/{size}"` indicating the digest of the missing blob. The server does not need to guarantee that a call to this method leads to at most one execution of the action. The server MAY execute the action multiple times, potentially in parallel. These redundant executions MAY continue to run, even if the operation is completed."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/actions_execute",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1118,35 +998,12 @@ fn main() {
|
||||
|
||||
("blobs", "methods: 'batch-read', 'batch-update', 'find-missing' and 'get-tree'", vec![
|
||||
("batch-read",
|
||||
Some(r##"Download many blobs at once.
|
||||
|
||||
The server may enforce a limit of the combined total size of blobs
|
||||
to be downloaded using this API. This limit may be obtained using the
|
||||
Capabilities API.
|
||||
Requests exceeding the limit should either be split into smaller
|
||||
chunks or downloaded using the
|
||||
ByteStream API, as appropriate.
|
||||
|
||||
This request is equivalent to calling a Bytestream `Read` request
|
||||
on each individual blob, in parallel. The requests may succeed or fail
|
||||
independently.
|
||||
|
||||
Errors:
|
||||
|
||||
* `INVALID_ARGUMENT`: The client attempted to read more than the
|
||||
server supported limit.
|
||||
|
||||
Every error on individual read will be returned in the corresponding digest
|
||||
status."##),
|
||||
Some(r##"Download many blobs at once. The server may enforce a limit of the combined total size of blobs to be downloaded using this API. This limit may be obtained using the Capabilities API. Requests exceeding the limit should either be split into smaller chunks or downloaded using the ByteStream API, as appropriate. This request is equivalent to calling a Bytestream `Read` request on each individual blob, in parallel. The requests may succeed or fail independently. Errors: * `INVALID_ARGUMENT`: The client attempted to read more than the server supported limit. Every error on individual read will be returned in the corresponding digest status."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/blobs_batch-read",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1169,39 +1026,12 @@ fn main() {
|
||||
Some(false)),
|
||||
]),
|
||||
("batch-update",
|
||||
Some(r##"Upload many blobs at once.
|
||||
|
||||
The server may enforce a limit of the combined total size of blobs
|
||||
to be uploaded using this API. This limit may be obtained using the
|
||||
Capabilities API.
|
||||
Requests exceeding the limit should either be split into smaller
|
||||
chunks or uploaded using the
|
||||
ByteStream API, as appropriate.
|
||||
|
||||
This request is equivalent to calling a Bytestream `Write` request
|
||||
on each individual blob, in parallel. The requests may succeed or fail
|
||||
independently.
|
||||
|
||||
Errors:
|
||||
|
||||
* `INVALID_ARGUMENT`: The client attempted to upload more than the
|
||||
server supported limit.
|
||||
|
||||
Individual requests may return the following errors, additionally:
|
||||
|
||||
* `RESOURCE_EXHAUSTED`: There is insufficient disk quota to store the blob.
|
||||
* `INVALID_ARGUMENT`: The
|
||||
Digest does not match the
|
||||
provided data."##),
|
||||
Some(r##"Upload many blobs at once. The server may enforce a limit of the combined total size of blobs to be uploaded using this API. This limit may be obtained using the Capabilities API. Requests exceeding the limit should either be split into smaller chunks or uploaded using the ByteStream API, as appropriate. This request is equivalent to calling a Bytestream `Write` request on each individual blob, in parallel. The requests may succeed or fail independently. Errors: * `INVALID_ARGUMENT`: The client attempted to upload more than the server supported limit. Individual requests may return the following errors, additionally: * `RESOURCE_EXHAUSTED`: There is insufficient disk quota to store the blob. * `INVALID_ARGUMENT`: The Digest does not match the provided data."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/blobs_batch-update",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1224,24 +1054,12 @@ fn main() {
|
||||
Some(false)),
|
||||
]),
|
||||
("find-missing",
|
||||
Some(r##"Determine if blobs are present in the CAS.
|
||||
|
||||
Clients can use this API before uploading blobs to determine which ones are
|
||||
already present in the CAS and do not need to be uploaded again.
|
||||
|
||||
Servers SHOULD increase the TTLs of the referenced blobs if necessary and
|
||||
applicable.
|
||||
|
||||
There are no method-specific errors."##),
|
||||
Some(r##"Determine if blobs are present in the CAS. Clients can use this API before uploading blobs to determine which ones are already present in the CAS and do not need to be uploaded again. Servers SHOULD increase the lifetimes of the referenced blobs if necessary and applicable. There are no method-specific errors."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/blobs_find-missing",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1264,45 +1082,18 @@ fn main() {
|
||||
Some(false)),
|
||||
]),
|
||||
("get-tree",
|
||||
Some(r##"Fetch the entire directory tree rooted at a node.
|
||||
|
||||
This request must be targeted at a
|
||||
Directory stored in the
|
||||
ContentAddressableStorage
|
||||
(CAS). The server will enumerate the `Directory` tree recursively and
|
||||
return every node descended from the root.
|
||||
|
||||
The GetTreeRequest.page_token parameter can be used to skip ahead in
|
||||
the stream (e.g. when retrying a partially completed and aborted request),
|
||||
by setting it to a value taken from GetTreeResponse.next_page_token of the
|
||||
last successfully processed GetTreeResponse).
|
||||
|
||||
The exact traversal order is unspecified and, unless retrieving subsequent
|
||||
pages from an earlier request, is not guaranteed to be stable across
|
||||
multiple invocations of `GetTree`.
|
||||
|
||||
If part of the tree is missing from the CAS, the server will return the
|
||||
portion present and omit the rest.
|
||||
|
||||
Errors:
|
||||
|
||||
* `NOT_FOUND`: The requested tree root is not present in the CAS."##),
|
||||
Some(r##"Fetch the entire directory tree rooted at a node. This request must be targeted at a Directory stored in the ContentAddressableStorage (CAS). The server will enumerate the `Directory` tree recursively and return every node descended from the root. The GetTreeRequest.page_token parameter can be used to skip ahead in the stream (e.g. when retrying a partially completed and aborted request), by setting it to a value taken from GetTreeResponse.next_page_token of the last successfully processed GetTreeResponse). The exact traversal order is unspecified and, unless retrieving subsequent pages from an earlier request, is not guaranteed to be stable across multiple invocations of `GetTree`. If part of the tree is missing from the CAS, the server will return the portion present and omit the rest. Errors: * `NOT_FOUND`: The requested tree root is not present in the CAS."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/blobs_get-tree",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
(Some(r##"hash"##),
|
||||
None,
|
||||
Some(r##"The hash. In the case of SHA-256, it will always be a lowercase hex string
|
||||
exactly 64 characters long."##),
|
||||
Some(r##"The hash. In the case of SHA-256, it will always be a lowercase hex string exactly 64 characters long."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1328,23 +1119,12 @@ fn main() {
|
||||
|
||||
("methods", "methods: 'get-capabilities'", vec![
|
||||
("get-capabilities",
|
||||
Some(r##"GetCapabilities returns the server capabilities configuration of the
|
||||
remote endpoint.
|
||||
Only the capabilities of the services supported by the endpoint will
|
||||
be returned:
|
||||
* Execution + CAS + Action Cache endpoints should return both
|
||||
CacheCapabilities and ExecutionCapabilities.
|
||||
* Execution only endpoints should return ExecutionCapabilities.
|
||||
* CAS + Action Cache only endpoints should return CacheCapabilities."##),
|
||||
Some(r##"GetCapabilities returns the server capabilities configuration of the remote endpoint. Only the capabilities of the services supported by the endpoint will be returned: * Execution + CAS + Action Cache endpoints should return both CacheCapabilities and ExecutionCapabilities. * Execution only endpoints should return ExecutionCapabilities. * CAS + Action Cache only endpoints should return CacheCapabilities."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/methods_get-capabilities",
|
||||
vec![
|
||||
(Some(r##"instance-name"##),
|
||||
None,
|
||||
Some(r##"The instance of the execution system to operate against. A server may
|
||||
support multiple instances of the execution system (with their own workers,
|
||||
storage, caches, etc.). The server MAY require use of this field to select
|
||||
between them in an implementation-defined fashion, otherwise it can be
|
||||
omitted."##),
|
||||
Some(r##"The instance of the execution system to operate against. A server may support multiple instances of the execution system (with their own workers, storage, caches, etc.). The server MAY require use of this field to select between them in an implementation-defined fashion, otherwise it can be omitted."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1364,18 +1144,12 @@ fn main() {
|
||||
|
||||
("operations", "methods: 'wait-execution'", vec![
|
||||
("wait-execution",
|
||||
Some(r##"Wait for an execution operation to complete. When the client initially
|
||||
makes the request, the server immediately responds with the current status
|
||||
of the execution. The server will leave the request stream open until the
|
||||
operation completes, and then respond with the completed operation. The
|
||||
server MAY choose to stream additional updates as execution progresses,
|
||||
such as to provide an update as to the state of the execution."##),
|
||||
Some(r##"Wait for an execution operation to complete. When the client initially makes the request, the server immediately responds with the current status of the execution. The server will leave the request stream open until the operation completes, and then respond with the completed operation. The server MAY choose to stream additional updates as execution progresses, such as to provide an update as to the state of the execution."##),
|
||||
"Details at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli/operations_wait-execution",
|
||||
vec![
|
||||
(Some(r##"name"##),
|
||||
None,
|
||||
Some(r##"The name of the Operation
|
||||
returned by Execute."##),
|
||||
Some(r##"The name of the Operation returned by Execute."##),
|
||||
Some(true),
|
||||
Some(false)),
|
||||
|
||||
@@ -1403,7 +1177,7 @@ fn main() {
|
||||
|
||||
let mut app = App::new("remotebuildexecution2")
|
||||
.author("Sebastian Thiel <byronimo@gmail.com>")
|
||||
.version("1.0.14+20200702")
|
||||
.version("2.0.0+20210329")
|
||||
.about("Supplies a Remote Execution API service for tools such as bazel.")
|
||||
.after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_remotebuildexecution2_cli")
|
||||
.arg(Arg::with_name("url")
|
||||
@@ -1418,12 +1192,7 @@ fn main() {
|
||||
.takes_value(true))
|
||||
.arg(Arg::with_name("debug")
|
||||
.long("debug")
|
||||
.help("Output all server communication to standard error. `tx` and `rx` are placed into the same stream.")
|
||||
.multiple(false)
|
||||
.takes_value(false))
|
||||
.arg(Arg::with_name("debug-auth")
|
||||
.long("debug-auth")
|
||||
.help("Output all communication related to authentication to standard error. `tx` and `rx` are placed into the same stream.")
|
||||
.help("Debug print all errors")
|
||||
.multiple(false)
|
||||
.takes_value(false));
|
||||
|
||||
@@ -1471,13 +1240,13 @@ fn main() {
|
||||
let matches = app.get_matches();
|
||||
|
||||
let debug = matches.is_present("debug");
|
||||
match Engine::new(matches) {
|
||||
match Engine::new(matches).await {
|
||||
Err(err) => {
|
||||
exit_status = err.exit_code;
|
||||
writeln!(io::stderr(), "{}", err).ok();
|
||||
},
|
||||
Ok(engine) => {
|
||||
if let Err(doit_err) = engine.doit() {
|
||||
if let Err(doit_err) = engine.doit().await {
|
||||
exit_status = 1;
|
||||
match doit_err {
|
||||
DoitError::IoError(path, err) => {
|
||||
@@ -1496,4 +1265,4 @@ fn main() {
|
||||
}
|
||||
|
||||
std::process::exit(exit_status);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user