Skip to content

Commit

Permalink
Merge branch 'v0.x' into v1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Normation GIT merger committed Apr 11, 2017
2 parents a7c1c9d + 5bb0204 commit 817490d
Show file tree
Hide file tree
Showing 3 changed files with 367 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
#######################################################
#
# Test checking if parameter is not present in the list of key-values in a file
#
#######################################################

bundle common acc_path
{
vars:
"root" string => getenv("NCF_TESTS_ACCEPTANCE", 1024);
}

body common control
{
inputs => { "${acc_path.root}/default.cf.sub", "${acc_path.root}/default_ncf.cf.sub", "@{ncf_inputs.default_files}" };
bundlesequence => { configuration, default("${this.promise_filename}") };
version => "1.0";
}

#######################################################

bundle agent init
{
vars:

"tmp" string => getenv("TEMP", 1024);

"file[1]" string => "${tmp}/test1";
"ref_file[1]" string => "${tmp}/ref1";
"file_canon[1]" string => canonify("${file[1]}");

"file[2]" string => "${tmp}/test2";
"ref_file[2]" string => "${tmp}/ref2";
"file_canon[2]" string => canonify("${file[2]}");

"file[3]" string => "${tmp}/test3";
"ref_file[3]" string => "${tmp}/ref3";
"file_canon[3]" string => canonify("${file[3]}");

"file[4]" string => "${tmp}/test4";
"ref_file[4]" string => "${tmp}/ref4";
"file_canon[4]" string => canonify("${file[4]}");

"file[5]" string => "${tmp}/test5";
"ref_file[5]" string => "${tmp}/ref5";
"file_canon[5]" string => canonify("${file[5]}");

"file[6]" string => "${tmp}/test6";
"ref_file[6]" string => "${tmp}/ref6";
"file_canon[6]" string => canonify("${file[6]}");

"file[7]" string => "${tmp}/test7";
"ref_file[7]" string => "${tmp}/ref7";
"file_canon[7]" string => canonify("${file[7]}");

"file[8]" string => "${tmp}/test8";
"ref_file[8]" string => "${tmp}/ref8";
"file_canon[8]" string => canonify("${file[8]}");


"tests_list" slist => getindices("file");
# First test: ensure that a value is correctly removed at the end
"base_text1" string => "# File with lhs=rhs text
JAVA_OPTS=\\\"-Djava.awt.headless=true -XX:+UseConcMarkSweepGC -Xmx1024m\\\"";

"ref_text1" string=> "# File with lhs=rhs text
JAVA_OPTS=\\\"-Djava.awt.headless=true -XX:+UseConcMarkSweepGC\\\"";

"key1" string => "JAVA_OPTS";
"parameter1" string => "-Xmx1024m";
"key_value_separator1" string => "=";
"parameter_separator1" string => " ";

# Second test: ensure that a key-value is correctly remove at the beggining of the line
"base_text2" string => "#
GRUB_CMDLINE_XEN=\\\"dom0_max_vcpus=32 dom0_mem=16G\\\"";

"ref_text2" string=> "#
GRUB_CMDLINE_XEN=\\\"dom0_mem=16G\\\"";

"key2" string => "GRUB_CMDLINE_XEN";
"parameter2" string => "dom0_max_vcpus=32";
"key_value_separator2" string => "=";
"parameter_separator2" string => " ";

# Third test: ensure that if key-value is already correct, nothing is done
"base_text3" string => "# File with lhs rhs text
GRUB_CMDLINE_XEN=\\\"dom0_max_vcpus=32 dom0_mem=16G\\\"";

"ref_text3" string => "# File with lhs rhs text
GRUB_CMDLINE_XEN=\\\"dom0_max_vcpus=32 dom0_mem=16G\\\"";

"key3" string => "GRUB_CMDLINE_XEN";
"parameter3" string => "dom_min_vcpus=5";
"key_value_separator3" string => "=";
"parameter_separator3" string => " ";

# Fourth test: key not present, nothing is done
"base_text4" string => "# File with lhs rhs text
GRUB_CMDLINE_XEN=\\\"dom0_max_vcpus=32 dom0_mem=16G\\\"";

"ref_text4" string => "# File with lhs rhs text
GRUB_CMDLINE_XEN=\\\"dom0_max_vcpus=32 dom0_mem=16G\\\"";

"key4" string => "GRUB_CMDLINE";
"parameter4" string => "dom0_max_vcpus=32";
"key_value_separator4" string => "=";
"parameter_separator4" string => " ";

# Fifth test: key present, value to be removed no quote separator
"base_text5" string => "# File with lhs rhs text
GRUB_CMDLINE_XEN=dom0_max_vcpus=32 dom0_mem=16G";

"ref_text5" string => "# File with lhs rhs text
GRUB_CMDLINE_XEN=dom0_mem=16G";

"key5" string => "GRUB_CMDLINE_XEN";
"parameter5" string => "dom0_max_vcpus=32";
"key_value_separator5" string => "=";
"parameter_separator5" string => " ";

# sixth test: key present, start and stop separator different
"base_text6" string => "# JS conf file
some.js.config.file = [ 'value1', 'value2', 'value3', 'value4']";

"ref_text6" string => "# JS conf file
some.js.config.file = [ 'value1', 'value2', 'value3']";

"key6" string => "some.js.config.file";
"parameter6" string => "'value4'";
"key_value_separator6" string => "=";
"parameter_separator6" string => ",";
"leading_char6" string => "[";
"closing_char6" string => "]";

# seventh test: key and value present, start and stop separator different
"base_text7" string => "# JS conf file
some.js.config.file = [ 'value1', 'value2', 'value3', 'value4' ]";

"ref_text7" string => "# JS conf file
some.js.config.file = [ 'value1', 'value2', 'value4' ]";

"key7" string => "some.js.config.file";
"parameter7" string => "'value3'";
"key_value_separator7" string => "=";
"parameter_separator7" string => ", ";
"leading_char7" string => "[";
"closing_char7" string => "]";

# eighth test: key not present and value present, start and stop separator different
"base_text8" string => "# JS conf file
some.js.config.file = [ 'value1', 'value2', 'value3', 'value4' ]";

"ref_text8" string => "# JS conf file
some.js.config.file = [ 'value1', 'value2', 'value3', 'value4' ]";

"key8" string => "js.config.file";
"parameter8" string => "'value4'";
"key_value_separator8" string => "=";
"parameter_separator8" string => ", ";
"leading_char8" string => "[";
"closing_char8" string => "]";


commands:
# Initialize test and reference files
"/bin/echo"
args => "\"${ref_text${tests_list}}\" > \"${ref_file[${tests_list}]}\"",
contain => in_shell;
"/bin/echo"
args => "\"${base_text${tests_list}}\" > \"${file[${tests_list}]}\"",
contain => in_shell;

}

#######################################################

bundle agent test
{
methods:
"removed key1" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[1]}", "${init.key1}", "${init.key_value_separator1}", "${init.parameter1}", "${init.parameter_separator1}", "\"", "\"");
"removed key2" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[2]}", "${init.key2}", "${init.key_value_separator2}", "${init.parameter2}", "${init.parameter_separator2}", "\"", "\"");
"success key" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[3]}", "${init.key3}", "${init.key_value_separator3}", "${init.parameter3}", "${init.parameter_separator3}", "\"", "\"");
"success key2" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[4]}", "${init.key4}", "${init.key_value_separator4}", "${init.parameter4}", "${init.parameter_separator4}", "", "");
"removed_key3" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[5]}", "${init.key5}", "${init.key_value_separator5}", "${init.parameter5}", "${init.parameter_separator5}", "", "");

"removed key4" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[6]}", "${init.key6}", "${init.key_value_separator6}", "${init.parameter6}", "${init.parameter_separator6}", "${init.leading_char6}", "${init.closing_char6}");
"removed key5" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[7]}", "${init.key7}", "${init.key_value_separator7}", "${init.parameter7}", "${init.parameter_separator7}", "${init.leading_char7}", "${init.closing_char7}");
"success key3" usebundle => file_ensure_key_value_parameter_not_in_list("${init.file[8]}", "${init.key8}", "${init.key_value_separator8}", "${init.parameter8}", "${init.parameter_separator8}", "${init.leading_char8}", "${init.closing_char8}");

}

#######################################################

bundle agent check
{
vars:
"file_diff_test[${init.tests_list}]" string => "/usr/bin/diff \"${init.ref_file[${init.tests_list}]}\" \"${init.file[${init.tests_list}]}\"";

classes:
"file${init.tests_list}_correct"
expression => returnszero("${file_diff_test[${init.tests_list}]}", "noshell"),
ifvarclass => canonify("file_ensure_key_value_parameter_not_in_list_${init.file_canon[${init.tests_list}]}_reached");

"ok_test1" expression => "file1_correct.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[1]}_kept.file_ensure_key_value_parameter_not_in_list_${init.file_canon[1]}_repaired.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[1]}_not_ok";
"ok_test2" expression => "file2_correct.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[2]}_kept.file_ensure_key_value_parameter_not_in_list_${init.file_canon[2]}_repaired.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[2]}_not_ok";
"ok_test3" expression => "file3_correct.file_ensure_key_value_parameter_not_in_list_${init.file_canon[3]}_kept.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[3]}_not_ok.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[3]}_repaired";
"ok_test4" expression => "file4_correct.file_ensure_key_value_parameter_not_in_list_${init.file_canon[4]}_kept.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[4]}_not_ok.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[4]}_repaired";
"ok_test5" expression => "file5_correct.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[5]}_kept.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[5]}_not_ok.file_ensure_key_value_parameter_not_in_list_${init.file_canon[5]}_repaired";

"ok_test6" expression => "file6_correct.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[6]}_kept.file_ensure_key_value_parameter_not_in_list_${init.file_canon[6]}_repaired.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[6]}_not_ok";
"ok_test7" expression => "file7_correct.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[7]}_kept.file_ensure_key_value_parameter_not_in_list_${init.file_canon[7]}_repaired.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[7]}_not_ok";
"ok_test8" expression => "file8_correct.file_ensure_key_value_parameter_not_in_list_${init.file_canon[8]}_kept.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[8]}_not_ok.!file_ensure_key_value_parameter_not_in_list_${init.file_canon[8]}_repaired";

"ok" and => {"ok_test1","ok_test2","ok_test3", "ok_test4", "ok_test5", "ok_test6", "ok_test7", "ok_test8" };


reports:
ok::
"$(this.promise_filename) Pass";
!ok::
"$(this.promise_filename) FAIL";
cfengine::
"diff command doesn't returns 0 for file ${init.tests_list} (command ${file_diff_test[${init.tests_list}]})"
ifvarclass => "!file${init.tests_list}_correct";

file1_correct.!ok_test1::
"Generic method return is invalid for first test (expected repaired)";
file2_correct.!ok_test3::
"Generic method return is invalid for second test (expected repaired)";
file3_correct.!ok_test3::
"Generic method return is invalid for third test (expected kept)";
file4_correct.!ok_test4::
"Generic method return is invalid for fourth test (expected kept)";
file5_correct.!ok_test5::
"Generic method return is invalid for fifth test (expected repaired)";
file6_correct.!ok_test6::
"Generic method return is invalid for sixth test (expected repaired)";
file7_correct.!ok_test7::
"Generic method return is invalid for seventh test (expected repaired)";
file8_correct.!ok_test8::
"Generic method return is invalid for eighth test (expected kept)";

}
14 changes: 14 additions & 0 deletions tree/20_cfe_basics/ncf_lib.cf
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,20 @@ bundle edit_line ncf_add_parameter_in_list_with_enclosing_chars(key, key_value_s
replace_with => ncf_add_parameter_with_separator_and_enclosing_characters("${parameter}", "${parameter_separator}");
}

# Remove parameter_regex in key->[values] line, where -> is key_value_separator and [ ] are leading and closing char separator. Note: any whitespace between parameter_regex and parameter_separator will be also removed
bundle edit_line ncf_remove_parameter_in_list(key, key_value_separator, parameter_separator, parameter_regex, leading_char_separator, closing_char_separator) {
vars:
"escaped_key" string => escape("${key}");
"escaped_leading_char" string => escape("${leading_char_separator}");
"escaped_closing_char" string => escape("${closing_char_separator}");

replace_patterns:
"^(${escaped_key}\s*${key_value_separator}\s*${escaped_leading_char}.*)(${parameter_separator}+\s*${parameter_regex}|${parameter_regex}\s*${parameter_separator}+)(.*${escaped_closing_char})\s*$"
replace_with => value("${match.1}${match.3}");

}


body replace_with ncf_add_parameter_with_separator(parameter, parameter_separator) {
occurrences => "first";
replace_value => "${match.1}${match.2}${parameter_separator}${parameter}";
Expand Down
109 changes: 109 additions & 0 deletions tree/30_generic_methods/file_ensure_key_value_parameter_not_in_list.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#####################################################################################
# Copyright 2017 Normation SAS
#####################################################################################
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#####################################################################################

# @name File ensure key value parameter not in list
# @description Ensure that a parameter doesn't exist in a list of parameters, on one single line, in the right hand side of a key->values line
# @documentation Edit the file, and ensure it does not contain the defined parameter in the list of values on the right hand side of a key->values line.
# If the parameter is there, it will be removed. Please note that the parameter can be a regular expression. It will also remove any whitespace character between the parameter and parameter_separator
# Optionnaly, you can define leading and closing character to enclose the parameters
#
# #### Example
#
# If you have an initial file (`/etc/default/grub`) containing
#
# ```
# GRUB_CMDLINE_XEN="dom0_mem=16G dom0_max_vcpus=32"
# ```
#
# To remove parameter `dom0_max_vcpus=32` in the right hand side of the line, you'll need the following policy
#
# ```
# file_ensure_key_value_parameter_not_in_list("/etc/default/grub", "GRUB_CMDLINE", "=", "dom0_max_vcpus=32", " ", "\"", "\"");
# ```
#
# @parameter file File name to edit
# @parameter key Full key name
# @parameter key_value_separator character used to separate key and value in a key-value line
# @parameter parameter_regex Regular expression matching the sub-value to ensure is not present in the list of parameters that form the value part of that line
# @parameter parameter_separator Character used to separate parameters in the list
# @parameter leading_char_separator leading character of the parameters
# @parameter closing_char_separator closing character of the parameters
# @parameter_constraint key_value_separator "allow_whitespace_string" : true
# @parameter_constraint parameter_separator "allow_whitespace_string" : true
# @parameter_constraint leading_char_separator "allow_empty_string" : true
# @parameter_constraint closing_char_separator "allow_empty_string" : true
#
# @class_prefix file_ensure_key_value_parameter_not_in_list
# @class_parameter file

bundle agent file_ensure_key_value_parameter_not_in_list(file, key, key_value_separator, parameter_regex, parameter_separator, leading_char_separator, closing_char_separator)
{
vars:
"class_prefix" string => canonify("file_ensure_key_value_parameter_not_in_list_${file}");

"escaped_key" string => escape("${key}");
"escaped_parameter" string => escape("${parameter_regex}");

"escaped_leading_char" string => escape("${leading_char_separator}");
"escaped_closing_char" string => escape("${closing_char_separator}");

classes:
"leading_char_defined" not => strcmp("${leading_char_separator}", "");
"closing_char_defined" not => strcmp("${closing_char_separator}", "");

"invalid_enclosing" expression => "(leading_char_defined.!closing_char_defined)|(!leading_char_defined.closing_char_defined)";
"defined_enclosing" expression => "leading_char_defined.closing_char_defined";

defined_enclosing.!pass1::
"line_with_parameter_present" expression => regline("^(${key}\s*${key_value_separator}\s*)${escaped_leading_char}.*(${parameter_separator})?${parameter_regex}(${parameter_separator})?.*(${escaped_closing_char})\s*$", "${file}");

!defined_enclosing.!invalid_enclosing.!pass1::
"line_with_parameter_present" expression => regline("^(${key}\s*${key_value_separator}\s*).*(${parameter_separator})?${parameter_regex}(${parameter_separator})?.*$", "${file}");

!pass1::
"line_with_key_present" expression => regline("^(${key}\s*${key_value_separator}\s*).*$", "${file}");

any::
"pass2" expression => "pass1";
"pass1" expression => "any";

files:
line_with_parameter_present.!invalid_enclosing::
"${file}"
edit_line => ncf_remove_parameter_in_list("${key}", "${key_value_separator}", "${parameter_separator}", "${parameter_regex}", "${leading_char_separator}", "${closing_char_separator}"),
edit_defaults => ncf_empty_select("false"),
classes => classes_generic("${class_prefix}"),
# This comment is necessary, see https://www.rudder-project.org/redmine/issues/10153
comment => "Editing file ${file} to remove parameter ${leading_char_separator} ${parameter_regex} ${closing_char_separator} for key ${key}";

methods:
pass2::
"success class" usebundle => _classes_success("${class_prefix}"),
ifvarclass => "!line_with_parameter_present";
"error_class" usebundle => _classes_failure("${class_prefix}"),
ifvarclass => "invalid_enclosing";

pass2.!invalid_enclosing.line_with_key_present::
"report" usebundle => _logger("Ensure ${parameter_regex} is not in ${key}${key_value_separator} values in ${file}", "${class_prefix}");

pass2.!invalid_enclosing.!line_with_key_present::
"report" usebundle => _logger("Non existing key ${key} with value ${leading_char_separator} ${parameter_regex} ${closing_char_separator} in ${file}", "${class_prefix}");

pass2.invalid_enclosing::
"report" usebundle => _logger("Ensure not ${parameter_regex} in line ${key}${key_value_separator} values in ${file} must have either no enclosing character, or two, but not only one", "${class_prefix}");
}

0 comments on commit 817490d

Please sign in to comment.