1 Puppet::Type.type(:file_line).provide(:ruby) do
6 found = line.chomp == resource[:line]
11 return found = lines_count > 0 if resource[:match].nil?
13 match_count = count_matches(new_match_regex)
14 found = if resource[:ensure] == :present
16 if lines_count.zero? && resource[:append_on_no_match].to_s == 'false'
17 true # lies, but gets the job done
18 elsif lines_count.zero? && resource[:append_on_no_match].to_s != 'false'
23 elsif resource[:replace_all_matches_not_matching_line].to_s == 'true'
24 false # maybe lies, but knows there's still work to do
25 elsif lines_count.zero?
26 resource[:replace].to_s == 'false'
30 elsif match_count.zero?
36 elsif lines_count.zero?
37 resource[:match_for_absence].to_s == 'true'
44 return if resource[:replace].to_s != 'true' && count_matches(new_match_regex) > 0
46 handle_create_with_match
47 elsif resource[:after]
48 handle_create_with_after
55 if resource[:match_for_absence].to_s == 'true' && resource[:match]
56 handle_destroy_with_match
65 # If this type is ever used with very large files, we should
66 # write this in a different way, using a temp
67 # file; for now assuming that this type is only used on
68 # small-ish config files that can fit into memory without
71 @lines ||= File.readlines(resource[:path], :encoding => resource[:encoding])
72 rescue TypeError => _e
73 # Ruby 1.8 doesn't support open_args
74 @lines ||= File.readlines(resource[:path])
78 resource[:after] ? Regexp.new(resource[:after]) : nil
82 resource[:match] ? Regexp.new(resource[:match]) : nil
85 def count_matches(regex)
87 if resource[:replace_all_matches_not_matching_line].to_s == 'true'
88 line.match(regex) unless line.chomp == resource[:line]
95 def handle_create_with_match
96 after_regex = new_after_regex
97 match_regex = new_match_regex
98 match_count = count_matches(new_match_regex)
100 if match_count > 1 && resource[:multiple].to_s != 'true'
101 raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
104 File.open(resource[:path], 'w') do |fh|
106 fh.puts(match_regex.match(line) ? resource[:line] : line)
107 next unless match_count.zero? && after_regex
108 if after_regex.match(line)
109 fh.puts(resource[:line])
110 match_count += 1 # Increment match_count to indicate that the new line has been inserted.
115 fh.puts(resource[:line])
120 def handle_create_with_after
121 after_regex = new_after_regex
122 after_count = count_matches(after_regex)
124 if after_count > 1 && resource[:multiple].to_s != 'true'
125 raise Puppet::Error, "#{after_count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
128 File.open(resource[:path], 'w') do |fh|
131 if after_regex.match(line)
132 fh.puts(resource[:line])
137 fh.puts(resource[:line])
142 def handle_destroy_with_match
143 match_regex = new_match_regex
144 match_count = count_matches(match_regex)
145 if match_count > 1 && resource[:multiple].to_s != 'true'
146 raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
150 File.open(resource[:path], 'w') do |fh|
151 fh.write(local_lines.reject { |line| match_regex.match(line) }.join(''))
155 def handle_destroy_line
157 File.open(resource[:path], 'w') do |fh|
158 fh.write(local_lines.reject { |line| line.chomp == resource[:line] }.join(''))
162 def handle_append_line
164 File.open(resource[:path], 'w') do |fh|
165 local_lines.each do |line|
168 fh.puts(resource[:line])