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
@@ -1,83 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
-
6
- define_resource_matchers([:create, :delete], [:file, :directory, :cookbook_file], :path)
7
-
8
- RSpec::Matchers.define :be_owned_by do |user, group|
9
- match do |file|
10
- file.nil? ? false : file.owner == user and file.group == group
11
- end
12
- end
13
-
14
- {:create_remote_file => [:create], :create_remote_file_if_missing => [:create_if_missing]}.each do |matcher, corr_action|
15
- RSpec::Matchers.define matcher do |path|
16
- match do |chef_run|
17
- if @attributes
18
- chef_run.resources.any? do |resource|
19
- expected_remote_file?(resource,path,corr_action) &&
20
- expected_attributes?(resource)
21
- end
22
- else
23
- chef_run.resources.any? do |resource|
24
- expected_remote_file?(resource,path,corr_action)
25
- end
26
- end
27
- end
28
-
29
- chain :with do |attributes|
30
- @attributes = attributes
31
- end
32
-
33
- def expected_remote_file?(resource,path,corr_action)
34
- resource_type(resource) == 'remote_file' &&
35
- resource.path == path &&
36
- !(corr_action & Array(resource.action).map(&:to_sym)).empty?
37
- end
38
-
39
- def expected_attributes?(resource)
40
- @attributes.all? do |attribute,expected|
41
- actual = resource.send(attribute)
42
- attribute.to_sym == :source ? equal_source?(actual, expected) :
43
- actual == expected
44
- end
45
- end
46
-
47
- # Compare two remote_file source attributes for equality.
48
- #
49
- # @param actual [String, Array<String>] The actual source.
50
- # @param expected [String, Array<String>] The expected source.
51
- # @return [Boolean] true if they are equal or false if not.
52
- def equal_source?(actual, expected)
53
- # NOTE: Chef stores the source attribute internally as an array since
54
- # version 11 in order to support mirrors.
55
- # (see http://docs.opscode.com/breaking_changes_chef_11.html#remote-file-mirror-support-may-break-subclasses)
56
-
57
- # Handle wrong formated expectation for Chef versions >= 11.
58
- if actual.is_a?(Array) && expected.is_a?(String)
59
- actual == [expected]
60
-
61
- # Handle wrong formated expectation for Chef versions < 11.
62
- elsif actual.is_a?(String) && expected.is_a?(Array)
63
- [actual] == expected
64
-
65
- # Else assume the actual matches the expected type (String or Array).
66
- else
67
- actual == expected
68
- end
69
- end
70
-
71
- failure_message_for_should do |actual|
72
- message = "No remote_file named '#{path}' for action #{corr_action} found"
73
- message << " with:\n#{@attributes}" unless @attributes.nil?
74
- message
75
- end
76
-
77
- failure_message_for_should_not do |actual|
78
- "Found remote_file named '#{path}' that should not exist."
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,32 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
- RSpec::Matchers.define :create_file_with_content do |path, expected|
6
- match do |chef_run|
7
- chef_run.resources.select { |resource| resource.name == path }.any? do |resource|
8
- unless ([:create, :create_if_missing] & Array(resource.action).map(&:to_sym)).empty?
9
- @actual_content = case resource_type(resource)
10
- when 'template'
11
- content_from_template(chef_run, resource)
12
- when 'file'
13
- content_from_file(chef_run, resource)
14
- when 'cookbook_file'
15
- content_from_cookbook_file(chef_run, resource)
16
- end
17
-
18
- if expected.is_a?(Regexp)
19
- @actual_content.to_s =~ expected
20
- else
21
- @actual_content.to_s.include?(expected)
22
- end
23
- end
24
- end
25
- end
26
-
27
- failure_message_for_should do |actual|
28
- "File content:\n#{@actual_content} does not match expected:\n#{expected}"
29
- end
30
- end
31
- end
32
- end
@@ -1,8 +0,0 @@
1
-
2
- require 'chefspec/matchers/shared'
3
-
4
- module ChefSpec
5
- module Matchers
6
- define_resource_matchers([:create, :remove], [:group], :group_name)
7
- end
8
- end
@@ -1,20 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
- RSpec::Matchers.define :include_recipe do |expected_recipe|
6
- match do |chef_run|
7
- if chef_run.run_context.respond_to?(:loaded_recipe?)
8
- chef_run.run_context.loaded_recipe?(expected_recipe) # Chef 11+
9
- else
10
- chef_run.node.run_state[:seen_recipes].include?(expected_recipe) # Chef 10 and lower
11
- end
12
- end
13
-
14
- failure_message_for_should do |chef_run|
15
- "expected: ['#{expected_recipe}']\n" +
16
- " got: #{chef_run.run_context.respond_to?(:loaded_recipes) ? chef_run.run_context.loaded_recipes : chef_run.node.run_state[:seen_recipes]}"
17
- end
18
- end
19
- end
20
- end
@@ -1,14 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
-
6
- define_resource_matchers([:create, :delete], [:link], :target_file)
7
-
8
- RSpec::Matchers.define :link_to do |path|
9
- match do |link|
10
- link.nil? ? false : link.to == path
11
- end
12
- end
13
- end
14
- end
@@ -1,21 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- # RSpec Matchers
5
- module Matchers
6
- RSpec::Matchers.define :log do |message|
7
- match do |chef_run|
8
- chef_run.resources.any? do |resource|
9
- if resource_type(resource) != 'log'
10
- false
11
- elsif resource.respond_to?(:message)
12
- # Chef 10.18 added message attribute to the log resource
13
- message === resource.message
14
- else
15
- message === resource.name
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,43 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
-
6
-
7
- RSpec::Matchers.define :notify do |expected_resource,expected_resource_action|
8
-
9
- expected_resource.match(/^([^\[]*)\[(.*)\]$/)
10
- expected_resource_name = $2
11
- expected_resource_type = $1
12
- match do |actual_resource|
13
- notifications = actual_resource.delayed_notifications
14
- notifications+= actual_resource.immediate_notifications
15
- notifications.any? do |rs|
16
-
17
- actual_resource_name = rs.resource.name.to_s
18
- actual_resource_type = rs.resource.resource_name.to_s
19
- actual_resource_action = rs.action
20
-
21
- (actual_resource_name == expected_resource_name) and
22
- (actual_resource_type == expected_resource_type) and
23
- (actual_resource_action.to_s == expected_resource_action.to_s)
24
- end
25
- end
26
-
27
- failure_message_for_should do |actual_resource|
28
- "expected: ['#{expected_resource_action}, #{expected_resource}']\n" +
29
- " got: #{format_notifications(actual_resource)} "
30
- end
31
-
32
- def format_notifications(resource)
33
- notifications = resource.delayed_notifications
34
- notifications += resource.immediate_notifications
35
- msg="["
36
- notifications.each do |res|
37
- msg+= "'#{res.action}, #{res.resource.resource_name}[#{res.resource.name}]'"
38
- end
39
- msg+="]"
40
- end
41
- end
42
- end
43
- end
@@ -1,39 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
- define_resource_matchers([:install, :remove, :upgrade, :purge], [:package, :gem_package, :chef_gem, :yum_package], :package_name)
6
-
7
- RSpec::Matchers.define :install_package_at_version do |package_name, version|
8
- match do |chef_run|
9
- chef_run.resources.any? do |resource|
10
- resource_type(resource) == 'package' and resource.package_name == package_name and resource.action.to_s.include? 'install' and resource.version == version
11
- end
12
- end
13
- end
14
-
15
- RSpec::Matchers.define :install_yum_package_at_version do |package_name, version|
16
- match do |chef_run|
17
- chef_run.resources.any? do |resource|
18
- resource_type(resource) == 'yum_package' and resource.package_name == package_name and resource.action.to_s.include? 'install' and resource.version == version
19
- end
20
- end
21
- end
22
-
23
- RSpec::Matchers.define :install_gem_package_at_version do |package_name, version|
24
- match do |chef_run|
25
- chef_run.resources.any? do |resource|
26
- resource_type(resource) == 'gem_package' and resource.package_name == package_name and resource.action.to_s.include? 'install' and resource.version == version
27
- end
28
- end
29
- end
30
-
31
- RSpec::Matchers.define :install_chef_gem_at_version do |package_name, version|
32
- match do |chef_run|
33
- chef_run.resources.any? do |resource|
34
- resource_type(resource) == 'chef_gem' and resource.package_name == package_name and resource.action.to_s.include? 'install' and resource.version == version
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,7 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
- define_resource_matchers([:install, :upgrade, :remove, :purge], [:python_pip], :name)
6
- end
7
- end
@@ -1,13 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
- RSpec::Matchers.define :execute_ruby_block do |block_name|
6
- match do |chef_run|
7
- chef_run.resources.any? do |resource|
8
- resource_type(resource) == 'ruby_block' and block_name === resource.name
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,34 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
- %w(bash csh perl python ruby).each do |interpreter|
6
- RSpec::Matchers.define "execute_#{interpreter}_script".to_sym do |name|
7
- match do |chef_run|
8
- if @attributes
9
- chef_run.resources.any? do |resource|
10
- (resource_type(resource) == interpreter ||
11
- (resource_type(resource) == 'script' && resource.interpreter == interpreter)) &&
12
- resource.name == name &&
13
- expected_attributes?(resource)
14
- end
15
- else
16
- chef_run.resources.any? do |resource|
17
- (resource_type(resource) == interpreter ||
18
- (resource_type(resource) == 'script' && resource.interpreter == interpreter)) &&
19
- resource.name == name
20
- end
21
- end
22
- end
23
-
24
- chain :with do |attributes|
25
- @attributes = attributes
26
- end
27
-
28
- def expected_attributes?(resource)
29
- @attributes.all? { |k,v| v === resource.send(k) }
30
- end
31
- end
32
- end
33
- end
34
- end
@@ -1,25 +0,0 @@
1
- require 'chefspec/matchers/shared'
2
-
3
- module ChefSpec
4
- module Matchers
5
-
6
- define_resource_matchers([:start, :stop, :restart, :reload, :nothing, :enable, :disable], [:service], :service_name)
7
-
8
- RSpec::Matchers.define :set_service_to_start_on_boot do |service|
9
- match do |chef_run|
10
- chef_run.resources.any? do |resource|
11
- resource_type(resource) == 'service' and resource.service_name == service and resource.action.include? :enable
12
- end
13
- end
14
- end
15
-
16
- RSpec::Matchers.define :set_service_to_not_start_on_boot do |service|
17
- match do |chef_run|
18
- chef_run.resources.any? do |resource|
19
- resource_type(resource) == 'service' and resource.service_name == service and resource.action.include? :disable
20
- end
21
- end
22
- end
23
-
24
- end
25
- end
@@ -1,132 +0,0 @@
1
- begin
2
- require 'chef/mixin/template'
3
- require 'chef/provider/template_finder'
4
- rescue LoadError
5
- end
6
-
7
- # Given a resource return the unqualified type it is
8
- #
9
- # @param [String] resource A Chef Resource
10
- # @return [String] The resource type
11
- def resource_type(resource)
12
- resource.resource_name.to_s
13
- end
14
-
15
- # Given a resource return an array of action strings
16
- #
17
- # @param [String] resource A Chef Resource
18
- # @return [Array] An array of actions as Strings
19
- def resource_actions(resource)
20
- resource.action.kind_of?(Array) ? resource.action.map{ |action| action.to_s } : [ resource.action.to_s ]
21
- end
22
-
23
- # Define simple RSpec matchers for the product of resource types and actions
24
- #
25
- # @param [Array] actions The valid actions - for example [:create, :delete]
26
- # @param [Array] resource_types The resource types
27
- # @param [Symbol] name_attribute The name attribute of the resource types
28
- def define_resource_matchers(actions, resource_types, name_attribute)
29
- actions.product(resource_types).flatten.each_slice(2) do |action, resource_type|
30
- RSpec::Matchers.define "#{action}_#{resource_type}".to_sym do |name|
31
- match do |chef_run|
32
- accepted_types = [resource_type.to_s]
33
- accepted_types += ['template', 'cookbook_file'] if action.to_s == 'create' and resource_type.to_s == 'file'
34
- chef_run.resources.any? do |resource|
35
- if (accepted_types.include? resource_type(resource) and
36
- name === resource.send(name_attribute) and
37
- resource_actions(resource).include? action.to_s)
38
- @resource_name = resource.send(name_attribute)
39
- true
40
- end
41
- end
42
- end
43
- failure_message_for_should do |actual|
44
- "No #{resource_type} resource matching name '#{name}' with action :#{action} found."
45
- end
46
- failure_message_for_should_not do |actual|
47
- "Found #{resource_type} resource named '#{@resource_name}' matching name: '#{name}' with action :#{action} that should not exist."
48
- end
49
- end
50
- end
51
- end
52
-
53
- # Compute the contents of a template using Chef's templating logic.
54
- #
55
- # @param [Chef::RunContext] chef_run
56
- # the run context for the node
57
- # @param [Chef::Provider::Template] template
58
- # the template resource
59
- #
60
- # @return [String]
61
- def content_from_template(chef_run, template)
62
- cookbook_name = template.cookbook || template.cookbook_name
63
- template_location = cookbook_collection(chef_run.node)[cookbook_name].preferred_filename_on_disk_location(chef_run.node, :templates, template.source)
64
-
65
- if Chef::Mixin::Template.const_defined?(:TemplateContext) # Chef 11+
66
- template_context = Chef::Mixin::Template::TemplateContext.new([])
67
- template_context.update({
68
- :node => chef_run.node,
69
- :template_finder => template_finder(chef_run, cookbook_name),
70
- }.merge(template.variables))
71
- template_context.render_template(template_location)
72
- else
73
- template.provider.new(template, chef_run.run_context).send(:render_with_context, template_location) do |file|
74
- File.read(file.path)
75
- end
76
- end
77
- end
78
-
79
- # Get the contents of a file resource.
80
- #
81
- # @param [Chef::RunContext] chef_run
82
- # the run context for the node
83
- # @param [Chef::Provider::File] file
84
- # the file resource
85
- #
86
- # @return [String]
87
- def content_from_file(chef_run, file)
88
- file.content
89
- end
90
-
91
- # Get the contents of a cookbook file using Chef.
92
- #
93
- # @param [Chef::RunContext] chef_run
94
- # the run context for the node
95
- # @param [Chef::Provider::CookbookFile] cookbook_file
96
- # the file resource
97
- def content_from_cookbook_file(chef_run, cookbook_file)
98
- cookbook_name = cookbook_file.cookbook || cookbook_file.cookbook_name
99
- cookbook = chef_run.run_context.cookbook_collection[cookbook_name]
100
- File.read(cookbook.preferred_filename_on_disk_location(chef_run.node, :files, cookbook_file.source, cookbook_file.path))
101
- end
102
-
103
- # The cookbook collection for the current Chef run context. Handles
104
- # the differing cases between Chef 10 and Chef 11.
105
- #
106
- # @param [Chef::Node] node
107
- # the Chef node to get the cookbook collection from
108
- #
109
- # @return [Array<Chef::Cookbook>]
110
- def cookbook_collection(node)
111
- if node.respond_to?(:run_context)
112
- node.run_context.cookbook_collection # Chef 11+
113
- else
114
- node.cookbook_collection # Chef 10
115
- end
116
- end
117
-
118
- # Return a new instance of the TemplateFinder if we are running on Chef 11.
119
- #
120
- # @param [Chef::RunContext] chef_run
121
- # the run context for the noe
122
- # @param [String] cookbook_name
123
- # the name of the cookbook
124
- #
125
- # @return [Chef::Provider::TemplateFinder, nil]
126
- def template_finder(chef_run, cookbook_name)
127
- if Chef::Provider.const_defined?(:TemplateFinder) # Chef 11+
128
- Chef::Provider::TemplateFinder.new(chef_run.run_context, cookbook_name, chef_run.node)
129
- else
130
- nil
131
- end
132
- end