+require 'spec_helper'
+
+provider_class = Puppet::Type.type(:file_line).provider(:ruby)
+# These tests fail on windows when run as part of the rake task. Individually they pass
+describe provider_class, :unless => Puppet::Util::Platform.windows? do
+ include PuppetlabsSpec::Files
+
+ let :tmpfile do
+ tmpfilename('file_line_test')
+ end
+ let :content do
+ ''
+ end
+ let :params do
+ {}
+ end
+ let :resource do
+ Puppet::Type::File_line.new({
+ :name => 'foo',
+ :path => tmpfile,
+ :line => 'foo',
+ }.merge(params))
+ end
+ let :provider do
+ provider_class.new(resource)
+ end
+
+ before :each do
+ File.open(tmpfile, 'w') do |fh|
+ fh.write(content)
+ end
+ end
+
+ describe '#create' do
+ context 'when adding' do
+ pending('To be added.')
+ end
+ context 'when replacing' do
+ let :params do
+ {
+ :line => 'foo = bar',
+ :match => '^foo\s*=.*$',
+ :replace => false,
+ }
+ end
+ let(:content) { "foo1\nfoo=blah\nfoo2\nfoo3" }
+
+ it "providor 'be_exists'" do
+ expect(provider).to be_exists
+ end
+ it 'does not replace the matching line' do
+ provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo=blah\nfoo2\nfoo3")
+ end
+ it 'appends the line if no matches are found' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2") }
+ expect(provider.exists?).to be false
+ provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo2\nfoo = bar")
+ end
+ it 'raises an error with invalid values' do
+ expect {
+ @resource = Puppet::Type::File_line.new(
+ :name => 'foo', :path => tmpfile, :line => 'foo = bar', :match => '^foo\s*=.*$', :replace => 'asgadga',
+ )
+ }.to raise_error(Puppet::Error, %r{Invalid value "asgadga"\. Valid values are true, false\.})
+ end
+ end
+ end
+ describe '#destroy' do
+ pending('To be added?')
+ end
+ context 'when matching' do
+ # rubocop:disable RSpec/InstanceVariable : replacing before with let breaks the tests, variables need to be altered within it block : multi
+ before :each do
+ @resource = Puppet::Type::File_line.new(
+ :name => 'foo',
+ :path => tmpfile,
+ :line => 'foo = bar',
+ :match => '^foo\s*=.*$',
+ )
+ @provider = provider_class.new(@resource)
+ end
+ describe 'using match' do
+ it 'raises an error if more than one line matches, and should not have modified the file' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") }
+ expect { @provider.create }.to raise_error(Puppet::Error, %r{More than one line.*matches})
+ expect(File.read(tmpfile)).to eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
+ end
+
+ it 'replaces all lines that matches' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo = bar', :match => '^foo\s*=.*$', :multiple => true)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz") }
+ @provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
+ end
+
+ it 'replaces all lines that match, even when some lines are correct' do
+ @resource = Puppet::Type::File_line.new(:name => 'neil', :path => tmpfile, :line => "\thard\tcore\t0\n", :match => '^[ \t]hard[ \t]+core[ \t]+.*', :multiple => true)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("\thard\tcore\t90\n\thard\tcore\t0\n") }
+ @provider.create
+ expect(File.read(tmpfile).chomp).to eql("\thard\tcore\t0\n\thard\tcore\t0")
+ end
+
+ it 'raises an error with invalid values' do
+ expect {
+ @resource = Puppet::Type::File_line.new(
+ :name => 'foo', :path => tmpfile, :line => 'foo = bar', :match => '^foo\s*=.*$', :multiple => 'asgadga',
+ )
+ }.to raise_error(Puppet::Error, %r{Invalid value "asgadga"\. Valid values are true, false\.})
+ end
+
+ it 'replaces a line that matches' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo=blah\nfoo2") }
+ @provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
+ end
+ it 'adds a new line if no lines match' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2") }
+ @provider.create
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo = bar\n")
+ end
+ it 'does nothing if the exact line already exists' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = bar\nfoo2") }
+ @provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
+ end
+ end
+ describe 'using match+append_on_no_match - when there is a match' do
+ it 'replaces line' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'inserted = line', :match => '^foo3$', :append_on_no_match => false)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") }
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
+ end
+ end
+ describe 'using match+append_on_no_match - when there is no match' do
+ it 'does not add line after no matches found' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'inserted = line', :match => '^foo3$', :append_on_no_match => false)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") }
+ expect(File.read(tmpfile).chomp).to eql("foo1\nfoo = blah\nfoo2\nfoo = baz")
+ end
+ end
+ end
+ context 'when match+replace+append_on_no_match' do
+ pending('to do')
+ end
+ context 'when after' do
+ let :resource do
+ Puppet::Type::File_line.new(
+ :name => 'foo',
+ :path => tmpfile,
+ :line => 'inserted = line',
+ :after => '^foo1',
+ )
+ end
+
+ let :provider do
+ provider_class.new(resource)
+ end
+
+ context 'when match and after set' do
+ shared_context 'when resource_create' do
+ let(:match) { '^foo2$' }
+ let(:after) { '^foo1$' }
+ let(:resource) do
+ Puppet::Type::File_line.new(
+ :name => 'foo',
+ :path => tmpfile,
+ :line => 'inserted = line',
+ :after => after,
+ :match => match,
+ )
+ end
+ end
+ before :each do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nfoo = baz") }
+ end
+ describe 'inserts at match' do
+ include_context 'resource_create'
+ it {
+ provider.create
+ expect(File.read(tmpfile).chomp).to eq("foo1\ninserted = line\nfoo = baz")
+ }
+ end
+ describe 'inserts a new line after when no match' do
+ include_context 'resource_create' do
+ let(:match) { '^nevergoingtomatch$' }
+ end
+ it {
+ provider.create
+ expect(File.read(tmpfile).chomp).to eq("foo1\ninserted = line\nfoo2\nfoo = baz")
+ }
+ end
+ describe 'append to end of file if no match for both after and match' do
+ include_context 'resource_create' do
+ let(:match) { '^nevergoingtomatch$' }
+ let(:after) { '^stillneverafter' }
+ end
+ it {
+ provider.create
+ expect(File.read(tmpfile).chomp).to eq("foo1\nfoo2\nfoo = baz\ninserted = line")
+ }
+ end
+ end
+ context 'with one line matching the after expression' do
+ before :each do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz") }
+ end
+
+ it 'inserts the specified line after the line matching the "after" expression' do
+ provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo = baz")
+ end
+ end
+ context 'with multiple lines matching the after expression' do
+ before :each do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz") }
+ end
+
+ it 'errors out stating "One or no line must match the pattern"' do
+ expect { provider.create }.to raise_error(Puppet::Error, %r{One or no line must match the pattern})
+ end
+
+ it 'adds the line after all lines matching the after expression' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'inserted = line', :after => '^foo1$', :multiple => true)
+ @provider = provider_class.new(@resource)
+ @provider.create
+ expect(File.read(tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo1\ninserted = line\nfoo = baz")
+ end
+ end
+ context 'with no lines matching the after expression' do
+ let :content do
+ "foo3\nfoo = blah\nfoo2\nfoo = baz\n"
+ end
+
+ before :each do
+ File.open(tmpfile, 'w') { |fh| fh.write(content) }
+ end
+
+ it 'appends the specified line to the file' do
+ provider.create
+ expect(File.read(tmpfile)).to eq(content << resource[:line] << "\n")
+ end
+ end
+ end
+ context 'when removing with a line' do
+ before :each do
+ # TODO: these should be ported over to use the PuppetLabs spec_helper
+ # file fixtures once the following pull request has been merged:
+ # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
+ @resource = Puppet::Type::File_line.new(
+ :name => 'foo',
+ :path => tmpfile,
+ :line => 'foo',
+ :ensure => 'absent',
+ )
+ @provider = provider_class.new(@resource)
+ end
+ it 'removes the line if it exists' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2")
+ end
+ it 'removes the line without touching the last new line' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\n") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\n")
+ end
+ it 'removes any occurence of the line' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\n")
+ end
+ it 'example in the docs' do
+ @resource = Puppet::Type::File_line.new(:name => 'bashrc_proxy', :ensure => 'absent', :path => tmpfile, :line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128')
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nexport HTTP_PROXY=http://squid.puppetlabs.vm:3128\nfoo4\n") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo4\n")
+ end
+ end
+ context 'when removing with a match' do
+ before :each do
+ @resource = Puppet::Type::File_line.new(
+ :name => 'foo',
+ :path => tmpfile,
+ :line => 'foo2',
+ :ensure => 'absent',
+ :match => 'o$',
+ :match_for_absence => true,
+ )
+ @provider = provider_class.new(@resource)
+ end
+
+ it 'finds a line to match' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ expect(@provider.exists?).to be true
+ end
+
+ it 'removes one line if it matches' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2")
+ end
+
+ it 'the line parameter is actually not used at all but is silently ignored if here' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'supercalifragilisticexpialidocious', :ensure => 'absent', :match => 'o$', :match_for_absence => true)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2")
+ end
+
+ it 'and may not be here and does not need to be here' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :ensure => 'absent', :match => 'o$', :match_for_absence => true)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2")
+ end
+
+ it 'raises an error if more than one line matches' do
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") }
+ expect { @provider.destroy }.to raise_error(Puppet::Error, %r{More than one line})
+ end
+
+ it 'removes multiple lines if :multiple is true' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo2', :ensure => 'absent', :match => 'o$', :multiple => true, :match_for_absence => true)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2\nfoo\nfoo") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\n")
+ end
+
+ it 'ignores the match if match_for_absence is not specified' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo2', :ensure => 'absent', :match => 'o$')
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo\n")
+ end
+
+ it 'ignores the match if match_for_absence is false' do
+ @resource = Puppet::Type::File_line.new(:name => 'foo', :path => tmpfile, :line => 'foo2', :ensure => 'absent', :match => 'o$', :match_for_absence => false)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo\nfoo2") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo\n")
+ end
+
+ it 'example in the docs' do
+ @resource = Puppet::Type::File_line.new(
+ :name => 'bashrc_proxy', :ensure => 'absent', :path => tmpfile, :line => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+ :match => '^export\ HTTP_PROXY\=', :match_for_absence => true
+ )
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nexport HTTP_PROXY=foo\nfoo4\n") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo4\n")
+ end
+
+ it 'example in the docs showing line is redundant' do
+ @resource = Puppet::Type::File_line.new(:name => 'bashrc_proxy', :ensure => 'absent', :path => tmpfile, :match => '^export\ HTTP_PROXY\=', :match_for_absence => true)
+ @provider = provider_class.new(@resource)
+ File.open(tmpfile, 'w') { |fh| fh.write("foo1\nfoo2\nexport HTTP_PROXY=foo\nfoo4\n") }
+ @provider.destroy
+ expect(File.read(tmpfile)).to eql("foo1\nfoo2\nfoo4\n")
+ end
+ end
+end