puppet-spec 1.0.2
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.
- checksums.yaml +7 -0
- data/lib/puppet-spec/tasks.rb +6 -0
- data/lib/puppet/application/spec.rb +160 -0
- data/lib/puppet/parser/functions/stub_class.rb +7 -0
- data/lib/puppet/parser/functions/stub_facts.rb +9 -0
- data/lib/puppet/parser/functions/stub_type.rb +15 -0
- data/lib/puppet/type/assertion.rb +41 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0345031ab1c4f7933dc095e0c18df8013024955b
|
4
|
+
data.tar.gz: 6793e3f07d6e388b31ff7d52298e9cc233a6cd93
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3c2297d9f5306ca4808b5b7e06eee0183998901f11d4b5216364fe9f77aea2d5b492ceca5455f160145cb4bb6a70dc2916909a56bf18aab724da25570f8c7ab3
|
7
|
+
data.tar.gz: 7381fa58926e80438f6f75d41625a862b187dac73332b3604e540e78c5d6c6425e176f73acbeb613a3a7bd16d833239ec579eb6d9d851525ceb50c514b767859
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'puppet'
|
2
|
+
require 'puppet/test/test_helper'
|
3
|
+
require 'puppet/util/colors'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class Puppet::Application::Spec < Puppet::Application
|
7
|
+
include Puppet::Util::Colors
|
8
|
+
|
9
|
+
def run_command
|
10
|
+
output = Hash.new
|
11
|
+
|
12
|
+
begin
|
13
|
+
Puppet::Test::TestHelper.initialize
|
14
|
+
output = process_spec_directory(specdir)
|
15
|
+
rescue Exception => e
|
16
|
+
print colorize(:red, "#{e.message}\n")
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
if output[:failed] == 0
|
21
|
+
exit 0
|
22
|
+
else
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_spec_directory(specdir)
|
28
|
+
results = Dir.glob("#{specdir}/**/*_spec.pp").map { |spec| process_spec(spec) }.flatten
|
29
|
+
output = visit_assertions(results)
|
30
|
+
print_results(output)
|
31
|
+
output
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_spec(path)
|
35
|
+
catalog = catalog(path)
|
36
|
+
notify_compiled
|
37
|
+
|
38
|
+
assertions = catalog.resources.select {|res| res.type == 'Assertion' }
|
39
|
+
|
40
|
+
# Get the subject resource from the catalog rather than the
|
41
|
+
# reference provided from the parser. The reference's resource
|
42
|
+
# object does not contain any parameters for whatever reason.
|
43
|
+
assertions.map do |res|
|
44
|
+
res[:subject] = catalog.resource(res[:subject].to_s)
|
45
|
+
res
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def catalog(path)
|
50
|
+
Puppet::Test::TestHelper.before_each_test
|
51
|
+
Puppet[:code] = File.read(path)
|
52
|
+
|
53
|
+
node = Puppet::Node.new("spec")
|
54
|
+
modulepath = get_modulepath(node)
|
55
|
+
link_module(modulepath)
|
56
|
+
catalog = Puppet::Resource::Catalog.indirection.find(node.name, :use_node => node)
|
57
|
+
catalog.to_ral
|
58
|
+
|
59
|
+
Puppet::Test::TestHelper.after_each_test
|
60
|
+
catalog
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return a hash that contains
|
64
|
+
# data to be displayed to the
|
65
|
+
# user which represents the results
|
66
|
+
# of the assertions.
|
67
|
+
def visit_assertions(assertions)
|
68
|
+
count = 0
|
69
|
+
failed_count = 0
|
70
|
+
|
71
|
+
msg = assertions.map do |assertion|
|
72
|
+
count += 1
|
73
|
+
validate_assertion(assertion)
|
74
|
+
|
75
|
+
unless assertion[:expectation] == assertion[:subject][assertion[:attribute]]
|
76
|
+
failed_count += 1
|
77
|
+
file = assertion[:subject].file.split('manifests/').last
|
78
|
+
|
79
|
+
msg = colorize(:red, "#{failed_count}) Assertion #{assertion[:name]} failed on #{assertion[:subject].to_s}\n")
|
80
|
+
msg += colorize(:yellow, " On line #{assertion[:subject].line} of #{file}\n")
|
81
|
+
msg += colorize(:blue, " Wanted: ")
|
82
|
+
msg += "#{assertion[:attribute]} => '#{assertion[:expectation]}'\n"
|
83
|
+
msg += colorize(:blue, " Got: ")
|
84
|
+
msg += "#{assertion[:attribute]} => '#{assertion[:subject][assertion[:attribute]]}'\n\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
{
|
89
|
+
:msg => msg.join,
|
90
|
+
:count => count,
|
91
|
+
:failed => failed_count,
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
# Given the resulting hash
|
96
|
+
# from .visit_assertions,
|
97
|
+
# present the output to the
|
98
|
+
# user.
|
99
|
+
def print_results(results)
|
100
|
+
print "\n\n"
|
101
|
+
print results[:msg] if results[:msg]
|
102
|
+
|
103
|
+
if results[:count] == 1
|
104
|
+
print colorize(:yellow, "Evaluated #{results[:count]} assertion\n")
|
105
|
+
else
|
106
|
+
print colorize(:yellow, "Evaluated #{results[:count]} assertions\n")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Validate assertion raises an error
|
111
|
+
# if the assertion does not contain
|
112
|
+
# a subject, or if it contains a
|
113
|
+
# expectation without attribute.
|
114
|
+
def validate_assertion(assertion)
|
115
|
+
raise Puppet::Error, "#{assertion} requires a subject" unless assertion[:subject]
|
116
|
+
raise Puppet::Error, "#{assertion} requires an attribute when an expectation is given" if assertion[:expectation] and not assertion[:attribute]
|
117
|
+
end
|
118
|
+
|
119
|
+
# Print an rspec style dot
|
120
|
+
# to signify spec compilation
|
121
|
+
def notify_compiled
|
122
|
+
print colorize(:green, '.')
|
123
|
+
end
|
124
|
+
|
125
|
+
# Given a node object, return
|
126
|
+
# the first modulepath
|
127
|
+
def get_modulepath(node)
|
128
|
+
node.environment.full_modulepath[0]
|
129
|
+
end
|
130
|
+
|
131
|
+
# Ensure that a symlink is present
|
132
|
+
# pointing from the node's env
|
133
|
+
# to the current directory
|
134
|
+
def link_module(modulepath)
|
135
|
+
pwd = Dir.pwd
|
136
|
+
name = File.basename(pwd)
|
137
|
+
symlink = File.join(modulepath, name)
|
138
|
+
|
139
|
+
# Ensure that the modulepath exists
|
140
|
+
# within the temp environment
|
141
|
+
FileUtils.mkdir_p(modulepath) unless Dir.exist?(modulepath)
|
142
|
+
|
143
|
+
# Ensure that a symlink to the
|
144
|
+
# cwd exists
|
145
|
+
FileUtils.ln_s(pwd, symlink) unless File.symlink?(symlink)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Return the specdir under the
|
149
|
+
# CWD or raise an error if not
|
150
|
+
# found.
|
151
|
+
def specdir
|
152
|
+
pwd = Dir.pwd
|
153
|
+
specdir = File.join(pwd, 'spec')
|
154
|
+
unless Dir.exist?(specdir)
|
155
|
+
raise 'No spec directory was found under the CWD. You can optionally specifiy one with --specdir'
|
156
|
+
end
|
157
|
+
specdir
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Puppet::Parser::Functions.newfunction(:stub_class, :arity => 1) do |values|
|
2
|
+
|
3
|
+
raise Puppet::Error, "stub_class accepts a class name in the form of a string" unless values[0].is_a?(String)
|
4
|
+
|
5
|
+
compiler.environment.known_resource_types << Puppet::Resource::Type.new(:hostclass, values[0])
|
6
|
+
|
7
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Puppet::Resource::Type::Stub < Puppet::Resource::Type
|
2
|
+
# Allow the stub type to receive
|
3
|
+
# assignments on any parameter key.
|
4
|
+
def valid_parameter?(name)
|
5
|
+
true
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Puppet::Parser::Functions.newfunction(:stub_type, :arity => 1) do |values|
|
10
|
+
|
11
|
+
raise Puppet::Error, "stub_type accepts a type name in the form of a string" unless values[0].is_a?(String)
|
12
|
+
|
13
|
+
compiler.environment.known_resource_types << Puppet::Resource::Type::Stub.new(:definition, values[0])
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
Puppet::Type.newtype(:assertion) do
|
2
|
+
|
3
|
+
@doc = "Makes assertions on the state of a resource in the catalog.
|
4
|
+
|
5
|
+
The assertion type defines an assertion that will be evaluated by the
|
6
|
+
spec application.
|
7
|
+
"
|
8
|
+
|
9
|
+
newparam(:name) do
|
10
|
+
desc "A plain text message describing what the assertion is intended to prove.
|
11
|
+
|
12
|
+
The given text should form a sentence using the type's name.
|
13
|
+
Example: assertion { 'that the configuration file has the correct contents': }
|
14
|
+
"
|
15
|
+
end
|
16
|
+
|
17
|
+
newparam(:subject) do
|
18
|
+
desc "A reference to the resource to be asserted upon.
|
19
|
+
|
20
|
+
The referenced resource will be the subject of any assertions made as a result of this resource declaration.
|
21
|
+
"
|
22
|
+
|
23
|
+
validate do |value|
|
24
|
+
fail Puppet::Error, "You must provide an assertion subject" unless value
|
25
|
+
fail Puppet::Error, "Attributes must be a resource reference" unless value.is_a? Puppet::Resource
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
newparam(:attribute) do
|
30
|
+
desc "An attribute of the subject resource to assert against"
|
31
|
+
|
32
|
+
validate do |value|
|
33
|
+
fail Puppet::Error, "You must provide attribute to be asserted" unless value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
newparam(:expectation) do
|
38
|
+
desc "The expected value of the subject's attribute"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: puppet-spec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jordan Olshevski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: puppet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: puppetlabs_spec_helper
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.10.3
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.10.3
|
41
|
+
description: A Puppet testing framework implemented in the native DSL
|
42
|
+
email:
|
43
|
+
- jordan@puppetlabs.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/puppet-spec/tasks.rb
|
49
|
+
- lib/puppet/application/spec.rb
|
50
|
+
- lib/puppet/parser/functions/stub_class.rb
|
51
|
+
- lib/puppet/parser/functions/stub_facts.rb
|
52
|
+
- lib/puppet/parser/functions/stub_type.rb
|
53
|
+
- lib/puppet/type/assertion.rb
|
54
|
+
homepage: http://github.com/jolshevski/puppet-spec
|
55
|
+
licenses:
|
56
|
+
- Apache-2.0
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.4.6
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Test Puppet code with Puppet code
|
78
|
+
test_files: []
|