diff --git a/lib/files.cf b/lib/files.cf index d7525bee37..e2853d5ce7 100644 --- a/lib/files.cf +++ b/lib/files.cf @@ -437,25 +437,33 @@ bundle edit_line set_variable_values_ini(tab, sectionName) # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); + "_escaped_section" string => escape("$(sectionName)"); classes: "edit_$(cindex[$(index)])" not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"), comment => "Create conditions to make changes"; + "section_$(sectionName)_exists" + expression => regline("^\[$(_escaped_section)\]", "$(edit.filename)"), + if => fileexists("$(edit.filename)"), + comment => "Check if the section header already exists in the file"; + field_edits: # If the line is there, but commented out, first uncomment it "#+\s*$(index)\s*=.*" select_region => INI_section(escape("$(sectionName)")), edit_field => col("\s*=\s*","1","$(index)","set"), - if => "edit_$(cindex[$(index)])"; + if => and("edit_$(cindex[$(index)])", + canonify("section_$(sectionName)_exists")); # match a line starting like the key something "\s*$(index)\s*=.*" edit_field => col("\s*=\s*","2","$($(tab)[$(sectionName)][$(index)])","set"), select_region => INI_section(escape("$(sectionName)")), classes => results("bundle", "set_variable_values_ini_not_$(cindex[$(index)])"), - if => "edit_$(cindex[$(index)])"; + if => and("edit_$(cindex[$(index)])", + canonify("section_$(sectionName)_exists")); insert_lines: "[$(sectionName)]" @@ -464,7 +472,16 @@ bundle edit_line set_variable_values_ini(tab, sectionName) "$(index)=$($(tab)[$(sectionName)][$(index)])" select_region => INI_section(escape("$(sectionName)")), - if => "!(set_variable_values_ini_not_$(cindex[$(index)])_kept|set_variable_values_ini_not_$(cindex[$(index)])_repaired).edit_$(cindex[$(index)])"; + if => and("!(set_variable_values_ini_not_$(cindex[$(index)])_kept|set_variable_values_ini_not_$(cindex[$(index)])_repaired)", + "edit_$(cindex[$(index)])", + canonify("section_$(sectionName)_exists")), + handle => "insert_key_in_existing_section_$(sectionName)_$(cindex[$(index)])"; + + "$(index)=$($(tab)[$(sectionName)][$(index)])" + location => after("^\[$(_escaped_section)\]"), + if => and("edit_$(cindex[$(index)])", + not(canonify("section_$(sectionName)_exists"))), + handle => "insert_key_in_new_section_$(sectionName)_$(cindex[$(index)])"; } diff --git a/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf b/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf new file mode 100644 index 0000000000..6671d8af72 --- /dev/null +++ b/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf @@ -0,0 +1,67 @@ +####################################################### +# +# Test that set_variable_values_ini does not error when section doesn't exist +# +####################################################### + +body common control +{ + inputs => { "../../default.cf.sub" }; + bundlesequence => { default("$(this.promise_filename)") }; + version => "1.0"; +} + +####################################################### + +bundle agent init +{ + files: + # The tested file "actual" is copied from our seeded starting position. + "$(G.testfile).actual" + copy_from => local_cp("$(this.promise_filename).actual"); + + # Next we place the file which we will compare the final result with. + "$(G.testfile).expected" + copy_from => local_cp("$(this.promise_filename).expected"); +} + +####################################################### + +bundle agent test +{ + meta: + "description" -> { "CFE-3866" } + string => "Test that set_variable_values_ini does not error when section doesn't exist"; + + vars: + "config[section1][key1]" string => "value1"; + "config[section1][key2]" string => "value2"; + "config[section2][key3]" string => "value3"; + "config[section2][key4]" string => "value4"; + + files: + "$(G.testfile).actual" + create => "true", + edit_line => set_variable_values_ini("test.config", "section1"); + + "$(G.testfile).actual" + edit_line => set_variable_values_ini("test.config", "section2"); +} + +####################################################### + +bundle agent check +{ + methods: + "check" + usebundle => dcs_if_diff("$(G.testfile).actual", "$(G.testfile).expected", + "pass", "_fail"); + + "fail" + usebundle => dcs_fail($(this.promise_filename)), + if => "_fail"; + + pass:: + "pass" + usebundle => dcs_pass($(this.promise_filename)); +} diff --git a/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf.actual b/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf.actual new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf.expected b/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf.expected new file mode 100644 index 0000000000..4adafa063c --- /dev/null +++ b/tests/acceptance/lib/files/set_variable_values_ini_missing_section.cf.expected @@ -0,0 +1,6 @@ +[section2] +key3=value3 +key4=value4 +[section1] +key2=value2 +key1=value1