puppet-spec 1.0.2 → 1.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0345031ab1c4f7933dc095e0c18df8013024955b
4
- data.tar.gz: 6793e3f07d6e388b31ff7d52298e9cc233a6cd93
3
+ metadata.gz: e1b2a6f102ca870df851cd6b7e8b3fe181466d71
4
+ data.tar.gz: fbf64c3b18cda7e63ffd17261dae625ecd7dab38
5
5
  SHA512:
6
- metadata.gz: 3c2297d9f5306ca4808b5b7e06eee0183998901f11d4b5216364fe9f77aea2d5b492ceca5455f160145cb4bb6a70dc2916909a56bf18aab724da25570f8c7ab3
7
- data.tar.gz: 7381fa58926e80438f6f75d41625a862b187dac73332b3604e540e78c5d6c6425e176f73acbeb613a3a7bd16d833239ec579eb6d9d851525ceb50c514b767859
6
+ metadata.gz: f14eb73db5ebfe8cf67ff076159ef9ba3dc1bd9fe6ff0082a0780be50475316e799a7c9108db91e51ee0130cd2bf23193894550f4a658b882045a4eab61ff6ff
7
+ data.tar.gz: 656f782afe6f0ce5b44b57a5cc77e0a7a60dbd0565885a884bf10c7012fa218e5389a3832497f7a77af1e3710541dccd9794c5545266d86f84d93a56264e4c27
@@ -1,48 +1,52 @@
1
1
  require 'puppet'
2
2
  require 'puppet/test/test_helper'
3
- require 'puppet/util/colors'
3
+ require 'puppet/util/assertion/reporter'
4
4
  require 'fileutils'
5
5
 
6
6
  class Puppet::Application::Spec < Puppet::Application
7
- include Puppet::Util::Colors
7
+
8
+ option("--manifest manifest", "-m manifest")
9
+
10
+ attr_reader :reporter
8
11
 
9
12
  def run_command
10
- output = Hash.new
13
+ @reporter = Puppet::Util::Assertion::Reporter.new
11
14
 
12
15
  begin
13
16
  Puppet::Test::TestHelper.initialize
14
- output = process_spec_directory(specdir)
17
+ evaluate_assertions
18
+ reporter.print_footer
15
19
  rescue Exception => e
16
- print colorize(:red, "#{e.message}\n")
17
- exit 1
20
+ reporter.print_error(e)
18
21
  end
19
22
 
20
- if output[:failed] == 0
21
- exit 0
23
+ exit 1 unless reporter.failed == 0
24
+ exit 0
25
+ end
26
+
27
+ def evaluate_assertions
28
+ if options[:manifest]
29
+ process_spec(options[:manifest])
22
30
  else
23
- exit 1
31
+ process_spec_directory(specdir)
24
32
  end
25
33
  end
26
34
 
27
35
  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
36
+ Dir.glob("#{specdir}/**/*_spec.pp").map { |spec| process_spec(spec) }
32
37
  end
33
38
 
34
39
  def process_spec(path)
35
40
  catalog = catalog(path)
36
- notify_compiled
37
-
38
41
  assertions = catalog.resources.select {|res| res.type == 'Assertion' }
39
42
 
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|
43
+ assertions.each do |res|
44
+ # Get the subject resource from the catalog rather than the
45
+ # reference provided from the parser. The reference's resource
46
+ # object does not contain any parameters for whatever reason.
44
47
  res[:subject] = catalog.resource(res[:subject].to_s)
45
- res
48
+
49
+ reporter << res.to_ral
46
50
  end
47
51
  end
48
52
 
@@ -60,68 +64,6 @@ class Puppet::Application::Spec < Puppet::Application
60
64
  catalog
61
65
  end
62
66
 
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
67
  # Given a node object, return
126
68
  # the first modulepath
127
69
  def get_modulepath(node)
@@ -152,7 +94,7 @@ class Puppet::Application::Spec < Puppet::Application
152
94
  pwd = Dir.pwd
153
95
  specdir = File.join(pwd, 'spec')
154
96
  unless Dir.exist?(specdir)
155
- raise 'No spec directory was found under the CWD. You can optionally specifiy one with --specdir'
97
+ raise 'No spec directory was found under the CWD. A spec manifest can be specified with the --manifest flag'
156
98
  end
157
99
  specdir
158
100
  end
@@ -1,7 +1,9 @@
1
+ require 'puppet/util/assertion/stubs'
2
+
1
3
  Puppet::Parser::Functions.newfunction(:stub_class, :arity => 1) do |values|
2
4
 
3
5
  raise Puppet::Error, "stub_class accepts a class name in the form of a string" unless values[0].is_a?(String)
4
6
 
5
- compiler.environment.known_resource_types << Puppet::Resource::Type.new(:hostclass, values[0])
7
+ compiler.environment.known_resource_types << Puppet::Util::Assertion::Stubs::Type.new(:hostclass, values[0])
6
8
 
7
9
  end
@@ -1,15 +1,9 @@
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
1
+ require 'puppet/util/assertion/stubs'
8
2
 
9
3
  Puppet::Parser::Functions.newfunction(:stub_type, :arity => 1) do |values|
10
4
 
11
5
  raise Puppet::Error, "stub_type accepts a type name in the form of a string" unless values[0].is_a?(String)
12
6
 
13
- compiler.environment.known_resource_types << Puppet::Resource::Type::Stub.new(:definition, values[0])
7
+ compiler.environment.known_resource_types << Puppet::Util::Assertion::Stubs::Type.new(:definition, values[0])
14
8
 
15
9
  end
@@ -0,0 +1,31 @@
1
+ Puppet::Type.type(:assertion).provide(:evaluator) do
2
+
3
+ # Returns the complete path to the
4
+ # subject's manifest after /manifests
5
+ def relative_path
6
+ @resource[:subject].file.split('manifests/').last
7
+ end
8
+
9
+ # Returns a hash containing the assertion's
10
+ # attribute as the single key, with the value
11
+ # of the expectation. Used for rendering the
12
+ # results to the console.
13
+ def wanted
14
+ { @resource[:attribute] => @resource[:expectation] }
15
+ end
16
+
17
+ # Returns a hash containing the assertion's
18
+ # attribute as the single key, with the value
19
+ # of the subject's attribute. Used for rendering the
20
+ # results to the console.
21
+ def got
22
+ { @resource[:attribute] => @resource[:subject][@resource[:attribute]] }
23
+ end
24
+
25
+ # Return false if the subject's attribute is
26
+ # equal to the expectation, true otherwise.
27
+ def failed?
28
+ @resource[:expectation] != @resource[:subject][@resource[:attribute]]
29
+ end
30
+
31
+ end
@@ -6,6 +6,12 @@ Puppet::Type.newtype(:assertion) do
6
6
  spec application.
7
7
  "
8
8
 
9
+ validate do
10
+ fail Puppet::Error, "a subject is required" unless @parameters[:subject]
11
+ fail Puppet::Error, "an attribute is required when an expectation is given" if @parameters[:expectation] and not @parameters[:attribute]
12
+ fail Puppet::Error, "an expectation is required when an attribute is given" if @parameters[:attribute] and not @parameters[:expectation]
13
+ end
14
+
9
15
  newparam(:name) do
10
16
  desc "A plain text message describing what the assertion is intended to prove.
11
17
 
@@ -21,17 +27,12 @@ Puppet::Type.newtype(:assertion) do
21
27
  "
22
28
 
23
29
  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
30
+ fail Puppet::Error, "Subject must be a resource reference" unless value.is_a? Puppet::Resource
26
31
  end
27
32
  end
28
33
 
29
34
  newparam(:attribute) do
30
35
  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
36
  end
36
37
 
37
38
  newparam(:expectation) do
@@ -0,0 +1,52 @@
1
+ require 'puppet/util/colors'
2
+
3
+ module Puppet::Util
4
+ module Assertion
5
+ class Printer
6
+ include Puppet::Util::Colors
7
+
8
+ attr_reader :stack
9
+
10
+ def initialize
11
+ @stack = []
12
+ end
13
+
14
+ def red(msg)
15
+ stack << colorize(:red, msg)
16
+ end
17
+
18
+ def blue(msg)
19
+ stack << colorize(:blue, msg)
20
+ end
21
+
22
+ def yellow(msg)
23
+ stack << colorize(:yellow, msg)
24
+ end
25
+
26
+ def white(msg)
27
+ stack << msg
28
+ end
29
+
30
+ def newline
31
+ stack << "\n"
32
+ end
33
+
34
+ def to_s
35
+ stack.join
36
+ end
37
+
38
+ # Styler is a mixin that provides a helper
39
+ # method that parses a styled string by
40
+ # evaluating the given proc on an instance
41
+ # of Printer.
42
+ module Styler
43
+ def style(&proc)
44
+ printer = Puppet::Util::Assertion::Printer.new
45
+ printer.instance_eval(&proc)
46
+ print printer.to_s
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,82 @@
1
+ require 'puppet/util/assertion/printer'
2
+
3
+ module Puppet::Util
4
+ module Assertion
5
+ class Reporter
6
+ include Puppet::Util::Assertion::Printer::Styler
7
+
8
+ attr_reader :evaluated, :failed
9
+
10
+ def initialize
11
+ @evaluated = 0
12
+ @failed = 0
13
+ end
14
+
15
+ # Given an assertion resource, evaluate it for success
16
+ # and send it to .report on failure. Increment the counter
17
+ # for each resource, and the failed counter for failed resources.
18
+ def <<(assertion)
19
+ count
20
+ if assertion.provider.failed?
21
+ fail
22
+ report(assertion)
23
+ end
24
+ end
25
+
26
+ # Print the summary of evaluated assertions
27
+ def print_footer
28
+ # Shim the reporter into the local scope
29
+ reporter = self
30
+
31
+ style do
32
+ if reporter.evaluated == 1
33
+ yellow "Evaluated 1 assertion\n"
34
+ else
35
+ yellow "Evaluated #{reporter.evaluated} assertions\n"
36
+ end
37
+ end
38
+ end
39
+
40
+ def print_error(err)
41
+ fail #Mark an assertion so the application exits 1
42
+ style do
43
+ red err.message
44
+ end
45
+ end
46
+
47
+ # Pretty print the results of an assertion to the console
48
+ def report(assertion)
49
+ # Shim the value of failed into the
50
+ # local scope in order to access it
51
+ # from the style proc.
52
+ failed = @failed
53
+
54
+ style do
55
+ red "#{failed}) Assertion #{assertion[:name]} failed on #{assertion[:subject].to_s}"
56
+ newline
57
+
58
+ yellow " On line #{assertion[:subject].line} of #{assertion.provider.relative_path}"
59
+ newline
60
+
61
+ blue " Wanted: "
62
+ white assertion.provider.wanted.to_s
63
+ newline
64
+
65
+ blue " Got: "
66
+ white assertion.provider.got.to_s
67
+ newline
68
+ newline
69
+ end
70
+ end
71
+
72
+ def count
73
+ @evaluated += 1
74
+ end
75
+
76
+ def fail
77
+ @failed += 1
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,16 @@
1
+ require 'puppet/resource/type'
2
+
3
+ module Puppet::Util::Assertion
4
+ class Stubs
5
+
6
+ # This type reimplements the Puppet::Resource::Type class
7
+ # and overwrites the parameter validation in order to
8
+ # allow any param to be assigned a value.
9
+ class Type < Puppet::Resource::Type
10
+ def valid_parameter?(name)
11
+ true
12
+ end
13
+ end
14
+
15
+ end
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Olshevski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-03 00:00:00.000000000 Z
11
+ date: 2015-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puppet
@@ -50,7 +50,11 @@ files:
50
50
  - lib/puppet/parser/functions/stub_class.rb
51
51
  - lib/puppet/parser/functions/stub_facts.rb
52
52
  - lib/puppet/parser/functions/stub_type.rb
53
+ - lib/puppet/provider/assertion/evaluator.rb
53
54
  - lib/puppet/type/assertion.rb
55
+ - lib/puppet/util/assertion/printer.rb
56
+ - lib/puppet/util/assertion/reporter.rb
57
+ - lib/puppet/util/assertion/stubs.rb
54
58
  homepage: http://github.com/jolshevski/puppet-spec
55
59
  licenses:
56
60
  - Apache-2.0