Skip to content

Commit e84090d

Browse files
committed
Merge pull request #499 from jearls/2370-use-match-for-ensure-absent
[MODULES-2370] allow `match` parameter to influence `ensure => absent` behavior.
2 parents 605fffd + 9bacf14 commit e84090d

File tree

3 files changed

+141
-3
lines changed

3 files changed

+141
-3
lines changed

lib/puppet/provider/file_line/ruby.rb

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ def create
2222
end
2323

2424
def destroy
25-
local_lines = lines
26-
File.open(resource[:path],'w') do |fh|
27-
fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
25+
if resource[:match_for_absence].to_s == 'true' and resource[:match]
26+
handle_destroy_with_match
27+
else
28+
handle_destroy_line
2829
end
2930
end
3031

@@ -93,6 +94,25 @@ def count_matches(regex)
9394
lines.select{|l| l.match(regex)}.size
9495
end
9596

97+
def handle_destroy_with_match
98+
match_count = count_matches(match_regex)
99+
if match_count > 1 && resource[:multiple].to_s != 'true'
100+
raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
101+
end
102+
103+
local_lines = lines
104+
File.open(resource[:path],'w') do |fh|
105+
fh.write(local_lines.reject{|l| match_regex.match(l) }.join(''))
106+
end
107+
end
108+
109+
def handle_destroy_line
110+
local_lines = lines
111+
File.open(resource[:path],'w') do |fh|
112+
fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
113+
end
114+
end
115+
96116
##
97117
# append the line to the file.
98118
#

lib/puppet/type/file_line.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,20 @@
3434
In this code example match will look for a line beginning with export
3535
followed by HTTP_PROXY and replace it with the value in line.
3636
37+
Match Example With `ensure => absent`:
38+
39+
file_line { 'bashrc_proxy':
40+
ensure => absent,
41+
path => '/etc/bashrc',
42+
line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
43+
match => '^export\ HTTP_PROXY\=',
44+
match_for_absence => true,
45+
}
46+
47+
In this code example match will look for a line beginning with export
48+
followed by HTTP_PROXY and delete it. If multiple lines match, an
49+
error will be raised unless the `multiple => true` parameter is set.
50+
3751
**Autorequires:** If Puppet is managing the file that will contain the line
3852
being managed, the file_line resource will autorequire that file.
3953
@@ -55,6 +69,14 @@
5569
' match an exception will be raised. '
5670
end
5771

72+
newparam(:match_for_absence) do
73+
desc 'An optional value to determine if match should be applied when ensure => absent.' +
74+
' If set to true and match is set, the line that matches match will be deleted.' +
75+
' If set to false (the default), match is ignored when ensure => absent.'
76+
newvalues(true, false)
77+
defaultto false
78+
end
79+
5880
newparam(:multiple) do
5981
desc 'An optional value to determine if match can change multiple lines.' +
6082
' If set to false, an exception will be raised if more than one line matches'

spec/unit/puppet/provider/file_line/ruby_spec.rb

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,4 +341,100 @@
341341
expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
342342
end
343343
end
344+
345+
context "when removing with a match" do
346+
before :each do
347+
# TODO: these should be ported over to use the PuppetLabs spec_helper
348+
# file fixtures once the following pull request has been merged:
349+
# https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
350+
tmp = Tempfile.new('tmp')
351+
@tmpfile = tmp.path
352+
tmp.close!
353+
@resource = Puppet::Type::File_line.new(
354+
{
355+
:name => 'foo',
356+
:path => @tmpfile,
357+
:line => 'foo2',
358+
:ensure => 'absent',
359+
:match => 'o$',
360+
:match_for_absence => true,
361+
}
362+
)
363+
@provider = provider_class.new(@resource)
364+
end
365+
366+
it 'should remove one line if it matches' do
367+
File.open(@tmpfile, 'w') do |fh|
368+
fh.write("foo1\nfoo\nfoo2")
369+
end
370+
@provider.destroy
371+
expect(File.read(@tmpfile)).to eql("foo1\nfoo2")
372+
end
373+
374+
it 'should raise an error if more than one line matches' do
375+
File.open(@tmpfile, 'w') do |fh|
376+
fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
377+
end
378+
expect { @provider.destroy }.to raise_error(Puppet::Error, /More than one line/)
379+
end
380+
381+
it 'should remove multiple lines if :multiple is true' do
382+
@resource = Puppet::Type::File_line.new(
383+
{
384+
:name => 'foo',
385+
:path => @tmpfile,
386+
:line => 'foo2',
387+
:ensure => 'absent',
388+
:match => 'o$',
389+
:multiple => true,
390+
:match_for_absence => true,
391+
}
392+
)
393+
@provider = provider_class.new(@resource)
394+
File.open(@tmpfile, 'w') do |fh|
395+
fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
396+
end
397+
@provider.destroy
398+
expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
399+
end
400+
401+
it 'should ignore the match if match_for_absense is not specified' do
402+
@resource = Puppet::Type::File_line.new(
403+
{
404+
:name => 'foo',
405+
:path => @tmpfile,
406+
:line => 'foo2',
407+
:ensure => 'absent',
408+
:match => 'o$',
409+
}
410+
)
411+
@provider = provider_class.new(@resource)
412+
File.open(@tmpfile, 'w') do |fh|
413+
fh.write("foo1\nfoo\nfoo2")
414+
end
415+
@provider.destroy
416+
expect(File.read(@tmpfile)).to eql("foo1\nfoo\n")
417+
end
418+
419+
it 'should ignore the match if match_for_absense is false' do
420+
@resource = Puppet::Type::File_line.new(
421+
{
422+
:name => 'foo',
423+
:path => @tmpfile,
424+
:line => 'foo2',
425+
:ensure => 'absent',
426+
:match => 'o$',
427+
:match_for_absence => false,
428+
}
429+
)
430+
@provider = provider_class.new(@resource)
431+
File.open(@tmpfile, 'w') do |fh|
432+
fh.write("foo1\nfoo\nfoo2")
433+
end
434+
@provider.destroy
435+
expect(File.read(@tmpfile)).to eql("foo1\nfoo\n")
436+
end
437+
438+
end
439+
344440
end

0 commit comments

Comments
 (0)