rspec-puppet-augeas 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/README.md +11 -2
- data/lib/rspec-puppet-augeas/example/run_augeas_example_group.rb +21 -10
- data/lib/rspec-puppet-augeas/fixtures.rb +1 -16
- data/rspec-puppet-augeas.gemspec +2 -1
- data/spec/classes/sshd_config_spec.rb +51 -17
- data/spec/fixtures/modules/sshd/manifests/init.pp +6 -0
- data/spec/spec_helper.rb +5 -0
- metadata +18 -2
data/.gitignore
CHANGED
data/Gemfile
CHANGED
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
|
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)
|
26
|
+
let(:target) do
|
27
|
+
target || resource[:incl]
|
28
|
+
end
|
28
29
|
|
29
|
-
# TODO: ditto
|
30
30
|
lens = options.delete(:lens)
|
31
|
-
let(:lens)
|
31
|
+
let(:lens) do
|
32
|
+
lens || resource[:lens]
|
33
|
+
end
|
32
34
|
|
33
35
|
fixture = options.delete(:fixture)
|
34
|
-
fixture
|
35
|
-
|
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
|
57
|
+
def resource
|
53
58
|
unless @resource
|
54
59
|
title = self.class.description
|
55
60
|
title = $1 if title =~ /^Augeas\[(.*)\]$/
|
56
|
-
@resource =
|
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
|
-
|
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
|
data/rspec-puppet-augeas.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rspec-puppet-augeas'
|
3
|
-
s.version = '0.2.
|
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
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
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.
|
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-
|
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: []
|