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.csa...@proxmox.com>
---
changes from v1:
* don't special encode arrays anymore, but instead have always the whole
  array as parameter in the create/updateSchema
 src/PVE/SectionConfig.pm    | 64 +++++++++++++++++++++++++++----------
 test/section_config_test.pl | 26 +++++++++++++++
 2 files changed, 74 insertions(+), 16 deletions(-)

diff --git a/src/PVE/SectionConfig.pm b/src/PVE/SectionConfig.pm
index f36cede..03f6a52 100644
--- a/src/PVE/SectionConfig.pm
+++ b/src/PVE/SectionConfig.pm
@@ -51,6 +51,17 @@ sub plugindata {
     return {};
 }
 
+my $copy_property = sub {
+    my ($src) = @_;
+
+    my $res = {};
+    foreach my $k (keys %$src) {
+       $res->{$k} = $src->{$k};
+    }
+
+    return $res;
+};
+
 sub createSchema {
     my ($class, $skip_type) = @_;
 
@@ -60,17 +71,6 @@ sub createSchema {
 
     my $props = {};
 
-    my $copy_property = sub {
-       my ($src) = @_;
-
-       my $res = {};
-       foreach my $k (keys %$src) {
-           $res->{$k} = $src->{$k};
-       }
-
-       return $res;
-    };
-
     foreach my $p (keys %$propertyList) {
        next if $skip_type && $p eq 'type';
 
@@ -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 '';
     }
diff --git a/test/section_config_test.pl b/test/section_config_test.pl
index 22a9643..02242bc 100755
--- a/test/section_config_test.pl
+++ b/test/section_config_test.pl
@@ -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);
-- 
2.30.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to