From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 35EB01FF138 for ; Mon, 20 Jul 2026 14:02:21 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 8C5A6214AF; Mon, 20 Jul 2026 14:02:20 +0200 (CEST) Message-ID: <5b25fce3-23ab-4a95-9756-b153a23c41cc@proxmox.com> Date: Mon, 20 Jul 2026 14:01:44 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Beta Subject: Re: [RFC pve-common v2 02/17] jsonschema: support 'patternProperties' and allow 'x-' keywords To: pve-devel@lists.proxmox.com References: <20260717154943.696411-1-m.carrara@proxmox.com> <20260717154943.696411-3-m.carrara@proxmox.com> Content-Language: en-US From: Jakob Klocker In-Reply-To: <20260717154943.696411-3-m.carrara@proxmox.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1784548879958 X-SPAM-LEVEL: Spam detection results: 0 AWL 1.033 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_LOW -0.7 Sender listed at https://www.dnswl.org/, low trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: TCWBVB727LCRJSXJO3RM3GDOCBGYLX5L X-Message-ID-Hash: TCWBVB727LCRJSXJO3RM3GDOCBGYLX5L X-MailFrom: j.klocker@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: comments inline On 7/17/26 5:49 PM, Max R. Carrara wrote: > by adding the necessary validation code before the > `additionalProperties` handling in `check_object()` and extending the > default schema (the schema for JSON schemas). > > At the same time, allow all keywords beginning with 'x-' to be > included in a given schema. This makes it possible specify custom > extension keywords that can be used for e.g. hints, flags, and other > things. > > Signed-off-by: Max R. Carrara > --- > NOTE: This patch is experimental and thus marked as RFC. > > src/PVE/JSONSchema.pm | 61 +++++++++++++++++++++++++++++++++++----- > test/json-schema-test.pl | 2 +- > 2 files changed, 55 insertions(+), 8 deletions(-) > > diff --git a/src/PVE/JSONSchema.pm b/src/PVE/JSONSchema.pm > index 49f6aa6..1bfa5f6 100644 > --- a/src/PVE/JSONSchema.pm > +++ b/src/PVE/JSONSchema.pm > @@ -1073,6 +1073,9 @@ sub parse_property_string { > # In property strings we default to not allowing additional properties > $additional_properties = 0 if !defined($additional_properties); > > + # In property strings we do not allow pattern properties at all > + my $pattern_properties = 0; > + > # Support named formats here, too: > my $validator; > if (!ref($format)) { > @@ -1141,7 +1144,7 @@ sub parse_property_string { > } > > my $errors = {}; > - check_object($path, $format, $res, $additional_properties, $errors); > + check_object($path, $format, $res, $pattern_properties, $additional_properties, $errors); > if (scalar(%$errors)) { > raise "format error\n", errors => $errors; > } > @@ -1294,7 +1297,7 @@ my sub get_instance_type { > } > > sub check_object { > - my ($path, $schema, $value, $additional_properties, $errors) = @_; > + my ($path, $schema, $value, $pattern_properties, $additional_properties, $errors) = @_; > > # print "Check Object " . Dumper($value) . "\nSchema: " . Dumper($schema); > > @@ -1367,6 +1370,23 @@ sub check_object { > next if $matched_type; # value is already checked above > } > > + if (defined($pattern_properties) && $pattern_properties) { checking if the variable is defined and then the variable itself seems redundant - if `$pattern_properties` is undef the `if` check would be false anyway > + my $has_err = 0; > + my $pattern_schema = undef; > + > + for my $pattern (keys $pattern_properties->%*) { > + if ($k =~ $pattern) { > + $pattern_schema = $pattern_properties->{$pattern}; > + last; > + } > + } > + > + next if $has_err; `$has_err` is initialized to 0 and never changed, so this next is dead code. Was it meant to handle the case where no pattern matches $k? > + > + check_prop($value->{$k}, $pattern_schema, $newpath, $errors); > + next; > + } > + > if (defined($additional_properties) && !$additional_properties) { > add_error( > $errors, [snip]