Skip to content

Commit f4db736

Browse files
committed
Merge pull request #174 from dprince/file_line_after
Update file_line resource to support 'after'.
2 parents 8064302 + 948be0b commit f4db736

3 files changed

Lines changed: 164 additions & 71 deletions

File tree

lib/puppet/provider/file_line/ruby.rb

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
Puppet::Type.type(:file_line).provide(:ruby) do
2-
32
def exists?
43
lines.find do |line|
54
line.chomp == resource[:line].chomp
@@ -8,9 +7,11 @@ def exists?
87

98
def create
109
if resource[:match]
11-
handle_create_with_match()
10+
handle_create_with_match
11+
elsif resource[:after]
12+
handle_create_with_after
1213
else
13-
handle_create_without_match()
14+
append_line
1415
end
1516
end
1617

@@ -48,11 +49,35 @@ def handle_create_with_match()
4849
end
4950
end
5051

51-
def handle_create_without_match
52+
def handle_create_with_after
53+
regex = Regexp.new(resource[:after])
54+
55+
count = lines.count {|l| l.match(regex)}
56+
57+
case count
58+
when 1 # find the line to put our line after
59+
File.open(resource[:path], 'w') do |fh|
60+
lines.each do |l|
61+
fh.puts(l)
62+
if regex.match(l) then
63+
fh.puts(resource[:line])
64+
end
65+
end
66+
end
67+
when 0 # append the line to the end of the file
68+
append_line
69+
else
70+
raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern."
71+
end
72+
end
73+
74+
##
75+
# append the line to the file.
76+
#
77+
# @api private
78+
def append_line
5279
File.open(resource[:path], 'a') do |fh|
5380
fh.puts resource[:line]
5481
end
5582
end
56-
57-
5883
end

lib/puppet/type/file_line.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
newvalues(true, false)
4343
end
4444

45+
newparam(:after) do
46+
desc 'An optional value used to specify the line after which we will add any new lines. (Existing lines are added in place)'
47+
end
48+
4549
newparam(:line) do
4650
desc 'The line to be appended to the file located by the path parameter.'
4751
end

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

Lines changed: 129 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,36 @@
33
provider_class = Puppet::Type.type(:file_line).provider(:ruby)
44
describe provider_class do
55
context "when adding" do
6-
before :each do
7-
# TODO: these should be ported over to use the PuppetLabs spec_helper
8-
# file fixtures once the following pull request has been merged:
9-
# https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
6+
let :tmpfile do
107
tmp = Tempfile.new('tmp')
11-
@tmpfile = tmp.path
8+
path = tmp.path
129
tmp.close!
13-
@resource = Puppet::Type::File_line.new(
14-
{:name => 'foo', :path => @tmpfile, :line => 'foo'}
10+
path
11+
end
12+
let :resource do
13+
Puppet::Type::File_line.new(
14+
{:name => 'foo', :path => tmpfile, :line => 'foo'}
1515
)
16-
@provider = provider_class.new(@resource)
1716
end
17+
let :provider do
18+
provider_class.new(resource)
19+
end
20+
1821
it 'should detect if the line exists in the file' do
19-
File.open(@tmpfile, 'w') do |fh|
22+
File.open(tmpfile, 'w') do |fh|
2023
fh.write('foo')
2124
end
22-
@provider.exists?.should be_true
25+
provider.exists?.should be_true
2326
end
2427
it 'should detect if the line does not exist in the file' do
25-
File.open(@tmpfile, 'w') do |fh|
28+
File.open(tmpfile, 'w') do |fh|
2629
fh.write('foo1')
2730
end
28-
@provider.exists?.should be_nil
31+
provider.exists?.should be_nil
2932
end
3033
it 'should append to an existing file when creating' do
31-
@provider.create
32-
File.read(@tmpfile).chomp.should == 'foo'
34+
provider.create
35+
File.read(tmpfile).chomp.should == 'foo'
3336
end
3437
end
3538

@@ -52,71 +55,132 @@
5255
@provider = provider_class.new(@resource)
5356
end
5457

55-
it 'should raise an error if more than one line matches, and should not have modified the file' do
56-
File.open(@tmpfile, 'w') do |fh|
57-
fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
58+
describe 'using match' do
59+
it 'should raise an error if more than one line matches, and should not have modified the file' do
60+
File.open(@tmpfile, 'w') do |fh|
61+
fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
62+
end
63+
@provider.exists?.should be_nil
64+
expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/)
65+
File.read(@tmpfile).should eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
5866
end
59-
@provider.exists?.should be_nil
60-
expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/)
61-
File.read(@tmpfile).should eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
62-
end
6367

64-
it 'should replace all lines that matches' do
65-
@resource = Puppet::Type::File_line.new(
68+
it 'should replace all lines that matches' do
69+
@resource = Puppet::Type::File_line.new(
6670
{
67-
:name => 'foo',
68-
:path => @tmpfile,
69-
:line => 'foo = bar',
70-
:match => '^foo\s*=.*$',
71-
:multiple => true
71+
:name => 'foo',
72+
:path => @tmpfile,
73+
:line => 'foo = bar',
74+
:match => '^foo\s*=.*$',
75+
:multiple => true
7276
}
73-
)
74-
@provider = provider_class.new(@resource)
75-
File.open(@tmpfile, 'w') do |fh|
76-
fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
77+
)
78+
@provider = provider_class.new(@resource)
79+
File.open(@tmpfile, 'w') do |fh|
80+
fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
81+
end
82+
@provider.exists?.should be_nil
83+
@provider.create
84+
File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
85+
end
86+
87+
it 'should raise an error with invalid values' do
88+
expect {
89+
@resource = Puppet::Type::File_line.new(
90+
{
91+
:name => 'foo',
92+
:path => @tmpfile,
93+
:line => 'foo = bar',
94+
:match => '^foo\s*=.*$',
95+
:multiple => 'asgadga'
96+
}
97+
)
98+
}.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
99+
end
100+
101+
it 'should replace a line that matches' do
102+
File.open(@tmpfile, 'w') do |fh|
103+
fh.write("foo1\nfoo=blah\nfoo2")
104+
end
105+
@provider.exists?.should be_nil
106+
@provider.create
107+
File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2")
108+
end
109+
it 'should add a new line if no lines match' do
110+
File.open(@tmpfile, 'w') do |fh|
111+
fh.write("foo1\nfoo2")
112+
end
113+
@provider.exists?.should be_nil
114+
@provider.create
115+
File.read(@tmpfile).should eql("foo1\nfoo2\nfoo = bar\n")
116+
end
117+
it 'should do nothing if the exact line already exists' do
118+
File.open(@tmpfile, 'w') do |fh|
119+
fh.write("foo1\nfoo = bar\nfoo2")
120+
end
121+
@provider.exists?.should be_true
122+
@provider.create
123+
File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2")
77124
end
78-
@provider.exists?.should be_nil
79-
@provider.create
80-
File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
81125
end
82126

83-
it 'should raise an error with invalid values' do
84-
expect {
85-
@resource = Puppet::Type::File_line.new(
127+
describe 'using after' do
128+
let :resource do
129+
Puppet::Type::File_line.new(
86130
{
87-
:name => 'foo',
88-
:path => @tmpfile,
89-
:line => 'foo = bar',
90-
:match => '^foo\s*=.*$',
91-
:multiple => 'asgadga'
131+
:name => 'foo',
132+
:path => @tmpfile,
133+
:line => 'inserted = line',
134+
:after => '^foo1',
92135
}
93136
)
94-
}.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
95-
end
137+
end
96138

97-
it 'should replace a line that matches' do
98-
File.open(@tmpfile, 'w') do |fh|
99-
fh.write("foo1\nfoo=blah\nfoo2")
139+
let :provider do
140+
provider_class.new(resource)
100141
end
101-
@provider.exists?.should be_nil
102-
@provider.create
103-
File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2")
104-
end
105-
it 'should add a new line if no lines match' do
106-
File.open(@tmpfile, 'w') do |fh|
107-
fh.write("foo1\nfoo2")
142+
143+
context 'with one line matching the after expression' do
144+
before :each do
145+
File.open(@tmpfile, 'w') do |fh|
146+
fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz")
147+
end
148+
end
149+
150+
it 'inserts the specified line after the line matching the "after" expression' do
151+
provider.create
152+
File.read(@tmpfile).chomp.should eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo = baz")
153+
end
108154
end
109-
@provider.exists?.should be_nil
110-
@provider.create
111-
File.read(@tmpfile).should eql("foo1\nfoo2\nfoo = bar\n")
112-
end
113-
it 'should do nothing if the exact line already exists' do
114-
File.open(@tmpfile, 'w') do |fh|
115-
fh.write("foo1\nfoo = bar\nfoo2")
155+
156+
context 'with two lines matching the after expression' do
157+
before :each do
158+
File.open(@tmpfile, 'w') do |fh|
159+
fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz")
160+
end
161+
end
162+
163+
it 'errors out stating "One or no line must match the pattern"' do
164+
expect { provider.create }.to raise_error(Puppet::Error, /One or no line must match the pattern/)
165+
end
166+
end
167+
168+
context 'with no lines matching the after expression' do
169+
let :content do
170+
"foo3\nfoo = blah\nfoo2\nfoo = baz\n"
171+
end
172+
173+
before :each do
174+
File.open(@tmpfile, 'w') do |fh|
175+
fh.write(content)
176+
end
177+
end
178+
179+
it 'appends the specified line to the file' do
180+
provider.create
181+
File.read(@tmpfile).should eq(content << resource[:line] << "\n")
182+
end
116183
end
117-
@provider.exists?.should be_true
118-
@provider.create
119-
File.read(@tmpfile).chomp.should eql("foo1\nfoo = bar\nfoo2")
120184
end
121185
end
122186

0 commit comments

Comments
 (0)