[pve-devel] [RFC common] cli: more generic interactive parameter definition
Wolfgang Bumiller
w.bumiller at proxmox.com
Mon Mar 12 13:04:15 CET 2018
Instead of hardcoding 'password' as a special case in the
JSONSchema's getopt handling, extend the new parameter
mapping to allow defining a parameters as 'interactive'.
They also take an optional argument on the command line
directly.
This effectively deprecates the password special case which
should be replaced in pct/pveum/... and then dropped in
pve-common.
Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
src/PVE/JSONSchema.pm | 20 ++++++++++++++++++--
src/PVE/RESTHandler.pm | 13 +++++++------
2 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/src/PVE/JSONSchema.pm b/src/PVE/JSONSchema.pm
index 9861a8f..0e722b8 100644
--- a/src/PVE/JSONSchema.pm
+++ b/src/PVE/JSONSchema.pm
@@ -1333,7 +1333,7 @@ sub method_get_child_link {
# a way to parse command line parameters, using a
# schema to configure Getopt::Long
sub get_options {
- my ($schema, $args, $arg_param, $fixed_param, $pwcallback) = @_;
+ my ($schema, $args, $arg_param, $fixed_param, $pwcallback, $param_mapping_hash) = @_;
if (!$schema || !$schema->{properties}) {
raise("too many arguments\n", code => HTTP_BAD_REQUEST)
@@ -1349,13 +1349,20 @@ sub get_options {
$list_param = $arg_param;
}
+ my @interactive = ();
my @getopt = ();
foreach my $prop (keys %{$schema->{properties}}) {
my $pd = $schema->{properties}->{$prop};
next if $list_param && $prop eq $list_param;
next if defined($fixed_param->{$prop});
- if ($prop eq 'password' && $pwcallback) {
+ my $mapping = $param_mapping_hash->{$prop};
+ if ($mapping && $mapping->{interactive}) {
+ # interactive parameters such as passwords: make the argument
+ # optional and call the mapping function afterwards.
+ push @getopt, "$prop:s";
+ push @interactive, [$prop, $mapping->{func}];
+ } elsif ($prop eq 'password' && $pwcallback) {
# we do not accept plain password on input line, instead
# we turn this into a boolean option and ask for password below
# using $pwcallback() (for security reasons).
@@ -1409,6 +1416,15 @@ sub get_options {
}
}
+ foreach my $entry (@interactive) {
+ my ($opt, $func) = @$entry;
+ my $pd = $schema->{properties}->{$opt};
+ my $value = $opts->{$opt};
+ if (defined($value) || !$pd->{optional}) {
+ $opts->{$opt} = $func->($value);
+ }
+ }
+
# decode after Getopt as we are not sure how well it handles unicode
foreach my $p (keys %$opts) {
if (!ref($opts->{$p})) {
diff --git a/src/PVE/RESTHandler.pm b/src/PVE/RESTHandler.pm
index 0a64158..3f5c732 100644
--- a/src/PVE/RESTHandler.pm
+++ b/src/PVE/RESTHandler.pm
@@ -514,15 +514,15 @@ my $compute_param_mapping_hash = sub {
return $res if !defined($mapping_array);
foreach my $item (@$mapping_array) {
- my ($name, $func, $desc);
+ my ($name, $func, $desc, $interactive);
if (ref($item) eq 'ARRAY') {
- ($name, $func, $desc) = @$item;
+ ($name, $func, $desc, $interactive) = @$item;
} else {
$name = $item;
$func = sub { return PVE::Tools::file_get_contents($_[0]) };
}
$desc //= '<filepath>';
- $res->{$name} = { desc => $desc, func => $func };
+ $res->{$name} = { desc => $desc, func => $func, interactive => $interactive };
}
return $res;
@@ -691,6 +691,7 @@ my $replace_file_names_with_contents = sub {
my ($param, $param_mapping_hash) = @_;
while (my ($k, $d) = each %$param_mapping_hash) {
+ next if $d->{interactive}; # handled by the JSONSchema's get_options code
$param->{$k} = $d->{func}->($param->{$k})
if defined($param->{$k});
}
@@ -705,10 +706,10 @@ sub cli_handler {
my $res;
eval {
- my $param = PVE::JSONSchema::get_options($info->{parameters}, $args, $arg_param, $fixed_param, $read_password_func);
+ my $param_mapping_hash = $compute_param_mapping_hash->($param_mapping_func->($name)) if $param_mapping_func;
+ my $param = PVE::JSONSchema::get_options($info->{parameters}, $args, $arg_param, $fixed_param, $read_password_func, $param_mapping_hash);
- if (defined($param_mapping_func)) {
- my $param_mapping_hash = $compute_param_mapping_hash->(&$param_mapping_func($name));
+ if (defined($param_mapping_hash)) {
&$replace_file_names_with_contents($param, $param_mapping_hash);
}
--
2.11.0
More information about the pve-devel
mailing list