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.bumil...@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


_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to