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