diff --git a/src/PVE/SectionConfig.pm b/src/PVE/SectionConfig.pm index f36cede..97492db 100644 --- a/src/PVE/SectionConfig.pm +++ b/src/PVE/SectionConfig.pm @@ -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);