chefspec-chef 9.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +30 -0
- data/LICENSE +22 -0
- data/Rakefile +85 -0
- data/chefspec-chef.gemspec +30 -0
- data/lib/chefspec/api/core.rb +217 -0
- data/lib/chefspec/api/described.rb +53 -0
- data/lib/chefspec/api/do_nothing.rb +26 -0
- data/lib/chefspec/api/include_any_recipe.rb +24 -0
- data/lib/chefspec/api/include_recipe.rb +28 -0
- data/lib/chefspec/api/link.rb +28 -0
- data/lib/chefspec/api/notifications.rb +40 -0
- data/lib/chefspec/api/reboot.rb +14 -0
- data/lib/chefspec/api/render_file.rb +37 -0
- data/lib/chefspec/api/state_attrs.rb +30 -0
- data/lib/chefspec/api/stubs.rb +183 -0
- data/lib/chefspec/api/stubs_for.rb +139 -0
- data/lib/chefspec/api/subscriptions.rb +37 -0
- data/lib/chefspec/api/user.rb +230 -0
- data/lib/chefspec/api.rb +39 -0
- data/lib/chefspec/berkshelf.rb +63 -0
- data/lib/chefspec/cacher.rb +64 -0
- data/lib/chefspec/coverage/filters.rb +82 -0
- data/lib/chefspec/coverage.rb +247 -0
- data/lib/chefspec/deprecations.rb +46 -0
- data/lib/chefspec/errors.rb +48 -0
- data/lib/chefspec/expect_exception.rb +51 -0
- data/lib/chefspec/extensions/chef/client.rb +21 -0
- data/lib/chefspec/extensions/chef/conditional.rb +16 -0
- data/lib/chefspec/extensions/chef/cookbook/gem_installer.rb +33 -0
- data/lib/chefspec/extensions/chef/cookbook_loader.rb +14 -0
- data/lib/chefspec/extensions/chef/cookbook_uploader.rb +12 -0
- data/lib/chefspec/extensions/chef/data_query.rb +49 -0
- data/lib/chefspec/extensions/chef/lwrp_base.rb +29 -0
- data/lib/chefspec/extensions/chef/provider.rb +39 -0
- data/lib/chefspec/extensions/chef/resource/freebsd_package.rb +17 -0
- data/lib/chefspec/extensions/chef/resource.rb +188 -0
- data/lib/chefspec/extensions/chef/run_context/cookbook_compiler.rb +84 -0
- data/lib/chefspec/extensions/chef/securable.rb +19 -0
- data/lib/chefspec/extensions/ohai/system.rb +11 -0
- data/lib/chefspec/extensions.rb +21 -0
- data/lib/chefspec/file_cache_path_proxy.rb +15 -0
- data/lib/chefspec/formatter.rb +282 -0
- data/lib/chefspec/librarian.rb +51 -0
- data/lib/chefspec/matchers/do_nothing_matcher.rb +52 -0
- data/lib/chefspec/matchers/include_any_recipe_matcher.rb +51 -0
- data/lib/chefspec/matchers/include_recipe_matcher.rb +46 -0
- data/lib/chefspec/matchers/link_to_matcher.rb +37 -0
- data/lib/chefspec/matchers/notifications_matcher.rb +143 -0
- data/lib/chefspec/matchers/render_file_matcher.rb +140 -0
- data/lib/chefspec/matchers/resource_matcher.rb +175 -0
- data/lib/chefspec/matchers/state_attrs_matcher.rb +71 -0
- data/lib/chefspec/matchers/subscribes_matcher.rb +72 -0
- data/lib/chefspec/matchers.rb +13 -0
- data/lib/chefspec/mixins/normalize.rb +22 -0
- data/lib/chefspec/policyfile.rb +69 -0
- data/lib/chefspec/renderer.rb +145 -0
- data/lib/chefspec/rspec.rb +21 -0
- data/lib/chefspec/runner.rb +8 -0
- data/lib/chefspec/server.rb +4 -0
- data/lib/chefspec/server_methods.rb +173 -0
- data/lib/chefspec/server_runner.rb +76 -0
- data/lib/chefspec/solo_runner.rb +516 -0
- data/lib/chefspec/stubs/command_registry.rb +11 -0
- data/lib/chefspec/stubs/command_stub.rb +37 -0
- data/lib/chefspec/stubs/data_bag_item_registry.rb +13 -0
- data/lib/chefspec/stubs/data_bag_item_stub.rb +25 -0
- data/lib/chefspec/stubs/data_bag_registry.rb +13 -0
- data/lib/chefspec/stubs/data_bag_stub.rb +23 -0
- data/lib/chefspec/stubs/registry.rb +32 -0
- data/lib/chefspec/stubs/search_registry.rb +13 -0
- data/lib/chefspec/stubs/search_stub.rb +25 -0
- data/lib/chefspec/stubs/stub.rb +38 -0
- data/lib/chefspec/util.rb +58 -0
- data/lib/chefspec/version.rb +3 -0
- data/lib/chefspec/zero_server.rb +142 -0
- data/lib/chefspec.rb +75 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/hash.rb +35 -0
- data/spec/unit/cacher_spec.rb +70 -0
- data/spec/unit/coverage/filters_spec.rb +60 -0
- data/spec/unit/deprecations_spec.rb +52 -0
- data/spec/unit/errors_spec.rb +57 -0
- data/spec/unit/expect_exception_spec.rb +32 -0
- data/spec/unit/macros_spec.rb +119 -0
- data/spec/unit/matchers/do_nothing_matcher.rb +5 -0
- data/spec/unit/matchers/include_any_recipe_matcher_spec.rb +52 -0
- data/spec/unit/matchers/include_recipe_matcher_spec.rb +38 -0
- data/spec/unit/matchers/link_to_matcher_spec.rb +55 -0
- data/spec/unit/matchers/notifications_matcher_spec.rb +39 -0
- data/spec/unit/matchers/render_file_matcher_spec.rb +68 -0
- data/spec/unit/matchers/resource_matcher_spec.rb +5 -0
- data/spec/unit/matchers/state_attrs_matcher_spec.rb +68 -0
- data/spec/unit/matchers/subscribes_matcher_spec.rb +63 -0
- data/spec/unit/renderer_spec.rb +69 -0
- data/spec/unit/server_runner_spec.rb +28 -0
- data/spec/unit/solo_runner_spec.rb +171 -0
- data/spec/unit/stubs/command_registry_spec.rb +27 -0
- data/spec/unit/stubs/command_stub_spec.rb +61 -0
- data/spec/unit/stubs/data_bag_item_registry_spec.rb +39 -0
- data/spec/unit/stubs/data_bag_item_stub_spec.rb +36 -0
- data/spec/unit/stubs/data_bag_registry_spec.rb +39 -0
- data/spec/unit/stubs/data_bag_stub_spec.rb +35 -0
- data/spec/unit/stubs/registry_spec.rb +29 -0
- data/spec/unit/stubs/search_registry_spec.rb +39 -0
- data/spec/unit/stubs/search_stub_spec.rb +36 -0
- data/spec/unit/stubs/stub_spec.rb +64 -0
- data/templates/coverage/human.erb +22 -0
- data/templates/coverage/json.erb +8 -0
- data/templates/coverage/table.erb +14 -0
- data/templates/errors/cookbook_path_not_found.erb +3 -0
- data/templates/errors/erb_template_parse_error.erb +5 -0
- data/templates/errors/gem_load_error.erb +7 -0
- data/templates/errors/invalid_berkshelf_options.erb +4 -0
- data/templates/errors/may_need_to_specify_platform.erb +25 -0
- data/templates/errors/no_conversion_error.erb +1 -0
- data/templates/errors/not_stubbed.erb +7 -0
- data/templates/errors/shell_out_not_stubbed.erb +10 -0
- data/templates/errors/template_not_found.erb +9 -0
- metadata +221 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
RSpec.configure do |config|
|
|
2
|
+
unless ENV["CHEFSPEC_NO_INCLUDE"]
|
|
3
|
+
config.include(ChefSpec::API)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
config.add_setting :berkshelf_options, default: {}
|
|
7
|
+
config.add_setting :policyfile_path
|
|
8
|
+
config.add_setting :file_cache_path
|
|
9
|
+
config.add_setting :cookbook_root
|
|
10
|
+
config.add_setting :cookbook_path
|
|
11
|
+
config.add_setting :role_path
|
|
12
|
+
config.add_setting :environment_path
|
|
13
|
+
config.add_setting :file_cache_path
|
|
14
|
+
config.add_setting :log_level, default: :warn
|
|
15
|
+
config.add_setting :path
|
|
16
|
+
config.add_setting :platform
|
|
17
|
+
config.add_setting :version
|
|
18
|
+
config.add_setting :server_runner_data_store, default: :in_memory
|
|
19
|
+
config.add_setting :server_runner_clear_cookbooks, default: true
|
|
20
|
+
config.add_setting :server_runner_port, default: (8889..8899)
|
|
21
|
+
end
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
module ChefSpec
|
|
2
|
+
# This module contains the list of methods that are specific to creating and
|
|
3
|
+
# managing resources within an Chef Zero instance. It is designed to be
|
|
4
|
+
# included in a class which exposes a `server` instance variable or method
|
|
5
|
+
# that returns a {ChefZero::Server} instance.
|
|
6
|
+
module ServerMethods
|
|
7
|
+
#
|
|
8
|
+
# The actual Chef Zero Server object.
|
|
9
|
+
#
|
|
10
|
+
# @return [ChefZero::Server]
|
|
11
|
+
#
|
|
12
|
+
def server
|
|
13
|
+
ChefSpec::ZeroServer.server
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# @macro entity
|
|
18
|
+
# @method create_$1(name, data = {})
|
|
19
|
+
# Create a new $1 on the Chef Server
|
|
20
|
+
#
|
|
21
|
+
# @param [String] name
|
|
22
|
+
# the name of the $1
|
|
23
|
+
# @param [Hash] data
|
|
24
|
+
# the list of data to load
|
|
25
|
+
#
|
|
26
|
+
#
|
|
27
|
+
# @method $1(name)
|
|
28
|
+
# Find a $1 at the given name
|
|
29
|
+
#
|
|
30
|
+
# @param [String] name
|
|
31
|
+
# the name of the $1
|
|
32
|
+
#
|
|
33
|
+
# @return [$2, nil]
|
|
34
|
+
#
|
|
35
|
+
#
|
|
36
|
+
# @method $3
|
|
37
|
+
# The list of $1 on the Chef Server
|
|
38
|
+
#
|
|
39
|
+
# @return [Array<Hash>]
|
|
40
|
+
# all the $1 on the Chef Server
|
|
41
|
+
#
|
|
42
|
+
#
|
|
43
|
+
# @method has_$1?(name)
|
|
44
|
+
# Determine if the Chef Server has the given $1
|
|
45
|
+
#
|
|
46
|
+
# @param [String] name
|
|
47
|
+
# the name of the $1 to find
|
|
48
|
+
#
|
|
49
|
+
# @return [true, false]
|
|
50
|
+
#
|
|
51
|
+
def self.entity(method, klass, key)
|
|
52
|
+
class_eval <<-EOH, __FILE__, __LINE__ + 1
|
|
53
|
+
def create_#{method}(name, data = {})
|
|
54
|
+
# Automatically set the "name" if no explicit one was given
|
|
55
|
+
data[:name] ||= name
|
|
56
|
+
|
|
57
|
+
# Convert it to JSON
|
|
58
|
+
data = JSON.fast_generate(data)
|
|
59
|
+
|
|
60
|
+
load_data(name, '#{key}', data)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def get_#{method}(name)
|
|
64
|
+
data = get('#{key}', name)
|
|
65
|
+
json = JSON.parse(data)
|
|
66
|
+
|
|
67
|
+
case
|
|
68
|
+
when #{klass}.respond_to?(:json_create)
|
|
69
|
+
#{klass}.json_create(json)
|
|
70
|
+
when #{klass}.respond_to?(:from_hash)
|
|
71
|
+
#{klass}.from_hash(json)
|
|
72
|
+
else
|
|
73
|
+
#{klass}.new(json)
|
|
74
|
+
end
|
|
75
|
+
rescue ChefZero::DataStore::DataNotFoundError
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def get_#{key}
|
|
80
|
+
get('#{key}')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def has_#{method}?(name)
|
|
84
|
+
!get('#{key}', name).nil?
|
|
85
|
+
rescue ChefZero::DataStore::DataNotFoundError
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
EOH
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
entity :client, Chef::Client, "clients"
|
|
92
|
+
entity :data_bag, Chef::DataBag, "data"
|
|
93
|
+
entity :environment, Chef::Environment, "environments"
|
|
94
|
+
entity :node, Chef::Node, "nodes"
|
|
95
|
+
entity :role, Chef::Role, "roles"
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# Create a new data_bag on the Chef Server. This overrides the method
|
|
99
|
+
# created by {entity}
|
|
100
|
+
#
|
|
101
|
+
# @param [String] name
|
|
102
|
+
# the name of the data bag
|
|
103
|
+
# @param [Hash] data
|
|
104
|
+
# the data to load into the data bag
|
|
105
|
+
#
|
|
106
|
+
def create_data_bag(name, data = {})
|
|
107
|
+
load_data(name, "data", data)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Create a new node on the Chef Server. This overrides the method created
|
|
112
|
+
# by {entity}, permitting users to pass a raw +Chef::Node+ object in
|
|
113
|
+
# addition to a hash.
|
|
114
|
+
#
|
|
115
|
+
# @example Create a node from a hash
|
|
116
|
+
#
|
|
117
|
+
# create_node('bacon', attribute: 'value')
|
|
118
|
+
#
|
|
119
|
+
# @example Create a node from a +Chef::Node+ object
|
|
120
|
+
#
|
|
121
|
+
# node = stub_node('bacon', platform: 'ubuntu', version: '18.04')
|
|
122
|
+
# create_node(node)
|
|
123
|
+
#
|
|
124
|
+
# @param [String, Chef::Node] object
|
|
125
|
+
# the object to create; this can be the name of the node, or an actual
|
|
126
|
+
# +Chef::Node+ object
|
|
127
|
+
# @param [Hash] data
|
|
128
|
+
# the list of data to populate the node with; this is ignored if an
|
|
129
|
+
# actual node object is given
|
|
130
|
+
#
|
|
131
|
+
def create_node(object, data = {})
|
|
132
|
+
if object.is_a?(Chef::Node)
|
|
133
|
+
name = object.name
|
|
134
|
+
data = object.to_json
|
|
135
|
+
else
|
|
136
|
+
name = object.to_s
|
|
137
|
+
data[:name] ||= name
|
|
138
|
+
data = JSON.fast_generate(data)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
load_data(name, "nodes", data)
|
|
142
|
+
end
|
|
143
|
+
alias_method :update_node, :create_node
|
|
144
|
+
|
|
145
|
+
#
|
|
146
|
+
# Shortcut method for loading data into Chef Zero.
|
|
147
|
+
#
|
|
148
|
+
# @param [String] name
|
|
149
|
+
# the name or id of the item to load
|
|
150
|
+
# @param [String, Symbol] key
|
|
151
|
+
# the key to load
|
|
152
|
+
# @param [Hash] data
|
|
153
|
+
# the data for the object, which will be converted to JSON and uploaded
|
|
154
|
+
# to the server
|
|
155
|
+
#
|
|
156
|
+
def load_data(name, key, data = {})
|
|
157
|
+
ChefSpec::ZeroServer.load_data(name, key, data)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
#
|
|
161
|
+
# Get the path to an item in the data store.
|
|
162
|
+
#
|
|
163
|
+
def get(*args)
|
|
164
|
+
args.unshift("organizations", "chef")
|
|
165
|
+
|
|
166
|
+
if args.size == 3
|
|
167
|
+
server.data_store.list(args)
|
|
168
|
+
else
|
|
169
|
+
server.data_store.get(args)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require "chef/cookbook_loader"
|
|
2
|
+
require "chef/cookbook_uploader"
|
|
3
|
+
|
|
4
|
+
require_relative "zero_server"
|
|
5
|
+
require_relative "file_cache_path_proxy"
|
|
6
|
+
require_relative "server_methods"
|
|
7
|
+
require_relative "solo_runner"
|
|
8
|
+
|
|
9
|
+
module ChefSpec
|
|
10
|
+
class ServerRunner < SoloRunner
|
|
11
|
+
include ChefSpec::ServerMethods
|
|
12
|
+
|
|
13
|
+
# @see (SoloRunner#initialize)
|
|
14
|
+
def initialize(options = {})
|
|
15
|
+
# Unlike the SoloRunner, the file_cache_path needs to remain consistent
|
|
16
|
+
# for every Chef run or else the Chef client tries to loads the same
|
|
17
|
+
# cookbook multiple times and will encounter deprecated logic when
|
|
18
|
+
# creating LWRPs. It also slows down the entire process.
|
|
19
|
+
options[:file_cache_path] ||= RSpec.configuration.file_cache_path ||
|
|
20
|
+
ChefSpec::FileCachePathProxy.instance.file_cache_path
|
|
21
|
+
|
|
22
|
+
# Call super, but do not pass in the block because we want to customize
|
|
23
|
+
# our yielding.
|
|
24
|
+
super(options, &nil)
|
|
25
|
+
|
|
26
|
+
# Unlike the SoloRunner, the node AND server object are yielded for
|
|
27
|
+
# customization
|
|
28
|
+
yield node, self if block_given?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @see (SoloRunner#converge)
|
|
32
|
+
def converge(*recipe_names)
|
|
33
|
+
ChefSpec::ZeroServer.upload_cookbooks!
|
|
34
|
+
|
|
35
|
+
super do
|
|
36
|
+
yield if block_given?
|
|
37
|
+
|
|
38
|
+
# Save the node back to the server for searching purposes
|
|
39
|
+
client.register
|
|
40
|
+
node.save
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# The path to the insecure Chef Zero private key on disk. Because Chef
|
|
48
|
+
# requires the path to a file instead of the contents of the key (why),
|
|
49
|
+
# this method dynamically writes the +ChefZero::PRIVATE_KEY+ to disk and
|
|
50
|
+
# then returns that path.
|
|
51
|
+
#
|
|
52
|
+
# @return [String]
|
|
53
|
+
# the path to the client key on disk
|
|
54
|
+
#
|
|
55
|
+
def client_key
|
|
56
|
+
tmp = Dir.mktmpdir
|
|
57
|
+
path = File.join(tmp, "client.pem")
|
|
58
|
+
File.open(path, "wb") { |f| f.write(ChefZero::PRIVATE_KEY) }
|
|
59
|
+
at_exit { FileUtils.rm_rf(tmp) }
|
|
60
|
+
path
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# (see SoloRunner#apply_chef_config!)
|
|
64
|
+
def apply_chef_config!
|
|
65
|
+
super
|
|
66
|
+
Chef::Config[:client_key] = client_key
|
|
67
|
+
Chef::Config[:client_name] = "chefspec"
|
|
68
|
+
Chef::Config[:node_name] = "chefspec"
|
|
69
|
+
Chef::Config[:solo] = false
|
|
70
|
+
Chef::Config[:solo_legacy_mode] = false
|
|
71
|
+
|
|
72
|
+
Chef::Config[:chef_server_url] = server.url
|
|
73
|
+
Chef::Config[:http_retry_count] = 0
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|