X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FJSONSchema.pm;h=95529258f19c24535e09dae21dc54471da8b1d37;hp=0cb281d9e84ffbb2b25df4aa3e68e30e950b6035;hb=d1e490c12f6c5cf22b5ddd7c5dc78bab0950726b;hpb=94dd44353294418b389414c260e1e1c4b991950c diff --git a/src/PVE/JSONSchema.pm b/src/PVE/JSONSchema.pm index 0cb281d..9552925 100644 --- a/src/PVE/JSONSchema.pm +++ b/src/PVE/JSONSchema.pm @@ -248,7 +248,7 @@ register_format('CIDRv4', \&pve_verify_cidrv4); sub pve_verify_cidrv4 { my ($cidr, $noerr) = @_; - if ($cidr =~ m!^(?:$IPV4RE)(?:/(\d+))$! && ($1 > 7) && ($1 < 32)) { + if ($cidr =~ m!^(?:$IPV4RE)(?:/(\d+))$! && ($1 > 7) && ($1 <= 32)) { return $cidr; } @@ -488,7 +488,10 @@ sub format_size { }; sub parse_property_string { - my ($format, $data, $path) = @_; + my ($format, $data, $path, $additional_properties) = @_; + + # In property strings we default to not allowing additional properties + $additional_properties = 0 if !defined($additional_properties); my $default_key; @@ -498,16 +501,20 @@ sub parse_property_string { if ($part =~ /^([^=]+)=(.+)$/) { my ($k, $v) = ($1, $2); - die "duplicate key in comma-separated list property: $k" if defined($res->{$k}); + die "duplicate key in comma-separated list property: $k\n" if defined($res->{$k}); my $schema = $format->{$k}; - die "invalid key in comma-separated list property: $k" if !$schema; + if (my $alias = $schema->{alias}) { + $k = $alias; + $schema = $format->{$k}; + } + die "invalid key in comma-separated list property: $k\n" if !$schema; if ($schema->{type} && $schema->{type} eq 'boolean') { $v = 1 if $v =~ m/^(1|on|yes|true)$/i; $v = 0 if $v =~ m/^(0|off|no|false)$/i; } $res->{$k} = $v; } elsif ($part !~ /=/) { - die "duplicate key in comma-separated list property: $default_key" if $default_key; + die "duplicate key in comma-separated list property: $default_key\n" if $default_key; foreach my $key (keys %$format) { if ($format->{$key}->{default_key}) { $default_key = $key; @@ -515,18 +522,18 @@ sub parse_property_string { $res->{$default_key} = $part; last; } - die "duplicate key in comma-separated list property: $default_key"; + die "duplicate key in comma-separated list property: $default_key\n"; } } } else { - die "missing key in comma-separated list property"; + die "missing key in comma-separated list property\n"; } } my $errors = {}; - check_object($path, $format, $res, undef, $errors); + check_object($path, $format, $res, $additional_properties, $errors); if (scalar(%$errors)) { - raise "format error", errors => $errors; + raise "format error\n", errors => $errors; } return $res; @@ -553,7 +560,7 @@ sub print_property_string { my %required; # this is a set, all present keys are required regardless of value foreach my $key (keys %$format) { $allowed{$key} = 1; - if (!$format->{$key}->{optional} && !$skipped{$key}) { + if (!$format->{$key}->{optional} && !$format->{$key}->{alias} && !$skipped{$key}) { $required{$key} = 1; } @@ -578,15 +585,16 @@ sub print_property_string { } foreach my $key (sort keys %$data) { - die "invalid key: $key" if !$allowed{$key}; delete $required{$key}; next if $skipped{$key}; + die "invalid key: $key" if !$allowed{$key}; - my $type = $format->{$key}->{type}; + my $typeformat = $format->{$key}->{format}; my $value = $data->{$key}; + next if !defined($value); $text .= $comma; $comma = ','; - if ($type eq 'disk-size') { + if ($typeformat && $typeformat eq 'disk-size') { $text .= "$key=" . format_size($value); } else { $text .= "$key=$value"; @@ -810,7 +818,7 @@ sub check_prop { if (!defined ($value)) { return if $schema->{type} && $schema->{type} eq 'null'; - if (!$schema->{optional}) { + if (!$schema->{optional} && !$schema->{alias}) { add_error($errors, $path, "property is missing and it is not optional"); } return; @@ -1048,6 +1056,11 @@ my $default_schema_noref = { optional => 1, description => "Whether this is the default key in a comma separated list property string.", }, + alias => { + type => 'string', + optional => 1, + description => "When a key represents the same property as another it can be an alias to it, causing the parsed datastructure to use the other key to store the current value under.", + }, default => { type => "any", optional => 1,