X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FJSONSchema.pm;h=9c624f694c6f423ee643ef025620c369b713f5bb;hp=5131e4dc07b7ed27c855950c681e4c81b79fffc5;hb=24197a9f6c698985b7255fbf7792b0b6bd8188b5;hpb=32f8e0c75bab20a363192f5bd5d0b7037fd7f918 diff --git a/src/PVE/JSONSchema.pm b/src/PVE/JSONSchema.pm index 5131e4d..9c624f6 100644 --- a/src/PVE/JSONSchema.pm +++ b/src/PVE/JSONSchema.pm @@ -4,6 +4,8 @@ use strict; use warnings; use Storable; # for dclone use Getopt::Long; +use Encode::Locale; +use Encode; use Devel::Cycle -quiet; # todo: remove? use PVE::Tools qw(split_list $IPV6RE $IPV4RE); use PVE::Exception qw(raise); @@ -84,6 +86,12 @@ register_standard_option('pve-config-digest', { maxLength => 40, # sha1 hex digest lenght is 40 }); +register_standard_option('skiplock', { + description => "Ignore locks - only root is allowed to use this option.", + type => 'boolean', + optional => 1, +}); + register_standard_option('extra-args', { description => "Extra arguments as array", type => 'array', @@ -229,7 +237,9 @@ my $ipv4_mask_hash = { '255.255.255.224' => 27, '255.255.255.240' => 28, '255.255.255.248' => 29, - '255.255.255.252' => 30 + '255.255.255.252' => 30, + '255.255.255.254' => 31, + '255.255.255.255' => 32, }; register_format('ipv4mask', \&pve_verify_ipv4mask); @@ -504,6 +514,17 @@ sub parse_property_string { # In property strings we default to not allowing additional properties $additional_properties = 0 if !defined($additional_properties); + # Support named formats here, too: + if (!ref($format)) { + if (my $desc = $format_list->{$format}) { + $format = $desc; + } else { + die "unknown format: $format\n"; + } + } elsif (ref($format) ne 'HASH') { + die "unexpected format value of type ".ref($format)."\n"; + } + my $default_key; my $res = {}; @@ -643,6 +664,9 @@ sub check_type { return undef; } return 1; + } elsif ($type eq 'string' && $vt eq 'Regexp') { + # qr// regexes can be used as strings and make sense for format=regex + return 1; } else { if ($vt) { add_error($errors, $path, "type check ('$type') failed - got $vt"); @@ -656,7 +680,7 @@ sub check_type { return 1; #} elsif ($value =~ m/^(0|false|no|off)$/i) { } elsif ($value eq '0') { - return 0; + return 1; # return success (not value) } else { add_error($errors, $path, "type check ('$type') failed - got '$value'"); return undef; @@ -715,7 +739,7 @@ sub check_object { check_prop($value, $requires, $path, $errors); } elsif (!defined($value->{$requires})) { add_error($errors, $path ? "$path.$requires" : $requires, - "missing property - '$newpath' requiers this property"); + "missing property - '$newpath' requires this property"); } } @@ -1174,11 +1198,6 @@ my $method_schema = { description => "JSON Schema for parameters.", optional => 1, }, - formatter => { - type => 'object', - description => "Used to store page formatter information (set by PVE::RESTHandler->register_page_formatter).", - optional => 1, - }, returns => { type => 'object', description => "JSON Schema for return value.", @@ -1332,7 +1351,9 @@ sub get_options { } } - $opts = PVE::Tools::decode_utf8_parameters($opts); + foreach my $p (keys %$opts) { + $opts->{$p} = decode('locale', $opts->{$p}); + } foreach my $p (keys %$opts) { if (my $pd = $schema->{properties}->{$p}) { @@ -1469,7 +1490,7 @@ my $find_schema_default_key = sub { }; sub generate_typetext { - my ($format) = @_; + my ($format, $list_enums) = @_; my ($default_key, $keyAliasProps) = &$find_schema_default_key($format); @@ -1502,7 +1523,11 @@ sub generate_typetext { } elsif (my $text = $phash->{typetext}) { $typetext .= $text; } elsif (my $enum = $phash->{enum}) { - $typetext .= '<' . join('|', @$enum) . '>'; + if ($list_enums || (scalar(@$enum) <= 3)) { + $typetext .= '<' . join('|', @$enum) . '>'; + } else { + $typetext .= ''; + } } elsif ($phash->{type} eq 'boolean') { $typetext .= '<1|0>'; } elsif ($phash->{type} eq 'integer') { @@ -1601,7 +1626,7 @@ sub print_property_string { my $done = { map { $_ => 1 } @$skip }; my $cond_add_key = sub { - my ($key) = @_; + my ($key, $isdefault) = @_; return if $done->{$key}; # avoid duplicates @@ -1633,11 +1658,15 @@ sub print_property_string { die "internal error" if defined($phash->{alias}); my $value_str = &$format_value($key, $value, $phash->{format}); - &$add_option_string("$key=${value_str}"); + if ($isdefault) { + &$add_option_string($value_str); + } else { + &$add_option_string("$key=${value_str}"); + } }; # add default key first - &$cond_add_key($default_key) if defined($default_key); + &$cond_add_key($default_key, 1) if defined($default_key); # add required keys first foreach my $key (sort keys %$data) { @@ -1654,7 +1683,7 @@ sub print_property_string { } sub schema_get_type_text { - my ($phash) = @_; + my ($phash, $style) = @_; my $type = $phash->{type} || 'string'; @@ -1663,27 +1692,31 @@ sub schema_get_type_text { } elsif ($phash->{format_description}) { return "<$phash->{format_description}>"; } elsif ($phash->{enum}) { - return "(" . join(' | ', sort @{$phash->{enum}}) . ")"; + return "<" . join(' | ', sort @{$phash->{enum}}) . ">"; } elsif ($phash->{pattern}) { return $phash->{pattern}; } elsif ($type eq 'integer' || $type eq 'number') { + # NOTE: always access values as number (avoid converion to string) if (defined($phash->{minimum}) && defined($phash->{maximum})) { - return "$type ($phash->{minimum} - $phash->{maximum})"; + return "<$type> (" . ($phash->{minimum} + 0) . " - " . + ($phash->{maximum} + 0) . ")"; } elsif (defined($phash->{minimum})) { - return "$type ($phash->{minimum} - N)"; + return "<$type> (" . ($phash->{minimum} + 0) . " - N)"; } elsif (defined($phash->{maximum})) { - return "$type (-N - $phash->{maximum})"; + return "<$type> (-N - " . ($phash->{maximum} + 0) . ")"; } } elsif ($type eq 'string') { if (my $format = $phash->{format}) { $format = get_format($format) if ref($format) ne 'HASH'; if (ref($format) eq 'HASH') { - return generate_typetext($format); + my $list_enums = 0; + $list_enums = 1 if $style && $style eq 'config-sub'; + return generate_typetext($format, $list_enums); } } } - return $type; + return "<$type>"; } 1;