From 24038f65685c4b02be915c9512a67476e98b5b6e Mon Sep 17 00:00:00 2001 From: Nicolas CHARLES Date: Sun, 15 Dec 2013 10:05:34 +0100 Subject: [PATCH] Fixes #4268: ensure section in block --- .../file_ensure_block_in_section.cf | 76 +++++++++++++++++++ tree/20_cfe_basics/ncf_lib.cf | 36 +++++++++ .../file_ensure_block_in_section.cf | 46 +++++++++++ 3 files changed, 158 insertions(+) create mode 100644 tests/acceptance/30_generic_methods/file_ensure_block_in_section.cf create mode 100644 tree/30_generic_methods/file_ensure_block_in_section.cf diff --git a/tests/acceptance/30_generic_methods/file_ensure_block_in_section.cf b/tests/acceptance/30_generic_methods/file_ensure_block_in_section.cf new file mode 100644 index 000000000..5e7404ca3 --- /dev/null +++ b/tests/acceptance/30_generic_methods/file_ensure_block_in_section.cf @@ -0,0 +1,76 @@ +####################################################### +# +# Test checking if a text block is present 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 => { default("$#this.promise_filename}") }; + version => "1.0"; +} + +####################################################### + +bundle agent init +{ + vars: + "tmp" string => getenv("TEMP", 1024); + "reference_file" string => "${tmp}/reference"; + "file" string => "${tmp}/test"; + "file_canon" string => canonify("${file}"); + "section_start" string => ""; + "section_end" string => ""; + "block_to_add" string => "This is a test block +with multiple lines +to check content in section"; + + "reference_content" string => "${section_start} +${block_to_add} +${section_end}"; + + commands: + "/bin/echo" + args => "\"${reference_content}\" > \"${reference_file}\"", + contain => in_shell; +} + +####################################################### + +bundle agent test +{ + methods: + "ph1" usebundle => file_ensure_block_in_section("${init.file}", "${init.section_start}", "${init.section_end}", "${init.block_to_add}"); +} + +####################################################### + +bundle agent check +{ + vars: + "line_exists_test" string => "/usr/bin/diff \"${init.reference_file}\" \"${init.file}\""; + + classes: + # By default, file_ensure_block_in_section should create the file if it doesn't exist + "file_exists" expression => fileexists("${init.file}"); + "block_exists" expression => returnszero("${line_exists_test}", "noshell"); + + "ok" expression => "file_exists.block_exists.file_ensure_block_in_section_${init.file_canon}_ok.!file_ensure_block_in_section_${init.file_canon}_error"; + + reports: + ok:: + "$(this.promise_filename) Pass"; + !ok:: + "$(this.promise_filename) FAIL"; + !file_exists:: + "fileexists returns false for file ${init.file}"; + !block_exists:: + "diff command doesn't return 0 for command: ${line_exists_test}"; +} diff --git a/tree/20_cfe_basics/ncf_lib.cf b/tree/20_cfe_basics/ncf_lib.cf index 4fd09cc9d..7331bbfae 100644 --- a/tree/20_cfe_basics/ncf_lib.cf +++ b/tree/20_cfe_basics/ncf_lib.cf @@ -110,3 +110,39 @@ bundle edit_line ncf_insert_block(block) { insert_type => "preserve_block", comment => "Append a text block if it does not exist"; } + +# enforce content of section +bundle edit_line ncf_ensure_section_content(section_start, section_end, content) +{ + vars: + "csection" string => canonify("$(section_start)"); + "escaped_section_start" string => escape(${section_start}); + "escaped_section_end" string => escape(${section_end}); + + classes: + # Detect if section is already there + "has_$(csection)" expression => regline("${escaped_section_start}", "$(edit.filename)"); + + delete_lines: + ".*" + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"), + ifvarclass => "has_$(csection)"; + + insert_lines: + # Insert new, empty section if it doesn't exist already. + "${section_start} +${section_end}" + insert_type => "preserve_block", + ifvarclass => "!has_$(csection)"; + + # Insert missing lines into the section + "$(content)" + select_region => ncf_section_selector("${escaped_section_start}", "${escaped_section_end}"); +} + + +body select_region ncf_section_selector(section_start, section_end) +{ + select_start => "${section_start}"; + select_end => "${section_end}"; +} diff --git a/tree/30_generic_methods/file_ensure_block_in_section.cf b/tree/30_generic_methods/file_ensure_block_in_section.cf new file mode 100644 index 000000000..6f68ed0a7 --- /dev/null +++ b/tree/30_generic_methods/file_ensure_block_in_section.cf @@ -0,0 +1,46 @@ +##################################################################################### +# Copyright 2013 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 . +# +##################################################################################### + +# @name File ensure block in section +# @description This is a bundle to ensure that a section contain exactly a text block +# +# @parameter file File name to edit +# @parameter section_start Start of the section +# @parameter section_end End of the section +# @parameter block Block representing the content of the section +# +# @class_prefix file_ensure_block_in_section +# @class_parameter file +# +# This bundle will define a class file_ensure_block_in_section_${file}_{kept,repaired,error,ok,reached} +bundle agent file_ensure_block_in_section(file, section_start, section_end, block) +{ + vars: + "class_prefix" string => canonify("file_ensure_block_in_section_${file}"); + + files: + "${file}" + create => "true", + edit_line => ncf_ensure_section_content("${section_start}", "${section_end}", "${block}"), + edit_defaults => no_backup, + classes => classes_generic("${class_prefix}"); + + methods: + "report" + usebundle => _logger("Insert text block ${block} into ${file}", "${class_prefix}"); +}