puppet-spec 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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