rspec-puppet 2.7.0 → 2.9.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 +5 -5
- data/CHANGELOG.md +137 -1
- data/README.md +45 -7
- data/lib/rspec-puppet/adapters.rb +8 -1
- data/lib/rspec-puppet/cache.rb +11 -6
- data/lib/rspec-puppet/coverage.rb +112 -13
- data/lib/rspec-puppet/matchers/allow_value.rb +8 -0
- data/lib/rspec-puppet/matchers/compile.rb +8 -0
- data/lib/rspec-puppet/matchers/count_generic.rb +13 -3
- data/lib/rspec-puppet/matchers/create_generic.rb +24 -8
- data/lib/rspec-puppet/matchers/include_class.rb +8 -1
- data/lib/rspec-puppet/matchers/parameter_matcher.rb +5 -16
- data/lib/rspec-puppet/matchers/raise_error.rb +23 -0
- data/lib/rspec-puppet/matchers/run.rb +8 -0
- data/lib/rspec-puppet/matchers/type_matchers.rb +0 -3
- data/lib/rspec-puppet/matchers/unique_values.rb +31 -0
- data/lib/rspec-puppet/matchers.rb +2 -0
- data/lib/rspec-puppet/monkey_patches.rb +63 -1
- data/lib/rspec-puppet/sensitive.rb +51 -0
- data/lib/rspec-puppet/support.rb +115 -18
- data/lib/rspec-puppet.rb +5 -0
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 420f47c99ab3190a3e97c2b172e694694a5d997a56e70366bd168c8338c21fb9
|
|
4
|
+
data.tar.gz: 21f2d247e5169ba70e490d6b9c66fc8542a1c3c1cd99d1e5895a1322a9cfac1b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5b2ef185120131a07fc6e063a7ee2d2cb191db8a765bb5cdda1fce92081547c4d0aea83b386faaf1d20e8051d51d84ba05facc5f9deb74f3aecdeea67798b86
|
|
7
|
+
data.tar.gz: 4714dac2b13e5a4eb44a8c965a61e08cc7e2ded172271ea61f85bfae22d43f51dde5d609f0a1d3515844fb5924b48ad8441fbb071eef267c0af6f886c0e21c9c
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,113 @@
|
|
|
2
2
|
All notable changes to this project will be documented in this file. This
|
|
3
3
|
project adheres to [Semantic Versioning](http://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [2.9.0]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
* Allow users to disable app_management for Puppet 4
|
|
9
|
+
* Added support for regexp arguments to Sensitive
|
|
10
|
+
* Handle all auto*, not just autorequire
|
|
11
|
+
* Set up loaders so that 4.x functions resolve properly
|
|
12
|
+
|
|
13
|
+
## [2.8.0]
|
|
14
|
+
|
|
15
|
+
### Breaking Changes
|
|
16
|
+
* As of the 2.8.0 release, the `rspec-puppet` project no longer guarantees compatibility
|
|
17
|
+
with Puppet 2.x or 3.x (running under Ruby 1.8.7) or Puppet 4.x (running under Ruby 1.9.3).
|
|
18
|
+
* This release adds support for the [`Sensitive`](https://puppet.com/docs/puppet/latest/lang_data_sensitive.html)
|
|
19
|
+
data type, however existing tests that were expecting `String` content may need to be updated
|
|
20
|
+
to wrap the expected value in the new `sensitive` helper:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
# Old
|
|
24
|
+
it { is_expected.to contain_file('/etc/mysecret.conf').with_content("top secret\n") }
|
|
25
|
+
|
|
26
|
+
# New
|
|
27
|
+
it { is_expected.to contain_file('/etc/mysecret.conf').with_content(sensitive("top secret\n")) }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
* Added support for [trusted external fact data](https://github.com/rodjek/rspec-puppet#specifying-trusted-external-data).
|
|
32
|
+
* Added the ability to exclude resources from the coverage report calculations using a regular expression.
|
|
33
|
+
(See [documentation](https://rspec-puppet.com/documentation/coverage/#excluded-resources) for an example.
|
|
34
|
+
* Added `have_unique_values_for_all` matcher to assert a specific resource parameter value is unique across
|
|
35
|
+
the entire catalogue.
|
|
36
|
+
(See [documentation](https://rspec-puppet.com/documentation/classes/#test-resource-parameter-values-for-uniqueness).)
|
|
37
|
+
* Added ability to customize module-layer Hiera configuration via new settings. See
|
|
38
|
+
[documentation](https://rspec-puppet.com/documentation/configuration/#disable_module_hiera) for details.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
* `RSpec::Puppet::Cache` now evicts least recently used entries when it reaches max size.
|
|
42
|
+
* `rspec-puppet`'s implementation of `match_manifests` will no longer look in `init.pp` for class
|
|
43
|
+
declarations if a manifest file exactly matching the class name exists.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
* Resolved compatibility issues with Ruby 2.7.x and added Ruby 2.7.x to the test matrix.
|
|
47
|
+
* Resolved issues calculating coverage and reporting results when there are 0 tested resources.
|
|
48
|
+
* Resolved compatibility issue with `rspec-expectations` 3.10.0.
|
|
49
|
+
|
|
50
|
+
## [2.7.10]
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
* Fix issues with removal of `default_env` method in Puppet 6.17.0.
|
|
54
|
+
|
|
55
|
+
## [2.7.9]
|
|
56
|
+
|
|
57
|
+
This release had unintended breaking changes and was withdrawn.
|
|
58
|
+
|
|
59
|
+
## [2.7.8]
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
* Fix cross-platform testing for Puppet >= 6.9.0 when there is no `ipaddress6`
|
|
63
|
+
fact defined.
|
|
64
|
+
|
|
65
|
+
## [2.7.7]
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
* Fix the support for rspec-expectations >= 3.8.5.
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
* Remove the rspec-expectations dependency limit introduced in 2.7.6.
|
|
72
|
+
|
|
73
|
+
## [2.7.6]
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
* Limit rspec-expectations dependency to < 3.8.5 due to an incompatible
|
|
77
|
+
change.
|
|
78
|
+
|
|
79
|
+
## [2.7.5]
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
* Minor refactor to prevent the fix introduced in 2.7.4 from raising
|
|
83
|
+
a deprecation warning on latest RSpec.
|
|
84
|
+
|
|
85
|
+
## [2.7.4]
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
* Fix the resource coverage test so that rspec will exit non-zero if the
|
|
89
|
+
desired coverage is not met.
|
|
90
|
+
|
|
91
|
+
## [2.7.3]
|
|
92
|
+
|
|
93
|
+
### Fixed
|
|
94
|
+
* Puppet 6 deferred functions are now evaluated and resolved as part of the
|
|
95
|
+
catalogue compilation process.
|
|
96
|
+
* If running with parallel\_tests, the resources that are filtered out of the
|
|
97
|
+
resource coverage report are now taken into account when merging the final
|
|
98
|
+
report, fixing false negative results that can occur.
|
|
99
|
+
|
|
100
|
+
## [2.7.2]
|
|
101
|
+
|
|
102
|
+
### Changed
|
|
103
|
+
* Reverted the change introduced in 2.7.0 that reencoded resource parameter
|
|
104
|
+
values to modify their line endings.
|
|
105
|
+
|
|
106
|
+
## [2.7.1]
|
|
107
|
+
|
|
108
|
+
### Fixed
|
|
109
|
+
* Fixed a bug that prevented the platform pretending/stubbing logic from being
|
|
110
|
+
temporarily disabled when loading Ruby code.
|
|
111
|
+
|
|
5
112
|
## [2.7.0]
|
|
6
113
|
|
|
7
114
|
### Changed
|
|
@@ -447,7 +554,36 @@ Thanks to Adrien Thebo, Alex Harvey, Brian, Dan Bode, Dominic Cleal, Javier Pala
|
|
|
447
554
|
## 1.0.1 and earlier
|
|
448
555
|
For changelog of versions 1.0.1 and earlier, see http://rspec-puppet.com/changelog/
|
|
449
556
|
|
|
450
|
-
[2.x]: https://github.com/rodjek/rspec-puppet/compare/v2.
|
|
557
|
+
[2.x]: https://github.com/rodjek/rspec-puppet/compare/v2.9.0...master
|
|
558
|
+
[2.9.0]: https://github.com/rodjek/rspec-puppet/compare/v2.8.0...v2.9.0
|
|
559
|
+
[2.8.0]: https://github.com/rodjek/rspec-puppet/compare/v2.7.10...v2.8.0
|
|
560
|
+
[2.7.10]: https://github.com/rodjek/rspec-puppet/compare/v2.7.9...v2.7.10
|
|
561
|
+
[2.7.9]: https://github.com/rodjek/rspec-puppet/compare/v2.7.8...v2.7.9
|
|
562
|
+
[2.7.8]: https://github.com/rodjek/rspec-puppet/compare/v2.7.7...v2.7.8
|
|
563
|
+
[2.7.7]: https://github.com/rodjek/rspec-puppet/compare/v2.7.6...v2.7.7
|
|
564
|
+
[2.7.6]: https://github.com/rodjek/rspec-puppet/compare/v2.7.5...v2.7.6
|
|
565
|
+
[2.7.5]: https://github.com/rodjek/rspec-puppet/compare/v2.7.4...v2.7.5
|
|
566
|
+
[2.7.4]: https://github.com/rodjek/rspec-puppet/compare/v2.7.3...v2.7.4
|
|
567
|
+
[2.7.3]: https://github.com/rodjek/rspec-puppet/compare/v2.7.2...v2.7.3
|
|
568
|
+
[2.7.2]: https://github.com/rodjek/rspec-puppet/compare/v2.7.1...v2.7.2
|
|
569
|
+
[2.7.1]: https://github.com/rodjek/rspec-puppet/compare/v2.7.0...v2.7.1
|
|
570
|
+
[2.7.0]: https://github.com/rodjek/rspec-puppet/compare/v2.6.15...v2.7.0
|
|
571
|
+
[2.6.15]: https://github.com/rodjek/rspec-puppet/compare/v2.6.14...v2.6.15
|
|
572
|
+
[2.6.14]: https://github.com/rodjek/rspec-puppet/compare/v2.6.13...v2.6.14
|
|
573
|
+
[2.6.13]: https://github.com/rodjek/rspec-puppet/compare/v2.6.12...v2.6.13
|
|
574
|
+
[2.6.12]: https://github.com/rodjek/rspec-puppet/compare/v2.6.11...v2.6.12
|
|
575
|
+
[2.6.11]: https://github.com/rodjek/rspec-puppet/compare/v2.6.10...v2.6.11
|
|
576
|
+
[2.6.10]: https://github.com/rodjek/rspec-puppet/compare/v2.6.9...v2.6.10
|
|
577
|
+
[2.6.9]: https://github.com/rodjek/rspec-puppet/compare/v2.6.8...v2.6.9
|
|
578
|
+
[2.6.8]: https://github.com/rodjek/rspec-puppet/compare/v2.6.7...v2.6.8
|
|
579
|
+
[2.6.7]: https://github.com/rodjek/rspec-puppet/compare/v2.6.6...v2.6.7
|
|
580
|
+
[2.6.6]: https://github.com/rodjek/rspec-puppet/compare/v2.6.5...v2.6.6
|
|
581
|
+
[2.6.5]: https://github.com/rodjek/rspec-puppet/compare/v2.6.4...v2.6.5
|
|
582
|
+
[2.6.4]: https://github.com/rodjek/rspec-puppet/compare/v2.6.3...v2.6.4
|
|
583
|
+
[2.6.3]: https://github.com/rodjek/rspec-puppet/compare/v2.6.2...v2.6.3
|
|
584
|
+
[2.6.2]: https://github.com/rodjek/rspec-puppet/compare/v2.6.1...v2.6.2
|
|
585
|
+
[2.6.1]: https://github.com/rodjek/rspec-puppet/compare/v2.6.0...v2.6.1
|
|
586
|
+
[2.6.0]: https://github.com/rodjek/rspec-puppet/compare/2.5.0...v2.6.0
|
|
451
587
|
[2.5.0]: https://github.com/rodjek/rspec-puppet/compare/v2.4.0...v2.5.0
|
|
452
588
|
[2.4.0]: https://github.com/rodjek/rspec-puppet/compare/v2.3.2...v2.4.0
|
|
453
589
|
[2.3.2]: https://github.com/rodjek/rspec-puppet/compare/v2.3.1...v2.3.2
|
data/README.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
[](https://travis-ci.org/rodjek/rspec-puppet)
|
|
3
3
|
[](https://coveralls.io/r/rodjek/rspec-puppet?branch=master)
|
|
4
4
|
|
|
5
|
+
#### Table of Contents
|
|
6
|
+
|
|
7
|
+
* [Installation](#installation)
|
|
8
|
+
* [Starting out with a new module](#starting-out-with-a-new-module)
|
|
9
|
+
* [Configure manifests for Puppet 4](#configure-manifests-for-puppet-4)
|
|
10
|
+
* [Configuration](#configuration)
|
|
11
|
+
* [Naming conventions](#naming-conventions)
|
|
12
|
+
* [Example groups](#example-groups)
|
|
13
|
+
* [Defined Types, Classes & Applications](#defined-types-classes--applications)
|
|
14
|
+
* [Functions](#functions)
|
|
15
|
+
* [Hiera integration](#hiera-integration)
|
|
16
|
+
* [Producing coverage reports](#producing-coverage-reports)
|
|
17
|
+
* [Related projects](#related-projects)
|
|
18
|
+
|
|
5
19
|
## Installation
|
|
6
20
|
|
|
7
21
|
gem install rspec-puppet
|
|
@@ -759,6 +773,30 @@ RSpec.configure do |c|
|
|
|
759
773
|
end
|
|
760
774
|
```
|
|
761
775
|
|
|
776
|
+
#### Specifying trusted external data
|
|
777
|
+
|
|
778
|
+
When testing with Puppet >= 6.14, the trusted facts hash will have an additional `external`
|
|
779
|
+
key for trusted external data.
|
|
780
|
+
|
|
781
|
+
By default, the test environment contains no trusted external data (as usually obtained from
|
|
782
|
+
trusted external commands and found in the `external` key). If you need to test against specific
|
|
783
|
+
trusted external data you can set those with a hash. The hash will then be available in
|
|
784
|
+
`$trusted['external']`
|
|
785
|
+
|
|
786
|
+
```ruby
|
|
787
|
+
let(:trusted_external_data) { {'foo' => 'bar'} }
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
You can also create a set of default trusted external data provided to all specs in your spec_helper:
|
|
791
|
+
|
|
792
|
+
```ruby
|
|
793
|
+
RSpec.configure do |c|
|
|
794
|
+
c.default_trusted_external_data = {
|
|
795
|
+
'foo' => 'bar'
|
|
796
|
+
}
|
|
797
|
+
end
|
|
798
|
+
```
|
|
799
|
+
|
|
762
800
|
#### Testing Exported Resources
|
|
763
801
|
|
|
764
802
|
You can test if a resource was exported from the catalogue by using the
|
|
@@ -829,7 +867,7 @@ Puppet functions.
|
|
|
829
867
|
|
|
830
868
|
```ruby
|
|
831
869
|
it 'should be able to do something' do
|
|
832
|
-
subject.
|
|
870
|
+
subject.execute('foo') == 'bar'
|
|
833
871
|
end
|
|
834
872
|
```
|
|
835
873
|
|
|
@@ -869,11 +907,11 @@ either the `with_params` chain method in the `run` matcher
|
|
|
869
907
|
it { is_expected.to run.with_params('foo', 'bar', ['baz']) }
|
|
870
908
|
```
|
|
871
909
|
|
|
872
|
-
Or by using the `
|
|
910
|
+
Or by using the `execute` method on the subject directly
|
|
873
911
|
|
|
874
912
|
```ruby
|
|
875
913
|
it 'something' do
|
|
876
|
-
subject.
|
|
914
|
+
subject.execute('foo', 'bar', ['baz'])
|
|
877
915
|
end
|
|
878
916
|
```
|
|
879
917
|
|
|
@@ -900,8 +938,8 @@ Or by using any of the existing RSpec matchers on the subject directly
|
|
|
900
938
|
|
|
901
939
|
```ruby
|
|
902
940
|
it 'something' do
|
|
903
|
-
subject.
|
|
904
|
-
subject.
|
|
941
|
+
subject.execute('foo') == 'bar'
|
|
942
|
+
subject.execute('baz').should be_an Array
|
|
905
943
|
end
|
|
906
944
|
```
|
|
907
945
|
|
|
@@ -919,8 +957,8 @@ Or by using the existing `raises_error` RSpec matcher
|
|
|
919
957
|
|
|
920
958
|
```ruby
|
|
921
959
|
it 'something' do
|
|
922
|
-
expect { subject.
|
|
923
|
-
expect { subject.
|
|
960
|
+
expect { subject.execute('a', 'b') }.should raise_error(Puppet::ParseError)
|
|
961
|
+
expect { subject.execute('a') }.should_not raise_error(Puppet::ParseError)
|
|
924
962
|
end
|
|
925
963
|
```
|
|
926
964
|
|
|
@@ -139,7 +139,8 @@ module RSpec::Puppet
|
|
|
139
139
|
Puppet.push_context(
|
|
140
140
|
{
|
|
141
141
|
:environments => loader,
|
|
142
|
-
:current_environment => env
|
|
142
|
+
:current_environment => env,
|
|
143
|
+
:loaders => (Puppet::Pops::Loaders.new(env) if Gem::Version.new(Puppet.version) >= Gem::Version.new('6.0.0')),
|
|
143
144
|
},
|
|
144
145
|
"Setup rspec-puppet environments"
|
|
145
146
|
)
|
|
@@ -199,6 +200,12 @@ module RSpec::Puppet
|
|
|
199
200
|
[:vendormoduledir, :vendormoduledir],
|
|
200
201
|
])
|
|
201
202
|
end
|
|
203
|
+
|
|
204
|
+
def catalog(node, _exported)
|
|
205
|
+
super.tap do |c|
|
|
206
|
+
Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, c)
|
|
207
|
+
end
|
|
208
|
+
end
|
|
202
209
|
end
|
|
203
210
|
|
|
204
211
|
class Adapter30 < Base
|
data/lib/rspec-puppet/cache.rb
CHANGED
|
@@ -11,12 +11,17 @@ module RSpec::Puppet
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def get(*args, &blk)
|
|
14
|
-
# decouple the hash key from whatever the blk might do to it
|
|
15
14
|
key = Marshal.load(Marshal.dump(args))
|
|
16
|
-
if
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
if @cache.has_key?(key)
|
|
16
|
+
# Cache hit
|
|
17
|
+
# move that entry last to make it "most recenty used"
|
|
18
|
+
@lra.insert(-1, @lra.delete_at(@lra.index(args)))
|
|
19
|
+
else
|
|
20
|
+
# Cache miss
|
|
21
|
+
# Ensure room by evicting least recently used if no space left
|
|
19
22
|
expire!
|
|
23
|
+
@cache[args] = (blk || @default_proc).call(*args)
|
|
24
|
+
@lra << args
|
|
20
25
|
end
|
|
21
26
|
|
|
22
27
|
@cache[key]
|
|
@@ -25,8 +30,8 @@ module RSpec::Puppet
|
|
|
25
30
|
private
|
|
26
31
|
|
|
27
32
|
def expire!
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
# delete one entry (the oldest) when there is no room in cache
|
|
34
|
+
@cache.delete(@lra.shift) if @cache.size == MAX_ENTRIES
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
37
|
end
|
|
@@ -17,13 +17,25 @@ end
|
|
|
17
17
|
module RSpec::Puppet
|
|
18
18
|
class Coverage
|
|
19
19
|
|
|
20
|
-
attr_accessor :filters
|
|
20
|
+
attr_accessor :filters, :filters_regex
|
|
21
21
|
|
|
22
22
|
class << self
|
|
23
23
|
extend Forwardable
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
|
|
25
|
+
delegated_methods = [
|
|
26
|
+
:instance,
|
|
27
|
+
:add,
|
|
28
|
+
:cover!,
|
|
29
|
+
:report!,
|
|
30
|
+
:filters,
|
|
31
|
+
:filters_regex,
|
|
32
|
+
:add_filter,
|
|
33
|
+
:add_filter_regex,
|
|
34
|
+
:add_from_catalog,
|
|
35
|
+
:results,
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
def_delegators(*delegated_methods)
|
|
27
39
|
|
|
28
40
|
attr_writer :instance
|
|
29
41
|
|
|
@@ -35,10 +47,17 @@ module RSpec::Puppet
|
|
|
35
47
|
def initialize
|
|
36
48
|
@collection = {}
|
|
37
49
|
@filters = ['Stage[main]', 'Class[Settings]', 'Class[main]', 'Node[default]']
|
|
50
|
+
@filters_regex = []
|
|
38
51
|
end
|
|
39
52
|
|
|
40
53
|
def save_results
|
|
41
54
|
slug = "#{Digest::MD5.hexdigest(Dir.pwd)}-#{Process.pid}"
|
|
55
|
+
File.open(File.join(Dir.tmpdir, "rspec-puppet-filter-#{slug}"), 'w+') do |f|
|
|
56
|
+
f.puts @filters.to_json
|
|
57
|
+
end
|
|
58
|
+
File.open(File.join(Dir.tmpdir, "rspec-puppet-filter_regex-#{slug}"), 'w+') do |f|
|
|
59
|
+
f.puts @filters_regex.to_json
|
|
60
|
+
end
|
|
42
61
|
File.open(File.join(Dir.tmpdir, "rspec-puppet-coverage-#{slug}"), 'w+') do |f|
|
|
43
62
|
f.puts @collection.to_json
|
|
44
63
|
end
|
|
@@ -52,6 +71,21 @@ module RSpec::Puppet
|
|
|
52
71
|
end
|
|
53
72
|
end
|
|
54
73
|
|
|
74
|
+
def merge_filters
|
|
75
|
+
pattern = File.join(Dir.tmpdir, "rspec-puppet-filter-#{Digest::MD5.hexdigest(Dir.pwd)}-*")
|
|
76
|
+
regex_filter_pattern = File.join(Dir.tmpdir, "rspec-puppet-filter_regex-#{Digest::MD5.hexdigest(Dir.pwd)}-*")
|
|
77
|
+
|
|
78
|
+
Dir[pattern].each do |result_file|
|
|
79
|
+
load_filters(result_file)
|
|
80
|
+
FileUtils.rm(result_file)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
Dir[regex_filter_pattern].each do |result_file|
|
|
84
|
+
load_filters_regex(result_file)
|
|
85
|
+
FileUtils.rm(result_file)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
55
89
|
def load_results(path)
|
|
56
90
|
saved_results = JSON.parse(File.read(path))
|
|
57
91
|
saved_results.each do |resource, data|
|
|
@@ -60,6 +94,23 @@ module RSpec::Puppet
|
|
|
60
94
|
end
|
|
61
95
|
end
|
|
62
96
|
|
|
97
|
+
def load_filters(path)
|
|
98
|
+
saved_filters = JSON.parse(File.read(path))
|
|
99
|
+
saved_filters.each do |resource|
|
|
100
|
+
@filters << resource
|
|
101
|
+
@collection.delete(resource) if @collection.key?(resource)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def load_filters_regex(path)
|
|
106
|
+
saved_regex_filters = JSON.parse(File.read(path))
|
|
107
|
+
saved_regex_filters.each do |pattern|
|
|
108
|
+
regex = Regexp.new(pattern)
|
|
109
|
+
@filters_regex << regex
|
|
110
|
+
@collection.delete_if { |resource, _| resource =~ regex }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
63
114
|
def add(resource)
|
|
64
115
|
if !exists?(resource) && !filtered?(resource)
|
|
65
116
|
@collection[resource.to_s] = ResourceWrapper.new(resource)
|
|
@@ -67,11 +118,8 @@ module RSpec::Puppet
|
|
|
67
118
|
end
|
|
68
119
|
|
|
69
120
|
def add_filter(type, title)
|
|
70
|
-
def capitalize_name(name)
|
|
71
|
-
name.split('::').map { |subtitle| subtitle.capitalize }.join('::')
|
|
72
|
-
end
|
|
73
|
-
|
|
74
121
|
type = capitalize_name(type)
|
|
122
|
+
|
|
75
123
|
if type == 'Class'
|
|
76
124
|
title = capitalize_name(title)
|
|
77
125
|
end
|
|
@@ -79,6 +127,34 @@ module RSpec::Puppet
|
|
|
79
127
|
@filters << "#{type}[#{title}]"
|
|
80
128
|
end
|
|
81
129
|
|
|
130
|
+
def add_filter_regex(type, pattern)
|
|
131
|
+
raise ArgumentError.new('pattern argument must be a Regexp') unless pattern.is_a?(Regexp)
|
|
132
|
+
|
|
133
|
+
type = capitalize_name(type)
|
|
134
|
+
|
|
135
|
+
# avoid recompiling the regular expression during processing
|
|
136
|
+
src = pattern.source
|
|
137
|
+
|
|
138
|
+
# switch from anchors to wildcards since it is embedded into a larger pattern
|
|
139
|
+
src = if src.start_with?('\\A', '^')
|
|
140
|
+
src.gsub(/\A(?:\\A|\^)/, '')
|
|
141
|
+
else
|
|
142
|
+
# no anchor at the start
|
|
143
|
+
".*#{src}"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# match an even number of backslashes before the anchor - this indicates that the anchor was not escaped
|
|
147
|
+
# note the necessity for the negative lookbehind `(?<!)` to assert that there is no backslash before this
|
|
148
|
+
src = if src.match(/(?<!\\)(\\\\)*(?:\\[zZ]|\$)\z/)
|
|
149
|
+
src.gsub(/(?:\\[zZ]|\$)\z/, '')
|
|
150
|
+
else
|
|
151
|
+
# no anchor at the end
|
|
152
|
+
"#{src}.*"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
@filters_regex << /\A#{Regexp.escape(type)}\[#{src}\]\z/
|
|
156
|
+
end
|
|
157
|
+
|
|
82
158
|
# add all resources from catalog declared in module test_module
|
|
83
159
|
def add_from_catalog(catalog, test_module)
|
|
84
160
|
coverable_resources = catalog.to_a.reject { |resource| !test_module.nil? && filter_resource?(resource, test_module) }
|
|
@@ -88,7 +164,10 @@ module RSpec::Puppet
|
|
|
88
164
|
end
|
|
89
165
|
|
|
90
166
|
def filtered?(resource)
|
|
91
|
-
filters.include?(resource.to_s)
|
|
167
|
+
return true if filters.include?(resource.to_s)
|
|
168
|
+
return true if filters_regex.any? { |f| resource.to_s =~ f }
|
|
169
|
+
|
|
170
|
+
false
|
|
92
171
|
end
|
|
93
172
|
|
|
94
173
|
def cover!(resource)
|
|
@@ -117,13 +196,16 @@ module RSpec::Puppet
|
|
|
117
196
|
end
|
|
118
197
|
|
|
119
198
|
def run_report(coverage_desired = nil)
|
|
120
|
-
|
|
199
|
+
if parallel_tests?
|
|
200
|
+
merge_filters
|
|
201
|
+
merge_results
|
|
202
|
+
end
|
|
121
203
|
|
|
122
204
|
report = results
|
|
123
205
|
|
|
124
206
|
coverage_test(coverage_desired, report)
|
|
125
207
|
|
|
126
|
-
puts report[:text]
|
|
208
|
+
puts "\n\nCoverage Report:\n\n#{report[:text]}"
|
|
127
209
|
end
|
|
128
210
|
|
|
129
211
|
def coverage_test(coverage_desired, report)
|
|
@@ -137,6 +219,17 @@ module RSpec::Puppet
|
|
|
137
219
|
end
|
|
138
220
|
coverage_test.run(RSpec.configuration.reporter)
|
|
139
221
|
|
|
222
|
+
status = if coverage_results.execution_result.respond_to?(:status)
|
|
223
|
+
coverage_results.execution_result.status
|
|
224
|
+
else
|
|
225
|
+
coverage_results.execution_result[:status]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
if status == :failed
|
|
229
|
+
RSpec.world.non_example_failure = true
|
|
230
|
+
RSpec.world.wants_to_quit = true
|
|
231
|
+
end
|
|
232
|
+
|
|
140
233
|
# This is not available on RSpec 2.x
|
|
141
234
|
if coverage_results.execution_result.respond_to?(:pending_message)
|
|
142
235
|
coverage_results.execution_result.pending_message = report[:text]
|
|
@@ -154,7 +247,9 @@ module RSpec::Puppet
|
|
|
154
247
|
report[:total] = @collection.size
|
|
155
248
|
report[:touched] = @collection.count { |_, resource| resource.touched? }
|
|
156
249
|
report[:untouched] = report[:total] - report[:touched]
|
|
157
|
-
|
|
250
|
+
|
|
251
|
+
coverage = report[:total].to_f > 0 ? ((report[:touched].to_f / report[:total].to_f) * 100) : 100.0
|
|
252
|
+
report[:coverage] = "%5.2f" % coverage
|
|
158
253
|
|
|
159
254
|
report[:resources] = Hash[*@collection.map do |name, wrapper|
|
|
160
255
|
[name, wrapper.to_hash]
|
|
@@ -193,7 +288,7 @@ module RSpec::Puppet
|
|
|
193
288
|
# @param test_module [String] The name of the module under test
|
|
194
289
|
# @return [true, false]
|
|
195
290
|
def filter_resource?(resource, test_module)
|
|
196
|
-
if
|
|
291
|
+
if filtered?(resource)
|
|
197
292
|
return true
|
|
198
293
|
end
|
|
199
294
|
|
|
@@ -234,6 +329,10 @@ module RSpec::Puppet
|
|
|
234
329
|
!find(resource).nil?
|
|
235
330
|
end
|
|
236
331
|
|
|
332
|
+
def capitalize_name(name)
|
|
333
|
+
name.split('::').map { |subtitle| subtitle.capitalize }.join('::')
|
|
334
|
+
end
|
|
335
|
+
|
|
237
336
|
class ResourceWrapper
|
|
238
337
|
attr_reader :resource
|
|
239
338
|
|
|
@@ -34,6 +34,14 @@ module RSpec::Puppet
|
|
|
34
34
|
def failure_message_when_negated
|
|
35
35
|
"expected that the type alias would not " + description + " but it does"
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
def supports_block_expectations
|
|
39
|
+
true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def supports_value_expectations
|
|
43
|
+
true
|
|
44
|
+
end
|
|
37
45
|
end
|
|
38
46
|
|
|
39
47
|
def allow_value(*values)
|
|
@@ -7,13 +7,15 @@ module RSpec::Puppet
|
|
|
7
7
|
'Stage[main]',
|
|
8
8
|
].freeze
|
|
9
9
|
|
|
10
|
+
attr_reader :resource_type
|
|
11
|
+
|
|
10
12
|
def initialize(type, count, *method)
|
|
11
13
|
if type.nil?
|
|
12
14
|
@type = method[0].to_s.gsub(/^have_(.+)_resource_count$/, '\1')
|
|
13
15
|
else
|
|
14
16
|
@type = type
|
|
15
17
|
end
|
|
16
|
-
@
|
|
18
|
+
@resource_type = referenced_type(@type)
|
|
17
19
|
@expected_number = count.to_i
|
|
18
20
|
end
|
|
19
21
|
|
|
@@ -30,7 +32,7 @@ module RSpec::Puppet
|
|
|
30
32
|
end
|
|
31
33
|
else
|
|
32
34
|
resources.count do |res|
|
|
33
|
-
res.type == @
|
|
35
|
+
res.type == @resource_type
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
|
|
@@ -45,7 +47,7 @@ module RSpec::Puppet
|
|
|
45
47
|
desc << "#{@expected_number == 1 ? "class" : "classes" }"
|
|
46
48
|
else
|
|
47
49
|
unless @type == "resource"
|
|
48
|
-
desc << "#{@
|
|
50
|
+
desc << "#{@resource_type}"
|
|
49
51
|
end
|
|
50
52
|
desc << "#{@expected_number == 1 ? "resource" : "resources" }"
|
|
51
53
|
end
|
|
@@ -61,6 +63,14 @@ module RSpec::Puppet
|
|
|
61
63
|
"expected that the catalogue would not " + description + " but it does"
|
|
62
64
|
end
|
|
63
65
|
|
|
66
|
+
def supports_block_expectations
|
|
67
|
+
true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def supports_value_expectations
|
|
71
|
+
true
|
|
72
|
+
end
|
|
73
|
+
|
|
64
74
|
private
|
|
65
75
|
|
|
66
76
|
def referenced_type(type)
|
|
@@ -89,6 +89,11 @@ module RSpec::Puppet
|
|
|
89
89
|
else
|
|
90
90
|
RSpec::Puppet::Coverage.cover!(resource)
|
|
91
91
|
rsrc_hsh = resource.to_hash
|
|
92
|
+
if resource.respond_to?(:sensitive_parameters)
|
|
93
|
+
resource.sensitive_parameters.each do |s_param|
|
|
94
|
+
rsrc_hsh[s_param] = ::Puppet::Pops::Types::PSensitiveType::Sensitive.new(rsrc_hsh[s_param])
|
|
95
|
+
end
|
|
96
|
+
end
|
|
92
97
|
|
|
93
98
|
if resource.builtin_type?
|
|
94
99
|
namevar = resource.resource_type.key_attributes.first.to_s
|
|
@@ -177,6 +182,14 @@ module RSpec::Puppet
|
|
|
177
182
|
true
|
|
178
183
|
end
|
|
179
184
|
|
|
185
|
+
def supports_block_expectations
|
|
186
|
+
true
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def supports_value_expectations
|
|
190
|
+
true
|
|
191
|
+
end
|
|
192
|
+
|
|
180
193
|
def expected
|
|
181
194
|
@errors.map {|e| e.expected if e.respond_to?(:expected)}.compact.join("\n\n")
|
|
182
195
|
end
|
|
@@ -294,14 +307,17 @@ module RSpec::Puppet
|
|
|
294
307
|
end
|
|
295
308
|
end
|
|
296
309
|
|
|
297
|
-
# Add
|
|
298
|
-
if
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
310
|
+
# Add auto* (autorequire etc) if any
|
|
311
|
+
if [:before, :notify, :require, :subscribe].include?(type)
|
|
312
|
+
func = "eachauto#{type}".to_sym
|
|
313
|
+
if resource.resource_type.respond_to?(func)
|
|
314
|
+
resource.resource_type.send(func) do |t, b|
|
|
315
|
+
Array(resource.to_ral.instance_eval(&b)).each do |dep|
|
|
316
|
+
res = "#{t.to_s.capitalize}[#{dep}]"
|
|
317
|
+
if r = relationship_refs(res, type, visited)
|
|
318
|
+
results << res
|
|
319
|
+
results << r
|
|
320
|
+
end
|
|
305
321
|
end
|
|
306
322
|
end
|
|
307
323
|
end
|
|
@@ -4,7 +4,7 @@ module RSpec::Puppet
|
|
|
4
4
|
|
|
5
5
|
matcher :include_class do |expected_class|
|
|
6
6
|
match do |catalogue|
|
|
7
|
-
RSpec.deprecate(
|
|
7
|
+
RSpec.deprecate('include_class()', :replacement => 'contain_class()')
|
|
8
8
|
catalogue.call.classes.include?(expected_class)
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -22,6 +22,13 @@ module RSpec::Puppet
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def supports_block_expectations
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def supports_value_expectations
|
|
30
|
+
true
|
|
31
|
+
end
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
end
|
|
@@ -21,10 +21,7 @@ module RSpec::Puppet
|
|
|
21
21
|
#
|
|
22
22
|
# @return [true, false]
|
|
23
23
|
def matches?(resource)
|
|
24
|
-
|
|
25
|
-
@resource = resource
|
|
26
|
-
|
|
27
|
-
actual = @resource[@parameter]
|
|
24
|
+
actual = resource[@parameter]
|
|
28
25
|
expected = @value
|
|
29
26
|
|
|
30
27
|
# Puppet flattens an array with a single value into just the value and
|
|
@@ -65,6 +62,8 @@ module RSpec::Puppet
|
|
|
65
62
|
check_hash(expected, actual)
|
|
66
63
|
when Array
|
|
67
64
|
check_array(expected, actual)
|
|
65
|
+
when RSpec::Puppet::Sensitive
|
|
66
|
+
expected == actual
|
|
68
67
|
else
|
|
69
68
|
check_string(expected, actual)
|
|
70
69
|
end
|
|
@@ -78,7 +77,7 @@ module RSpec::Puppet
|
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
def check_regexp(expected, actual)
|
|
81
|
-
!!(
|
|
80
|
+
!!(actual.to_s.match expected) == @should_match
|
|
82
81
|
end
|
|
83
82
|
|
|
84
83
|
# Ensure that two hashes have the same number of keys, and that for each
|
|
@@ -119,17 +118,7 @@ module RSpec::Puppet
|
|
|
119
118
|
end
|
|
120
119
|
|
|
121
120
|
def check_string(expected, actual)
|
|
122
|
-
(expected.to_s ==
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def munge_line_endings(value)
|
|
126
|
-
return value unless value.respond_to?(:encode)
|
|
127
|
-
|
|
128
|
-
if Puppet::Util::Platform.windows?
|
|
129
|
-
value.encode(:crlf_newline => true)
|
|
130
|
-
else
|
|
131
|
-
value.encode(:universal_newline => true)
|
|
132
|
-
end
|
|
121
|
+
(expected.to_s == actual.to_s) == @should_match
|
|
133
122
|
end
|
|
134
123
|
end
|
|
135
124
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module RSpec::Puppet
|
|
2
|
+
module GenericMatchers
|
|
3
|
+
# Due to significant code base depending on the
|
|
4
|
+
#
|
|
5
|
+
# is_expected.to raise_error Puppet::Error
|
|
6
|
+
#
|
|
7
|
+
# syntax, and removal of this syntax from RSpec, extend RSpec's built-in
|
|
8
|
+
# `raise_error` matcher to accept a value target, e.g. a subject defined
|
|
9
|
+
# as a lambda, e.g.:
|
|
10
|
+
#
|
|
11
|
+
# subject(:catalogue) { lambda { load_catalogue } }
|
|
12
|
+
#
|
|
13
|
+
class RaiseError < RSpec::Matchers::BuiltIn::RaiseError
|
|
14
|
+
def supports_value_expectations?
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def raise_error(error=defined?(RSpec::Matchers::BuiltIn::RaiseError::UndefinedValue) ? RSpec::Matchers::BuiltIn::RaiseError::UndefinedValue : nil, message=nil, &block)
|
|
20
|
+
RaiseError.new(error, message, &block)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RSpec
|
|
4
|
+
module Puppet
|
|
5
|
+
module ManifestMatchers
|
|
6
|
+
extend RSpec::Matchers::DSL
|
|
7
|
+
|
|
8
|
+
matcher :have_unique_values_for_all do |type, attribute|
|
|
9
|
+
match do |catalogue|
|
|
10
|
+
catalogue.call.resources.select { |rsrc| rsrc.type == type.capitalize }
|
|
11
|
+
.group_by { |rsrc| rsrc[attribute.to_sym] }
|
|
12
|
+
.all? { |_, group| group.size == 1 }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
description do
|
|
16
|
+
"have unique attribute values for #{type.capitalize}[#{attribute.to_sym}]"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if RSpec::Version::STRING < '3'
|
|
20
|
+
failure_message_for_should do |_actual|
|
|
21
|
+
"expected that the catalogue would have no duplicate values for #{type.capitalize}[#{attribute.to_sym}]"
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
failure_message do |_actual|
|
|
25
|
+
"expected that the catalogue would have no duplicate values for #{type.capitalize}[#{attribute.to_sym}]"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -6,3 +6,5 @@ require 'rspec-puppet/matchers/count_generic'
|
|
|
6
6
|
require 'rspec-puppet/matchers/dynamic_matchers'
|
|
7
7
|
require 'rspec-puppet/matchers/type_matchers'
|
|
8
8
|
require 'rspec-puppet/matchers/allow_value'
|
|
9
|
+
require 'rspec-puppet/matchers/raise_error'
|
|
10
|
+
require 'rspec-puppet/matchers/unique_values'
|
|
@@ -132,6 +132,16 @@ module Puppet
|
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
module Util
|
|
135
|
+
# Fix for removal of default_env function
|
|
136
|
+
# Bug: https://github.com/rodjek/rspec-puppet/issues/796
|
|
137
|
+
# Upstream: https://github.com/puppetlabs/puppet/commit/94df3c1a3992d89b2d7d5db8a70373c135bdd86b
|
|
138
|
+
if !respond_to?(:default_env)
|
|
139
|
+
def default_env()
|
|
140
|
+
DEFAULT_ENV
|
|
141
|
+
end
|
|
142
|
+
module_function :default_env
|
|
143
|
+
end
|
|
144
|
+
|
|
135
145
|
if respond_to?(:get_env)
|
|
136
146
|
alias :old_get_env :get_env
|
|
137
147
|
module_function :old_get_env
|
|
@@ -213,7 +223,7 @@ module Puppet
|
|
|
213
223
|
end
|
|
214
224
|
|
|
215
225
|
class Autoload
|
|
216
|
-
if
|
|
226
|
+
if respond_to?(:load_file)
|
|
217
227
|
singleton_class.send(:alias_method, :old_load_file, :load_file)
|
|
218
228
|
|
|
219
229
|
def self.load_file(*args)
|
|
@@ -258,6 +268,40 @@ module Puppet
|
|
|
258
268
|
end
|
|
259
269
|
end
|
|
260
270
|
end
|
|
271
|
+
|
|
272
|
+
if Puppet::Util::Package.versioncmp(Puppet.version, '4.9.0') >= 0
|
|
273
|
+
class Module
|
|
274
|
+
old_hiera_conf_file = instance_method(:hiera_conf_file)
|
|
275
|
+
define_method(:hiera_conf_file) do
|
|
276
|
+
if RSpec::Puppet.rspec_puppet_example?
|
|
277
|
+
if RSpec.configuration.disable_module_hiera
|
|
278
|
+
return nil
|
|
279
|
+
elsif RSpec.configuration.fixture_hiera_configs.key?(name)
|
|
280
|
+
config = RSpec.configuration.fixture_hiera_configs[name]
|
|
281
|
+
config = File.absolute_path(config, path) unless config.nil?
|
|
282
|
+
return config
|
|
283
|
+
elsif RSpec.configuration.use_fixture_spec_hiera
|
|
284
|
+
config = RSpec::Puppet.current_example.fixture_spec_hiera_conf(self)
|
|
285
|
+
return config unless config.nil? && RSpec.configuration.fallback_to_default_hiera
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
old_hiera_conf_file.bind(self).call
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
class Pops::Lookup::ModuleDataProvider
|
|
293
|
+
old_configuration_path = instance_method(:configuration_path)
|
|
294
|
+
define_method(:configuration_path) do |lookup_invocation|
|
|
295
|
+
if RSpec::Puppet.rspec_puppet_example?
|
|
296
|
+
env = lookup_invocation.scope.environment
|
|
297
|
+
mod = env.module(module_name)
|
|
298
|
+
raise Puppet::DataBinding::LookupError, _("Environment '%{env}', cannot find module '%{module_name}'") % { :env => env.name, :module_name => module_name } unless mod
|
|
299
|
+
return Pathname.new(mod.hiera_conf_file)
|
|
300
|
+
end
|
|
301
|
+
old_configuration_path.bind(self).call(lookup_invocation)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
261
305
|
end
|
|
262
306
|
|
|
263
307
|
class Pathname
|
|
@@ -292,6 +336,24 @@ class Pathname
|
|
|
292
336
|
end
|
|
293
337
|
end
|
|
294
338
|
|
|
339
|
+
# Puppet loads init.pp, then foo.pp, to find class "mod::foo". If
|
|
340
|
+
# class "mod" has been mocked using pre_condition when testing
|
|
341
|
+
# "mod::foo", this causes duplicate declaration for "mod".
|
|
342
|
+
# This monkey patch only loads "init.pp" if "foo.pp" does not exist.
|
|
343
|
+
class Puppet::Module
|
|
344
|
+
if [:match_manifests, 'match_manifests'].any? { |r| instance_methods.include?(r) }
|
|
345
|
+
old_match_manifests = instance_method(:match_manifests)
|
|
346
|
+
|
|
347
|
+
define_method(:match_manifests) do |rest|
|
|
348
|
+
result = old_match_manifests.bind(self).call(rest)
|
|
349
|
+
if result.length > 1 && File.basename(result[0]) == 'init.pp'
|
|
350
|
+
result.shift
|
|
351
|
+
end
|
|
352
|
+
result
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
295
357
|
# Prevent the File type from munging paths (which uses File.expand_path to
|
|
296
358
|
# normalise paths, which does very bad things to *nix paths on Windows.
|
|
297
359
|
file_path_munge = Puppet::Type.type(:file).paramclass(:path).instance_method(:unsafe_munge)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module RSpec::Puppet
|
|
2
|
+
if defined?(::Puppet::Pops::Types::PSensitiveType::Sensitive)
|
|
3
|
+
# A wrapper representing Sensitive data type, eg. in class params.
|
|
4
|
+
class Sensitive < ::Puppet::Pops::Types::PSensitiveType::Sensitive
|
|
5
|
+
# Create a new Sensitive object
|
|
6
|
+
# @param [Object] value to wrap
|
|
7
|
+
def initialize(value)
|
|
8
|
+
@value = value
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @return the wrapped value
|
|
12
|
+
def unwrap
|
|
13
|
+
@value
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @return true
|
|
17
|
+
def sensitive?
|
|
18
|
+
true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return inspect of the wrapped value, inside Sensitive()
|
|
22
|
+
def inspect
|
|
23
|
+
"Sensitive(#{@value.inspect})"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Check for equality with another value.
|
|
27
|
+
# If compared to Puppet Sensitive type, it compares the wrapped values.
|
|
28
|
+
|
|
29
|
+
# @param other [#unwrap, Object] value to compare to
|
|
30
|
+
def == other
|
|
31
|
+
if other.respond_to? :unwrap
|
|
32
|
+
if unwrap.kind_of?(Regexp)
|
|
33
|
+
return unwrap =~ other.unwrap
|
|
34
|
+
else
|
|
35
|
+
return unwrap == other.unwrap
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
else
|
|
43
|
+
#:nocov:
|
|
44
|
+
class Sensitive
|
|
45
|
+
def initialize(value)
|
|
46
|
+
raise 'The use of the Sensitive data type is not supported by this Puppet version'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
#:nocov:
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/rspec-puppet/support.rb
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
require 'rspec-puppet/cache'
|
|
2
2
|
require 'rspec-puppet/adapters'
|
|
3
3
|
require 'rspec-puppet/raw_string'
|
|
4
|
+
require 'rspec-puppet/sensitive'
|
|
4
5
|
|
|
5
6
|
module RSpec::Puppet
|
|
6
7
|
module Support
|
|
8
|
+
include GenericMatchers
|
|
9
|
+
|
|
7
10
|
@@cache = RSpec::Puppet::Cache.new
|
|
11
|
+
@@fixture_hiera_configs = Hash.new { |h, k| h[k] = nil }
|
|
8
12
|
|
|
9
13
|
def subject
|
|
10
14
|
lambda { catalogue }
|
|
@@ -84,10 +88,29 @@ module RSpec::Puppet
|
|
|
84
88
|
hiera_config_value = self.respond_to?(:hiera_config) ? hiera_config : nil
|
|
85
89
|
hiera_data_value = self.respond_to?(:hiera_data) ? hiera_data : nil
|
|
86
90
|
|
|
91
|
+
rspec_config_values = [
|
|
92
|
+
:trusted_server_facts,
|
|
93
|
+
:disable_module_hiera,
|
|
94
|
+
:use_fixture_spec_hiera,
|
|
95
|
+
:fixture_hiera_configs,
|
|
96
|
+
:fallback_to_default_hiera,
|
|
97
|
+
].map { |setting| RSpec.configuration.send(setting) }
|
|
98
|
+
|
|
87
99
|
build_facts = facts_hash(node_name)
|
|
88
|
-
catalogue = build_catalog(
|
|
89
|
-
|
|
90
|
-
|
|
100
|
+
catalogue = build_catalog(
|
|
101
|
+
nodename: node_name,
|
|
102
|
+
facts_val: build_facts,
|
|
103
|
+
trusted_facts_val: trusted_facts_hash(node_name),
|
|
104
|
+
hiera_config_val: hiera_config_value,
|
|
105
|
+
code: build_code(type, manifest_opts),
|
|
106
|
+
exported: exported,
|
|
107
|
+
node_params: node_params_hash,
|
|
108
|
+
trusted_external_data: trusted_external_data_hash,
|
|
109
|
+
ignored_cache_params: {
|
|
110
|
+
hiera_data_value: hiera_data_value,
|
|
111
|
+
rspec_config_values: rspec_config_values,
|
|
112
|
+
}
|
|
113
|
+
)
|
|
91
114
|
|
|
92
115
|
test_module = type == :host ? nil : class_name.split('::').first
|
|
93
116
|
if type == :define
|
|
@@ -129,13 +152,18 @@ module RSpec::Puppet
|
|
|
129
152
|
end
|
|
130
153
|
|
|
131
154
|
def site_pp_str
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
155
|
+
return '' unless (path = adapter.manifest)
|
|
156
|
+
|
|
157
|
+
if File.file?(path)
|
|
158
|
+
File.read(path)
|
|
159
|
+
elsif File.directory?(path)
|
|
160
|
+
# Read and concatenate all .pp files.
|
|
161
|
+
Dir[File.join(path, '*.pp')].sort.map do |f|
|
|
162
|
+
File.read(f)
|
|
163
|
+
end.join("\n")
|
|
164
|
+
else
|
|
165
|
+
''
|
|
137
166
|
end
|
|
138
|
-
site_pp_str
|
|
139
167
|
end
|
|
140
168
|
|
|
141
169
|
def test_manifest(type, opts = {})
|
|
@@ -219,10 +247,11 @@ module RSpec::Puppet
|
|
|
219
247
|
}
|
|
220
248
|
|
|
221
249
|
node_facts = {
|
|
222
|
-
'hostname'
|
|
223
|
-
'fqdn'
|
|
224
|
-
'domain'
|
|
225
|
-
'clientcert'
|
|
250
|
+
'hostname' => node.split('.').first,
|
|
251
|
+
'fqdn' => node,
|
|
252
|
+
'domain' => node.split('.', 2).last,
|
|
253
|
+
'clientcert' => node,
|
|
254
|
+
'ipaddress6' => 'FE80:0000:0000:0000:AAAA:AAAA:AAAA',
|
|
226
255
|
}
|
|
227
256
|
|
|
228
257
|
networking_facts = {
|
|
@@ -285,6 +314,19 @@ module RSpec::Puppet
|
|
|
285
314
|
extensions
|
|
286
315
|
end
|
|
287
316
|
|
|
317
|
+
def trusted_external_data_hash
|
|
318
|
+
return {} unless Puppet::Util::Package.versioncmp(Puppet.version, '6.14.0') >= 0
|
|
319
|
+
|
|
320
|
+
external_data = {}
|
|
321
|
+
|
|
322
|
+
if RSpec.configuration.default_trusted_external_data.any?
|
|
323
|
+
external_data.merge!(munge_facts(RSpec.configuration.default_trusted_external_data))
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
external_data.merge!(munge_facts(trusted_external_data)) if self.respond_to?(:trusted_external_data)
|
|
327
|
+
external_data
|
|
328
|
+
end
|
|
329
|
+
|
|
288
330
|
def server_facts_hash
|
|
289
331
|
server_facts = {}
|
|
290
332
|
|
|
@@ -350,7 +392,7 @@ module RSpec::Puppet
|
|
|
350
392
|
|
|
351
393
|
# Enable app_management by default for Puppet versions that support it
|
|
352
394
|
if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0 && Puppet.version.to_i < 5
|
|
353
|
-
Puppet[:app_management] = true
|
|
395
|
+
Puppet[:app_management] = ENV.include?('PUPPET_NOAPP_MANAGMENT') ? false : true
|
|
354
396
|
end
|
|
355
397
|
|
|
356
398
|
adapter.modulepath.map do |d|
|
|
@@ -372,6 +414,29 @@ module RSpec::Puppet
|
|
|
372
414
|
end
|
|
373
415
|
|
|
374
416
|
def build_catalog_without_cache(nodename, facts_val, trusted_facts_val, hiera_config_val, code, exported, node_params, *_)
|
|
417
|
+
build_catalog_without_cache_v2({
|
|
418
|
+
nodename: nodename,
|
|
419
|
+
facts_val: facts_val,
|
|
420
|
+
trusted_facts_val: trusted_facts_val,
|
|
421
|
+
hiera_config_val: hiera_config_val,
|
|
422
|
+
code: code,
|
|
423
|
+
exported: exported,
|
|
424
|
+
node_params: node_params,
|
|
425
|
+
trusted_external: {},
|
|
426
|
+
})
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def build_catalog_without_cache_v2(
|
|
430
|
+
nodename: nil,
|
|
431
|
+
facts_val: nil,
|
|
432
|
+
trusted_facts_val: nil,
|
|
433
|
+
hiera_config_val: nil,
|
|
434
|
+
code: nil,
|
|
435
|
+
exported: nil,
|
|
436
|
+
node_params: nil,
|
|
437
|
+
trusted_external_data: nil,
|
|
438
|
+
ignored_cache_params: {}
|
|
439
|
+
)
|
|
375
440
|
|
|
376
441
|
# If we're going to rebuild the catalog, we should clear the cached instance
|
|
377
442
|
# of Hiera that Puppet is using. This opens the possibility of the catalog
|
|
@@ -393,10 +458,14 @@ module RSpec::Puppet
|
|
|
393
458
|
|
|
394
459
|
node_obj = Puppet::Node.new(nodename, { :parameters => node_params, :facts => node_facts })
|
|
395
460
|
|
|
461
|
+
trusted_info = ['remote', nodename, trusted_facts_val]
|
|
462
|
+
if Puppet::Util::Package.versioncmp(Puppet.version, '6.14.0') >= 0
|
|
463
|
+
trusted_info.push(trusted_external_data)
|
|
464
|
+
end
|
|
396
465
|
if Puppet::Util::Package.versioncmp(Puppet.version, '4.3.0') >= 0
|
|
397
466
|
Puppet.push_context(
|
|
398
467
|
{
|
|
399
|
-
:trusted_information => Puppet::Context::TrustedInformation.new(
|
|
468
|
+
:trusted_information => Puppet::Context::TrustedInformation.new(*trusted_info)
|
|
400
469
|
},
|
|
401
470
|
"Context for spec trusted hash"
|
|
402
471
|
)
|
|
@@ -415,7 +484,11 @@ module RSpec::Puppet
|
|
|
415
484
|
|
|
416
485
|
def build_catalog(*args)
|
|
417
486
|
@@cache.get(*args) do |*args|
|
|
418
|
-
|
|
487
|
+
if args.length == 1 && args.first.is_a?(Hash)
|
|
488
|
+
build_catalog_without_cache_v2(args.first)
|
|
489
|
+
else
|
|
490
|
+
build_catalog_without_cache(*args)
|
|
491
|
+
end
|
|
419
492
|
end
|
|
420
493
|
end
|
|
421
494
|
|
|
@@ -432,8 +505,7 @@ module RSpec::Puppet
|
|
|
432
505
|
end
|
|
433
506
|
|
|
434
507
|
def escape_special_chars(string)
|
|
435
|
-
string.gsub
|
|
436
|
-
string
|
|
508
|
+
string.gsub(/\$/, "\\$")
|
|
437
509
|
end
|
|
438
510
|
|
|
439
511
|
def rspec_compatibility
|
|
@@ -444,6 +516,23 @@ module RSpec::Puppet
|
|
|
444
516
|
end
|
|
445
517
|
end
|
|
446
518
|
|
|
519
|
+
def fixture_spec_hiera_conf(mod)
|
|
520
|
+
return @@fixture_hiera_configs[mod.name] if @@fixture_hiera_configs.key?(mod.name)
|
|
521
|
+
|
|
522
|
+
path = Pathname.new(mod.path)
|
|
523
|
+
if path.join('spec').exist?
|
|
524
|
+
path.join('spec').find do |file|
|
|
525
|
+
Find.prune if %w[modules work-dir].any? do |dir|
|
|
526
|
+
file.relative_path_from(path).to_s.start_with?("spec/fixtures/#{dir}")
|
|
527
|
+
end
|
|
528
|
+
if file.basename.to_s.eql?(Puppet::Pops::Lookup::HieraConfig::CONFIG_FILE_NAME)
|
|
529
|
+
return @@fixture_hiera_configs[mod.name] = file.to_s
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
@@fixture_hiera_configs[mod.name]
|
|
534
|
+
end
|
|
535
|
+
|
|
447
536
|
# Helper to return a resource/node reference, so it gets translated in params to a raw string
|
|
448
537
|
# without quotes.
|
|
449
538
|
#
|
|
@@ -454,6 +543,14 @@ module RSpec::Puppet
|
|
|
454
543
|
return RSpec::Puppet::RawString.new("#{type}['#{title}']")
|
|
455
544
|
end
|
|
456
545
|
|
|
546
|
+
# Helper to return value wrapped in Sensitive type.
|
|
547
|
+
#
|
|
548
|
+
# @param [Object] value to wrap
|
|
549
|
+
# @return [RSpec::Puppet::Sensitive] a new Sensitive wrapper with the new value
|
|
550
|
+
def sensitive(value)
|
|
551
|
+
return RSpec::Puppet::Sensitive.new(value)
|
|
552
|
+
end
|
|
553
|
+
|
|
457
554
|
# @!attribute [r] adapter
|
|
458
555
|
# @api private
|
|
459
556
|
# @return [Class < RSpec::Puppet::Adapters::Base]
|
data/lib/rspec-puppet.rb
CHANGED
|
@@ -42,6 +42,7 @@ RSpec.configure do |c|
|
|
|
42
42
|
c.add_setting :default_facts, :default => {}
|
|
43
43
|
c.add_setting :default_node_params, :default => {}
|
|
44
44
|
c.add_setting :default_trusted_facts, :default => {}
|
|
45
|
+
c.add_setting :default_trusted_external_data, :default => {}
|
|
45
46
|
c.add_setting :hiera_config, :default => Puppet::Util::Platform.actually_windows? ? 'c:/nul/' : '/dev/null'
|
|
46
47
|
c.add_setting :parser, :default => 'current'
|
|
47
48
|
c.add_setting :trusted_node_data, :default => false
|
|
@@ -54,6 +55,10 @@ RSpec.configure do |c|
|
|
|
54
55
|
c.add_setting :platform, :default => Puppet::Util::Platform.actual_platform
|
|
55
56
|
c.add_setting :vendormoduledir, :default => Puppet::Util::Platform.actually_windows? ? 'c:/nul/' : '/dev/null'
|
|
56
57
|
c.add_setting :basemodulepath, :default => Puppet::Util::Platform.actually_windows? ? 'c:/nul/' : '/dev/null'
|
|
58
|
+
c.add_setting :disable_module_hiera, :default => false
|
|
59
|
+
c.add_setting :fixture_hiera_configs, :default => {}
|
|
60
|
+
c.add_setting :use_fixture_spec_hiera, :default => false
|
|
61
|
+
c.add_setting :fallback_to_default_hiera, :default => true
|
|
57
62
|
|
|
58
63
|
c.instance_eval do
|
|
59
64
|
def trusted_server_facts
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rspec-puppet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tim Sharpe
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-05-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|
|
@@ -57,14 +57,17 @@ files:
|
|
|
57
57
|
- lib/rspec-puppet/matchers/dynamic_matchers.rb
|
|
58
58
|
- lib/rspec-puppet/matchers/include_class.rb
|
|
59
59
|
- lib/rspec-puppet/matchers/parameter_matcher.rb
|
|
60
|
+
- lib/rspec-puppet/matchers/raise_error.rb
|
|
60
61
|
- lib/rspec-puppet/matchers/run.rb
|
|
61
62
|
- lib/rspec-puppet/matchers/type_matchers.rb
|
|
63
|
+
- lib/rspec-puppet/matchers/unique_values.rb
|
|
62
64
|
- lib/rspec-puppet/monkey_patches.rb
|
|
63
65
|
- lib/rspec-puppet/monkey_patches/win32/registry.rb
|
|
64
66
|
- lib/rspec-puppet/monkey_patches/win32/taskscheduler.rb
|
|
65
67
|
- lib/rspec-puppet/monkey_patches/windows/taskschedulerconstants.rb
|
|
66
68
|
- lib/rspec-puppet/rake_task.rb
|
|
67
69
|
- lib/rspec-puppet/raw_string.rb
|
|
70
|
+
- lib/rspec-puppet/sensitive.rb
|
|
68
71
|
- lib/rspec-puppet/setup.rb
|
|
69
72
|
- lib/rspec-puppet/spec_helper.rb
|
|
70
73
|
- lib/rspec-puppet/support.rb
|
|
@@ -88,8 +91,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
88
91
|
- !ruby/object:Gem::Version
|
|
89
92
|
version: '0'
|
|
90
93
|
requirements: []
|
|
91
|
-
|
|
92
|
-
rubygems_version: 2.6.14.1
|
|
94
|
+
rubygems_version: 3.2.5
|
|
93
95
|
signing_key:
|
|
94
96
|
specification_version: 4
|
|
95
97
|
summary: RSpec tests for your Puppet manifests
|