Skip to content

Commit

Permalink
RuleBaseEditor.pm: address initial comments by @stdweird in quattor#151
Browse files Browse the repository at this point in the history
  • Loading branch information
jouvin committed Apr 24, 2016
1 parent 32882db commit cef896e
Showing 1 changed file with 199 additions and 129 deletions.
328 changes: 199 additions & 129 deletions src/main/perl/RuleBasedEditor.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2,124 +2,28 @@
# ${developer-info}
# ${author-info}
# ${build-info}
#
#
# This module implements a rule-based editor that is used to modify the content
# of an existing file without taking care of the whole file. Each rule
# driving the edition process is applied to all matching lines. The input for
# updating the file is the Quattor configuration and conditions can be defined
# based on the contents of this configuration.
#
# This module is a subclass of the CAF FileEditor: it extends the base methods of
# the CAF FileEditor. In addition to the constructor it has only one public method.
# The methods provided in this module can be used at the same time as the
# base methods of the FileEditor.
#
#
#######################################################################

package CAF::RuleBasedEditor;

use strict;
use warnings;
use vars qw(@ISA $EC);
$EC=LC::Exception::Context->new->will_store_all;

use parent qw(CAF::FileEditor Exporter);

use EDG::WP4::CCM::Element;

use Readonly;

use Encode qw(encode_utf8);

local(*DTA);

# Constants from FileEditor
use CAF::FileEditor qw(BEGINNING_OF_FILE ENDING_OF_FILE);


#########################################################
# Constants use to format lines in configuration files. #
# These constants are exported. #
#########################################################

# LINE_FORMAT_xxx: general syntax of the line (key/val format)
# LINE_FORMAT_SH_VAR: key=val (e.g. SH shell family)
# LINE_FORMAT_ENV_VAR: export key=val (e.g. SH shell family)
# LINE_FORMAT_KEY_VAL: key val (e.g. Xrootd, Apache)
# LINE_FORMAT_KEY_VAL_SETENV: setenv key val (used by Xrootd in particular)
# LINE_FORMAT_KEY_VAL_SET: set key val (used by Xrootd in particular)
use enum qw(LINE_FORMAT_SH_VAR=1
LINE_FORMAT_ENV_VAR
LINE_FORMAT_KEY_VAL
LINE_FORMAT_KEY_VAL_SETENV
LINE_FORMAT_KEY_VAL_SET
);

# LINE_VALUE_xxx: how to interpret the configuration value
# LINE_VALUE_INSTANCE_PARAMS is specific to Xrootd.
use enum qw(LINE_VALUE_AS_IS
LINE_VALUE_BOOLEAN
LINE_VALUE_ARRAY
LINE_VALUE_HASH_KEYS
LINE_VALUE_STRING_HASH
LINE_VALUE_INSTANCE_PARAMS
);

# LINE_VALUE_OPT_xxx: options for rendering the value
# (mainly apply to lists and dictionnaries)
use enum qw(BITMASK: LINE_VALUE_OPT_SINGLE
LINE_VALUE_OPT_UNIQUE
LINE_VALUE_OPT_SORTED
);

# Internal constants
Readonly my $LINE_FORMAT_DEFAULT => LINE_FORMAT_SH_VAR;
Readonly my $LINE_QUATTOR_COMMENT => "\t\t# Line generated by Quattor";
Readonly my $LINE_OPT_DEF_REMOVE_IF_UNDEF => 0;
Readonly my $LINE_OPT_DEF_ALWAYS_RULES_ONLY => 0;
Readonly my $RULE_CONDITION_ALWAYS => 'ALWAYS';
Readonly my $RULE_OPTION_SET_GLOBAL => 'GLOBAL';


# Export constants used to build rules
Readonly my @RULE_CONSTANTS => qw(LINE_FORMAT_SH_VAR
LINE_FORMAT_ENV_VAR
LINE_FORMAT_KEY_VAL
LINE_FORMAT_KEY_VAL_SETENV
LINE_FORMAT_KEY_VAL_SET
LINE_VALUE_AS_IS
LINE_VALUE_BOOLEAN
LINE_VALUE_INSTANCE_PARAMS
LINE_VALUE_ARRAY
LINE_VALUE_HASH_KEYS
LINE_VALUE_STRING_HASH
LINE_VALUE_OPT_SINGLE
LINE_VALUE_OPT_UNIQUE
LINE_VALUE_OPT_SORTED
);
our @EXPORT_OK;
our %EXPORT_TAGS;
push @EXPORT_OK, @RULE_CONSTANTS;
$EXPORT_TAGS{rule_constants} = \@RULE_CONSTANTS;


# Backup file extension
Readonly my $BACKUP_FILE_EXT => ".old";


=pod
=head1 DESCRIPTION
This module implements a rule-based editor. It is a subclass of the B<CAF::FileEditor>
and extends it. In addition to the constructor, it has only
one public method: B<updatefile> (see below).
This module implements a rule-based editor that is used to modify the content
of an existing file without taking care of the whole file. Each rule
driving the edition process is applied to all matching lines. The input for
updating the file is the Quattor configuration and conditions can be defined
based on the contents of this configuration.
This module is a subclass of the L<CAF::FileEditor>: it extends the base methods of
the CAF FileEditor. In addition to the constructor it has only one public method.
The methods provided in this module can be used at the same time as the
base methods of the L<CAF::FileEditor>.
Rules used to edit the file are defined as hashes: each entry defines a rule.
Multiple rules can be applied to the same file: it is important that they are
orthogonal, else the result is unpredictable.
orthogonal, else the result is unpredictable. The order used to apply rules is undefined.
The result of applying the rules with the same configuration is idempotent when starting
from the same initial file but sucessive edition of a file (with different configuration values)
may not necessarily be idempotent (in general they are).
The hash entry key represents the line keyword in configuration file and
hash value is the parsing rule for the keyword value. Parsing rule format is :
Expand All @@ -133,7 +37,7 @@ matching line must be removed/commented out if the option is undefined.
=over
=item condtion
=item condition
an option or an option set that must exist for the rule to be applied.
Both option_set and option_name:option_set are accepted (see below).
Expand Down Expand Up @@ -162,23 +66,23 @@ supported (see LINE_FORMAT_xxx constants below):
=item
a sh shell environment variable definition (export VAR=val)
a SH shell environment variable definition (export key=val).
=item
a sh shell variable definition (VAR=val)
a SH shell variable definition (key=val).
=item
a 'keyword value' line, as used by Xrootd or Apache config files.
=item
a 'setenv keyword value' line, as used by Xrootd config files mainly.
a 'setenv keyword value' line, as used by Xrootd config files mainly. It can also be used in a CSH shell script.
=item
a 'set keyword value' line, as used by Xrootd config files mainly.
a 'set keyword value' line, as used by Xrootd config files mainly. It doesn't work in a CSH shell script (C<=> missing).
=back
Expand All @@ -196,31 +100,197 @@ boolean values, list and hashes. See LINE_VALUE_xxx constants below for the poss
=back
For an example of rules, look at ncm-dpmlfc or ncm-xrootd source code in
An example of rule declaration is:
my %dpm_config_rules_2 = (
"ALLOW_COREDUMP" => "allowCoreDump:dpm;".LINE_FORMAT_SH_VAR.";".LINE_VALUE_BOOLEAN,
"GLOBUS_THREAD_MODEL" => "globusThreadModel:dpm;".LINE_FORMAT_ENV_VAR,
"DISKFLAGS" =>"DiskFlags:dpm;".LINE_FORMAT_SH_VAR.";".LINE_VALUE_ARRAY,
);
For more comprehensive examples of rules, look at L<ncm-dpmlfc> or L<ncm-xrootd> source code in
configuration-modules-grid repository.
=cut


package CAF::RuleBasedEditor;

use strict;
use warnings;
use vars qw($EC);
$EC=LC::Exception::Context->new->will_store_all;

use parent qw(CAF::FileEditor Exporter);

use EDG::WP4::CCM::Element;

use Readonly;

use Encode qw(encode_utf8);

# Constants from FileEditor
use CAF::FileEditor qw(BEGINNING_OF_FILE ENDING_OF_FILE);


=pod
=head2 Rule Constants
The constants described here are used to build the rules. All these
constants are exported. Add the following to use them:
use RuleBasedEditor qw(:rule_constants);
There is a different group of constants for each part of the rule.
=head2 Public methods
=head3 LINE_FORMAT_xxx: general syntax of the line
=over
=item new
=item
This is the constructor. It mainly executes the FileEditor constructor and supports the
same arguments.
LINE_FORMAT_SH_VAR: key=val (e.g. SH shell family)
==cut
=item
sub new
{
my $class = shift;
my $self = $class->SUPER::new (@_);
return $self;
}
LINE_FORMAT_ENV_VAR: export key=val (e.g. SH shell family)
=item
LINE_FORMAT_KEY_VAL: key val (e.g. Xrootd, Apache)
=item
LINE_FORMAT_KEY_VAL_SETENV: setenv key val (used by Xrootd in particular)
=item
LINE_FORMAT_KEY_VAL_SET: set key val (used by Xrootd in particular)
=back
=cut

use enum qw(LINE_FORMAT_SH_VAR=1
LINE_FORMAT_ENV_VAR
LINE_FORMAT_KEY_VAL
LINE_FORMAT_KEY_VAL_SETENV
LINE_FORMAT_KEY_VAL_SET
);

=pod
=head3
LINE_VALUE_xxx: how to interpret the configuration value
=over
=item
LINE_VALUE_AS_IS: take the value as it is, do not attempt any conversion
=item
LINE_VALUE_BOOLEAN: interpret the value as a boolean rendered as C<yes> or C<no>
=item
LINE_VALUE_ARRAY: the value is an array. Rendering controlled by LINE_VALUE_OPT_xxx constants.
=item
LINE_VALUE_HASH_KEYS: the value is hash whose keys are the value. Rendering similar to arrays.
=item
LINE_VALUE_STRING_HASH: the value is a hash of string. Rendering controlled by LINE_VALUE_OPT_xxx constants.
=item
LINE_VALUE_INSTANCE_PARAMS: specific to L<ncm-xrootd>
=back
=cut

use enum qw(LINE_VALUE_AS_IS
LINE_VALUE_BOOLEAN
LINE_VALUE_ARRAY
LINE_VALUE_HASH_KEYS
LINE_VALUE_STRING_HASH
LINE_VALUE_INSTANCE_PARAMS
);

=pod
=head3 LINE_VALUE_OPT_xxx: options for rendering the value
These options mainly apply to lists and hashes and are interpreted as a bitmask.
=item
LINE_VALUE_OPT_SINGLE: each value must be a separate instance of the keyword (multiple lines)
=item
LINE_VALUE_OPT_UNIQUE: each values are concataneted as a space-separated string
=item
LINE_VALUE_OPT_SORTED: values are sorted
=cut

use enum qw(BITMASK: LINE_VALUE_OPT_SINGLE
LINE_VALUE_OPT_UNIQUE
LINE_VALUE_OPT_SORTED
);

# Internal constants
Readonly my $LINE_FORMAT_DEFAULT => LINE_FORMAT_SH_VAR;
Readonly my $LINE_QUATTOR_COMMENT => "\t\t# Line generated by Quattor";
Readonly my $LINE_OPT_DEF_REMOVE_IF_UNDEF => 0;
Readonly my $LINE_OPT_DEF_ALWAYS_RULES_ONLY => 0;
Readonly my $RULE_CONDITION_ALWAYS => 'ALWAYS';
Readonly my $RULE_OPTION_SET_GLOBAL => 'GLOBAL';


# Export constants used to build rules
# Needs to be updated when a constant is added or removed
Readonly my @RULE_CONSTANTS => qw(LINE_FORMAT_SH_VAR
LINE_FORMAT_ENV_VAR
LINE_FORMAT_KEY_VAL
LINE_FORMAT_KEY_VAL_SETENV
LINE_FORMAT_KEY_VAL_SET
LINE_VALUE_AS_IS
LINE_VALUE_BOOLEAN
LINE_VALUE_INSTANCE_PARAMS
LINE_VALUE_ARRAY
LINE_VALUE_HASH_KEYS
LINE_VALUE_STRING_HASH
LINE_VALUE_OPT_SINGLE
LINE_VALUE_OPT_UNIQUE
LINE_VALUE_OPT_SORTED
);


our @EXPORT_OK;
our %EXPORT_TAGS;
push @EXPORT_OK, @RULE_CONSTANTS;
$EXPORT_TAGS{rule_constants} = \@RULE_CONSTANTS;


# Backup file extension
Readonly my $BACKUP_FILE_EXT => ".old";

=pod
=head2 Public methods
=over
=item updateFile
Update configuration file contents, applying configuration rules.
Expand Down Expand Up @@ -259,9 +329,9 @@ sub updateFile {
$self->seek_begin();

# Check that config file has an appropriate header
my $intro_pattern = "# This file is managed by Quattor";
Readonly my $INTRO_PATTERN => "# This file is managed by Quattor";
my $intro = "# This file is managed by Quattor - DO NOT EDIT lines generated by Quattor";
$self->add_or_replace_lines(qr/^$intro_pattern/,
$self->add_or_replace_lines(qr/^$INTRO_PATTERN/,
qr/^$intro$/,
$intro."\n#\n",
BEGINNING_OF_FILE,
Expand Down

0 comments on commit cef896e

Please sign in to comment.