rspec-puppet 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Tim Sharpe
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,126 @@
1
+ # RSpec tests for your Puppet manifests
2
+
3
+ ## Installation
4
+
5
+ gem install rspec-puppet
6
+
7
+ ## Naming conventions
8
+
9
+ For clarity and consistency, I recommend that you use the following directory
10
+ structure and naming convention.
11
+
12
+ module
13
+ |
14
+ +-- manifests
15
+ |
16
+ +-- lib
17
+ |
18
+ +-- spec
19
+ |
20
+ +-- spec_helper.rb
21
+ |
22
+ +-- classes
23
+ | |
24
+ | +-- <class_name>_spec.rb
25
+ |
26
+ +-- defines
27
+ |
28
+ +-- <define_name>_spec.rb
29
+
30
+ ## Example groups
31
+
32
+ If you use the above directory structure, your examples will automatically be
33
+ placed in the correct groups and have access to the custom matchers. If you
34
+ choose not to, you can force the examples into the required groups as follows.
35
+
36
+ describe 'myclass', :type => :class do
37
+ ...
38
+ end
39
+
40
+ describe 'mydefine', :type => :define do
41
+ ...
42
+ end
43
+
44
+ ## Matchers
45
+
46
+ ### Checking if a class has been included
47
+
48
+ You can test if a class has been included in the catalogue with the
49
+ `include_class` matcher. It takes the class name as a string as its only
50
+ argument
51
+
52
+ it { should include_class('foo') }
53
+
54
+ ### Checking if a resources exists
55
+
56
+ You can test if a resource exists in the catalogue with the generic
57
+ `creates_<resource type>` matcher. If your resource type includes :: (e.g.
58
+ `foo::bar` simply replace the :: with -
59
+
60
+ it { should create_augeas('bleh') }
61
+ it { should create_foo-bar('baz') }
62
+
63
+ You can further test the parameters that have been passed to the resources with
64
+ the generic `with_<parameter>` chains.
65
+
66
+ it { should create_package('mysql-server').with_ensure('present') }
67
+
68
+ ## Writing tests
69
+
70
+ ### Basic test structure
71
+
72
+ To test that
73
+
74
+ sysctl { 'baz'
75
+ value => 'foo',
76
+ }
77
+
78
+ Will cause the following resource to be in included in catalogue for a host
79
+
80
+ exec { 'sysctl/reload':
81
+ command => '/sbin/sysctl -p /etc/sysctl.conf',
82
+ }
83
+
84
+ We can write the following testcase
85
+
86
+ describe 'sysctl' do
87
+ let(:title) { 'baz' }
88
+ let(:params) { { :value => 'foo' } }
89
+
90
+ it { should create_exec('sysctl/reload').with_command("/sbin/sysctl -p /etc/sysctl.conf") }
91
+ end
92
+
93
+ ### Specifying the title of a resource
94
+
95
+ let(:title) { 'foo' }
96
+
97
+ ### Specifying the parameters to pass to a resources or parametised class
98
+
99
+ let(:params) { {:ensure => 'present', ...} }
100
+
101
+ ### Specifying the FQDN of the test node
102
+
103
+ If the manifest you're testing expects to run on host with a particular name,
104
+ you can specify this as follows
105
+
106
+ let(:node) { 'testhost.example.com' }
107
+
108
+ ### Specifying the facts that should be available to your manifest
109
+
110
+ By default, the test environment contains no facts for your manifest to use.
111
+ You can set them with a hash
112
+
113
+ let(:facts) { {:operatingsystem => 'Debian', :kernel => 'Linux', ...} }
114
+
115
+ ### Specifying the path to find your modules
116
+
117
+ I recommend setting a default module path by adding the following code to your
118
+ `spec_helper.rb`
119
+
120
+ RSpec.configure do |c|
121
+ c.module_path = '/path/to/your/module/dir'
122
+ end
123
+
124
+ However, if you want to specify it in each example, you can do so
125
+
126
+ let(:module_path) { '/path/to/your/module/dir' }
@@ -0,0 +1,6 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ task :default => :test
5
+
6
+ RSpec::Core::RakeTask.new(:test)
@@ -1,3 +1,7 @@
1
1
  require 'puppet'
2
2
  require 'rspec-puppet/matchers'
3
3
  require 'rspec-puppet/example'
4
+
5
+ RSpec.configure do |c|
6
+ c.add_setting :module_path, :default => '/etc/puppet/modules'
7
+ end
@@ -7,10 +7,10 @@ RSpec::configure do |c|
7
7
  end
8
8
 
9
9
  c.include RSpec::Puppet::DefineExampleGroup, :type => :define, :example_group => {
10
- :file_path => c.escaped_path(%w[spec define])
10
+ :file_path => c.escaped_path(%w[spec defines])
11
11
  }
12
12
 
13
13
  c.include RSpec::Puppet::ClassExampleGroup, :type => :class, :example_group => {
14
- :file_path => c.escaped_path(%w[spec class])
14
+ :file_path => c.escaped_path(%w[spec classes])
15
15
  }
16
16
  end
@@ -7,13 +7,23 @@ module RSpec::Puppet
7
7
  end
8
8
 
9
9
  def catalogue
10
- Puppet[:modulepath] = module_path
10
+ Puppet[:modulepath] = self.respond_to?(:module_path) ? module_path : RSpec.configuration.module_path
11
11
 
12
12
  klass_name = self.class.top_level_description.downcase
13
+
14
+ # If we're testing a standalone module (i.e. one that's outside of a
15
+ # puppet tree), the autoloader won't work, so we need to fudge it a bit.
16
+ if File.exists?(File.join(Puppet[:modulepath], 'manifests', 'init.pp'))
17
+ path_to_manifest = File.join([Puppet[:modulepath], 'manifests', klass_name.split('::')[1..-1]].flatten)
18
+ import_str = "import '#{Puppet[:modulepath]}/manifests/init.pp'\nimport '#{path_to_manifest}.pp'\n"
19
+ else
20
+ import_str = ""
21
+ end
22
+
13
23
  if !self.respond_to?(:params) || params == {}
14
- Puppet[:code] = "include #{klass_name}"
24
+ Puppet[:code] = import_str + "include #{klass_name}"
15
25
  else
16
- Puppet[:code] = 'class' + " { " + klass_name + ": " + params.keys.map { |r| "#{r.to_s} => '#{params[r].to_s}'"
26
+ Puppet[:code] = import_str + 'class' + " { " + klass_name + ": " + params.keys.map { |r| "#{r.to_s} => '#{params[r].to_s}'"
17
27
  }.join(', ') + " }"
18
28
  end
19
29
 
@@ -9,7 +9,16 @@ module RSpec::Puppet
9
9
  def catalogue
10
10
  define_name = self.class.top_level_description.downcase
11
11
 
12
- Puppet[:modulepath] = module_path
12
+ Puppet[:modulepath] = self.respond_to?(:module_path) ? module_path : RSpec.configuration.module_path
13
+
14
+ # If we're testing a standalone module (i.e. one that's outside of a
15
+ # puppet tree), the autoloader won't work, so we need to fudge it a bit.
16
+ if File.exists?(File.join(Puppet[:modulepath], 'manifests', 'init.pp'))
17
+ path_to_manifest = File.join([Puppet[:modulepath], 'manifests', define_name.split('::')[1..-1]].flatten)
18
+ import_str = "import '#{Puppet[:modulepath]}/manifests/init.pp'\nimport '#{path_to_manifest}.pp'\n"
19
+ else
20
+ import_str = ""
21
+ end
13
22
 
14
23
  if self.respond_to? :params
15
24
  param_str = params.keys.map { |r|
@@ -19,7 +28,7 @@ module RSpec::Puppet
19
28
  param_str = ""
20
29
  end
21
30
 
22
- Puppet[:code] = define_name + " { \"" + title + "\": " + param_str + " }"
31
+ Puppet[:code] = import_str + define_name + " { \"" + title + "\": " + param_str + " }"
23
32
 
24
33
  nodename = self.respond_to?(:node) ? node : Puppet[:certname]
25
34
  facts_val = self.respond_to?(:facts) ? facts : {}
@@ -1,20 +1,27 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rspec-puppet'
3
- s.version = '0.0.1'
3
+ s.version = '0.0.2'
4
4
  s.homepage = 'https://github.com/rodjek/rspec-puppet/'
5
5
  s.summary = 'RSpec tests for your Puppet manifests'
6
6
  s.description = 'RSpec tests for your Puppet manifests'
7
7
 
8
8
  s.files = [
9
- 'rspec-puppet.gemspec',
10
- 'lib/rspec-puppet.rb',
11
- 'lib/rspec-puppet/matchers.rb',
9
+ 'lib/rspec-puppet/example/class_example_group.rb',
10
+ 'lib/rspec-puppet/example/define_example_group.rb',
11
+ 'lib/rspec-puppet/example.rb',
12
12
  'lib/rspec-puppet/matchers/create_generic.rb',
13
13
  'lib/rspec-puppet/matchers/create_resource.rb',
14
14
  'lib/rspec-puppet/matchers/include_class.rb',
15
- 'lib/rspec-puppet/example.rb',
16
- 'lib/rspec-puppet/example/define_example_group.rb',
17
- 'lib/rspec-puppet/example/class_example_group.rb',
15
+ 'lib/rspec-puppet/matchers.rb',
16
+ 'lib/rspec-puppet.rb',
17
+ 'LICENSE',
18
+ 'Rakefile',
19
+ 'README.md',
20
+ 'rspec-puppet.gemspec',
21
+ 'spec/classes/sysctl_common_spec.rb',
22
+ 'spec/defines/sysctl_spec.rb',
23
+ 'spec/fixtures/sysctl/manifests/init.pp',
24
+ 'spec/spec_helper.rb',
18
25
  ]
19
26
 
20
27
  s.add_dependency 'rspec'
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'sysctl::common' do
4
+ it { should create_exec('sysctl/reload') \
5
+ .with_command('/sbin/sysctl -p /etc/sysctl.conf').with_returns([0, 2]) }
6
+ it { should_not create_augeas('foo') }
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'sysctl' do
4
+ let(:title) { 'vm.swappiness' }
5
+ let(:params) { {:value => '60'} }
6
+
7
+ it { should include_class('sysctl::common') }
8
+ it { should create_augeas('sysctl/vm.swappiness') \
9
+ .with_context('/files/etc/sysctl.conf') \
10
+ .with_changes("set vm.swappiness '60'") \
11
+ .with_onlyif("match vm.swappiness[.='60'] size == 0") \
12
+ .with_notify('Exec[sysctl/reload]') }
13
+ end
@@ -0,0 +1,18 @@
1
+ class sysctl::common {
2
+ exec { 'sysctl/reload':
3
+ command => '/sbin/sysctl -p /etc/sysctl.conf',
4
+ refreshonly => true,
5
+ returns => [0, 2],
6
+ }
7
+ }
8
+
9
+ define sysctl($value) {
10
+ include sysctl::common
11
+
12
+ augeas { "sysctl/${name}":
13
+ context => '/files/etc/sysctl.conf',
14
+ changes => "set ${name} '${value}'",
15
+ onlyif => "match ${name}[.='${value}'] size == 0",
16
+ notify => Exec['sysctl/reload'],
17
+ }
18
+ }
@@ -0,0 +1,5 @@
1
+ require 'rspec-puppet'
2
+
3
+ RSpec.configure do |c|
4
+ c.module_path = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures')
5
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-puppet
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tim Sharpe
@@ -41,15 +41,22 @@ extensions: []
41
41
  extra_rdoc_files: []
42
42
 
43
43
  files:
44
- - rspec-puppet.gemspec
45
- - lib/rspec-puppet.rb
46
- - lib/rspec-puppet/matchers.rb
44
+ - lib/rspec-puppet/example/class_example_group.rb
45
+ - lib/rspec-puppet/example/define_example_group.rb
46
+ - lib/rspec-puppet/example.rb
47
47
  - lib/rspec-puppet/matchers/create_generic.rb
48
48
  - lib/rspec-puppet/matchers/create_resource.rb
49
49
  - lib/rspec-puppet/matchers/include_class.rb
50
- - lib/rspec-puppet/example.rb
51
- - lib/rspec-puppet/example/define_example_group.rb
52
- - lib/rspec-puppet/example/class_example_group.rb
50
+ - lib/rspec-puppet/matchers.rb
51
+ - lib/rspec-puppet.rb
52
+ - LICENSE
53
+ - Rakefile
54
+ - README.md
55
+ - rspec-puppet.gemspec
56
+ - spec/classes/sysctl_common_spec.rb
57
+ - spec/defines/sysctl_spec.rb
58
+ - spec/fixtures/sysctl/manifests/init.pp
59
+ - spec/spec_helper.rb
53
60
  has_rdoc: true
54
61
  homepage: https://github.com/rodjek/rspec-puppet/
55
62
  licenses: []