Skip to content

Commit

Permalink
Fixes #3293: add possibility to enforce content of section
Browse files Browse the repository at this point in the history
  • Loading branch information
ncharles committed Dec 16, 2013
1 parent 493e26c commit 6761c72
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
Expand Up @@ -51,6 +51,13 @@ bundle agent check_generic_file_content {
&GENERIC_FILE_CONTENT_MODIFICATION_REGEXP:{delreg |"generic_file_content_modification_regexp[&i&]" string => "&delreg&";
}&
&GENERIC_FILE_CONTENT_MODIFICATION_DESTINATION:{destination |"generic_file_content_modification_destination[&i&]" string => "&destination&";
}&
&GENERIC_FILE_SECTION_HEADER:{header |"generic_file_content_section_header[&i&]" string => "&header&";
}&
# Since content is multiline, it is not indented to prevent spurious space from being inserted within
&GENERIC_FILE_SECTION_CONTENT:{content |"generic_file_content_section_content[&i&]" string => "&content&";
}&
&GENERIC_FILE_SECTION_FOOTER:{footer |"generic_file_content_section_footer[&i&]" string => "&footer&";
}&
&TRACKINGKEY:{piuuid |"generic_file_content_uuid[&i&]" string => "&piuuid&";
}&
Expand Down Expand Up @@ -79,6 +86,11 @@ classes:
}&
&GENERIC_FILE_CONTENT_ENFORCE_CREATE_ONLY_BOOLEAN:{enforce_at_creation_only |"enforce_at_creation_only_&i&" expression => strcmp("&enforce_at_creation_only&", "true");
}&

&GENERIC_FILE_CONTENT_SECTION_MANAGEMENT:{enforce_section |"enforce_section_&i&" expression => strcmp("&enforce_section&", "true");
}&
"edit_section_valid_${index}" and => { isvariable("generic_file_content_section_header[${index}]"), isvariable("generic_file_content_section_footer[${index}]") } ;

"file_doesnt_exist_${index}" not => fileexists("$(generic_file_content_path[$(index)])");
"creation_only_but_already_exists_${index}" expression => "enforce_at_creation_only_${index}.!file_doesnt_exist_${index}";

Expand Down Expand Up @@ -135,6 +147,15 @@ classes:
ifvarclass => "modify_lines_$(index).!generic_file_content_modification_destination_defined_$(index).!creation_only_but_already_exists_${index}",
comment => "Replacing lines in $(generic_file_content_path[$(index)]) using the given regexps...";

# Enforce the content of section in file
"${generic_file_content_path[${index}]}"
edit_line => rudder_ensure_section_content("${generic_file_content_section_header[${index}]}", "${generic_file_content_section_footer[${index}]}", "${generic_file_content_section_content[${index}]}"),
create => "${generic_file_content_creation[${index}]}",
classes => kept_if_else("section_content_modification_kept_${index}", "section_content_modification_modified_${index}", "section_content_modification_failed_${index}"),
ifvarclass => "enforce_section_${index}.!creation_only_but_already_exists_${index}.edit_section_valid_${index}",
comment => "Enforcing content of section in ${generic_file_content_path[${index}]}";


"$(generic_file_content_path[$(index)])"
create => "$(generic_file_content_creation[$(index)])",
perms => mog("$(generic_file_content_perms[$(index)])", "$(generic_file_content_owner[$(index)])", "$(generic_file_content_group[$(index)])"),
Expand All @@ -149,7 +170,7 @@ classes:
"$(generic_file_content_posthook[$(index)])"
classes => if_else("generic_file_content_posthook_$(index)_command_run_ok", "generic_file_content_posthook_$(index)_command_run_failed"),
contain => in_shell,
ifvarclass => "execute_command_$(index).!(content_$(index)_failed|content_deletion_failed_$(index)|content_modification_failed_$(index)).(content_$(index)_modified|content_deletion_modified_$(index)|content_modification_modified_$(index))";
ifvarclass => "execute_command_$(index).!(content_$(index)_failed|content_deletion_failed_$(index)|content_modification_failed_$(index)).(content_$(index)_modified|content_deletion_modified_$(index)|content_modification_modified_$(index)|section_content_modification_modified_${index})";

reports:

Expand Down Expand Up @@ -215,6 +236,27 @@ classes:
"@@checkGenericFileContent@@result_success@@$(generic_file_content_uuid[$(index)])@@Permission adjustment@@$(generic_file_content_path[$(index)])@@$(g.execRun)##$(g.uuid)@#The file $(generic_file_content_path[$(index)]) was already existing, skipping permission checking"
ifvarclass => "adjust_permissions_$(index).creation_only_but_already_exists_${index}";

#Section edition
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was not set for section edition, skipping"
ifvarclass => "!enforce_section_${index}";

"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was set for section edition, but no header or footer was defined"
ifvarclass => "enforce_section_${index}.!edit_section_valid_${index}";

"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} already exists, skipping section edition"
ifvarclass => "enforce_section_${index}.creation_only_but_already_exists_${index}";

"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the section content policy"
ifvarclass => "section_content_modification_kept_${index}.!section_content_modification_modified_${index}";

"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated using the section content policy"
ifvarclass => "section_content_modification_modified_${index}.!section_content_modification_failed_${index}";

"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated using the section content policy"
ifvarclass => "section_content_modification_failed_${index}";



# Posthook report
"@@checkGenericFileContent@@result_success@@$(generic_file_content_uuid[$(index)])@@Post-modification hook@@$(generic_file_content_path[$(index)])@@$(g.execRun)##$(g.uuid)@#No command for $(generic_file_content_path[$(index)]) was to be executed"
ifvarclass => "!execute_command_$(index)";
Expand Down
Expand Up @@ -132,6 +132,44 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</CONSTRAINT>
</INPUT>
</SECTION>
<SECTION name="Enforce content by section" component="true" componentKey="GENERIC_FILE_CONTENT_PATH">
<INPUT>
<NAME>GENERIC_FILE_CONTENT_SECTION_MANAGEMENT</NAME>
<DESCRIPTION>Enforce the content of a section in the file</DESCRIPTION>
<CONSTRAINT>
<TYPE>boolean</TYPE>
<DEFAULT>false</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>GENERIC_FILE_SECTION_HEADER</NAME>
<DESCRIPTION>Header of the section to enforce</DESCRIPTION>
<LONGDESCRIPTION>The line corresponding to the beginning of the section to enforce content. If left empty, no section edition will be done.</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>string</TYPE>
<MAYBEEMPTY>true</MAYBEEMPTY>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>GENERIC_FILE_SECTION_CONTENT</NAME>
<DESCRIPTION>Content of the section</DESCRIPTION>
<LONGDESCRIPTION>The exact content of the section (without the header and footer).</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>textarea</TYPE>
<MAYBEEMPTY>true</MAYBEEMPTY>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>GENERIC_FILE_SECTION_FOOTER</NAME>
<DESCRIPTION>Footer of the section to enforce</DESCRIPTION>
<LONGDESCRIPTION>The line corresponding to the ending of the section to enforce content. If left empty, no section edition will be done.</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>string</TYPE>
<MAYBEEMPTY>true</MAYBEEMPTY>
</CONSTRAINT>
</INPUT>
</SECTION>

<SECTION name="Permission adjustment" component="true" componentKey="GENERIC_FILE_CONTENT_PATH">
<INPUT>
<NAME>GENERIC_FILE_CONTENT_PERMISSION_ADJUSTMENT</NAME>
Expand Down
35 changes: 35 additions & 0 deletions techniques/system/common/1.0/rudder_stdlib.st
Expand Up @@ -113,6 +113,41 @@ body file_select rudder_common_minutes_old(minutes)
file_result => "mtime";
}

# enforce content of section
bundle edit_line rudder_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 => rudder_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 => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}");
}
body select_region rudder_section_selector(section_start, section_end)
{
select_start => "${section_start}";
select_end => "${section_end}";
}
################################################
# Reporting bundles
################################################
Expand Down

0 comments on commit 6761c72

Please sign in to comment.