Config-Model-Systemd
view release on metacpan or search on metacpan
contrib/parse-man.pl view on Meta::CPAN
my @choices;
# handle "Takes the same settings as ..." (seen only for enum)
if ($desc =~ /takes the same values as the (?:setting )?C<(\w+)>/i) {
my $other = $1;
my $other_obj = $obj->grab("- element:$other");
@choices = $other_obj->fetch_element('choice')->fetch;
say "Copy enum choices from $other to ", $obj->location;
}
elsif ($extra_info =~ /\w\|\w/) {
@choices = split /\|/, $extra_info ;
}
elsif ($desc =~ /Takes a boolean (argument,? )?or /) {
my ($choices) = ($desc =~ /Takes a boolean (?:argument,? )?or (?:the )?(?:special values|architecture identifiers\s*)?([^.]+?)\./);
@choices = ('no','yes');
push @choices, extract_choices($choices);
push @load, qw/replace:false=no replace:true=yes replace:0=no replace:1=yes/;
}
if ($desc =~ /Takes one of/) {
my ($choices) = ($desc =~ /Takes one of ([^.]+?)(?:\.|to test)/);
@choices = extract_choices($choices);
}
die "Error in $config_class: cannot find the values of $element enum type from «$desc»\n"
unless @choices;
push @log, "enum choices are '".join("', '", sort @choices)."'";
push @load_extra, 'choice='.join(',',sort @choices);
}
push @load_extra, "min=$min" if defined $min;
push @load_extra, "max=$max" if defined $max;
if ($value_type eq 'integer' and $desc =~ /defaults? (?:value )?(?:to|is) (\d+)/i) {
push @load_extra, "upstream_default=$1" ;
}
if ($value_type eq 'enum' and $desc =~ /Defaults? (?:value )?(?:to|is) (\w+)\./) {
my $v = ($1 =~ s/true|on/yes/r);
$v =~ s/false|off/no/;
push @load_extra, "upstream_default=$v" ;
}
if ($value_type eq 'boolean' and $desc =~ /Defaults? (?:value )?(?:to|is) (C<)?(true|on|yes)>?\./) {
push @load_extra, "upstream_default=yes" ;
}
if ($value_type eq 'boolean' and $desc =~ /Defaults? (?:value )?(?:to|is) (C<)?(false|off|no)>?\./) {
push @load_extra, "upstream_default=no" ;
}
if ($supersedes) {
push @load_extra, "status=deprecated";
push @log, "deprecated in favor of $supersedes";
# put migration in place for the other element
my $new = $meta_root->grab(
step => "class:$config_class element:$supersedes",
autoadd => 1
);
$new->load(steps => qq!migrate_from variables:old="- $element" formula="\$old"!);
}
$obj->load(step => [@load, @load_extra]);
say "class $config_class element $element:\n\t".join("\n\t", @log) if @log;
return $obj;
}
sub extract_choices($choices) {
my @choices = ($choices =~ m!C<([/\w\-+]+)>!g );
if ($choices =~ m{possibly prefixed with (?:a )?C<([!\w]+)>} ) {
push @choices, map { "$1$_"} @choices;
}
return @choices;
}
sub move_deprecated_element ($meta_root, $from, $to) {
say "Handling move of service/$from to unit/$to...";
# create deprecated moved element in Service for backward compat
my $warn = $from eq $to ? "$from is now part of Unit."
: "service/$from is now Unit/$to.";
$meta_root->load( steps => [
'class:Systemd::Section::Service',
qq!element:$from type=leaf value_type=uniline status=deprecated!,
qq!warn="$warn"!
]);
# Due to the fact that Unit are used in Service, Timer, Socket but
# only Service needs backward compat, a special Unit class is created
# for each Service.
# Saving $to definition stored from data extracted from Systemd
# doc
my $from_element_dump = $meta_root->grab(
"class:Systemd::Section::Unit element:$to"
)->dump_tree;
# remove $from element from common Unit class
$meta_root->load("class:Systemd::Section::Unit element:.rm($to)");
foreach my $service (@service_list) {
my $unit_class = "Systemd::Section::". ucfirst($service).'Unit';
# inject $from element in Special Unit class
$meta_root
->grab("class:$unit_class element:$to")
->load($from_element_dump);
# make sure that special Unit class provide all elements from
# common Unit class
$meta_root->load(steps => [
"class:$unit_class include=Systemd::Section::Unit",
'accept:".*" type=leaf value_type=uniline warn="$unknown_param_msg"'
]);
}
# inject the migration instruction that retrieve $from element setting
# from Service class (where it's deprecated) and copy them to the new
# $from element in Unit class in a service file (hence this migration
# instruction is done only in ServiceUnit class)
$meta_root->load( steps => [
qq!class:Systemd::Section::ServiceUnit element:$to!,
qq!migrate_from variables:service="- - Service $from" formula="\$service"!
]);
}
my $data = parse_xml([@list, @service_list], \%map) ;
# Itself constructor returns an object to read or write the data
# structure containing the model to be edited
my $rw_obj = Config::Model::Itself -> new () ;
# now load the existing model to be edited
$rw_obj -> read_all() ;
my $meta_root = $rw_obj->meta_root;
# remove old generated classes
foreach my $config_class ($meta_root->fetch_element('class')->fetch_all_indexes) {
my $gen = $meta_root->grab_value(
step => qq!class:$config_class generated_by!,
mode => 'loose',
);
next unless $gen and $gen =~ /parse-man/;
$meta_root->load(qq!class:-$config_class!);
}
say "Creating systemd model...";
foreach my $config_class (keys $data->{class}->%*) {
say "Creating model class $config_class";
my $desc_ref = $data->{class}{$config_class};
# cleanup leading white space and add formatting
my $desc_text = join("\n\n", map { s/\n[\t ]+/\n/gr =~ s/C<([A-Z]\w+)=>/C<$1>/gr;} $desc_ref->@*);
$desc_text.="\nThis configuration class was generated from systemd documentation.\n"
."by L<parse-man.pl|https://github.com/dod38fr/config-model-systemd/contrib/parse-man.pl>\n";
# detect verbatim parts setup with programlisting tag
$desc_text =~ s/^\+-\+/ /gm;
my $steps = "class:$config_class class_description";
$meta_root->grab(step => $steps, autoadd => 1)->store($desc_text);
$meta_root->load( steps => [
qq!class:$config_class generated_by="parse-man.pl from systemd $systemd_version doc"!,
qq!copyright:0="2010-2016 Lennart Poettering and others"!,
qq!copyright:1="2016 Dominique Dumont"!,
qq!license="LGPLv2.1+"!,
qq!accept:".*" type=leaf value_type=uniline warn="$unknown_param_msg"!,
]);
}
foreach my $cdata ($data->{element}->@*) {
my ($config_class, $element, $desc, $extra_info, $supersedes) = $cdata->@*;
my $obj = setup_element ($meta_root, $config_class, $element, $desc, $extra_info, $supersedes);
$desc =~ s/ +$//gm;
$obj->fetch_element("description")->store(wrap('','',$desc));
}
contrib/parse-man.pl view on Meta::CPAN
$meta_root->load(
qq!
class:Systemd::StandAlone::$name
element:$name
type=node
config_class_name=$sub_class -
element:Unit
type=node
config_class_name=Systemd::Section::$unit_class -
element:Install
type=node
config_class_name=Systemd::Section::Install -
rw_config
backend=Systemd::Unit
auto_delete=1
auto_create=1 !
);
# Link the class above to base Systemd class
$meta_root->load(
qq!
class:Systemd
generated_by="parse-man.pl from systemd doc"
element:$service
type=hash
index_type=string
cargo
type=node
config_class_name=Systemd::$name - -
rw_config
backend=Systemd
auto_create=1
auto_delete=1 -
!
);
}
my @moved = qw/FailureAction SuccessAction StartLimitBurst StartLimitInterval RebootArgument/;
my %move_target = qw/StartLimitInterval StartLimitIntervalSec/;
# check also src/core/load-fragment-gperf.gperf.m4 is systemd source
# for "compatibility" elements
foreach my $from (@moved) {
my $to = $move_target{$from} || $from;
move_deprecated_element($meta_root, $from, $to);
}
# StartLimitInterval is also deprecated in Unit
say "Handling move of StartLimitInterval to StartLimitIntervalSec in unit";
$meta_root->load( steps => [
'class:Systemd::Section::Unit',
qq!element:StartLimitInterval type=leaf value_type=uniline status=deprecated!,
qq!warn="StartLimitInterval is now StartLimitIntervalSec."!
]);
# handle migration from both service and unit
$meta_root->load( steps => [
qq!class:Systemd::Section::ServiceUnit element:StartLimitIntervalSec!,
qq!migrate_from variables:unit="- StartLimitInterval"!,
# $service variable is defined in move_deprecated element function
q!use_eval=1 formula="$unit || $service"!
]);
# renamed element in Unit
say "Handling move of OnFailureIsolate to OnFailureJobMode in unit";
$meta_root->load( steps => [
'class:Systemd::Section::Unit',
q!element:OnFailureIsolate type=leaf value_type=uniline status=deprecated!,
q!warn="OnFailureIsolate is now OnFailureJobMode." -!,
q!element:OnFailureJobMode!,
q!migrate_from variables:unit="- OnFailureIsolate"!,
q!formula="$unit"!
]);
say "Saving systemd model...";
$rw_obj->write_all;
say "Done.";
( run in 0.673 second using v1.01-cache-2.11-cpan-df04353d9ac )