chefspec-chef 9.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +30 -0
  3. data/LICENSE +22 -0
  4. data/Rakefile +85 -0
  5. data/chefspec-chef.gemspec +30 -0
  6. data/lib/chefspec/api/core.rb +217 -0
  7. data/lib/chefspec/api/described.rb +53 -0
  8. data/lib/chefspec/api/do_nothing.rb +26 -0
  9. data/lib/chefspec/api/include_any_recipe.rb +24 -0
  10. data/lib/chefspec/api/include_recipe.rb +28 -0
  11. data/lib/chefspec/api/link.rb +28 -0
  12. data/lib/chefspec/api/notifications.rb +40 -0
  13. data/lib/chefspec/api/reboot.rb +14 -0
  14. data/lib/chefspec/api/render_file.rb +37 -0
  15. data/lib/chefspec/api/state_attrs.rb +30 -0
  16. data/lib/chefspec/api/stubs.rb +183 -0
  17. data/lib/chefspec/api/stubs_for.rb +139 -0
  18. data/lib/chefspec/api/subscriptions.rb +37 -0
  19. data/lib/chefspec/api/user.rb +230 -0
  20. data/lib/chefspec/api.rb +39 -0
  21. data/lib/chefspec/berkshelf.rb +63 -0
  22. data/lib/chefspec/cacher.rb +64 -0
  23. data/lib/chefspec/coverage/filters.rb +82 -0
  24. data/lib/chefspec/coverage.rb +247 -0
  25. data/lib/chefspec/deprecations.rb +46 -0
  26. data/lib/chefspec/errors.rb +48 -0
  27. data/lib/chefspec/expect_exception.rb +51 -0
  28. data/lib/chefspec/extensions/chef/client.rb +21 -0
  29. data/lib/chefspec/extensions/chef/conditional.rb +16 -0
  30. data/lib/chefspec/extensions/chef/cookbook/gem_installer.rb +33 -0
  31. data/lib/chefspec/extensions/chef/cookbook_loader.rb +14 -0
  32. data/lib/chefspec/extensions/chef/cookbook_uploader.rb +12 -0
  33. data/lib/chefspec/extensions/chef/data_query.rb +49 -0
  34. data/lib/chefspec/extensions/chef/lwrp_base.rb +29 -0
  35. data/lib/chefspec/extensions/chef/provider.rb +39 -0
  36. data/lib/chefspec/extensions/chef/resource/freebsd_package.rb +17 -0
  37. data/lib/chefspec/extensions/chef/resource.rb +188 -0
  38. data/lib/chefspec/extensions/chef/run_context/cookbook_compiler.rb +84 -0
  39. data/lib/chefspec/extensions/chef/securable.rb +19 -0
  40. data/lib/chefspec/extensions/ohai/system.rb +11 -0
  41. data/lib/chefspec/extensions.rb +21 -0
  42. data/lib/chefspec/file_cache_path_proxy.rb +15 -0
  43. data/lib/chefspec/formatter.rb +282 -0
  44. data/lib/chefspec/librarian.rb +51 -0
  45. data/lib/chefspec/matchers/do_nothing_matcher.rb +52 -0
  46. data/lib/chefspec/matchers/include_any_recipe_matcher.rb +51 -0
  47. data/lib/chefspec/matchers/include_recipe_matcher.rb +46 -0
  48. data/lib/chefspec/matchers/link_to_matcher.rb +37 -0
  49. data/lib/chefspec/matchers/notifications_matcher.rb +143 -0
  50. data/lib/chefspec/matchers/render_file_matcher.rb +140 -0
  51. data/lib/chefspec/matchers/resource_matcher.rb +175 -0
  52. data/lib/chefspec/matchers/state_attrs_matcher.rb +71 -0
  53. data/lib/chefspec/matchers/subscribes_matcher.rb +72 -0
  54. data/lib/chefspec/matchers.rb +13 -0
  55. data/lib/chefspec/mixins/normalize.rb +22 -0
  56. data/lib/chefspec/policyfile.rb +69 -0
  57. data/lib/chefspec/renderer.rb +145 -0
  58. data/lib/chefspec/rspec.rb +21 -0
  59. data/lib/chefspec/runner.rb +8 -0
  60. data/lib/chefspec/server.rb +4 -0
  61. data/lib/chefspec/server_methods.rb +173 -0
  62. data/lib/chefspec/server_runner.rb +76 -0
  63. data/lib/chefspec/solo_runner.rb +516 -0
  64. data/lib/chefspec/stubs/command_registry.rb +11 -0
  65. data/lib/chefspec/stubs/command_stub.rb +37 -0
  66. data/lib/chefspec/stubs/data_bag_item_registry.rb +13 -0
  67. data/lib/chefspec/stubs/data_bag_item_stub.rb +25 -0
  68. data/lib/chefspec/stubs/data_bag_registry.rb +13 -0
  69. data/lib/chefspec/stubs/data_bag_stub.rb +23 -0
  70. data/lib/chefspec/stubs/registry.rb +32 -0
  71. data/lib/chefspec/stubs/search_registry.rb +13 -0
  72. data/lib/chefspec/stubs/search_stub.rb +25 -0
  73. data/lib/chefspec/stubs/stub.rb +38 -0
  74. data/lib/chefspec/util.rb +58 -0
  75. data/lib/chefspec/version.rb +3 -0
  76. data/lib/chefspec/zero_server.rb +142 -0
  77. data/lib/chefspec.rb +75 -0
  78. data/spec/spec_helper.rb +12 -0
  79. data/spec/support/hash.rb +35 -0
  80. data/spec/unit/cacher_spec.rb +70 -0
  81. data/spec/unit/coverage/filters_spec.rb +60 -0
  82. data/spec/unit/deprecations_spec.rb +52 -0
  83. data/spec/unit/errors_spec.rb +57 -0
  84. data/spec/unit/expect_exception_spec.rb +32 -0
  85. data/spec/unit/macros_spec.rb +119 -0
  86. data/spec/unit/matchers/do_nothing_matcher.rb +5 -0
  87. data/spec/unit/matchers/include_any_recipe_matcher_spec.rb +52 -0
  88. data/spec/unit/matchers/include_recipe_matcher_spec.rb +38 -0
  89. data/spec/unit/matchers/link_to_matcher_spec.rb +55 -0
  90. data/spec/unit/matchers/notifications_matcher_spec.rb +39 -0
  91. data/spec/unit/matchers/render_file_matcher_spec.rb +68 -0
  92. data/spec/unit/matchers/resource_matcher_spec.rb +5 -0
  93. data/spec/unit/matchers/state_attrs_matcher_spec.rb +68 -0
  94. data/spec/unit/matchers/subscribes_matcher_spec.rb +63 -0
  95. data/spec/unit/renderer_spec.rb +69 -0
  96. data/spec/unit/server_runner_spec.rb +28 -0
  97. data/spec/unit/solo_runner_spec.rb +171 -0
  98. data/spec/unit/stubs/command_registry_spec.rb +27 -0
  99. data/spec/unit/stubs/command_stub_spec.rb +61 -0
  100. data/spec/unit/stubs/data_bag_item_registry_spec.rb +39 -0
  101. data/spec/unit/stubs/data_bag_item_stub_spec.rb +36 -0
  102. data/spec/unit/stubs/data_bag_registry_spec.rb +39 -0
  103. data/spec/unit/stubs/data_bag_stub_spec.rb +35 -0
  104. data/spec/unit/stubs/registry_spec.rb +29 -0
  105. data/spec/unit/stubs/search_registry_spec.rb +39 -0
  106. data/spec/unit/stubs/search_stub_spec.rb +36 -0
  107. data/spec/unit/stubs/stub_spec.rb +64 -0
  108. data/templates/coverage/human.erb +22 -0
  109. data/templates/coverage/json.erb +8 -0
  110. data/templates/coverage/table.erb +14 -0
  111. data/templates/errors/cookbook_path_not_found.erb +3 -0
  112. data/templates/errors/erb_template_parse_error.erb +5 -0
  113. data/templates/errors/gem_load_error.erb +7 -0
  114. data/templates/errors/invalid_berkshelf_options.erb +4 -0
  115. data/templates/errors/may_need_to_specify_platform.erb +25 -0
  116. data/templates/errors/no_conversion_error.erb +1 -0
  117. data/templates/errors/not_stubbed.erb +7 -0
  118. data/templates/errors/shell_out_not_stubbed.erb +10 -0
  119. data/templates/errors/template_not_found.erb +9 -0
  120. metadata +221 -0
@@ -0,0 +1,29 @@
1
+ # XXX: This monkeypatch is somewhat terrible and dumps all of the
2
+ # resources in the sub-resource collection into the main resource
3
+ # collection. Chefspec needs to be taught how to deal with
4
+ # sub-resource collections.
5
+
6
+ if defined?(Chef::Provider::InlineResources)
7
+ Chef::Provider::InlineResources.prepend(Module.new do
8
+ def initialize(resource, run_context)
9
+ super
10
+ @run_context = run_context
11
+ @resource_collection = run_context.resource_collection
12
+ end
13
+ end)
14
+
15
+ Chef::Provider::InlineResources::ClassMethods.prepend(Module.new do
16
+ def action(name, &block)
17
+ # Note: This does not check $CHEFSPEC_MODE.
18
+ define_method("action_#{name}", &block)
19
+ end
20
+ end)
21
+ else # >= 13.0
22
+ Chef::Provider.prepend(Module.new do
23
+ def compile_and_converge_action(&block)
24
+ return super unless $CHEFSPEC_MODE
25
+
26
+ instance_eval(&block)
27
+ end
28
+ end)
29
+ end
@@ -0,0 +1,39 @@
1
+ require "chef/provider"
2
+ require_relative "../../api"
3
+
4
+ Chef::Provider.prepend(Module.new do
5
+ def self.name
6
+ "ChefSpec extensions for Chef::Provider"
7
+ end
8
+
9
+ def self.inspect
10
+ "#<Module: #{name}>"
11
+ end
12
+
13
+ # Hook for the stubs_for system.
14
+ def initialize(*args, &block)
15
+ super(*args, &block)
16
+ ChefSpec::API::StubsFor.setup_stubs_for(self, :provider) if $CHEFSPEC_MODE
17
+ end
18
+
19
+ # Defang shell_out and friends so it can never run.
20
+ if ChefSpec::API::StubsFor::HAS_SHELLOUT_COMPACTED.satisfied_by?(Gem::Version.create(Chef::VERSION))
21
+ def shell_out_compacted(*args)
22
+ return super unless $CHEFSPEC_MODE
23
+
24
+ raise ChefSpec::Error::ShellOutNotStubbed.new(args: args, type: "provider", resource: new_resource)
25
+ end
26
+
27
+ def shell_out_compacted!(*args)
28
+ return super unless $CHEFSPEC_MODE
29
+
30
+ shell_out_compacted(*args).tap(&:error!)
31
+ end
32
+ else
33
+ def shell_out(*args)
34
+ return super unless $CHEFSPEC_MODE
35
+
36
+ raise ChefSpec::Error::ShellOutNotStubbed.new(args: args, type: "provider", resource: new_resource)
37
+ end
38
+ end
39
+ end)
@@ -0,0 +1,17 @@
1
+ require "chef/resource/freebsd_package"
2
+
3
+ Chef::Resource::FreebsdPackage.prepend(Module.new do
4
+ #
5
+ # Chef decided it was a good idea to just shellout inside of a resource.
6
+ # Not only is that a horrible fucking idea, but I got flak when I asked
7
+ # to change it. So we are just going to monkey patch the fucking thing so
8
+ # it does not shell out.
9
+ #
10
+ # @return [false]
11
+ #
12
+ def supports_pkgng?
13
+ return super unless $CHEFSPEC_MODE
14
+
15
+ true
16
+ end
17
+ end)
@@ -0,0 +1,188 @@
1
+ require "chef/resource"
2
+ require "chef/version"
3
+ require_relative "../../api"
4
+
5
+ #
6
+ # Three concerns:
7
+ # - no-op'ing so that the action does not run the provider
8
+ # - tracking the actions that were performed
9
+ # - auto registering helper methods
10
+ #
11
+
12
+ module ChefSpec::Extensions::Chef::Resource
13
+
14
+ #
15
+ # Hooks for the stubs_for system
16
+ #
17
+ def initialize(*args, &block)
18
+ super(*args, &block)
19
+ if $CHEFSPEC_MODE
20
+ # Here be dragons.
21
+ # If we're directly inside a `load_current_resource`, this is probably
22
+ # something like `new_resource.class.new` so we want to call this a current_resource,
23
+ # Otherwise it's probably a normal resource instantiation.
24
+ mode = :resource
25
+ mode = :current_value if caller.any? { |x| x.include?("`load_current_resource'") || x.include?("`load_after_resource'") }
26
+ ChefSpec::API::StubsFor.setup_stubs_for(self, mode)
27
+ end
28
+ end
29
+
30
+ def dup
31
+ return super unless $CHEFSPEC_MODE
32
+
33
+ # Also here be dragons.
34
+ super.tap do |dup_resource|
35
+ # We're directly inside a load_current_resource, which is probably via
36
+ # the load_current_value DSL system, so call this a current resource.
37
+ ChefSpec::API::StubsFor.setup_stubs_for(dup_resource, :current_value) if caller.any? { |x| x.include?("`load_current_resource'") || x.include?("`load_after_resource'") }
38
+ end
39
+ end
40
+
41
+ # mix of no-op and tracking concerns
42
+ def run_action(action, notification_type = nil, notifying_resource = nil)
43
+ return super unless $CHEFSPEC_MODE
44
+
45
+ resolve_notification_references
46
+ validate_action(action)
47
+
48
+ Chef::Log.info("Processing #{self} action #{action} (#{defined_at})")
49
+
50
+ ChefSpec::Coverage.add(self)
51
+
52
+ unless should_skip?(action)
53
+ if node.runner.step_into?(self)
54
+ instance_eval { @not_if = []; @only_if = [] }
55
+ super
56
+ end
57
+
58
+ if node.runner.compiling?
59
+ perform_action(action, compile_time: true)
60
+ else
61
+ perform_action(action, converge_time: true)
62
+ end
63
+ end
64
+ end
65
+
66
+ #
67
+ # Defang shell_out and friends so it can never run.
68
+ #
69
+ if ChefSpec::API::StubsFor::HAS_SHELLOUT_COMPACTED.satisfied_by?(Gem::Version.create(Chef::VERSION))
70
+ def shell_out_compacted(*args)
71
+ return super unless $CHEFSPEC_MODE
72
+
73
+ raise ChefSpec::Error::ShellOutNotStubbed.new(args: args, type: "resource", resource: self)
74
+ end
75
+
76
+ def shell_out_compacted!(*args)
77
+ return super unless $CHEFSPEC_MODE
78
+
79
+ shell_out_compacted(*args).tap(&:error!)
80
+ end
81
+ else
82
+ def shell_out(*args)
83
+ return super unless $CHEFSPEC_MODE
84
+
85
+ raise ChefSpec::Error::ShellOutNotStubbed.new(args: args, type: "resource", resource: self)
86
+ end
87
+ end
88
+
89
+ #
90
+ # tracking
91
+ #
92
+
93
+ def perform_action(action, options = {})
94
+ @performed_actions ||= {}
95
+ @performed_actions[action.to_sym] ||= {}
96
+ @performed_actions[action.to_sym].merge!(options)
97
+ end
98
+
99
+ def performed_action(action)
100
+ @performed_actions ||= {}
101
+ @performed_actions[action.to_sym]
102
+ end
103
+
104
+ def performed_action?(action)
105
+ if action == :nothing
106
+ performed_actions.empty?
107
+ else
108
+ !!performed_action(action)
109
+ end
110
+ end
111
+
112
+ def performed_actions
113
+ @performed_actions ||= {}
114
+ @performed_actions.keys
115
+ end
116
+
117
+ #
118
+ # auto-registration
119
+ #
120
+
121
+ def self.prepended(base)
122
+ class << base
123
+ prepend ClassMethods
124
+ end
125
+ end
126
+
127
+ module ClassMethods
128
+ # XXX: kind of a crappy way to find all the names of a resource
129
+ def provides_names
130
+ @provides_names ||= []
131
+ end
132
+
133
+ def resource_name(name = ::Chef::NOT_PASSED)
134
+ unless name == ::Chef::NOT_PASSED
135
+ provides_names << name unless provides_names.include?(name)
136
+ inject_actions(*allowed_actions)
137
+ end
138
+ super
139
+ end
140
+
141
+ def provides(name, **options, &block)
142
+ provides_names << name unless provides_names.include?(name)
143
+ inject_actions(*allowed_actions)
144
+ super
145
+ end
146
+
147
+ def action(sym, description: nil, &block)
148
+ inject_actions(sym)
149
+ super(sym, &block)
150
+ end
151
+
152
+ def allowed_actions(*actions)
153
+ inject_actions(*actions) unless actions.empty?
154
+ super
155
+ end
156
+
157
+ def allowed_actions=(value)
158
+ inject_actions(*Array(value))
159
+ super
160
+ end
161
+
162
+ private
163
+
164
+ def inject_method(method, resource_name, action)
165
+ unless ChefSpec::API.respond_to?(method)
166
+ ChefSpec::API.send(:define_method, method) do |name|
167
+ ChefSpec::Matchers::ResourceMatcher.new(resource_name, action, name)
168
+ end
169
+ end
170
+ end
171
+
172
+ def inject_actions(*actions)
173
+ provides_names.each do |resource_name|
174
+ next unless resource_name
175
+
176
+ ChefSpec.define_matcher(resource_name)
177
+ actions.each do |action|
178
+ inject_method(:"#{action}_#{resource_name}", resource_name, action)
179
+ if action == :create_if_missing
180
+ inject_method(:"create_#{resource_name}_if_missing", resource_name, action)
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+ Chef::Resource.prepend(ChefSpec::Extensions::Chef::Resource)
@@ -0,0 +1,84 @@
1
+ require "chef/run_context/cookbook_compiler"
2
+
3
+ Chef::RunContext::CookbookCompiler.prepend(Module.new do
4
+ # List of compile phases as of Chef 14:
5
+ # compile_libraries
6
+ # compile_ohai_plugins
7
+ # compile_attributes
8
+ # compile_lwrps
9
+ # compile_resource_definitions
10
+ # compile_recipes
11
+
12
+ #
13
+ # Compile phases that should only ever run once, globally.
14
+ #
15
+
16
+ def load_libraries_from_cookbook(cookbook)
17
+ return super unless $CHEFSPEC_MODE
18
+
19
+ $CHEFSPEC_LIBRARY_PRELOAD ||= {}
20
+ # Already loaded this once.
21
+ return if $CHEFSPEC_LIBRARY_PRELOAD[cookbook]
22
+
23
+ $CHEFSPEC_LIBRARY_PRELOAD[cookbook] = true
24
+ super
25
+ end
26
+
27
+ def load_ohai_plugins_from_cookbook(cookbook)
28
+ return super unless $CHEFSPEC_MODE
29
+
30
+ $CHEFSPEC_OHAI_PRELOAD ||= {}
31
+ # Already loaded this once.
32
+ return if $CHEFSPEC_OHAI_PRELOAD[cookbook]
33
+
34
+ $CHEFSPEC_OHAI_PRELOAD[cookbook] = true
35
+ super
36
+ end
37
+
38
+ def load_lwrps_from_cookbook(cookbook)
39
+ return super unless $CHEFSPEC_MODE
40
+
41
+ $CHEFSPEC_LWRP_PRELOAD ||= {}
42
+ # Already loaded this once.
43
+ return if $CHEFSPEC_LWRP_PRELOAD[cookbook]
44
+
45
+ $CHEFSPEC_LWRP_PRELOAD[cookbook] = true
46
+ super
47
+ end
48
+
49
+ def load_resource_definitions_from_cookbook(cookbook)
50
+ return super unless $CHEFSPEC_MODE
51
+
52
+ $CHEFSPEC_DEFINITION_PRELOAD ||= {}
53
+ # Already loaded this once.
54
+ return if $CHEFSPEC_DEFINITION_PRELOAD[cookbook]
55
+
56
+ $CHEFSPEC_DEFINITION_PRELOAD[cookbook] = true
57
+ super
58
+ end
59
+
60
+ #
61
+ # Compile phases that should not run during preload
62
+ #
63
+
64
+ def compile_ohai_plugins
65
+ return super unless $CHEFSPEC_MODE
66
+ return if $CHEFSPEC_PRELOAD
67
+
68
+ super
69
+ end
70
+
71
+ def compile_attributes
72
+ return super unless $CHEFSPEC_MODE
73
+ return if $CHEFSPEC_PRELOAD
74
+
75
+ super
76
+ end
77
+
78
+ def compile_recipes
79
+ return super unless $CHEFSPEC_MODE
80
+ return if $CHEFSPEC_PRELOAD
81
+
82
+ super
83
+ end
84
+ end)
@@ -0,0 +1,19 @@
1
+ require "chef/mixin/securable"
2
+
3
+ class Chef
4
+ module Mixin
5
+ module Securable
6
+ # In Chef, this module is only included if the RUBY_PLATFORM is
7
+ # Windows-like. In ChefSpec, we want to include this, regardless of the
8
+ # platform, becuase this module holds the `inherits` attribute, which is
9
+ # critical in testing Windows resources.
10
+ include WindowsSecurableAttributes
11
+
12
+ def self.included(including_class)
13
+ including_class.extend(WindowsMacros)
14
+ including_class.rights_attribute(:rights)
15
+ including_class.rights_attribute(:deny_rights)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ require "ohai/system"
2
+
3
+ Ohai::System.prepend(Module.new do
4
+ # If an Ohai segment exists, don't actually pull data in for ohai.
5
+ # (we have fake data for that)
6
+ # @see Ohai::System#run_additional_plugins
7
+ def run_additional_plugins(plugin_path)
8
+ return super unless $CHEFSPEC_MODE
9
+ # noop
10
+ end
11
+ end)
@@ -0,0 +1,21 @@
1
+ require "rspec"
2
+
3
+ module ChefSpec::Extensions
4
+ module Chef
5
+ end
6
+ end
7
+
8
+ # STOP! DO NOT ALPHABETIZE!
9
+ require_relative "extensions/chef/data_query" # must be before Chef::Resource loads
10
+ require_relative "extensions/chef/resource" # must come before client extensions or anything that winds up loading resources
11
+ require_relative "extensions/chef/provider"
12
+ require_relative "extensions/chef/securable"
13
+ require_relative "extensions/chef/client"
14
+ require_relative "extensions/chef/conditional"
15
+ require_relative "extensions/chef/cookbook_uploader"
16
+ require_relative "extensions/chef/cookbook/gem_installer"
17
+ require_relative "extensions/chef/lwrp_base"
18
+ require_relative "extensions/chef/resource/freebsd_package"
19
+ require_relative "extensions/chef/run_context/cookbook_compiler"
20
+ require_relative "extensions/chef/cookbook_loader"
21
+ require_relative "extensions/ohai/system"
@@ -0,0 +1,15 @@
1
+ require "fileutils" unless defined?(FileUtils)
2
+ require "singleton" unless defined?(Singleton)
3
+
4
+ module ChefSpec
5
+ class FileCachePathProxy
6
+ include Singleton
7
+
8
+ attr_reader :file_cache_path
9
+
10
+ def initialize
11
+ @file_cache_path = Dir.mktmpdir(%w{chefspec file_cache_path})
12
+ at_exit { FileUtils.rm_rf(@file_cache_path) }
13
+ end
14
+ end
15
+ end