Skip to content

Commit

Permalink
Fixes #13667: Add condition_once and execute_once generic methods
Browse files Browse the repository at this point in the history
  • Loading branch information
amousset committed Oct 18, 2018
1 parent 5e744cb commit fc816c3
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 6 deletions.
12 changes: 11 additions & 1 deletion tests/acceptance/20_cfe_basics/flag_lib.cf
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ bundle agent test
"read an existing condition"
usebundle => get_flag("already"),
useresult => "get8";

"reserve"
usebundle => reserve_flag("test3"),
useresult => "reserve9";
"cancel" usebundle => cancel_flag("test3");
"read after"
usebundle => get_flag("test3"),
useresult => "get10";
}

bundle agent check
Expand All @@ -72,8 +80,10 @@ bundle agent check
"ok_6" expression => strcmp("${test.get6[1]}", "set");
"ok_7" expression => strcmp("${test.set7[1]}", "notreserved");
"ok_8" expression => strcmp("${test.get8[1]}", "set");
"ok_9" expression => strcmp("${test.reserve9[1]}", "ok");
"ok_10" expression => strcmp("${test.get10[1]}", "free");

"ok" expression => "ok_1.ok_2.ok_3.ok_4.ok_5.ok_6.ok_7.ok_8";
"ok" expression => "ok_1.ok_2.ok_3.ok_4.ok_5.ok_6.ok_7.ok_8.ok_9.ok_10";

reports:
ok::
Expand Down
75 changes: 75 additions & 0 deletions tests/acceptance/30_generic_methods/command_execution_once.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#######################################################
#
# Test the exit code of shell commands
#
#######################################################

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, initialization, default("${this.promise_filename}") };
version => "1.0";
}

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

bundle agent init
{
methods:
"clean" usebundle => file_absent("${configuration.flag_file}");
}

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

bundle agent test
{
vars:
"ok_codes" string => "0, 2,4";

methods:
"phA" usebundle => command_execution_once("exit 0", "${ok_codes}", "any", "testA");
"phAA" usebundle => command_execution_once("exit 0 ", "${ok_codes}", "any", "testA");

"phB" usebundle => command_execution_once("exit 1", "${ok_codes}", "any", "testB");
"phBB" usebundle => command_execution_once("exit 1 ", "${ok_codes}", "any", "testB");

"phC" usebundle => command_execution_once("exit 2", "${ok_codes}", "ok", "testC");
"phCC" usebundle => command_execution_once("exit 2 ", "${ok_codes}", "ok", "testC");

"phD" usebundle => command_execution_once("exit 3", "${ok_codes}", "ok", "testD");
"phDD" usebundle => command_execution_once("exit 3 ", "${ok_codes}", "ok", "testD");
"phDDD" usebundle => command_execution_once("exit 4", "${ok_codes}", "ok", "testD");
}

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

bundle agent check
{
classes:
"ok_A" expression => "!command_execution_once_exit_0_kept.command_execution_once_exit_0_repaired.!command_execution_once_exit_0_error";
"ok_AA" expression => "command_execution_once_exit_0__kept.!command_execution_once_exit_0__repaired.!command_execution_once_exit_0__error";

"ok_B" expression => "!command_execution_once_exit_1_kept.!command_execution_once_exit_1_repaired.command_execution_once_exit_1_error";
"ok_BB" expression => "command_execution_once_exit_1__kept.!command_execution_once_exit_1__repaired.!command_execution_once_exit_1__error";

"ok_C" expression => "!command_execution_once_exit_2_kept.command_execution_once_exit_2_repaired.!command_execution_once_exit_2_error";
"ok_CC" expression => "command_execution_once_exit_2__kept.!command_execution_once_exit_2__repaired.!command_execution_once_exit_2__error";

"ok_D" expression => "!command_execution_once_exit_3_kept.!command_execution_once_exit_3_repaired.command_execution_once_exit_3_error";
"ok_DD" expression => "!command_execution_once_exit_3__kept.!command_execution_once_exit_3__repaired.command_execution_once_exit_3__error";
"ok_DDD" expression => "!command_execution_once_exit_4_kept.command_execution_once_exit_4_repaired.!command_execution_once_exit_4_error";

"ok" expression => "ok_A.ok_AA.ok_B.ok_BB.ok_C.ok_CC.ok_D.ok_DD.ok_DDD";

reports:
ok::
"$(this.promise_filename) Pass";
!ok::
"$(this.promise_filename) FAIL";
}
63 changes: 63 additions & 0 deletions tests/acceptance/30_generic_methods/condition_once.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#######################################################
#
# Test if only success classes are created
#
#######################################################

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, initialization, default("$(this.promise_filename)") };
version => "1.0";
}

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

bundle agent init
{
methods:
"clean" usebundle => file_absent("${configuration.flag_file}");
}

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

bundle agent test
{
methods:
"ph1" usebundle => condition_once("first");
"enable dry-run" usebundle => set_dry_run_mode("true");
"ph2" usebundle => condition_once("second");
"disable dry-run" usebundle => set_dry_run_mode("false");
"reserve" usebundle => reserve_flag("condition_once_third");
"ph3" usebundle => condition_once("third");
"reserve" usebundle => reserve_flag("condition_once_fourth");
"re-enable" usebundle => set_dry_run_mode("true");
"ph4" usebundle => condition_once("fourth");
"re-disable" usebundle => set_dry_run_mode("true");

}

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

bundle agent check
{
classes:
"ok_class1" expression => "first.condition_once_first_repaired";
"ok_class2" expression => "second.condition_once_second_repaired";
"ok_class3" expression => "!third.condition_once_third_kept.!condition_once_third_repaired";
"ok_class4" expression => "!fourth.condition_once_fourth_kept.!condition_once_fourth_repaired";

"ok" expression => "ok_class1.ok_class2.ok_class3.ok_class4";

reports:
ok::
"$(this.promise_filename) Pass";
!ok::
"$(this.promise_filename) FAIL";
}
19 changes: 15 additions & 4 deletions tree/20_cfe_basics/flag_lib.cf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ bundle agent flag_initialization {
"flag_unique.value" string => "1";
}

bundle agent cancel_flag(name) {
vars:
"cname" string => canonify("${name}");
"cancel" string => "",
classes => if_ok_cancel("flag_reserved_${cname}"),
if => "flag_reserved_${cname}" ;
}

bundle agent reserve_flag(name) {
vars:
"cname" string => canonify("${name}");
Expand Down Expand Up @@ -124,8 +132,7 @@ bundle agent reserve_flag(name) {
comment => "${flag_unique.value}",
if => "free";

pass3::
"Failed, flag '${cname}' was not free"
"Could not reserve flag '${cname}', it was not free"
comment => "${flag_unique.value}",
if => "!free";
}
Expand All @@ -150,6 +157,7 @@ bundle agent set_flag(name) {
template_method => "mustache",
edit_template => "${sys.workdir}/modules/templates/datastate.json.tpl",
template_data => "@{set_flag.output}",
action => immediate_ignore_dry_run,
edit_defaults => no_backup,
classes => classes_generic("write_ncf_flag_${cname}"),
if => "flag_reserved_${cname}";
Expand All @@ -171,14 +179,15 @@ bundle agent set_flag(name) {
comment => "${flag_unique.value}",
if => "!flag_reserved_${cname}";

pass3::
"Flag '${cname}' (created ${time}) could not be set"
comment => "${flag_unique.value}",
if => "write_ncf_flag_${cname}_failed";
"Flag '${cname}' (created ${time}) could not be set as it was not reserved"
comment => "${flag_unique.value}",
if => "!flag_reserved_${cname}";

info::
pass3.info::
"Flag '${cname}' (created ${time}) was set"
comment => "${flag_unique.value}",
if => "write_ncf_flag_${cname}_ok";
Expand All @@ -193,6 +202,8 @@ bundle agent get_flag(name) {

classes:
"is_set" expression => isvariable("ncf_flags.data[${cname}]");
"pass3" expression => "pass2";
"pass2" expression => "pass1";
"pass1" expression => "any";

methods:
Expand All @@ -207,7 +218,7 @@ bundle agent get_flag(name) {
bundle_return_value_index => "1",
comment => "${flag_unique.value}",
if => "!is_set.!flag_reserved_${cname}";
info::
pass3.info::
"Flag '${cname}' is set"
comment => "${flag_unique.value}",
if => "is_set";
Expand Down
103 changes: 103 additions & 0 deletions tree/30_generic_methods/command_execution_once.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#####################################################################################
# Copyright 2018 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 Command execution once
# @description Execute a command and create result conditions depending on its exit code
# @action
# @documentation Execute a command and create result conditions
# depending on the exit codes given in parameters.
# If an exit code is not in the list it will lead to an error status.
# If you want 0 to be a success you have to list it in the kept_codes list
#
# @parameter command The command to run
# @parameter ok_codes List of codes that produce a kept status separated with commas (ex: 1,2,5). Defaults to 0.
# @parameter until Try to execute the command until a particular state: 'ok', 'any' (defaults to 'any')
# @parameter_constraint until "allow_empty_string" : true
# @parameter_constraint until "select" : [ "", "any", "ok" ]
# @parameter unique_id To identify the command (allow to change the command without losing track)
#
# @class_prefix command_execution_once
# @class_parameter command

bundle agent command_execution_once(command, ok_codes, until, unique_id)
{
vars:
"c_unique_id" string => canonify("${unique_id}");
"old_class_prefix" string => canonify("command_execution_once_${command}");
"args" slist => { "${command}", "${ok_codes}", "${until}", "${unique_id}" };
"report_param" string => join("_", args);
"full_class_prefix" string => canonify("command_execution_once_${report_param}");
"class_prefix" string => string_head("${full_class_prefix}", "1000");

"full_inner_class_prefix" string => canonify("command_execution_result_${command}_999_${ok_codes}");
"inner_class_prefix" string => string_head("${full_inner_class_prefix}", "1000");

defaults:
"until" string => "any", if_match_regex => "";
"ok_codes" string => "0", if_match_regex => "";

classes:
"until_ok" expression => strcmp("${until}", "ok");

"reserved" expression => strcmp("${reserve[1]}", "ok");
"already_set" expression => strcmp("${reserve[1]}", "failed");
"set_ok" expression => strcmp("${set[1]}", "ok");

"${c_condition}" expression => "set_ok",
scope => "namespace";

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

methods:
"reserve the flag" usebundle => reserve_flag("command_execution_once_${c_unique_id}"),
useresult => "reserve",
comment => "${report_param}";

reserved::
"run command" usebundle => command_execution_result("${command}", "999", "${ok_codes}");
"new result classes" usebundle => _classes_copy("${inner_class_prefix}", "${class_prefix}");
"result classes" usebundle => _classes_copy("${inner_class_prefix}", "${old_class_prefix}");

"set the flag" usebundle => set_flag("command_execution_once_${c_unique_id}"),
useresult => "set",
comment => "${report_param}",
if => "!until_ok|${class_prefix}_repaired";

"cancel flag" usebundle => cancel_flag("command_execution_once_${c_unique_id}"),
comment => "${report_param}",
if => "until_ok.!${class_prefix}_repaired";

# Problem when writing the flag
pass3.reserved.!set_ok::
"failure" usebundle => _classes_failure("${old_class_prefix}");
"failure" usebundle => _classes_failure("${class_prefix}");

pass3.already_set::
"success" usebundle => _classes_success("${old_class_prefix}");
"success" usebundle => _classes_success("${class_prefix}");

pass3::
"clean" usebundle => _classes_sanitize("${old_class_prefix}");
"clean" usebundle => _classes_sanitize("${class_prefix}");

"report"
usebundle => _log_v3("Execute the command '${command}' once", "${command}", "${old_class_prefix}", "${class_prefix}", @{args});
}
Loading

0 comments on commit fc816c3

Please sign in to comment.