3 provider_class = Puppet::Type.type(:file_line).provider(:ruby)
4 # These tests fail on windows when run as part of the rake task. Individually they pass
5 describe provider_class, :unless => Puppet::Util::Platform.windows? do
6 include PuppetlabsSpec::Files
9 tmpfilename('file_line_test')
18 Puppet::Type::File_line.new({
25 provider_class.new(resource)
29 File.open(tmpfile, 'w') do |fh|
35 context 'when adding' do
36 pending('To be added.')
38 context 'when replacing' do
42 :match => '^foo\s*=.*$',
46 let(:content) { "foo1\nfoo=blah\nfoo2\nfoo3" }
48 it "providor 'be_exists'" do
49 expect(provider).to be_exists
51 it 'does not replace the matching line' do
53 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo=blah\nfoo2\nfoo3")
55 it 'appends the line if no matches are found' do
56 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2") }
57 expect(provider.exists?).to be false
59 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo2\nfoo = bar")
61 it 'raises an error with invalid values' do
63 @resource = Puppet::Type::File_line.new(
64 :name => 'foo', :path => tmpfile, :line => 'foo = bar', :match => '^foo\s*=.*$', :replace => 'asgadga',
66 }.to raise_error(Puppet::Error, %r{Invalid value "asgadga"\. Valid values are true, false\.})
70 describe '#destroy' do
71 pending('To be added?')
73 context 'when matching' do
74 # rubocop:disable RSpec/InstanceVariable : replacing before with let breaks the tests, variables need to be altered within it block : multi
76 @resource = Puppet::Type::File_line.new(
80 :match => '^foo\s*=.*$',
82 @provider = provider_class.new(@resource)
84 describe 'using match' do
85 it 'raises an error if more than one line matches, and should not have modified the file' do
86 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") }
87 expect { @provider.create }.to raise_error(Puppet::Error, %r{More than one line.*matches})
88 expect(File.read(tmpfile)).to eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
91 it 'replaces all lines that matches' do
92 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo = bar', :match => '^foo\s*=.*$', :multiple => true)
93 @provider = provider_class.new(@resource)
94 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") }
96 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
99 it 'replaces all lines that match, even when some lines are correct' do
100 @resource = Puppet::Type::File_line.new(:name => 'neil', :path => tmpfile, :line => "\thard\tcore\t0\n", :match => '^[ \t]hard[ \t]+core[ \t]+.*', :multiple => true)
101 @provider = provider_class.new(@resource)
102 File.open(tmpfile, 'w') { |fh| fh.write("\thard\tcore\t90\n\thard\tcore\t0\n") }
104 expect(File.read(tmpfile).chomp).to eql("\thard\tcore\t0\n\thard\tcore\t0")
107 it 'raises an error with invalid values' do
109 @resource = Puppet::Type::File_line.new(
110 :name => 'foo', :path => tmpfile, :line => 'foo = bar', :match => '^foo\s*=.*$', :multiple => 'asgadga',
112 }.to raise_error(Puppet::Error, %r{Invalid value "asgadga"\. Valid values are true, false\.})
115 it 'replaces a line that matches' do
116 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo=blah\nfoo2") }
118 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
120 it 'adds a new line if no lines match' do
121 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2") }
123 expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo = bar\n")
125 it 'does nothing if the exact line already exists' do
126 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = bar\nfoo2") }
128 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
131 describe 'using match+append_on_no_match - when there is a match' do
132 it 'replaces line' do
133 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'inserted = line', :match => '^foo3$', :append_on_no_match => false)
134 @provider = provider_class.new(@resource)
135 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") }
136 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
139 describe 'using match+append_on_no_match - when there is no match' do
140 it 'does not add line after no matches found' do
141 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'inserted = line', :match => '^foo3$', :append_on_no_match => false)
142 @provider = provider_class.new(@resource)
143 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") }
144 expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
148 context 'when match+replace+append_on_no_match' do
151 context 'when after' do
153 Puppet::Type::File_line.new(
156 :line => 'inserted = line',
162 provider_class.new(resource)
165 context 'when match and after set' do
166 shared_context 'when resource_create' do
167 let(:match) { '^foo2$' }
168 let(:after) { '^foo1$' }
170 Puppet::Type::File_line.new(
173 :line => 'inserted = line',
180 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nfoo = baz") }
182 describe 'inserts at match' do
183 include_context 'resource_create'
186 expect(File.read(tmpfile).chomp).to eq("foo1\ninserted = line\nfoo = baz")
189 describe 'inserts a new line after when no match' do
190 include_context 'resource_create' do
191 let(:match) { '^nevergoingtomatch$' }
195 expect(File.read(tmpfile).chomp).to eq("foo1\ninserted = line\nfoo2\nfoo = baz")
198 describe 'append to end of file if no match for both after and match' do
199 include_context 'resource_create' do
200 let(:match) { '^nevergoingtomatch$' }
201 let(:after) { '^stillneverafter' }
205 expect(File.read(tmpfile).chomp).to eq("foo1\nfoo2\nfoo = baz\ninserted = line")
209 context 'with one line matching the after expression' do
211 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") }
214 it 'inserts the specified line after the line matching the "after" expression' do
216 expect(File.read(tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo = baz")
219 context 'with multiple lines matching the after expression' do
221 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz") }
224 it 'errors out stating "One or no line must match the pattern"' do
225 expect { provider.create }.to raise_error(Puppet::Error, %r{One or no line must match the pattern})
228 it 'adds the line after all lines matching the after expression' do
229 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'inserted = line', :after => '^foo1$', :multiple => true)
230 @provider = provider_class.new(@resource)
232 expect(File.read(tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo1\ninserted = line\nfoo = baz")
235 context 'with no lines matching the after expression' do
237 "foo3\nfoo = blah\nfoo2\nfoo = baz\n"
241 File.open(tmpfile, 'w') { |fh| fh.write(content) }
244 it 'appends the specified line to the file' do
246 expect(File.read(tmpfile)).to eq(content << resource[:line] << "\n")
250 context 'when removing with a line' do
252 # TODO: these should be ported over to use the PuppetLabs spec_helper
253 # file fixtures once the following pull request has been merged:
254 # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
255 @resource = Puppet::Type::File_line.new(
261 @provider = provider_class.new(@resource)
263 it 'removes the line if it exists' do
264 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
266 expect(File.read(tmpfile)).to eql("foo1\nfoo2")
268 it 'removes the line without touching the last new line' do
269 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\n") }
271 expect(File.read(tmpfile)).to eql("foo1\nfoo2\n")
273 it 'removes any occurence of the line' do
274 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") }
276 expect(File.read(tmpfile)).to eql("foo1\nfoo2\n")
278 it 'example in the docs' do
279 @resource = Puppet::Type::File_line.new(:name => 'bashrc_proxy', :ensure => 'absent', :path => tmpfile, :line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128')
280 @provider = provider_class.new(@resource)
281 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nexport HTTP_PROXY=http://squid.puppetlabs.vm:3128\nfoo4\n") }
283 expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo4\n")
286 context 'when removing with a match' do
288 @resource = Puppet::Type::File_line.new(
294 :match_for_absence => true,
296 @provider = provider_class.new(@resource)
299 it 'finds a line to match' do
300 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
301 expect(@provider.exists?).to be true
304 it 'removes one line if it matches' do
305 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
307 expect(File.read(tmpfile)).to eql("foo1\nfoo2")
310 it 'the line parameter is actually not used at all but is silently ignored if here' do
311 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'supercalifragilisticexpialidocious', :ensure => 'absent', :match => 'o$', :match_for_absence => true)
312 @provider = provider_class.new(@resource)
313 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
315 expect(File.read(tmpfile)).to eql("foo1\nfoo2")
318 it 'and may not be here and does not need to be here' do
319 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :ensure => 'absent', :match => 'o$', :match_for_absence => true)
320 @provider = provider_class.new(@resource)
321 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
323 expect(File.read(tmpfile)).to eql("foo1\nfoo2")
326 it 'raises an error if more than one line matches' do
327 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") }
328 expect { @provider.destroy }.to raise_error(Puppet::Error, %r{More than one line})
331 it 'removes multiple lines if :multiple is true' do
332 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo2', :ensure => 'absent', :match => 'o$', :multiple => true, :match_for_absence => true)
333 @provider = provider_class.new(@resource)
334 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") }
336 expect(File.read(tmpfile)).to eql("foo1\nfoo2\n")
339 it 'ignores the match if match_for_absence is not specified' do
340 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo2', :ensure => 'absent', :match => 'o$')
341 @provider = provider_class.new(@resource)
342 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
344 expect(File.read(tmpfile)).to eql("foo1\nfoo\n")
347 it 'ignores the match if match_for_absence is false' do
348 @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo2', :ensure => 'absent', :match => 'o$', :match_for_absence => false)
349 @provider = provider_class.new(@resource)
350 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
352 expect(File.read(tmpfile)).to eql("foo1\nfoo\n")
355 it 'example in the docs' do
356 @resource = Puppet::Type::File_line.new(
357 :name => 'bashrc_proxy', :ensure => 'absent', :path => tmpfile, :line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
358 :match => '^export\ HTTP_PROXY\=', :match_for_absence => true
360 @provider = provider_class.new(@resource)
361 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nexport HTTP_PROXY=foo\nfoo4\n") }
363 expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo4\n")
366 it 'example in the docs showing line is redundant' do
367 @resource = Puppet::Type::File_line.new(:name => 'bashrc_proxy', :ensure => 'absent', :path => tmpfile, :match => '^export\ HTTP_PROXY\=', :match_for_absence => true)
368 @provider = provider_class.new(@resource)
369 File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nexport HTTP_PROXY=foo\nfoo4\n") }
371 expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo4\n")