chefspec 4.7.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -21
- data/CHANGELOG.md +18 -0
- data/Gemfile +1 -0
- data/README.md +37 -20
- data/chefspec.gemspec +4 -4
- data/examples/apt_repository/recipes/add.rb +8 -0
- data/examples/apt_repository/recipes/remove.rb +4 -0
- data/examples/apt_repository/spec/add_spec.rb +14 -0
- data/examples/apt_repository/spec/remove_spec.rb +9 -0
- data/examples/apt_update/recipes/periodic.rb +5 -0
- data/examples/apt_update/recipes/update.rb +3 -0
- data/examples/apt_update/spec/periodic_spec.rb +14 -0
- data/examples/apt_update/spec/update_spec.rb +9 -0
- data/examples/attributes/spec/default_spec.rb +1 -1
- data/examples/notifications/recipes/before.rb +7 -0
- data/examples/notifications/spec/before_spec.rb +16 -0
- data/examples/server/spec/node_spec.rb +3 -3
- data/examples/server/spec/search_spec.rb +4 -4
- data/examples/stub_node/spec/default_spec.rb +2 -2
- data/examples/subscribes/recipes/before.rb +5 -0
- data/examples/subscribes/spec/before_spec.rb +16 -0
- data/examples/user/spec/create_spec.rb +1 -1
- data/examples/user/spec/lock_spec.rb +1 -1
- data/examples/user/spec/manage_spec.rb +1 -1
- data/examples/user/spec/modify_spec.rb +1 -1
- data/examples/user/spec/remove_spec.rb +1 -1
- data/examples/user/spec/unlock_spec.rb +1 -1
- data/features/chocolatey_package.feature +0 -10
- data/features/dsc_resource.feature +0 -9
- data/features/notifications.feature +8 -0
- data/features/reboot.feature +0 -7
- data/features/step_into.feature +0 -7
- data/features/subscribes.feature +8 -0
- data/features/windows_package.feature +0 -9
- data/features/windows_service.feature +0 -7
- data/gemfiles/chefspec.gemfile +6 -0
- data/lib/chefspec/api/apt_repository.rb +56 -0
- data/lib/chefspec/api/apt_update.rb +53 -0
- data/lib/chefspec/cacher.rb +3 -2
- data/lib/chefspec/coverage.rb +38 -5
- data/lib/chefspec/errors.rb +3 -0
- data/lib/chefspec/extensions/chef/data_query.rb +2 -2
- data/lib/chefspec/matchers/notifications_matcher.rb +23 -2
- data/lib/chefspec/matchers/subscribes_matcher.rb +9 -0
- data/lib/chefspec/version.rb +1 -1
- data/spec/spec_helper.rb +5 -0
- data/spec/unit/cacher_spec.rb +17 -1
- data/spec/unit/matchers/notifications_matcher_spec.rb +1 -0
- data/spec/unit/matchers/subscribes_matcher_spec.rb +1 -0
- data/spec/unit/solo_runner_spec.rb +1 -1
- data/templates/coverage/json.erb +8 -0
- data/templates/coverage/table.erb +14 -0
- data/templates/errors/erb_template_parse_error.erb +5 -0
- data/templates/errors/template_not_found.erb +9 -0
- metadata +26 -11
- data/spec/unit/extensions/lwrp_base_spec.rb +0 -96
@@ -2,8 +2,8 @@ require 'chefspec'
|
|
2
2
|
|
3
3
|
describe 'stub_node::default' do
|
4
4
|
let(:my_node) do
|
5
|
-
stub_node('example.com', platform: 'ubuntu', version: '
|
6
|
-
node.
|
5
|
+
stub_node('example.com', platform: 'ubuntu', version: '14.04') do |node|
|
6
|
+
node.normal['foo']['bar'] = 'zip'
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'chefspec'
|
2
|
+
|
3
|
+
describe 'subscribes::before' do
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
5
|
+
let(:service) { chef_run.service('receiving_resource') }
|
6
|
+
|
7
|
+
it 'subscribes to the template creation' do
|
8
|
+
expect(service).to subscribe_to('template[/tmp/notifying_resource]').before
|
9
|
+
expect(service).to_not subscribe_to('template[/tmp/not_notifying_resource]').before
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'subscribes to the specific action on the resource before' do
|
13
|
+
expect(service).to subscribe_to('template[/tmp/notifying_resource]').on(:create).before
|
14
|
+
expect(service).to_not subscribe_to('template[/tmp/notifying_resource]').on(:delete).immediately
|
15
|
+
end
|
16
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'chefspec'
|
2
2
|
|
3
3
|
describe 'user::create' do
|
4
|
-
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04').converge(described_recipe) }
|
5
5
|
|
6
6
|
it 'creates a user with the default action' do
|
7
7
|
expect(chef_run).to create_user('default_action')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'chefspec'
|
2
2
|
|
3
3
|
describe 'user::lock' do
|
4
|
-
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04').converge(described_recipe) }
|
5
5
|
|
6
6
|
it 'locks a user with an explicit action' do
|
7
7
|
expect(chef_run).to lock_user('explicit_action')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'chefspec'
|
2
2
|
|
3
3
|
describe 'user::manage' do
|
4
|
-
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04').converge(described_recipe) }
|
5
5
|
|
6
6
|
it 'manages a user with an explicit action' do
|
7
7
|
expect(chef_run).to manage_user('explicit_action')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'chefspec'
|
2
2
|
|
3
3
|
describe 'user::modify' do
|
4
|
-
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04').converge(described_recipe) }
|
5
5
|
|
6
6
|
it 'modifys a user with an explicit action' do
|
7
7
|
expect(chef_run).to modify_user('explicit_action')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'chefspec'
|
2
2
|
|
3
3
|
describe 'user::remove' do
|
4
|
-
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04').converge(described_recipe) }
|
5
5
|
|
6
6
|
it 'removes a user with an explicit action' do
|
7
7
|
expect(chef_run).to remove_user('explicit_action')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'chefspec'
|
2
2
|
|
3
3
|
describe 'user::unlock' do
|
4
|
-
let(:chef_run) { ChefSpec::SoloRunner.converge(described_recipe) }
|
4
|
+
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04').converge(described_recipe) }
|
5
5
|
|
6
6
|
it 'unlocks a user with an explicit action' do
|
7
7
|
expect(chef_run).to unlock_user('explicit_action')
|
@@ -1,17 +1,7 @@
|
|
1
|
-
@not_chef_11_14_2
|
2
|
-
@not_chef_11_14_6
|
3
|
-
@not_chef_11_16_0
|
4
|
-
@not_chef_11_16_2
|
5
|
-
@not_chef_11_16_4
|
6
|
-
@not_chef_11_18_0
|
7
|
-
@not_chef_11_18_6
|
8
1
|
@not_chef_12_0_3
|
9
|
-
@not_chef_12_1_0
|
10
|
-
@not_chef_12_1_1
|
11
2
|
@not_chef_12_1_2
|
12
3
|
@not_chef_12_2_1
|
13
4
|
@not_chef_12_3_0
|
14
|
-
@not_chef_12_4_0
|
15
5
|
@not_chef_12_4_3
|
16
6
|
@not_chef_12_5_1
|
17
7
|
@not_chef_12_6_0
|
@@ -1,13 +1,4 @@
|
|
1
|
-
@not_chef_11_14_2
|
2
|
-
@not_chef_11_14_6
|
3
|
-
@not_chef_11_16_0
|
4
|
-
@not_chef_11_16_2
|
5
|
-
@not_chef_11_16_4
|
6
|
-
@not_chef_11_18_0
|
7
|
-
@not_chef_11_18_6
|
8
1
|
@not_chef_12_0_3
|
9
|
-
@not_chef_12_1_0
|
10
|
-
@not_chef_12_1_1
|
11
2
|
@not_chef_12_1_2
|
12
3
|
Feature: The dsc_resource matcher
|
13
4
|
Background:
|
@@ -1,3 +1,10 @@
|
|
1
|
+
@not_chef_12_0_3
|
2
|
+
@not_chef_12_1_2
|
3
|
+
@not_chef_12_2_1
|
4
|
+
@not_chef_12_3_0
|
5
|
+
@not_chef_12_4_3
|
6
|
+
@not_chef_12_5_1
|
7
|
+
|
1
8
|
Feature: The notifications matcher
|
2
9
|
Background:
|
3
10
|
* I am using the "notifications" cookbook
|
@@ -7,6 +14,7 @@ Feature: The notifications matcher
|
|
7
14
|
* the output should contain "0 failures"
|
8
15
|
Examples:
|
9
16
|
| Matcher |
|
17
|
+
| before |
|
10
18
|
| chained |
|
11
19
|
| default |
|
12
20
|
| delayed |
|
data/features/reboot.feature
CHANGED
data/features/step_into.feature
CHANGED
data/features/subscribes.feature
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
@not_chef_12_0_3
|
2
|
+
@not_chef_12_1_2
|
3
|
+
@not_chef_12_2_1
|
4
|
+
@not_chef_12_3_0
|
5
|
+
@not_chef_12_4_3
|
6
|
+
@not_chef_12_5_1
|
7
|
+
|
1
8
|
Feature: The subscribes matcher
|
2
9
|
Background:
|
3
10
|
* I am using the "subscribes" cookbook
|
@@ -7,6 +14,7 @@ Feature: The subscribes matcher
|
|
7
14
|
* the output should contain "0 failures"
|
8
15
|
Examples:
|
9
16
|
| Matcher |
|
17
|
+
| before |
|
10
18
|
| chained |
|
11
19
|
| default |
|
12
20
|
| delayed |
|
@@ -1,13 +1,4 @@
|
|
1
|
-
@not_chef_11_14_2
|
2
|
-
@not_chef_11_14_6
|
3
|
-
@not_chef_11_16_0
|
4
|
-
@not_chef_11_16_2
|
5
|
-
@not_chef_11_16_4
|
6
|
-
@not_chef_11_18_0
|
7
|
-
@not_chef_11_18_6
|
8
1
|
@not_chef_12_0_3
|
9
|
-
@not_chef_12_1_0
|
10
|
-
@not_chef_12_1_1
|
11
2
|
@not_chef_12_1_2
|
12
3
|
@not_chef_12_2_1
|
13
4
|
@not_chef_12_3_0
|
data/gemfiles/chefspec.gemfile
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
+
# travis runs on older chef releases failed while including
|
4
|
+
# rack 2.X on Ruby 2.1. When we remove Ruby 2.1 support this can go
|
5
|
+
if ENV['CHEF_VERSION'].to_f < 12.6
|
6
|
+
gem 'rack', '~> 1.0'
|
7
|
+
end
|
8
|
+
|
3
9
|
if ENV['CHEF_VERSION'] == 'master'
|
4
10
|
gem 'chef', github: 'chef/chef'
|
5
11
|
else
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ChefSpec::API
|
2
|
+
# @since 3.0.0
|
3
|
+
module AptRepositoryMatchers
|
4
|
+
ChefSpec.define_matcher :apt_repository
|
5
|
+
|
6
|
+
#
|
7
|
+
# Assert that an +apt_repository+ resource exists in the Chef run with the
|
8
|
+
# action +:add+. Given a Chef Recipe that adds "rsyslog" as an
|
9
|
+
# +apt_repository+:
|
10
|
+
#
|
11
|
+
# apt_repository 'rsyslog' do
|
12
|
+
# uri 'ppa:adiscon/v8-stable'
|
13
|
+
# action :add
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# The Examples section demonstrates the different ways to test an
|
17
|
+
# +apt_repository+ resource with ChefSpec.
|
18
|
+
#
|
19
|
+
# @example Assert that an +apt_repository+ was added
|
20
|
+
# expect(chef_run).to add_apt_repository('rsyslog')
|
21
|
+
# @param [String, Regex] resource_name
|
22
|
+
# the name of the resource to match
|
23
|
+
#
|
24
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
25
|
+
|
26
|
+
def add_apt_repository(resource_name)
|
27
|
+
ChefSpec::Matchers::ResourceMatcher.new(:apt_repository, :add,
|
28
|
+
resource_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Assert that an +apt_repository+ resource exists in the Chef run with the
|
33
|
+
# action +:remove+. Given a Chef Recipe that removes "rsyslog" as an
|
34
|
+
# +apt_repository+:
|
35
|
+
#
|
36
|
+
# apt_repository 'rsyslog' do
|
37
|
+
# uri 'ppa:adiscon/v8-stable'
|
38
|
+
# action :remove
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# The Examples section demonstrates the different ways to test an
|
42
|
+
# +apt_repository+ resource with ChefSpec.
|
43
|
+
#
|
44
|
+
# @example Assert that an +apt_repository+ was removed
|
45
|
+
# expect(chef_run).to remove_apt_repository('rsyslog')
|
46
|
+
# @param [String, Regex] resource_name
|
47
|
+
# the name of the resource to match
|
48
|
+
#
|
49
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
50
|
+
|
51
|
+
def remove_apt_repository(resource_name)
|
52
|
+
ChefSpec::Matchers::ResourceMatcher.new(:apt_repository, :remove,
|
53
|
+
resource_name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ChefSpec::API
|
2
|
+
# @since 3.0.0
|
3
|
+
module AptUpdateMatchers
|
4
|
+
ChefSpec.define_matcher :apt_update
|
5
|
+
|
6
|
+
#
|
7
|
+
# Assert that an +apt_update+ resource exists in the Chef run with the
|
8
|
+
# action +:update+. Given a Chef Recipe that adds "rsyslog" as a repository
|
9
|
+
# to update.
|
10
|
+
# apt_repository 'rsyslog' do
|
11
|
+
# action :update
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# The Examples section demonstrates the different ways to test an
|
15
|
+
# +apt_update+ resource with ChefSpec.
|
16
|
+
#
|
17
|
+
# @example Assert that an +apt_update+ was run
|
18
|
+
# expect(chef_run).to update_apt_update('rsyslog')
|
19
|
+
# @param [String, Regex] resource_name
|
20
|
+
# the name of the resource to match
|
21
|
+
#
|
22
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
23
|
+
|
24
|
+
def update_apt_update(resource_name)
|
25
|
+
ChefSpec::Matchers::ResourceMatcher.new(:apt_update, :update,
|
26
|
+
resource_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Assert that an +apt_update+ resource exists in the Chef run
|
31
|
+
# with the action +:periodic+. Given a Chef Recipe that updates "rsyslog"
|
32
|
+
# as an +apt_update+: periodically
|
33
|
+
#
|
34
|
+
# apt_update 'rsyslog' do
|
35
|
+
# action :periodic
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# The Examples section demonstrates the different ways to test an
|
39
|
+
# +apt_update+ resource with ChefSpec.
|
40
|
+
#
|
41
|
+
# @example Assert that an +apt_update+ was updated periodically
|
42
|
+
# expect(chef_run).to periodic_apt_update('rsyslog')
|
43
|
+
# @param [String, Regex] resource_name
|
44
|
+
# the name of the resource to match
|
45
|
+
#
|
46
|
+
# @return [ChefSpec::Matchers::ResourceMatcher]
|
47
|
+
|
48
|
+
def periodic_apt_update(resource_name)
|
49
|
+
ChefSpec::Matchers::ResourceMatcher.new(:apt_update, :periodic,
|
50
|
+
resource_name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/chefspec/cacher.rb
CHANGED
@@ -35,8 +35,9 @@ module ChefSpec
|
|
35
35
|
|
36
36
|
def cached(name, &block)
|
37
37
|
location = ancestors.first.metadata[:location]
|
38
|
-
unless
|
39
|
-
location += ancestors.first.metadata[:description]
|
38
|
+
unless location.nil?
|
39
|
+
location += ancestors.first.metadata[:description] unless ancestors.first.metadata[:description].nil?
|
40
|
+
location += ancestors.first.metadata[:scoped_id] unless ancestors.first.metadata[:scoped_id].nil?
|
40
41
|
end
|
41
42
|
location ||= ancestors.first.metadata[:parent_example_group][:location]
|
42
43
|
|
data/lib/chefspec/coverage.rb
CHANGED
@@ -28,6 +28,7 @@ module ChefSpec
|
|
28
28
|
def initialize
|
29
29
|
@collection = {}
|
30
30
|
@filters = {}
|
31
|
+
@template = ChefSpec.root.join('templates', 'coverage', 'human.erb')
|
31
32
|
end
|
32
33
|
|
33
34
|
#
|
@@ -67,7 +68,26 @@ module ChefSpec
|
|
67
68
|
|
68
69
|
true
|
69
70
|
end
|
70
|
-
|
71
|
+
#
|
72
|
+
# Change the template for reporting of converage analysis.
|
73
|
+
#
|
74
|
+
# @param [string] path
|
75
|
+
# The template file to use for the output of the report
|
76
|
+
#
|
77
|
+
# @return [true]
|
78
|
+
#
|
79
|
+
def set_template(file = 'human.erb')
|
80
|
+
[
|
81
|
+
ChefSpec.root.join('templates', 'coverage', file),
|
82
|
+
File.expand_path(file, Dir.pwd)
|
83
|
+
].each do |temp|
|
84
|
+
if File.exist?(temp)
|
85
|
+
@template = temp
|
86
|
+
return
|
87
|
+
end
|
88
|
+
end
|
89
|
+
raise Error::TemplateNotFound.new(path: file)
|
90
|
+
end
|
71
91
|
#
|
72
92
|
# Add a resource to the resource collection. Only new resources are added
|
73
93
|
# and only resources that match the given filter are covered (which is *
|
@@ -130,10 +150,14 @@ module ChefSpec
|
|
130
150
|
report[:untouched_resources] = @collection.collect do |_, resource|
|
131
151
|
resource unless resource.touched?
|
132
152
|
end.compact
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
153
|
+
report[:all_resources] = @collection.values
|
154
|
+
|
155
|
+
begin
|
156
|
+
erb = Erubis::Eruby.new(File.read(@template))
|
157
|
+
puts erb.evaluate(report)
|
158
|
+
rescue NameError => e
|
159
|
+
raise Error::ErbTemplateParseError.new(original_error: e.message)
|
160
|
+
end
|
137
161
|
|
138
162
|
# Ensure we exit correctly (#351)
|
139
163
|
Kernel.exit(exit_status) if exit_status && exit_status > 0
|
@@ -160,6 +184,15 @@ module ChefSpec
|
|
160
184
|
@resource.to_s
|
161
185
|
end
|
162
186
|
|
187
|
+
def to_json
|
188
|
+
{
|
189
|
+
"source_file" => source_file,
|
190
|
+
"source_line" => source_line,
|
191
|
+
"touched" => touched?,
|
192
|
+
"resource" => to_s
|
193
|
+
}.to_json
|
194
|
+
end
|
195
|
+
|
163
196
|
def source_file
|
164
197
|
@source_file ||= if @resource.source_line
|
165
198
|
shortname(@resource.source_line.split(':').first)
|
data/lib/chefspec/errors.rb
CHANGED
@@ -33,8 +33,8 @@ module Chef::DSL::DataQuery
|
|
33
33
|
|
34
34
|
# @see Chef::DSL::DataQuery#data_bag_item
|
35
35
|
alias_method :old_data_bag_item, :data_bag_item
|
36
|
-
def data_bag_item(bag, id)
|
37
|
-
return old_data_bag_item(bag, id) unless Chef::Config[:solo]
|
36
|
+
def data_bag_item(bag, id, secret = nil)
|
37
|
+
return old_data_bag_item(bag, id, secret) unless Chef::Config[:solo]
|
38
38
|
|
39
39
|
stub = ChefSpec::Stubs::DataBagItemRegistry.stub_for(bag, id)
|
40
40
|
|