From: Dietmar Maurer Date: Wed, 25 Jul 2018 07:13:34 +0000 (+0200) Subject: PVE::CLIHandler - allow to define additional parameters for output formatter X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=commitdiff_plain;h=9da2722861bfcc1acdc2830e76a39b9ee14b041c PVE::CLIHandler - allow to define additional parameters for output formatter Best shown with a example: my $test_formatter = sub { my ($res, $result_schema, $fmt_param) = @_; PVE::CLIFormatter::print_api_result($res, $result_schema, undef, $fmt_param); }; $cmddef = [ __PACKAGE__, 'test', [], undef, $test_formatter, $PVE::RESTHandler::standard_output_options], --- diff --git a/src/PVE/CLIHandler.pm b/src/PVE/CLIHandler.pm index 2f59d2b..5c0671f 100644 --- a/src/PVE/CLIHandler.pm +++ b/src/PVE/CLIHandler.pm @@ -17,7 +17,9 @@ use base qw(PVE::RESTHandler); # A real command is always an array consisting of its class, name, array of # position fixed (required) parameters and hash of predefined parameters when # mapping a CLI command t o an API call. Optionally an output method can be -# passed at the end, e.g., for formatting or transformation purpose. +# passed at the end, e.g., for formatting or transformation purpose, and +# a schema of additional properties/arguments which are added to +# the method schema and gets passed to the formatter. # # [class, name, fixed_params, API_pre-set params, output_sub ] # @@ -200,12 +202,12 @@ sub generate_usage_str { foreach my $cmd (&$sortfunc($def)) { if (ref($def->{$cmd}) eq 'ARRAY') { - my ($class, $name, $arg_param, $fixed_param) = @{$def->{$cmd}}; + my ($class, $name, $arg_param, $fixed_param, undef, $formatter_properties) = @{$def->{$cmd}}; $str .= $separator if $oldclass && $oldclass ne $class; $str .= $indent; $str .= $class->usage_str($name, "$prefix $cmd", $arg_param, - $fixed_param, $format, $param_cb); + $fixed_param, $format, $param_cb, $formatter_properties); $oldclass = $class; } elsif (defined($def->{$cmd}->{alias}) && ($format eq 'asciidoc')) { @@ -224,11 +226,11 @@ sub generate_usage_str { } } else { - my ($class, $name, $arg_param, $fixed_param) = @$def; + my ($class, $name, $arg_param, $fixed_param, undef, $formatter_properties) = @$def; $abort->("unknown command '$cmd'") if !$class; $str .= $indent; - $str .= $class->usage_str($name, $prefix, $arg_param, $fixed_param, $format, $param_cb); + $str .= $class->usage_str($name, $prefix, $arg_param, $fixed_param, $format, $param_cb, $formatter_properties); } return $str; }; @@ -395,7 +397,7 @@ my $print_bash_completion = sub { my $skip_param = {}; - my ($class, $name, $arg_param, $uri_param) = @$def; + my ($class, $name, $arg_param, $uri_param, undef, $formatter_properties) = @$def; $arg_param //= []; $uri_param //= {}; @@ -406,7 +408,8 @@ my $print_bash_completion = sub { my $info = $class->map_method_by_name($name); - my $prop = $info->{parameters}->{properties}; + my $prop = { %{$info->{parameters}->{properties}} }; # copy + $prop = { %$prop, %$formatter_properties } if $formatter_properties; my $print_parameter_completion = sub { my ($pname) = @_; @@ -547,21 +550,22 @@ my $handle_cmd = sub { &$preparefunc() if $preparefunc; - my ($class, $name, $arg_param, $uri_param, $outsub) = @{$def || []}; + my ($class, $name, $arg_param, $uri_param, $outsub, $formatter_properties) = @{$def || []}; $abort->("unknown command '$cmd_str'") if !$class; - my $res = $class->cli_handler($cmd_str, $name, $cmd_args, $arg_param, $uri_param, $param_cb); + my ($res, $formatter_params) = $class->cli_handler( + $cmd_str, $name, $cmd_args, $arg_param, $uri_param, $param_cb, $formatter_properties); if (defined $outsub) { my $result_schema = $class->map_method_by_name($name)->{returns}; - $outsub->($res, $result_schema); + $outsub->($res, $result_schema, $formatter_params); } }; my $handle_simple_cmd = sub { my ($args, $preparefunc, $param_cb) = @_; - my ($class, $name, $arg_param, $uri_param, $outsub) = @{$cmddef}; + my ($class, $name, $arg_param, $uri_param, $outsub, $formatter_properties) = @{$cmddef}; die "no class specified" if !$class; if (scalar(@$args) >= 1) { @@ -588,11 +592,12 @@ my $handle_simple_cmd = sub { &$preparefunc() if $preparefunc; - my $res = $class->cli_handler($name, $name, \@ARGV, $arg_param, $uri_param, $param_cb); + my ($res, $formatter_params) = $class->cli_handler( + $name, $name, \@ARGV, $arg_param, $uri_param, $param_cb, $formatter_properties); if (defined $outsub) { my $result_schema = $class->map_method_by_name($name)->{returns}; - $outsub->($res, $result_schema); + $outsub->($res, $result_schema, $formatter_params); } }; diff --git a/src/PVE/RESTHandler.pm b/src/PVE/RESTHandler.pm index 148b4d8..5761ee3 100644 --- a/src/PVE/RESTHandler.pm +++ b/src/PVE/RESTHandler.pm @@ -576,15 +576,17 @@ my $compute_param_mapping_hash = sub { # 'short' ... command line only (text, one line) # 'full' ... text, include description # 'asciidoc' ... generate asciidoc for man pages (like 'full') -# $param_cb ... mapping for string parameters to file path parameters +# $param_cb ... mapping for string parameters to file path parameters +# $formatter_properties ... additional property definitions (passed to output formatter) sub getopt_usage { - my ($info, $prefix, $arg_param, $fixed_param, $format, $param_cb) = @_; + my ($info, $prefix, $arg_param, $fixed_param, $format, $param_cb, $formatter_properties) = @_; $format = 'long' if !$format; my $schema = $info->{parameters}; my $name = $info->{name}; - my $prop = $schema->{properties}; + my $prop = { %{$schema->{properties}} }; # copy + $prop = { %$prop, %$formatter_properties } if $formatter_properties; my $out = ''; @@ -680,11 +682,11 @@ sub getopt_usage { } sub usage_str { - my ($self, $name, $prefix, $arg_param, $fixed_param, $format, $param_cb) = @_; + my ($self, $name, $prefix, $arg_param, $fixed_param, $format, $param_cb, $formatter_properties) = @_; my $info = $self->map_method_by_name($name); - return getopt_usage($info, $prefix, $arg_param, $fixed_param, $format, $param_cb); + return getopt_usage($info, $prefix, $arg_param, $fixed_param, $format, $param_cb, $formatter_properties); } # generate docs from JSON schema properties @@ -802,15 +804,24 @@ sub extract_standard_output_properties { } sub cli_handler { - my ($self, $prefix, $name, $args, $arg_param, $fixed_param, $param_cb) = @_; + my ($self, $prefix, $name, $args, $arg_param, $fixed_param, $param_cb, $formatter_properties) = @_; my $info = $self->map_method_by_name($name); - my $res; + my $fmt_param = {}; + eval { my $param_map = {}; $param_map = $compute_param_mapping_hash->($param_cb->($name)) if $param_cb; - my $param = PVE::JSONSchema::get_options($info->{parameters}, $args, $arg_param, $fixed_param, $param_map); + my $schema = { %{$info->{parameters}} }; # copy + $schema->{properties} = { %{$schema->{properties}}, %$formatter_properties } if $formatter_properties; + my $param = PVE::JSONSchema::get_options($schema, $args, $arg_param, $fixed_param, $param_map); + + if ($formatter_properties) { + foreach my $opt (keys %$formatter_properties) { + $fmt_param->{$opt} = delete $param->{$opt} if defined($param->{$opt}); + } + } if (defined($param_map)) { $replace_file_names_with_contents->($param, $param_map); @@ -823,12 +834,12 @@ sub cli_handler { die $err if !$ec || $ec ne "PVE::Exception" || !$err->is_param_exc(); - $err->{usage} = $self->usage_str($name, $prefix, $arg_param, $fixed_param, 'short', $param_cb); + $err->{usage} = $self->usage_str($name, $prefix, $arg_param, $fixed_param, 'short', $param_cb, $formatter_properties); die $err; } - return $res; + return wantarray ? ($res, $fmt_param) : $res; } # utility methods