]> git.proxmox.com Git - pve-common.git/commitdiff
section config: implement array support
authorDominik Csapak <d.csapak@proxmox.com>
Tue, 6 Jun 2023 13:08:46 +0000 (15:08 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 7 Jun 2023 11:50:51 +0000 (13:50 +0200)
enables section configs in the style of:

----
type: id
    property value
    property value2
    property value3
----

can be combined with property strings

the provided create and update schema just pass through the array type
to the api, so the api call must always contain the complete array

also adds a test case for such array fields

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
src/PVE/SectionConfig.pm
test/section_config_test.pl

index f36cede9f75ba27e9591571b0e09fd924e84328d..97492db6289e8474b17699b55956b850876249fd 100644 (file)
@@ -254,7 +254,15 @@ sub check_value {
 
     if (!$skipSchemaCheck) {
        my $errors = {};
-       PVE::JSONSchema::check_prop($value, $schema, '', $errors);
+
+       my $checkschema = $schema;
+
+       if ($ct eq 'array') {
+           die "no item schema for array" if !defined($schema->{items});
+           $checkschema = $schema->{items};
+       }
+
+       PVE::JSONSchema::check_prop($value, $checkschema, '', $errors);
        if (scalar(keys %$errors)) {
            die "$errors->{$key}\n" if $errors->{$key};
            die "$errors->{_root}\n" if $errors->{_root};
@@ -311,6 +319,15 @@ sub parse_config {
        }
     };
 
+    my $is_array = sub {
+       my ($type, $key) = @_;
+
+       my $schema = $pdata->{propertyList}->{$key};
+       die "unknown property type\n" if !$schema;
+
+       return $schema->{type} eq 'array';
+    };
+
     my $errors = [];
     while (@lines) {
        my $line = $nextline->();
@@ -352,11 +369,19 @@ sub parse_config {
                    my ($k, $v) = ($1, $3);
 
                    eval {
-                       die "duplicate attribute\n" if defined($config->{$k});
-                       if (!$unknown) {
-                           $v = $plugin->check_value($type, $k, $v, $sectionId);
+                       if ($is_array->($type, $k)) {
+                           if (!$unknown) {
+                               $v = $plugin->check_value($type, $k, $v, $sectionId);
+                           }
+                           $config->{$k} = [] if !defined($config->{$k});
+                           push $config->{$k}->@*, $v;
+                       } else {
+                           die "duplicate attribute\n" if defined($config->{$k});
+                           if (!$unknown) {
+                               $v = $plugin->check_value($type, $k, $v, $sectionId);
+                           }
+                           $config->{$k} = $v;
                        }
-                       $config->{$k} = $v;
                    };
                    if (my $err = $@) {
                        warn "$errprefix (section '$sectionId') - unable to parse value of '$k': $err";
@@ -448,6 +473,13 @@ my $format_config_line = sub {
     if ($ct eq 'boolean') {
        return "\t$key " . ($value ? 1 : 0) . "\n"
            if defined($value);
+    } elsif ($ct eq 'array') {
+       die "property '$key' is not an array" if ref($value) ne 'ARRAY';
+       my $result = '';
+       for my $line ($value->@*) {
+           $result .= "\t$key $line\n" if $value ne '';
+       }
+       return $result;
     } else {
        return "\t$key $value\n" if "$value" ne '';
     }
index 22a964358c7e70594381ed89ab2fe66acee030a7..02242bc85b4e0312614eb65617ccdc2d1e45e118 100755 (executable)
@@ -105,6 +105,25 @@ sub properties {
            minimum => 3,
            maximum => 9,
        },
+       arrayfield => {
+           description => "Array Field with property string",
+           type => 'array',
+           items => {
+               type => 'string',
+               description => 'a property string',
+               format => {
+                   subfield1 => {
+                       type => 'string',
+                       description => 'first subfield'
+                   },
+                   subfield2 => {
+                       type => 'integer',
+                       minimum => 0,
+                       optional => 1,
+                   },
+               },
+           },
+       },
     };
 }
 
@@ -113,6 +132,7 @@ sub options {
        common => { optional => 1 },
        field2 => {},
        another => {},
+       arrayfield => { optional => 1 },
     };
 }
 
@@ -190,6 +210,10 @@ my $with_unknown_data = {
            type => 'two',
            field2 => 5,
            another => 'even more text',
+           arrayfield => [
+               'subfield1=test,subfield2=2',
+               'subfield1=test2',
+           ],
        },
        invalid => {
            type => 'bad',
@@ -214,6 +238,8 @@ bad: invalid
 two: t3
        field2 5
        another even more text
+       arrayfield subfield1=test,subfield2=2
+       arrayfield subfield1=test2
 EOF
 
 Conf->expect_fail('unknown-forbidden', $with_unknown_data, $with_unknown_text);