rspec-puppet-augeas 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ coverage/
1
2
  pkg/
2
3
  *.gem
3
4
  Gemfile.lock
data/Gemfile CHANGED
@@ -7,4 +7,5 @@ gem 'ruby-augeas'
7
7
  group :test do
8
8
  gem 'puppet'
9
9
  gem 'rake'
10
+ gem 'simplecov'
10
11
  end
data/README.md CHANGED
@@ -23,7 +23,7 @@ Extend your usual rspec-puppet class test, e.g. for the 'sshd' class:
23
23
  end
24
24
 
25
25
  # Expects Augeas['root login']
26
- describe_augeas 'root login' do
26
+ describe_augeas 'root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config' do
27
27
  it 'should change PermitRootLogin' do
28
28
  # Run the resource against the fixtures, check it changed
29
29
  should execute.with_change
@@ -57,6 +57,9 @@ fixtures directory.
57
57
 
58
58
  ## Usage
59
59
 
60
+ Read the spec file(s) at `spec/classes/*.rb` to see various real-life examples
61
+ of the features below.
62
+
60
63
  ### describe\_augeas example group
61
64
 
62
65
  `describe_augeas` adds an example group, like describe/context, but that describes
@@ -69,13 +72,14 @@ It takes optional hash arguments:
69
72
  * a hash of fixtures to copy from the source (under augeas\_fixtures) to a
70
73
  destination path, e.g. `{ 'dest/file/location' => 'src/file/location' }`
71
74
  * a string of the source path, copied to the path given by the resource's
72
- `incl` parameter (TODO: or `:target`)
75
+ `incl` parameter or `:target`
73
76
  * nil, by default copies all fixtures
74
77
  * `:target` is the path of the file that the resource should modify
75
78
  * `:lens` is the lens to use when opening the target file (for `aug_*` etc.)
76
79
 
77
80
  It sets the following variables inside examples:
78
81
 
82
+ * `resource` to the Puppet resource object
79
83
  * `subject` (used implicitly) to an object representing the resource
80
84
  * `output_root` to the path of the fixtures directory after one run
81
85
 
@@ -128,6 +132,11 @@ New RSpec configuration options:
128
132
  * `augeas_fixtures` is the path to the root of the fixtures directory
129
133
  containing source files
130
134
 
135
+ ## Background reading
136
+
137
+ This module inherited code from the tests used in [augeasproviders](http://augeasproviders.com).
138
+ The test methodology is described in [Testing techniques for Puppet providers using Augeas](http://augeasproviders.com/documentation/specs.html).
139
+
131
140
  ## Issues
132
141
 
133
142
  Please file any issues or suggestions [on GitHub](https://github.com/domcleal/rspec-puppet-augeas/issues).
@@ -22,17 +22,24 @@ module RSpec::Puppet::Augeas
22
22
  # to the augeas resource object
23
23
 
24
24
  # initialise arguments passed into the run_augeas block
25
- # TODO: target can be initialised from incl if available
26
25
  target = options.delete(:target)
27
- let(:target) { target }
26
+ let(:target) do
27
+ target || resource[:incl]
28
+ end
28
29
 
29
- # TODO: ditto
30
30
  lens = options.delete(:lens)
31
- let(:lens) { lens }
31
+ let(:lens) do
32
+ lens || resource[:lens]
33
+ end
32
34
 
33
35
  fixture = options.delete(:fixture)
34
- fixture = { target => fixture } if fixture.is_a? String and target
35
- let(:fixture) { fixture }
36
+ let(:fixture) do
37
+ if fixture and !fixture.is_a? Hash
38
+ raise ArgumentError, ":target must be supplied" unless self.target
39
+ fixture = { self.target => fixture.to_s }
40
+ end
41
+ fixture
42
+ end
36
43
 
37
44
  class_exec(&block)
38
45
  end
@@ -45,19 +52,23 @@ module RSpec::Puppet::Augeas
45
52
  end
46
53
 
47
54
  module InstanceMethods
48
- # Initialises the implicit example group 'subject' to an Augeas resource
49
- #
50
55
  # Requires that the title of this example group is the resource title and
51
56
  # that the parent example group subject is a catalog (use rspec-puppet)
52
- def subject
57
+ def resource
53
58
  unless @resource
54
59
  title = self.class.description
55
60
  title = $1 if title =~ /^Augeas\[(.*)\]$/
56
- @resource = Resource.new(catalogue.resource('Augeas', title), fixture)
61
+ @resource = catalogue.resource('Augeas', title)
57
62
  end
58
63
  @resource
59
64
  end
60
65
 
66
+ # Initialises the implicit example group 'subject' to a wrapped Augeas
67
+ # resource
68
+ def subject
69
+ @subject ||= Resource.new(self.resource, fixture)
70
+ end
71
+
61
72
  def output_root
62
73
  subject.root
63
74
  end
@@ -6,8 +6,6 @@ module RSpec::Puppet::Augeas
6
6
  module Fixtures
7
7
  # Copies test fixtures to a temporary directory
8
8
  # If file is nil, copies the entire augeas_fixtures directory
9
- # If file is a string, it copies that file from augeas_fixtures
10
- # to the path being edited by the resource
11
9
  # If file is a hash, it copies the "value" from augeas_fixtures
12
10
  # to each "key" path
13
11
  def load_fixtures(resource, file)
@@ -26,28 +24,15 @@ module RSpec::Puppet::Augeas
26
24
  def prepare_fixtures(dir, resource, file)
27
25
  if file.nil?
28
26
  FileUtils.cp_r File.join(RSpec.configuration.augeas_fixtures, "."), dir
29
- elsif file.is_a? Hash
27
+ else
30
28
  file.each do |dest,src|
31
29
  FileUtils.mkdir_p File.join(dir, File.dirname(dest))
32
30
  src = File.join(RSpec.configuration.augeas_fixtures, src) unless src.start_with? File::SEPARATOR
33
31
  FileUtils.cp_r src, File.join(dir, dest)
34
32
  end
35
- elsif file.respond_to? :to_s
36
- target = get_resource_target(resource)
37
- raise ArgumentError, "Unable to determine file being edited from #{resource.name}. Supply :fixtures as a hash of { '/dest/path' => 'source/fixture/path' } instead." unless target
38
- FileUtils.mkdir_p File.join(dir, File.dirname(target))
39
- FileUtils.cp File.join(RSpec.configuration.augeas_fixtures, file.to_s), File.join(dir, target)
40
33
  end
41
34
  end
42
35
 
43
- # Take a best guess at the file the user's editing
44
- def get_resource_target(resource)
45
- return resource[:incl] if resource[:incl]
46
- # TODO: make reliable
47
- #return $1 if resource[:context] and resource[:context] =~ %r{/files(/.*)}
48
- nil
49
- end
50
-
51
36
  # Runs a particular resource via a catalog
52
37
  def apply(resource)
53
38
  catalog = Puppet::Resource::Catalog.new
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rspec-puppet-augeas'
3
- s.version = '0.2.0'
3
+ s.version = '0.2.1'
4
4
  s.homepage = 'https://github.com/domcleal/rspec-puppet-augeas/'
5
5
  s.summary = 'RSpec tests for Augeas resources in Puppet manifests'
6
6
  s.description = 'RSpec tests for Augeas resources in Puppet manifests'
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
29
29
  ]
30
30
 
31
31
  s.add_dependency 'rspec-puppet'
32
+ s.add_dependency 'puppetlabs_spec_helper'
32
33
 
33
34
  s.authors = ['Dominic Cleal']
34
35
  s.email = 'dcleal@redhat.com'
@@ -1,25 +1,50 @@
1
1
  require 'spec_helper'
2
2
 
3
+ # Tests all features of rspec-puppet-augeas against the class under
4
+ # spec/fixtures/module/sshd/manifests/init.pp
3
5
  describe 'sshd' do
6
+ # Basic rspec-puppet example
4
7
  it 'should have an augeas resource' do
5
8
  should contain_augeas('root login')
6
9
  end
7
10
 
11
+ # Basic rspec-puppet-example
12
+ # uses all fixtures, lens + target are specified for aug_* functions to work
8
13
  describe 'specify target+lens upfront, use all fixtures' do
9
14
  describe_augeas 'root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config' do
10
15
  it 'should test resource' do
16
+ # Verify this is the right fixture, using Augeas and simple parsing
11
17
  aug_get('#comment[1]').should =~ /OpenBSD/
12
18
  open_target { |f| f.readline.should =~ /OpenBSD/ }
13
19
 
20
+ # Check it changes
14
21
  should execute.with_change
15
22
  aug_get('PermitRootLogin').should == 'yes'
16
23
  open_target { |f| f.read.should =~ /^PermitRootLogin\s+yes$/ }
17
24
 
25
+ # Idempotency test last, as a broken resource may cause false positives
18
26
  should execute.idempotently
19
27
  end
20
28
  end
21
29
  end
22
30
 
31
+ # Example of using a second fixture file to test a resource
32
+ describe 'specify target and non-standard fixture' do
33
+ describe_augeas 'root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config', :fixture => 'etc/ssh/sshd_config_2' do
34
+ it 'should test resource with second fixture' do
35
+ aug_get('#comment[1]').should == 'Fixture 2'
36
+ should execute.with_change
37
+ aug_get('PermitRootLogin').should == 'yes'
38
+ should execute.idempotently
39
+ end
40
+ end
41
+ end
42
+
43
+ # Fixtures can be a hash of destination path to source fixture path
44
+ # Note that all paths are relative to augeas_fixtures (in spec_helper.rb)
45
+ # and have no leading /
46
+ #
47
+ # Unusually, lens + target are specified on each aug_* function instead here.
23
48
  describe 'specify fixtures as a hash' do
24
49
  describe_augeas 'root login', :fixture => { 'etc/ssh/sshd_config' => 'etc/ssh/sshd_config_2' } do
25
50
  it 'should test resource with second fixture' do
@@ -31,9 +56,10 @@ describe 'sshd' do
31
56
  end
32
57
  end
33
58
 
34
- describe 'specify target and non-standard fixture' do
35
- describe_augeas 'root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config', :fixture => 'etc/ssh/sshd_config_2' do
36
- it 'should test resource with second fixture' do
59
+ # When incl/lens are given on the resource, :target and :lens are resolved
60
+ describe 'target detection from resource' do
61
+ describe_augeas 'incl root login', :fixture => 'etc/ssh/sshd_config_2' do
62
+ it 'should test resource with second fixture at incl location' do
37
63
  aug_get('#comment[1]').should == 'Fixture 2'
38
64
  should execute.with_change
39
65
  aug_get('PermitRootLogin').should == 'yes'
@@ -42,20 +68,10 @@ describe 'sshd' do
42
68
  end
43
69
  end
44
70
 
45
- describe_augeas 'fail to add root login' do
46
- it 'should fail to run entirely' do
47
- should_not execute
48
- end
49
- end
50
-
51
- run_augeas 'add root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config' do
52
- it 'should fail on idempotency' do
53
- should execute.with_change
54
- aug_match('PermitRootLogin').size.should == 2
55
- should_not execute.idempotently
56
- end
57
- end
58
-
71
+ # Other test utilities:
72
+ # augparse compares the entire fixture file to the { "key" = "value" } tree.
73
+ # Call augparse with no argument initially and it will print out the tree
74
+ # representation of the fixture file for reference.
59
75
  describe 'augparse' do
60
76
  describe_augeas 'root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config', :fixture => 'etc/ssh/sshd_config_2' do
61
77
  it 'should run augparse against the whole file' do
@@ -68,6 +84,8 @@ describe 'sshd' do
68
84
  end
69
85
  end
70
86
 
87
+ # augparse_filter first runs a filter against the fixture file before running
88
+ # it through augparse. Here, it filters out all non-comment entries.
71
89
  describe 'augparse_filter' do
72
90
  describe_augeas 'root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config', :fixture => 'etc/ssh/sshd_config_2' do
73
91
  it 'should filter non-comments' do
@@ -78,4 +96,20 @@ describe 'sshd' do
78
96
  end
79
97
  end
80
98
  end
99
+
100
+ # Testing for deliberate failure
101
+ describe_augeas 'fail to add root login' do
102
+ it 'should fail to run entirely' do
103
+ should_not execute
104
+ end
105
+ end
106
+
107
+ # Testing for deliberate idempotency failure
108
+ run_augeas 'add root login', :lens => 'Sshd', :target => 'etc/ssh/sshd_config' do
109
+ it 'should fail on idempotency' do
110
+ should execute.with_change
111
+ aug_match('PermitRootLogin').size.should == 2
112
+ should_not execute.idempotently
113
+ end
114
+ end
81
115
  end
@@ -4,6 +4,12 @@ class sshd {
4
4
  changes => 'set PermitRootLogin yes',
5
5
  }
6
6
 
7
+ augeas { "incl root login":
8
+ incl => '/etc/ssh/sshd_config',
9
+ lens => 'Sshd.lns',
10
+ changes => 'set PermitRootLogin yes',
11
+ }
12
+
7
13
  augeas { "add root login":
8
14
  context => '/files/etc/ssh/sshd_config',
9
15
  changes => [
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,8 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter "/spec/"
4
+ end
5
+
1
6
  require 'rspec-puppet-augeas'
2
7
 
3
8
  RSpec.configure do |c|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-puppet-augeas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-29 00:00:00.000000000 Z
12
+ date: 2013-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec-puppet
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: puppetlabs_spec_helper
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  description: RSpec tests for Augeas resources in Puppet manifests
31
47
  email: dcleal@redhat.com
32
48
  executables: []