prepare release of version 2.0, regen all APIs

This commit is contained in:
Sebastian Thiel
2021-04-01 23:46:26 +08:00
parent f1c05f2554
commit c606d37dd3
3415 changed files with 3620084 additions and 2930380 deletions

View File

@@ -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!();

View File

@@ -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_cloudasset1 as api;
use std::env;
use std::io::{self, Write};
use clap::{App, SubCommand, Arg};
mod cmn;
use google_cloudasset1::{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::CloudAsset<hyper::Client, Authenticator<DefaultAuthenticatorDelegate, JsonTokenStorage, hyper::Client>>,
hub: api::CloudAsset<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 _feeds_create(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _feeds_create(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut field_cursor = FieldCursor::default();
@@ -69,14 +65,18 @@ impl<'n> Engine<'n> {
let type_info: Option<(&'static str, JsonTypeInfo)> =
match &temp_cursor.to_string()[..] {
"feed.asset-types" => Some(("feed.assetTypes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"feed.asset-names" => Some(("feed.assetNames", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"feed.asset-types" => Some(("feed.assetTypes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"feed.condition.description" => Some(("feed.condition.description", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.condition.expression" => Some(("feed.condition.expression", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.condition.location" => Some(("feed.condition.location", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.condition.title" => Some(("feed.condition.title", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.content-type" => Some(("feed.contentType", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.name" => Some(("feed.name", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.feed-output-config.pubsub-destination.topic" => Some(("feed.feedOutputConfig.pubsubDestination.topic", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.name" => Some(("feed.name", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed-id" => Some(("feedId", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
_ => {
let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-names", "asset-types", "content-type", "feed", "feed-id", "feed-output-config", "name", "pubsub-destination", "topic"]);
let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-names", "asset-types", "condition", "content-type", "description", "expression", "feed", "feed-id", "feed-output-config", "location", "name", "pubsub-destination", "title", "topic"]);
err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string()))));
None
}
@@ -121,7 +121,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)),
@@ -136,7 +136,7 @@ impl<'n> Engine<'n> {
}
}
fn _feeds_delete(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _feeds_delete(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.feeds().delete(opt.value_of("name").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
@@ -173,7 +173,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)),
@@ -188,7 +188,7 @@ impl<'n> Engine<'n> {
}
}
fn _feeds_get(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _feeds_get(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.feeds().get(opt.value_of("name").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
@@ -225,7 +225,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)),
@@ -240,7 +240,7 @@ impl<'n> Engine<'n> {
}
}
fn _feeds_list(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _feeds_list(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.feeds().list(opt.value_of("parent").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
@@ -277,7 +277,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)),
@@ -292,7 +292,7 @@ impl<'n> Engine<'n> {
}
}
fn _feeds_patch(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _feeds_patch(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut field_cursor = FieldCursor::default();
@@ -315,14 +315,18 @@ impl<'n> Engine<'n> {
let type_info: Option<(&'static str, JsonTypeInfo)> =
match &temp_cursor.to_string()[..] {
"feed.asset-types" => Some(("feed.assetTypes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"feed.asset-names" => Some(("feed.assetNames", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"feed.asset-types" => Some(("feed.assetTypes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"feed.condition.description" => Some(("feed.condition.description", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.condition.expression" => Some(("feed.condition.expression", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.condition.location" => Some(("feed.condition.location", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.condition.title" => Some(("feed.condition.title", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.content-type" => Some(("feed.contentType", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.name" => Some(("feed.name", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.feed-output-config.pubsub-destination.topic" => Some(("feed.feedOutputConfig.pubsubDestination.topic", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"feed.name" => Some(("feed.name", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"update-mask" => Some(("updateMask", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
_ => {
let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-names", "asset-types", "content-type", "feed", "feed-output-config", "name", "pubsub-destination", "topic", "update-mask"]);
let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-names", "asset-types", "condition", "content-type", "description", "expression", "feed", "feed-output-config", "location", "name", "pubsub-destination", "title", "topic", "update-mask"]);
err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string()))));
None
}
@@ -367,7 +371,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)),
@@ -382,7 +386,193 @@ impl<'n> Engine<'n> {
}
}
fn _methods_batch_get_assets_history(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _methods_analyze_iam_policy(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.methods().analyze_iam_policy(opt.value_of("scope").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
let (key, value) = parse_kv_arg(&*parg, err, false);
match key {
"execution-timeout" => {
call = call.execution_timeout(value.unwrap_or(""));
},
"analysis-query-resource-selector-full-resource-name" => {
call = call.analysis_query_resource_selector_full_resource_name(value.unwrap_or(""));
},
"analysis-query-options-output-resource-edges" => {
call = call.analysis_query_options_output_resource_edges(arg_from_str(value.unwrap_or("false"), err, "analysis-query-options-output-resource-edges", "boolean"));
},
"analysis-query-options-output-group-edges" => {
call = call.analysis_query_options_output_group_edges(arg_from_str(value.unwrap_or("false"), err, "analysis-query-options-output-group-edges", "boolean"));
},
"analysis-query-options-expand-roles" => {
call = call.analysis_query_options_expand_roles(arg_from_str(value.unwrap_or("false"), err, "analysis-query-options-expand-roles", "boolean"));
},
"analysis-query-options-expand-resources" => {
call = call.analysis_query_options_expand_resources(arg_from_str(value.unwrap_or("false"), err, "analysis-query-options-expand-resources", "boolean"));
},
"analysis-query-options-expand-groups" => {
call = call.analysis_query_options_expand_groups(arg_from_str(value.unwrap_or("false"), err, "analysis-query-options-expand-groups", "boolean"));
},
"analysis-query-options-analyze-service-account-impersonation" => {
call = call.analysis_query_options_analyze_service_account_impersonation(arg_from_str(value.unwrap_or("false"), err, "analysis-query-options-analyze-service-account-impersonation", "boolean"));
},
"analysis-query-identity-selector-identity" => {
call = call.analysis_query_identity_selector_identity(value.unwrap_or(""));
},
"analysis-query-access-selector-roles" => {
call = call.add_analysis_query_access_selector_roles(value.unwrap_or(""));
},
"analysis-query-access-selector-permissions" => {
call = call.add_analysis_query_access_selector_permissions(value.unwrap_or(""));
},
_ => {
let mut found = false;
for param in &self.gp {
if key == *param {
found = true;
call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset"));
break;
}
}
if !found {
err.issues.push(CLIError::UnknownParameter(key.to_string(),
{let mut v = Vec::new();
v.extend(self.gp.iter().map(|v|*v));
v.extend(["analysis-query-identity-selector-identity", "execution-timeout", "analysis-query-options-output-group-edges", "analysis-query-resource-selector-full-resource-name", "analysis-query-access-selector-permissions", "analysis-query-options-analyze-service-account-impersonation", "analysis-query-options-output-resource-edges", "analysis-query-options-expand-groups", "analysis-query-options-expand-resources", "analysis-query-options-expand-roles", "analysis-query-access-selector-roles"].iter().map(|v|*v));
v } ));
}
}
}
}
let protocol = CallType::Standard;
if dry_run {
Ok(())
} else {
assert!(err.issues.len() == 0);
for scope in self.opt.values_of("url").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
call = call.add_scope(scope);
}
let mut ostream = match writer_from_opts(opt.value_of("out")) {
Ok(mut f) => f,
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
};
match match protocol {
CallType::Standard => call.doit().await,
_ => unreachable!()
} {
Err(api_err) => Err(DoitError::ApiError(api_err)),
Ok((mut response, output_schema)) => {
let mut value = json::value::to_value(&output_schema).expect("serde to work");
remove_json_null_values(&mut value);
json::to_writer_pretty(&mut ostream, &value).unwrap();
ostream.flush().unwrap();
Ok(())
}
}
}
}
async fn _methods_analyze_iam_policy_longrunning(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut field_cursor = FieldCursor::default();
let mut object = json::value::Value::Object(Default::default());
for kvarg in opt.values_of("kv").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
let last_errc = err.issues.len();
let (key, value) = parse_kv_arg(&*kvarg, err, false);
let mut temp_cursor = field_cursor.clone();
if let Err(field_err) = temp_cursor.set(&*key) {
err.issues.push(field_err);
}
if value.is_none() {
field_cursor = temp_cursor.clone();
if err.issues.len() > last_errc {
err.issues.remove(last_errc);
}
continue;
}
let type_info: Option<(&'static str, JsonTypeInfo)> =
match &temp_cursor.to_string()[..] {
"analysis-query.access-selector.permissions" => Some(("analysisQuery.accessSelector.permissions", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"analysis-query.access-selector.roles" => Some(("analysisQuery.accessSelector.roles", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"analysis-query.identity-selector.identity" => Some(("analysisQuery.identitySelector.identity", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"analysis-query.options.analyze-service-account-impersonation" => Some(("analysisQuery.options.analyzeServiceAccountImpersonation", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"analysis-query.options.expand-groups" => Some(("analysisQuery.options.expandGroups", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"analysis-query.options.expand-resources" => Some(("analysisQuery.options.expandResources", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"analysis-query.options.expand-roles" => Some(("analysisQuery.options.expandRoles", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"analysis-query.options.output-group-edges" => Some(("analysisQuery.options.outputGroupEdges", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"analysis-query.options.output-resource-edges" => Some(("analysisQuery.options.outputResourceEdges", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"analysis-query.resource-selector.full-resource-name" => Some(("analysisQuery.resourceSelector.fullResourceName", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"analysis-query.scope" => Some(("analysisQuery.scope", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.dataset" => Some(("outputConfig.bigqueryDestination.dataset", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.partition-key" => Some(("outputConfig.bigqueryDestination.partitionKey", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.table-prefix" => Some(("outputConfig.bigqueryDestination.tablePrefix", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.write-disposition" => Some(("outputConfig.bigqueryDestination.writeDisposition", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.gcs-destination.uri" => Some(("outputConfig.gcsDestination.uri", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
_ => {
let suggestion = FieldCursor::did_you_mean(key, &vec!["access-selector", "analysis-query", "analyze-service-account-impersonation", "bigquery-destination", "dataset", "expand-groups", "expand-resources", "expand-roles", "full-resource-name", "gcs-destination", "identity", "identity-selector", "options", "output-config", "output-group-edges", "output-resource-edges", "partition-key", "permissions", "resource-selector", "roles", "scope", "table-prefix", "uri", "write-disposition"]);
err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string()))));
None
}
};
if let Some((field_cursor_str, type_info)) = type_info {
FieldCursor::from(field_cursor_str).set_json_value(&mut object, value.unwrap(), type_info, err, &temp_cursor);
}
}
let mut request: api::AnalyzeIamPolicyLongrunningRequest = json::value::from_value(object).unwrap();
let mut call = self.hub.methods().analyze_iam_policy_longrunning(request, opt.value_of("scope").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
let (key, value) = parse_kv_arg(&*parg, err, false);
match key {
_ => {
let mut found = false;
for param in &self.gp {
if key == *param {
found = true;
call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset"));
break;
}
}
if !found {
err.issues.push(CLIError::UnknownParameter(key.to_string(),
{let mut v = Vec::new();
v.extend(self.gp.iter().map(|v|*v));
v } ));
}
}
}
}
let protocol = CallType::Standard;
if dry_run {
Ok(())
} else {
assert!(err.issues.len() == 0);
for scope in self.opt.values_of("url").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
call = call.add_scope(scope);
}
let mut ostream = match writer_from_opts(opt.value_of("out")) {
Ok(mut f) => f,
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
};
match match protocol {
CallType::Standard => call.doit().await,
_ => unreachable!()
} {
Err(api_err) => Err(DoitError::ApiError(api_err)),
Ok((mut response, output_schema)) => {
let mut value = json::value::to_value(&output_schema).expect("serde to work");
remove_json_null_values(&mut value);
json::to_writer_pretty(&mut ostream, &value).unwrap();
ostream.flush().unwrap();
Ok(())
}
}
}
}
async fn _methods_batch_get_assets_history(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.methods().batch_get_assets_history(opt.value_of("parent").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
@@ -413,7 +603,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(["asset-names", "read-time-window-end-time", "content-type", "read-time-window-start-time"].iter().map(|v|*v));
v.extend(["content-type", "asset-names", "read-time-window-start-time", "read-time-window-end-time"].iter().map(|v|*v));
v } ));
}
}
@@ -432,7 +622,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)),
@@ -447,7 +637,7 @@ impl<'n> Engine<'n> {
}
}
fn _methods_export_assets(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _methods_export_assets(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut field_cursor = FieldCursor::default();
@@ -471,15 +661,17 @@ impl<'n> Engine<'n> {
let type_info: Option<(&'static str, JsonTypeInfo)> =
match &temp_cursor.to_string()[..] {
"asset-types" => Some(("assetTypes", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Vec })),
"read-time" => Some(("readTime", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"content-type" => Some(("contentType", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.table" => Some(("outputConfig.bigqueryDestination.table", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.force" => Some(("outputConfig.bigqueryDestination.force", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.dataset" => Some(("outputConfig.bigqueryDestination.dataset", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.gcs-destination.uri-prefix" => Some(("outputConfig.gcsDestination.uriPrefix", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.force" => Some(("outputConfig.bigqueryDestination.force", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.partition-spec.partition-key" => Some(("outputConfig.bigqueryDestination.partitionSpec.partitionKey", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.separate-tables-per-asset-type" => Some(("outputConfig.bigqueryDestination.separateTablesPerAssetType", JsonTypeInfo { jtype: JsonType::Boolean, ctype: ComplexType::Pod })),
"output-config.bigquery-destination.table" => Some(("outputConfig.bigqueryDestination.table", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.gcs-destination.uri" => Some(("outputConfig.gcsDestination.uri", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"output-config.gcs-destination.uri-prefix" => Some(("outputConfig.gcsDestination.uriPrefix", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
"read-time" => Some(("readTime", JsonTypeInfo { jtype: JsonType::String, ctype: ComplexType::Pod })),
_ => {
let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-types", "bigquery-destination", "content-type", "dataset", "force", "gcs-destination", "output-config", "read-time", "table", "uri", "uri-prefix"]);
let suggestion = FieldCursor::did_you_mean(key, &vec!["asset-types", "bigquery-destination", "content-type", "dataset", "force", "gcs-destination", "output-config", "partition-key", "partition-spec", "read-time", "separate-tables-per-asset-type", "table", "uri", "uri-prefix"]);
err.issues.push(CLIError::Field(FieldError::Unknown(temp_cursor.to_string(), suggestion, value.map(|v| v.to_string()))));
None
}
@@ -524,7 +716,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)),
@@ -539,7 +731,137 @@ impl<'n> Engine<'n> {
}
}
fn _operations_get(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
async fn _methods_search_all_iam_policies(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.methods().search_all_iam_policies(opt.value_of("scope").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
let (key, value) = parse_kv_arg(&*parg, err, false);
match key {
"query" => {
call = call.query(value.unwrap_or(""));
},
"page-token" => {
call = call.page_token(value.unwrap_or(""));
},
"page-size" => {
call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer"));
},
_ => {
let mut found = false;
for param in &self.gp {
if key == *param {
found = true;
call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset"));
break;
}
}
if !found {
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", "query"].iter().map(|v|*v));
v } ));
}
}
}
}
let protocol = CallType::Standard;
if dry_run {
Ok(())
} else {
assert!(err.issues.len() == 0);
for scope in self.opt.values_of("url").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
call = call.add_scope(scope);
}
let mut ostream = match writer_from_opts(opt.value_of("out")) {
Ok(mut f) => f,
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
};
match match protocol {
CallType::Standard => call.doit().await,
_ => unreachable!()
} {
Err(api_err) => Err(DoitError::ApiError(api_err)),
Ok((mut response, output_schema)) => {
let mut value = json::value::to_value(&output_schema).expect("serde to work");
remove_json_null_values(&mut value);
json::to_writer_pretty(&mut ostream, &value).unwrap();
ostream.flush().unwrap();
Ok(())
}
}
}
}
async fn _methods_search_all_resources(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.methods().search_all_resources(opt.value_of("scope").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
let (key, value) = parse_kv_arg(&*parg, err, false);
match key {
"query" => {
call = call.query(value.unwrap_or(""));
},
"page-token" => {
call = call.page_token(value.unwrap_or(""));
},
"page-size" => {
call = call.page_size(arg_from_str(value.unwrap_or("-0"), err, "page-size", "integer"));
},
"order-by" => {
call = call.order_by(value.unwrap_or(""));
},
"asset-types" => {
call = call.add_asset_types(value.unwrap_or(""));
},
_ => {
let mut found = false;
for param in &self.gp {
if key == *param {
found = true;
call = call.param(self.gpm.iter().find(|t| t.0 == key).unwrap_or(&("", key)).1, value.unwrap_or("unset"));
break;
}
}
if !found {
err.issues.push(CLIError::UnknownParameter(key.to_string(),
{let mut v = Vec::new();
v.extend(self.gp.iter().map(|v|*v));
v.extend(["asset-types", "page-token", "page-size", "query", "order-by"].iter().map(|v|*v));
v } ));
}
}
}
}
let protocol = CallType::Standard;
if dry_run {
Ok(())
} else {
assert!(err.issues.len() == 0);
for scope in self.opt.values_of("url").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
call = call.add_scope(scope);
}
let mut ostream = match writer_from_opts(opt.value_of("out")) {
Ok(mut f) => f,
Err(io_err) => return Err(DoitError::IoError(opt.value_of("out").unwrap_or("-").to_string(), io_err)),
};
match match protocol {
CallType::Standard => call.doit().await,
_ => unreachable!()
} {
Err(api_err) => Err(DoitError::ApiError(api_err)),
Ok((mut response, output_schema)) => {
let mut value = json::value::to_value(&output_schema).expect("serde to work");
remove_json_null_values(&mut value);
json::to_writer_pretty(&mut ostream, &value).unwrap();
ostream.flush().unwrap();
Ok(())
}
}
}
}
async fn _operations_get(&self, opt: &ArgMatches<'n>, dry_run: bool, err: &mut InvalidOptionsError)
-> Result<(), DoitError> {
let mut call = self.hub.operations().get(opt.value_of("name").unwrap_or(""));
for parg in opt.values_of("v").map(|i|i.collect()).unwrap_or(Vec::new()).iter() {
@@ -576,7 +898,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)),
@@ -591,7 +913,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;
@@ -599,19 +921,19 @@ impl<'n> Engine<'n> {
("feeds", Some(opt)) => {
match opt.subcommand() {
("create", Some(opt)) => {
call_result = self._feeds_create(opt, dry_run, &mut err);
call_result = self._feeds_create(opt, dry_run, &mut err).await;
},
("delete", Some(opt)) => {
call_result = self._feeds_delete(opt, dry_run, &mut err);
call_result = self._feeds_delete(opt, dry_run, &mut err).await;
},
("get", Some(opt)) => {
call_result = self._feeds_get(opt, dry_run, &mut err);
call_result = self._feeds_get(opt, dry_run, &mut err).await;
},
("list", Some(opt)) => {
call_result = self._feeds_list(opt, dry_run, &mut err);
call_result = self._feeds_list(opt, dry_run, &mut err).await;
},
("patch", Some(opt)) => {
call_result = self._feeds_patch(opt, dry_run, &mut err);
call_result = self._feeds_patch(opt, dry_run, &mut err).await;
},
_ => {
err.issues.push(CLIError::MissingMethodError("feeds".to_string()));
@@ -621,11 +943,23 @@ impl<'n> Engine<'n> {
},
("methods", Some(opt)) => {
match opt.subcommand() {
("analyze-iam-policy", Some(opt)) => {
call_result = self._methods_analyze_iam_policy(opt, dry_run, &mut err).await;
},
("analyze-iam-policy-longrunning", Some(opt)) => {
call_result = self._methods_analyze_iam_policy_longrunning(opt, dry_run, &mut err).await;
},
("batch-get-assets-history", Some(opt)) => {
call_result = self._methods_batch_get_assets_history(opt, dry_run, &mut err);
call_result = self._methods_batch_get_assets_history(opt, dry_run, &mut err).await;
},
("export-assets", Some(opt)) => {
call_result = self._methods_export_assets(opt, dry_run, &mut err);
call_result = self._methods_export_assets(opt, dry_run, &mut err).await;
},
("search-all-iam-policies", Some(opt)) => {
call_result = self._methods_search_all_iam_policies(opt, dry_run, &mut err).await;
},
("search-all-resources", Some(opt)) => {
call_result = self._methods_search_all_resources(opt, dry_run, &mut err).await;
},
_ => {
err.issues.push(CLIError::MissingMethodError("methods".to_string()));
@@ -636,7 +970,7 @@ impl<'n> Engine<'n> {
("operations", Some(opt)) => {
match opt.subcommand() {
("get", Some(opt)) => {
call_result = self._operations_get(opt, dry_run, &mut err);
call_result = self._operations_get(opt, dry_run, &mut err).await;
},
_ => {
err.issues.push(CLIError::MissingMethodError("operations".to_string()));
@@ -661,41 +995,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, "cloudasset1-secret.json",
match client::application_secret_from_directory(&config_dir, "cloudasset1-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: "cloudasset1",
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!("{}/cloudasset1", 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::CloudAsset::new(client, auth),
@@ -711,37 +1030,33 @@ 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 = [
("feeds", "methods: 'create', 'delete', 'get', 'list' and 'patch'", vec![
("create",
Some(r##"Creates a feed in a parent project/folder/organization to listen to its
asset updates."##),
Some(r##"Creates a feed in a parent project/folder/organization to listen to its asset updates."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/feeds_create",
vec![
(Some(r##"parent"##),
None,
Some(r##"Required. The name of the project/folder/organization where this feed
should be created in. It can only be an organization number (such as
"organizations/123"), a folder number (such as "folders/123"), a project ID
(such as "projects/my-project-id")", or a project number (such as
"projects/12345")."##),
Some(r##"Required. The name of the project/folder/organization where this feed should be created in. It can only be an organization number (such as "organizations/123"), a folder number (such as "folders/123"), a project ID (such as "projects/my-project-id")", or a project number (such as "projects/12345")."##),
Some(true),
Some(false)),
@@ -769,10 +1084,7 @@ fn main() {
vec![
(Some(r##"name"##),
None,
Some(r##"Required. The name of the feed and it must be in the format of:
projects/project_number/feeds/feed_id
folders/folder_number/feeds/feed_id
organizations/organization_number/feeds/feed_id"##),
Some(r##"Required. The name of the feed and it must be in the format of: projects/project_number/feeds/feed_id folders/folder_number/feeds/feed_id organizations/organization_number/feeds/feed_id"##),
Some(true),
Some(false)),
@@ -794,10 +1106,7 @@ fn main() {
vec![
(Some(r##"name"##),
None,
Some(r##"Required. The name of the Feed and it must be in the format of:
projects/project_number/feeds/feed_id
folders/folder_number/feeds/feed_id
organizations/organization_number/feeds/feed_id"##),
Some(r##"Required. The name of the Feed and it must be in the format of: projects/project_number/feeds/feed_id folders/folder_number/feeds/feed_id organizations/organization_number/feeds/feed_id"##),
Some(true),
Some(false)),
@@ -819,9 +1128,7 @@ fn main() {
vec![
(Some(r##"parent"##),
None,
Some(r##"Required. The parent project/folder/organization whose feeds are to be
listed. It can only be using project/folder/organization number (such as
"folders/12345")", or a project ID (such as "projects/my-project-id")."##),
Some(r##"Required. The parent project/folder/organization whose feeds are to be listed. It can only be using project/folder/organization number (such as "folders/12345")", or a project ID (such as "projects/my-project-id")."##),
Some(true),
Some(false)),
@@ -843,13 +1150,7 @@ fn main() {
vec![
(Some(r##"name"##),
None,
Some(r##"Required. The format will be
projects/{project_number}/feeds/{client-assigned_feed_identifier} or
folders/{folder_number}/feeds/{client-assigned_feed_identifier} or
organizations/{organization_number}/feeds/{client-assigned_feed_identifier}
The client-assigned feed identifier must be unique within the parent
project/folder/organization."##),
Some(r##"Required. The format will be projects/{project_number}/feeds/{client-assigned_feed_identifier} or folders/{folder_number}/feeds/{client-assigned_feed_identifier} or organizations/{organization_number}/feeds/{client-assigned_feed_identifier} The client-assigned feed identifier must be unique within the parent project/folder/organization."##),
Some(true),
Some(false)),
@@ -873,22 +1174,64 @@ fn main() {
]),
]),
("methods", "methods: 'batch-get-assets-history' and 'export-assets'", vec![
("methods", "methods: 'analyze-iam-policy', 'analyze-iam-policy-longrunning', 'batch-get-assets-history', 'export-assets', 'search-all-iam-policies' and 'search-all-resources'", vec![
("analyze-iam-policy",
Some(r##"Analyzes IAM policies to answer which identities have what accesses on which resources."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/methods_analyze-iam-policy",
vec![
(Some(r##"scope"##),
None,
Some(r##"Required. The relative name of the root asset. Only resources and IAM policies within the scope will be analyzed. This can only be an organization number (such as "organizations/123"), a folder number (such as "folders/123"), a project ID (such as "projects/my-project-id"), or a project number (such as "projects/12345"). To know how to get organization id, visit [here ](https://cloud.google.com/resource-manager/docs/creating-managing-organization#retrieving_your_organization_id). To know how to get folder or project id, visit [here ](https://cloud.google.com/resource-manager/docs/creating-managing-folders#viewing_or_listing_folders_and_projects)."##),
Some(true),
Some(false)),
(Some(r##"v"##),
Some(r##"p"##),
Some(r##"Set various optional parameters, matching the key=value form"##),
Some(false),
Some(true)),
(Some(r##"out"##),
Some(r##"o"##),
Some(r##"Specify the file into which to write the program's output"##),
Some(false),
Some(false)),
]),
("analyze-iam-policy-longrunning",
Some(r##"Analyzes IAM policies asynchronously to answer which identities have what accesses on which resources, and writes the analysis results to a Google Cloud Storage or a BigQuery destination. For Cloud Storage destination, the output format is the JSON format that represents a AnalyzeIamPolicyResponse. This method implements the google.longrunning.Operation, which allows you to track the operation status. We recommend intervals of at least 2 seconds with exponential backoff retry to poll the operation result. The metadata contains the request to help callers to map responses to requests."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/methods_analyze-iam-policy-longrunning",
vec![
(Some(r##"scope"##),
None,
Some(r##"Required. The relative name of the root asset. Only resources and IAM policies within the scope will be analyzed. This can only be an organization number (such as "organizations/123"), a folder number (such as "folders/123"), a project ID (such as "projects/my-project-id"), or a project number (such as "projects/12345"). To know how to get organization id, visit [here ](https://cloud.google.com/resource-manager/docs/creating-managing-organization#retrieving_your_organization_id). To know how to get folder or project id, visit [here ](https://cloud.google.com/resource-manager/docs/creating-managing-folders#viewing_or_listing_folders_and_projects)."##),
Some(true),
Some(false)),
(Some(r##"kv"##),
Some(r##"r"##),
Some(r##"Set various fields of the request structure, matching the key=value form"##),
Some(true),
Some(true)),
(Some(r##"v"##),
Some(r##"p"##),
Some(r##"Set various optional parameters, matching the key=value form"##),
Some(false),
Some(true)),
(Some(r##"out"##),
Some(r##"o"##),
Some(r##"Specify the file into which to write the program's output"##),
Some(false),
Some(false)),
]),
("batch-get-assets-history",
Some(r##"Batch gets the update history of assets that overlap a time window.
For IAM_POLICY content, this API outputs history when the asset and its
attached IAM POLICY both exist. This can create gaps in the output history.
Otherwise, this API outputs history with asset in both non-delete or
deleted status.
If a specified asset does not exist, this API returns an INVALID_ARGUMENT
error."##),
Some(r##"Batch gets the update history of assets that overlap a time window. For IAM_POLICY content, this API outputs history when the asset and its attached IAM POLICY both exist. This can create gaps in the output history. Otherwise, this API outputs history with asset in both non-delete or deleted status. If a specified asset does not exist, this API returns an INVALID_ARGUMENT error."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/methods_batch-get-assets-history",
vec![
(Some(r##"parent"##),
None,
Some(r##"Required. The relative name of the root asset. It can only be an
organization number (such as "organizations/123"), a project ID (such as
"projects/my-project-id")", or a project number (such as "projects/12345")."##),
Some(r##"Required. The relative name of the root asset. It can only be an organization number (such as "organizations/123"), a project ID (such as "projects/my-project-id")", or a project number (such as "projects/12345")."##),
Some(true),
Some(false)),
@@ -905,24 +1248,12 @@ fn main() {
Some(false)),
]),
("export-assets",
Some(r##"Exports assets with time and resource types to a given Cloud Storage
location/BigQuery table. For Cloud Storage location destinations, the
output format is newline-delimited JSON. Each line represents a
google.cloud.asset.v1.Asset in the JSON format; for BigQuery table
destinations, the output table stores the fields in asset proto as columns.
This API implements the google.longrunning.Operation API
, which allows you to keep track of the export. We recommend intervals of
at least 2 seconds with exponential retry to poll the export operation
result. For regular-size resource parent, the export operation usually
finishes within 5 minutes."##),
Some(r##"Exports assets with time and resource types to a given Cloud Storage location/BigQuery table. For Cloud Storage location destinations, the output format is newline-delimited JSON. Each line represents a google.cloud.asset.v1.Asset in the JSON format; for BigQuery table destinations, the output table stores the fields in asset proto as columns. This API implements the google.longrunning.Operation API , which allows you to keep track of the export. We recommend intervals of at least 2 seconds with exponential retry to poll the export operation result. For regular-size resource parent, the export operation usually finishes within 5 minutes."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/methods_export-assets",
vec![
(Some(r##"parent"##),
None,
Some(r##"Required. The relative name of the root asset. This can only be an
organization number (such as "organizations/123"), a project ID (such as
"projects/my-project-id"), or a project number (such as "projects/12345"),
or a folder number (such as "folders/123")."##),
Some(r##"Required. The relative name of the root asset. This can only be an organization number (such as "organizations/123"), a project ID (such as "projects/my-project-id"), or a project number (such as "projects/12345"), or a folder number (such as "folders/123")."##),
Some(true),
Some(false)),
@@ -938,6 +1269,50 @@ fn main() {
Some(false),
Some(true)),
(Some(r##"out"##),
Some(r##"o"##),
Some(r##"Specify the file into which to write the program's output"##),
Some(false),
Some(false)),
]),
("search-all-iam-policies",
Some(r##"Searches all IAM policies within the specified scope, such as a project, folder, or organization. The caller must be granted the `cloudasset.assets.searchAllIamPolicies` permission on the desired scope, otherwise the request will be rejected."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/methods_search-all-iam-policies",
vec![
(Some(r##"scope"##),
None,
Some(r##"Required. A scope can be a project, a folder, or an organization. The search is limited to the IAM policies within the `scope`. The caller must be granted the [`cloudasset.assets.searchAllIamPolicies`](https://cloud.google.com/asset-inventory/docs/access-control#required_permissions) permission on the desired scope. The allowed values are: * projects/{PROJECT_ID} (e.g., "projects/foo-bar") * projects/{PROJECT_NUMBER} (e.g., "projects/12345678") * folders/{FOLDER_NUMBER} (e.g., "folders/1234567") * organizations/{ORGANIZATION_NUMBER} (e.g., "organizations/123456")"##),
Some(true),
Some(false)),
(Some(r##"v"##),
Some(r##"p"##),
Some(r##"Set various optional parameters, matching the key=value form"##),
Some(false),
Some(true)),
(Some(r##"out"##),
Some(r##"o"##),
Some(r##"Specify the file into which to write the program's output"##),
Some(false),
Some(false)),
]),
("search-all-resources",
Some(r##"Searches all Cloud resources within the specified scope, such as a project, folder, or organization. The caller must be granted the `cloudasset.assets.searchAllResources` permission on the desired scope, otherwise the request will be rejected."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/methods_search-all-resources",
vec![
(Some(r##"scope"##),
None,
Some(r##"Required. A scope can be a project, a folder, or an organization. The search is limited to the resources within the `scope`. The caller must be granted the [`cloudasset.assets.searchAllResources`](https://cloud.google.com/asset-inventory/docs/access-control#required_permissions) permission on the desired scope. The allowed values are: * projects/{PROJECT_ID} (e.g., "projects/foo-bar") * projects/{PROJECT_NUMBER} (e.g., "projects/12345678") * folders/{FOLDER_NUMBER} (e.g., "folders/1234567") * organizations/{ORGANIZATION_NUMBER} (e.g., "organizations/123456")"##),
Some(true),
Some(false)),
(Some(r##"v"##),
Some(r##"p"##),
Some(r##"Set various optional parameters, matching the key=value form"##),
Some(false),
Some(true)),
(Some(r##"out"##),
Some(r##"o"##),
Some(r##"Specify the file into which to write the program's output"##),
@@ -948,9 +1323,7 @@ fn main() {
("operations", "methods: 'get'", vec![
("get",
Some(r##"Gets the latest state of a long-running operation. Clients can use this
method to poll the operation result at intervals as recommended by the API
service."##),
Some(r##"Gets the latest state of a long-running operation. Clients can use this method to poll the operation result at intervals as recommended by the API service."##),
"Details at http://byron.github.io/google-apis-rs/google_cloudasset1_cli/operations_get",
vec![
(Some(r##"name"##),
@@ -977,7 +1350,7 @@ fn main() {
let mut app = App::new("cloudasset1")
.author("Sebastian Thiel <byronimo@gmail.com>")
.version("1.0.14+20200613")
.version("2.0.0+20210319")
.about("The cloud asset API manages the history and inventory of cloud resources.")
.after_help("All documentation details can be found at http://byron.github.io/google-apis-rs/google_cloudasset1_cli")
.arg(Arg::with_name("url")
@@ -992,12 +1365,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));
@@ -1045,13 +1413,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) => {
@@ -1070,4 +1438,4 @@ fn main() {
}
std::process::exit(exit_status);
}
}