diff --git a/README.md b/README.md index 5b741e4..4a49261 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,26 @@ Or with a regex: with "vm.swappiness=60" end + +replace_line_or_add +------------ + +Search the file line by line and match each line with the given regex if matched, replace the whole line with the replace parameter. +If no match is found, add entry like the append_line resource + + replace_line_or_add "/etc/sysctl.conf" do + replace "vm.swappiness" + with "vm.swappiness=60" + end + +Or with a regex: + + replace_line_or_add "/etc/sysctl.conf" do + replace /.*vm.swappiness.*/ + with "vm.swappiness=60" + end + + append_line ----------- diff --git a/libraries/matchers.rb b/libraries/matchers.rb index b6fcb45..d906ebc 100644 --- a/libraries/matchers.rb +++ b/libraries/matchers.rb @@ -14,4 +14,8 @@ def run_replace(resource_name) def run_replace_line(resource_name) ChefSpec::Matchers::ResourceMatcher.new(:replace_line, :run, resource_name) end + + def run_replace_line_or_add(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:replace_line_or_add, :run, resource_name) + end end diff --git a/recipes/default.rb b/recipes/default.rb deleted file mode 100644 index e69de29..0000000 diff --git a/resources/replace_line_or_add.rb b/resources/replace_line_or_add.rb new file mode 100644 index 0000000..e2adfda --- /dev/null +++ b/resources/replace_line_or_add.rb @@ -0,0 +1,59 @@ +resource_name 'replace_line_or_add' +actions :run +default_action :run + +property :name, :name_property => true, :kind_of => String, :required => true +property :file, :kind_of => String +property :path, :kind_of => String +property :replace, :kind_of => [String, Regexp], :required => true +property :with, :kind_of => String, :required => true + +action :run do + + file_path = file || path || name + + # Check if we got a regex or a string + if replace.is_a?(Regexp) + regex = replace + else + regex = Regexp.new(Regexp.escape(replace)) + end + + # Check if file matches the regex + if ::File.read(file_path) =~ regex + # Calculate file hash before changes + before = Digest::SHA256.file(file_path).hexdigest + + # Do changes + file = Chef::Util::FileEdit.new(file_path) + file.search_file_replace_line(regex, with) + file.write_file + + # Notify file changes + if Digest::SHA256.file(file_path).hexdigest != before + Chef::Log.info "- #{replace}" + Chef::Log.info "+ #{with}" + updated_by_last_action(true) + end + + else + regex = /^#{Regexp.escape(with)}$/ + # Calculate file hash before changes + before = Digest::SHA256.file(file_path).hexdigest + + # Do changes + file = Chef::Util::FileEdit.new(file_path) + file.insert_line_if_no_match(regex, with) + file.write_file + + # Notify file changes + if Digest::SHA256.file(file_path).hexdigest != before + Chef::Log.info "- #{replace}" + Chef::Log.info "+ #{with}" + updated_by_last_action(true) + end + + # Remove backup file + ::File.delete(file_path + ".old") if ::File.exist?(file_path + ".old") + end +end