chefspec 2.0.1 → 3.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chefspec.rb +30 -44
  3. data/lib/chefspec/api.rb +74 -0
  4. data/lib/chefspec/api/apt_package.rb +192 -0
  5. data/lib/chefspec/api/batch.rb +43 -0
  6. data/lib/chefspec/api/chef_gem.rb +191 -0
  7. data/lib/chefspec/api/cookbook_file.rb +166 -0
  8. data/lib/chefspec/api/cron.rb +80 -0
  9. data/lib/chefspec/api/deploy.rb +117 -0
  10. data/lib/chefspec/api/directory.rb +80 -0
  11. data/lib/chefspec/api/dpkg_package.rb +117 -0
  12. data/lib/chefspec/api/easy_install_package.rb +154 -0
  13. data/lib/chefspec/api/env.rb +117 -0
  14. data/lib/chefspec/api/erl_call.rb +43 -0
  15. data/lib/chefspec/api/execute.rb +43 -0
  16. data/lib/chefspec/api/file.rb +166 -0
  17. data/lib/chefspec/api/freebsd_package.rb +80 -0
  18. data/lib/chefspec/api/gem_package.rb +191 -0
  19. data/lib/chefspec/api/git.rb +117 -0
  20. data/lib/chefspec/api/group.rb +154 -0
  21. data/lib/chefspec/api/http_request.rb +228 -0
  22. data/lib/chefspec/api/ifconfig.rb +154 -0
  23. data/lib/chefspec/api/include_recipe.rb +26 -0
  24. data/lib/chefspec/api/ips_package.rb +117 -0
  25. data/lib/chefspec/api/link.rb +102 -0
  26. data/lib/chefspec/api/log.rb +43 -0
  27. data/lib/chefspec/api/macports_package.rb +154 -0
  28. data/lib/chefspec/api/mdadm.rb +117 -0
  29. data/lib/chefspec/api/mount.rb +192 -0
  30. data/lib/chefspec/api/notifications.rb +38 -0
  31. data/lib/chefspec/api/ohai.rb +43 -0
  32. data/lib/chefspec/api/package.rb +192 -0
  33. data/lib/chefspec/api/pacman_package.rb +155 -0
  34. data/lib/chefspec/api/portage_package.rb +155 -0
  35. data/lib/chefspec/api/powershell_script.rb +43 -0
  36. data/lib/chefspec/api/registry_key.rb +166 -0
  37. data/lib/chefspec/api/remote_directory.rb +120 -0
  38. data/lib/chefspec/api/remote_file.rb +166 -0
  39. data/lib/chefspec/api/render_file.rb +32 -0
  40. data/lib/chefspec/api/route.rb +80 -0
  41. data/lib/chefspec/api/rpm_package.rb +117 -0
  42. data/lib/chefspec/api/ruby_block.rb +37 -0
  43. data/lib/chefspec/api/script.rb +228 -0
  44. data/lib/chefspec/api/service.rb +246 -0
  45. data/lib/chefspec/api/smartos_package.rb +117 -0
  46. data/lib/chefspec/api/solaris_package.rb +80 -0
  47. data/lib/chefspec/api/subversion.rb +154 -0
  48. data/lib/chefspec/api/template.rb +166 -0
  49. data/lib/chefspec/api/user.rb +228 -0
  50. data/lib/chefspec/api/yum_package.rb +154 -0
  51. data/lib/chefspec/berkshelf.rb +37 -0
  52. data/lib/chefspec/deprecations.rb +151 -0
  53. data/lib/chefspec/errors.rb +99 -0
  54. data/lib/chefspec/expect_exception.rb +45 -0
  55. data/lib/chefspec/extensions/chef/client.rb +15 -0
  56. data/lib/chefspec/extensions/chef/conditional.rb +11 -0
  57. data/lib/chefspec/extensions/chef/data_query.rb +29 -0
  58. data/lib/chefspec/extensions/chef/lwrp_base.rb +44 -0
  59. data/lib/chefspec/extensions/chef/resource.rb +27 -0
  60. data/lib/chefspec/extensions/chef/securable.rb +19 -0
  61. data/lib/chefspec/formatter.rb +270 -0
  62. data/lib/chefspec/macros.rb +217 -0
  63. data/lib/chefspec/matchers.rb +9 -0
  64. data/lib/chefspec/matchers/include_recipe_matcher.rb +45 -0
  65. data/lib/chefspec/matchers/link_to_matcher.rb +28 -0
  66. data/lib/chefspec/matchers/notifications_matcher.rb +92 -0
  67. data/lib/chefspec/matchers/render_file_matcher.rb +72 -0
  68. data/lib/chefspec/matchers/resource_matcher.rb +143 -0
  69. data/lib/chefspec/renderer.rb +137 -0
  70. data/lib/chefspec/rspec.rb +17 -0
  71. data/lib/chefspec/runner.rb +274 -0
  72. data/lib/chefspec/stubs/command_registry.rb +11 -0
  73. data/lib/chefspec/stubs/command_stub.rb +37 -0
  74. data/lib/chefspec/stubs/data_bag_item_registry.rb +13 -0
  75. data/lib/chefspec/stubs/data_bag_item_stub.rb +25 -0
  76. data/lib/chefspec/stubs/data_bag_registry.rb +13 -0
  77. data/lib/chefspec/stubs/data_bag_stub.rb +23 -0
  78. data/lib/chefspec/stubs/registry.rb +32 -0
  79. data/lib/chefspec/stubs/search_registry.rb +13 -0
  80. data/lib/chefspec/stubs/search_stub.rb +25 -0
  81. data/lib/chefspec/stubs/stub.rb +37 -0
  82. data/lib/chefspec/version.rb +1 -2
  83. metadata +100 -103
  84. data/lib/chef/expect_exception.rb +0 -34
  85. data/lib/chef/formatters/chefspec.rb +0 -233
  86. data/lib/chef/knife/cookbook_create_specs.rb +0 -107
  87. data/lib/chefspec/chef_runner.rb +0 -275
  88. data/lib/chefspec/helpers/describe.rb +0 -17
  89. data/lib/chefspec/matchers/cron.rb +0 -7
  90. data/lib/chefspec/matchers/env.rb +0 -8
  91. data/lib/chefspec/matchers/execute.rb +0 -33
  92. data/lib/chefspec/matchers/file.rb +0 -83
  93. data/lib/chefspec/matchers/file_content.rb +0 -32
  94. data/lib/chefspec/matchers/group.rb +0 -8
  95. data/lib/chefspec/matchers/include_recipe.rb +0 -20
  96. data/lib/chefspec/matchers/link.rb +0 -14
  97. data/lib/chefspec/matchers/log.rb +0 -21
  98. data/lib/chefspec/matchers/notifications.rb +0 -43
  99. data/lib/chefspec/matchers/package.rb +0 -39
  100. data/lib/chefspec/matchers/python.rb +0 -7
  101. data/lib/chefspec/matchers/ruby_block.rb +0 -13
  102. data/lib/chefspec/matchers/script.rb +0 -34
  103. data/lib/chefspec/matchers/service.rb +0 -25
  104. data/lib/chefspec/matchers/shared.rb +0 -132
  105. data/lib/chefspec/matchers/user.rb +0 -8
  106. data/lib/chefspec/minitest.rb +0 -195
  107. data/lib/chefspec/monkey_patches/conditional.rb +0 -19
  108. data/lib/chefspec/monkey_patches/hash.rb +0 -23
  109. data/lib/chefspec/monkey_patches/lwrp_base.rb +0 -45
  110. data/lib/chefspec/monkey_patches/provider.rb +0 -43
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'berkshelf'
3
+ rescue LoadError
4
+ raise RuntimeError, "Berkshelf not found! You must have the berkshelf" \
5
+ " installed on your system before requiring chefspec/berkshelf. Install" \
6
+ " berkshelf by running:\n\n gem install berkshelf\n\nor add Berkshelf" \
7
+ " to your Gemfile:\n\n gem 'berkshelf'\n\n"
8
+ end
9
+
10
+ module ChefSpec
11
+ class Berkshelf
12
+ class << self
13
+ extend Forwardable
14
+ def_delegators :instance, :setup!
15
+ end
16
+
17
+ include Singleton
18
+
19
+ def initialize
20
+ setup!
21
+ end
22
+
23
+ def setup!
24
+ tmpdir = Dir.mktmpdir
25
+
26
+ ::Berkshelf.ui.mute do
27
+ ::Berkshelf::Berksfile.from_file('Berksfile').install(path: tmpdir)
28
+ end
29
+
30
+ ::RSpec.configure do |config|
31
+ config.cookbook_path = tmpdir
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ ChefSpec::Berkshelf.setup!
@@ -0,0 +1,151 @@
1
+ module Kernel
2
+ # Kernel extension to print deprecation notices.
3
+ #
4
+ # @example printing a deprecation warning
5
+ # deprecated 'no longer in use' #=> "[DEPRECATION] no longer in use"
6
+ #
7
+ # @param [Array<String>] messages
8
+ def deprecated(*messages)
9
+ messages.each do |message|
10
+ calling_spec = caller.find { |line| line =~ /(\/spec)|(_spec\.rb)/ }
11
+ calling_spec = 'spec/' + calling_spec.split('/spec/').last
12
+ warn "[DEPRECATION] #{message} (called from #{calling_spec})"
13
+ end
14
+ end
15
+ end
16
+
17
+ module ChefSpec
18
+ # @deprecated {ChefSpec::ChefRunner} is deprecated. Please use
19
+ # {ChefSpec::Runner} instead.
20
+ class ChefRunner
21
+ def self.new(*args, &block)
22
+ deprecated '`ChefSpec::ChefRunner` is deprecated. Please use' \
23
+ ' `ChefSpec::Runner` instead.'
24
+
25
+ ChefSpec::Runner.new(*args, &block)
26
+ end
27
+ end
28
+ end
29
+
30
+ module ChefSpec
31
+ class Runner
32
+ alias_method :existing_initialize, :initialize
33
+ def initialize(*args, &block)
34
+ if args.first.is_a?(Hash)
35
+ if args.first.has_key?(:evaluate_guards)
36
+ deprecated 'The `:evaluate_guards` option is deprecated. Guards are' \
37
+ ' automatically evaluated by default. Please use `stub_command` to' \
38
+ ' stub shell guards.'
39
+ end
40
+
41
+ if args.first.has_key?(:actually_run_shell_guards)
42
+ deprecated 'The `:actually_run_shell_guards` option is deprecated.' \
43
+ ' Shell commands must be stubbed using `stub_command`.'
44
+ end
45
+ end
46
+
47
+ existing_initialize(*args, &block)
48
+ end
49
+ end
50
+ end
51
+
52
+ module ChefSpec::API
53
+ module DeprecatedMatchers
54
+ def be_owned_by(user, group)
55
+ deprecated "The `be_owned_by` matcher is deprecated. Please use:" \
56
+ "\n\n" \
57
+ " expect(resource.owner).to eq('#{user}')\n" \
58
+ " expect(resource.group).to eq('#{group}')" \
59
+ "\n\n" \
60
+ "instead"
61
+ raise ChefSpec::NoConversionError.new('be_owned_by')
62
+ end
63
+
64
+ def create_file_with_content(path, content)
65
+ deprecated "The `create_file_with_content` matcher is deprecated." \
66
+ " Please use `render_file(#{path.inspect})" \
67
+ ".with_content(#{content.inspect})` instead."
68
+ ChefSpec::Matchers::RenderFileMatcher.new(path).with_content(content)
69
+ end
70
+
71
+ [:package, :yum_package, :gem_package, :chef_gem].each do |type|
72
+ matcher_name = "install_#{type}_at_version".to_sym
73
+ define_method(matcher_name) do |name, version|
74
+ deprecated "The `#{matcher_name}` matcher is deprecated." \
75
+ " Please use `install_package(#{name.inspect})" \
76
+ ".with(version: #{version.inspect})` instead."
77
+ ChefSpec::Matchers::ResourceMatcher.new(type, :install, package)
78
+ .with(version: version)
79
+ end
80
+ end
81
+
82
+ [:bash, :csh, :perl, :python, :ruby, :script].each do |type|
83
+ matcher_name = "execute_#{type}_script".to_sym
84
+ define_method(matcher_name) do |name|
85
+ deprecated "The `#{matcher_name}` matcher is deprecated." \
86
+ " Please use `run_#{type}(#{name.inspect})` instead."
87
+ ChefSpec::Matchers::ResourceMatcher.new(type, :run, name)
88
+ end
89
+ end
90
+
91
+ def log(message)
92
+ deprecated "The `log` matcher is deprcated. Please use" \
93
+ " `write_log(#{message.inspect}) instead."
94
+ ChefSpec::Matchers::ResourceMatcher.new(:log, :write, message)
95
+ end
96
+
97
+ def set_service_to_start_on_boot(service)
98
+ deprecated "The `set_service_to_start_on_boot` matcher is" \
99
+ " deprecated. Please use `enable_service(#{service.inspect})`" \
100
+ " instead."
101
+ ChefSpec::Matchers::ResourceMatcher.new(:service, :enable, service)
102
+ end
103
+
104
+ def set_service_to_not_start_on_boot(service)
105
+ deprecated "The `set_service_to_not_start_on_boot` matcher is" \
106
+ " deprecated. Please use `enable_service(#{service.inspect})`" \
107
+ " with a negating argument instead."
108
+ raise ChefSpec::NoConversionError.new('set_service_to_start_on_boot')
109
+ end
110
+
111
+ def execute_ruby_block(name)
112
+ deprecated "The `execute_ruby_block` matcher is deprecated. Please" \
113
+ " use `run_ruby_block(#{name.inspect})` instead."
114
+ ChefSpec::Matchers::ResourceMatcher.new(:ruby_block, :run, name)
115
+ end
116
+
117
+ def execute_command(command)
118
+ deprecated "The `execute_command` matcher is deprecated. Please" \
119
+ " use `run_execute(#{command.inspect})` instead."
120
+ ChefSpec::Matchers::ResourceMatcher.new(:execute, :run, command)
121
+ end
122
+ end
123
+ end
124
+
125
+ module ChefSpec::API
126
+ module NotificationsMatchers
127
+ alias_method :new_notify, :notify
128
+ def notify(resource, action = nil)
129
+ if action
130
+ deprecated "The `notify` matcher arity has changed. Please use" \
131
+ " `notify(#{resource.inspect}).to(#{action.to_sym.inspect})`" \
132
+ " instead."
133
+ new_notify(resource).to(action.to_sym)
134
+ else
135
+ new_notify(resource)
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ module ChefSpec
142
+ class NoConversionError < Error
143
+ def initialize(matcher)
144
+ message = "I cannot convert `#{matcher}` to use a new matcher format!" \
145
+ " Please see the ChefSpec documentation and CHANGELOG for details" \
146
+ " on converting this matcher. Sorry :("
147
+
148
+ super(message)
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,99 @@
1
+ module ChefSpec
2
+ class Error < StandardError; end
3
+
4
+ class CommandNotStubbedError < Error
5
+ def initialize(command)
6
+ message = "Real commands are disabled. Unregistered command: `#{command}`"
7
+ message << "\n\n"
8
+ message << "You can stub this command with:"
9
+ message << "\n\n"
10
+ message << " #{Stubs::CommandStub.new(command).and_return(true).signature}"
11
+
12
+ unless Stubs::CommandRegistry.stubs.empty?
13
+ message << "\n\n"
14
+ message << "registered command stubs:"
15
+ message << "\n"
16
+
17
+ Stubs::CommandRegistry.stubs.each do |command|
18
+ message << "\n #{command.signature}"
19
+ end
20
+ end
21
+
22
+ message << "\n\n"
23
+ message << "="*60
24
+ super(message)
25
+ end
26
+ end
27
+
28
+ class SearchNotStubbedError < Error
29
+ def initialize(type, query)
30
+ message = "Real searches are disabled. Unregistered search: search(#{type.inspect}, #{query.inspect})"
31
+ message << "\n\n"
32
+ message << "You can stub this search with:"
33
+ message << "\n\n"
34
+ message << " #{Stubs::SearchStub.new(type, query).and_return({}).signature}"
35
+
36
+ unless Stubs::SearchRegistry.stubs.empty?
37
+ message << "\n\n"
38
+ message << "registered search stubs:"
39
+ message << "\n"
40
+
41
+ Stubs::SearchRegistry.stubs.each do |search|
42
+ message << "\n #{search.signature}"
43
+ end
44
+ end
45
+
46
+ message << "\n\n"
47
+ message << "="*60
48
+ super(message)
49
+ end
50
+ end
51
+
52
+ class DataBagNotStubbedError < Error
53
+ def initialize(bag)
54
+ message = "Real data_bags are disabled. Unregistered data_bag: data_bag(#{bag.inspect})"
55
+ message << "\n\n"
56
+ message << "You can stub this data_bag with:"
57
+ message << "\n\n"
58
+ message << " #{Stubs::DataBagStub.new(bag).and_return({}).signature}"
59
+
60
+ unless Stubs::DataBagRegistry.stubs.empty?
61
+ message << "\n\n"
62
+ message << "registered data_bag stubs:"
63
+ message << "\n"
64
+
65
+ Stubs::DataBagRegistry.stubs.each do |data_bag|
66
+ message << "\n #{data_bag.signature}"
67
+ end
68
+ end
69
+
70
+ message << "\n\n"
71
+ message << "="*60
72
+ super(message)
73
+ end
74
+ end
75
+
76
+ class DataBagItemNotStubbedError < Error
77
+ def initialize(bag, id)
78
+ message = "Real data_bag_items are disabled. Unregistered search: data_bag_item(#{bag.inspect}, #{id.inspect})"
79
+ message << "\n\n"
80
+ message << "You can stub this data_bag_item with:"
81
+ message << "\n\n"
82
+ message << " #{Stubs::DataBagItemStub.new(bag, id).and_return({}).signature}"
83
+
84
+ unless Stubs::DataBagItemRegistry.stubs.empty?
85
+ message << "\n\n"
86
+ message << "registered data_bag_item stubs:"
87
+ message << "\n"
88
+
89
+ Stubs::DataBagItemRegistry.stubs.each do |data_bag_item|
90
+ message << "\n #{data_bag_item.signature}"
91
+ end
92
+ end
93
+
94
+ message << "\n\n"
95
+ message << "="*60
96
+ super(message)
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,45 @@
1
+ class RSpec::Matchers::BuiltIn::RaiseError
2
+ class << self
3
+ attr_accessor :last_run
4
+ end
5
+
6
+ attr_reader :expected_error, :expected_message
7
+
8
+ alias_method :old_matches?, :matches?
9
+ def matches?(*args)
10
+ self.class.last_run = self
11
+ old_matches?(*args)
12
+ end
13
+ end
14
+
15
+ module ChefSpec
16
+ class ExpectException
17
+ def initialize(formatter_exception, formatter_message = nil)
18
+ @formatter_exception = formatter_exception
19
+ @formatter_message = formatter_message
20
+ @matcher = RSpec::Matchers::BuiltIn::RaiseError.last_run
21
+ end
22
+
23
+ def expected?
24
+ return false if @matcher.nil?
25
+ exception_matched? && message_matched?
26
+ end
27
+
28
+ private
29
+ def exception_matched?
30
+ @formatter_exception == @matcher.expected_error ||
31
+ @matcher.expected_error === @formatter_exception
32
+ end
33
+
34
+ def message_matched?
35
+ case @formatter_message
36
+ when nil
37
+ true
38
+ when Regexp
39
+ @matcher.expected_message =~ @formatter_message
40
+ else
41
+ @matcher.expected_message == @formatter_message
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,15 @@
1
+ require 'chef/client'
2
+
3
+ # @private
4
+ class Chef::Client
5
+ attr_reader :events
6
+
7
+ #
8
+ # Don't actually run ohai (we have fake data for that)
9
+ #
10
+ # @see Chef::Client#run_ohai
11
+ #
12
+ def run_ohai
13
+ # noop
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require 'chef/resource/conditional'
2
+
3
+ class Chef::Resource::Conditional
4
+ # @see Chef::Resource::Conditional#evaluate_command
5
+ def evaluate_command
6
+ stub = ChefSpec::Stubs::CommandRegistry.stub_for(@command)
7
+ raise ChefSpec::CommandNotStubbedError.new(@command) if stub.nil?
8
+
9
+ stub.result
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ require 'chef/dsl/data_query'
2
+
3
+ module Chef::DSL::DataQuery
4
+ # @see Chef::DSL::DataQuery#search
5
+ def search(*args, &block)
6
+ type = args[0]
7
+ query = args[1] || '*:*'
8
+ stub = ChefSpec::Stubs::SearchRegistry.stub_for(type, query)
9
+ raise ChefSpec::SearchNotStubbedError.new(type, query) if stub.nil?
10
+
11
+ stub.result
12
+ end
13
+
14
+ # @see Chef::DSL::DataQuery#data_bag
15
+ def data_bag(bag)
16
+ stub = ChefSpec::Stubs::DataBagRegistry.stub_for(bag)
17
+ raise ChefSpec::DataBagNotStubbedError.new(bag) if stub.nil?
18
+
19
+ stub.result
20
+ end
21
+
22
+ # @see Chef::DSL::DataQuery#data_bag_item
23
+ def data_bag_item(bag, id)
24
+ stub = ChefSpec::Stubs::DataBagItemRegistry.stub_for(bag, id)
25
+ raise ChefSpec::DataBagItemNotStubbedError.new(bag, id) if stub.nil?
26
+
27
+ stub.result
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ # Override Chef LWRP creation to remove existing class to avoid redefinition warnings.
2
+ class Chef
3
+ class Provider
4
+ # Chef provider for a resource
5
+ class LWRPBase < Provider
6
+ class << self
7
+ alias_method :old_build_from_file, :build_from_file
8
+
9
+ #
10
+ # Override Opscode provider to remove any existing LWRP
11
+ #
12
+ # @param [String] cookbook_name
13
+ # The name of the cookbook
14
+ # @param [String] filename
15
+ # File to load as a LWRP
16
+ # @param [Chef::RunContext] run_context
17
+ # Context of a Chef Run
18
+ #
19
+ # @return [Chef::Provider]
20
+ #
21
+ def build_from_file(*args)
22
+ cookbook_name, filename = args[0,2]
23
+ remove_existing_lwrp(convert_to_class_name(filename_to_qualified_string(cookbook_name, filename)))
24
+ old_build_from_file(*args)
25
+ end
26
+
27
+ #
28
+ # Remove any existing Chef provider or resource with the specified name.
29
+ #
30
+ # @param [String] class_name
31
+ # The class name. Must be a valid constant name.
32
+ #
33
+ def remove_existing_lwrp(class_name)
34
+ [Chef::Resource::LWRPBase, Chef::Provider::LWRPBase, Chef::Resource, Chef::Provider].each do |resource_holder|
35
+ if resource_holder.const_defined? class_name, false
36
+ resource_holder.send(:remove_const, class_name)
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ require 'chef/resource'
2
+
3
+ class Chef::Resource
4
+ alias :old_run_action :run_action unless method_defined?(:old_run_action)
5
+
6
+ #
7
+ # Pretend to run resource actions, adding them to the resource collection
8
+ # to prevent actually executing resources
9
+ #
10
+ # @see Chef::Resource#run_action
11
+ #
12
+ def run_action(action, notification_type = nil, notifying_resource = nil)
13
+ return if should_skip?(action)
14
+
15
+ if node.runner.step_into.include?(self.resource_name.to_s)
16
+ instance_eval { @not_if = []; @only_if = [] }
17
+ old_run_action(action, notification_type, notifying_resource)
18
+ end
19
+
20
+ Chef::Log.info("Processing #{self} action #{action} (#{defined_at})")
21
+
22
+ # Append the currently run action to the existing resource actions,
23
+ # making sure it's a unique array of symbols.
24
+ @action = [self.action, action].flatten.compact.map(&:to_sym).uniq
25
+ node.runner.resources[self.to_s] ||= self
26
+ end
27
+ end