chefspec 0.2.1 → 0.3.0

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.
@@ -0,0 +1,107 @@
1
+ require 'chefspec'
2
+
3
+ if Chef.const_defined? :Knife
4
+ module ChefSpec
5
+ module Knife
6
+
7
+ # Knife plugin to create placeholder specs.
8
+ #
9
+ # $ knife cookbook create -o . my_new_cookbook
10
+ # $ knife cookbook create_specs -o . my_new_cookbook
11
+ # $ rspec my_new_cookbook
12
+ #
13
+ # http://help.opscode.com/kb/knife/manage-cookbooks-with-knife
14
+ class CookbookCreateSpecs < Chef::Knife
15
+
16
+ # Implemented as a separate knife command rather than extending the knife built-in create_cookbook_command.
17
+ # Extension may arguably have been better from the end user perspective but would be much more brittle.
18
+
19
+ banner "knife cookbook create_specs COOKBOOK (options)"
20
+
21
+ option :cookbook_path,
22
+ :short => "-o PATH",
23
+ :long => "--cookbook-path PATH",
24
+ :description => "The directory where the cookbook specs will be created"
25
+
26
+ # Invoke this command and create the new specs
27
+ def run
28
+ self.config = Chef::Config.merge!(config)
29
+ if @name_args.empty?
30
+ show_usage
31
+ ui.fatal("You must specify a cookbook name")
32
+ exit 1
33
+ end
34
+
35
+ if default_cookbook_path_empty? && parameter_empty?(config[:cookbook_path])
36
+ raise ArgumentError, "Default cookbook_path is not specified in the knife.rb config file, and a value to -o is not provided. Nowhere to write the new cookbook to."
37
+ end
38
+
39
+ create_specs(Array(config[:cookbook_path]).first, @name_args.first)
40
+ end
41
+
42
+ private
43
+
44
+ # Has a default cookbook path been set?
45
+ #
46
+ # @return [Boolean] True if cookbook path has been set in the Chef config.
47
+ def default_cookbook_path_empty?
48
+ Chef::Config[:cookbook_path].nil? || Chef::Config[:cookbook_path].empty?
49
+ end
50
+
51
+ # Create placeholder specs for the cookbook.
52
+ #
53
+ # @param [String] dir The directory to create the specs in
54
+ # @param [String] cookbook The name of the cookbook
55
+ # @param [String] recipe The name of the recipe to create a spec for
56
+ def create_specs(dir, cookbook)
57
+ spec_dir = "#{File.join(dir, cookbook, 'spec')}"
58
+ FileUtils.mkdir_p spec_dir
59
+ msg("** Creating specs for cookbook: #{cookbook}")
60
+ existing_recipes(dir, cookbook).each do |recipe|
61
+ create_spec(spec_dir, cookbook, recipe)
62
+ end
63
+ end
64
+
65
+ # The list of recipes for a cookbook
66
+ #
67
+ # @param [String] dir The directory
68
+ # @param [String] cookbook The name of the cookbook
69
+ # @return [Array] The list of recipes for the cookbook
70
+ def existing_recipes(dir, cookbook)
71
+ Dir[File.join(dir, cookbook, 'recipes/*.rb')].map{|recipe| File.basename recipe, '.rb'}
72
+ end
73
+
74
+ # Create a placeholder spec for the cookbook.
75
+ #
76
+ # @param [String] spec_dir The directory to create the specs in
77
+ # @param [String] cookbook The name of the cookbook
78
+ # @param [String] recipe The name of the recipe to create a spec for
79
+ def create_spec(spec_dir, cookbook, recipe)
80
+ unless File.exists?(File.join(spec_dir, "#{recipe}_spec.rb"))
81
+ open(File.join(spec_dir, "#{recipe}_spec.rb"), "w") do |file|
82
+ file.puts spec_file_content(cookbook, recipe)
83
+ end
84
+ end
85
+ end
86
+
87
+ # Generate the content for the placeholder spec file.
88
+ #
89
+ # @param [String] cookbook The name of the cookbook
90
+ # @param [String] recipe The name of the recipe
91
+ def spec_file_content(cookbook, recipe)
92
+ return <<-EOH
93
+ require 'chefspec'
94
+
95
+ describe '#{cookbook}::#{recipe}' do
96
+ let (:chef_run) { ChefSpec::ChefRunner.new.converge '#{cookbook}::#{recipe}' }
97
+ it 'should do something' do
98
+ pending 'Your recipe examples go here.'
99
+ end
100
+ end
101
+ EOH
102
+ end
103
+
104
+ end
105
+ end
106
+ end
107
+ end
data/lib/chefspec.rb CHANGED
@@ -8,5 +8,6 @@ require 'chefspec/matchers/log'
8
8
  require 'chefspec/matchers/package'
9
9
  require 'chefspec/matchers/service'
10
10
  require 'chefspec/matchers/shared'
11
+ require 'chefspec/matchers/file_content'
11
12
  require 'chefspec/monkey_patches/hash'
12
13
  require 'chefspec/monkey_patches/provider'
@@ -0,0 +1,27 @@
1
+ require 'chefspec/matchers/shared'
2
+
3
+ module ChefSpec
4
+ module Matchers
5
+ RSpec::Matchers.define :create_file_with_content do |path, content|
6
+ match do |chef_run|
7
+ chef_run.resources.any? do |resource|
8
+ if resource.name == path
9
+ if resource.action.include?(:create) || resource.action.include?(:create_if_missing)
10
+ case resource_type(resource)
11
+ when 'template'
12
+ @actual_content = render(resource, chef_run.node)
13
+ content == @actual_content
14
+ when 'file'
15
+ @actual_content = resource.content
16
+ content == @actual_content
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ failure_message_for_should do |actual|
23
+ "File content:\n#{@actual_content} does not match expected:\n#{content}"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,6 +1,7 @@
1
1
  require 'chefspec/matchers/shared'
2
2
 
3
3
  module ChefSpec
4
+ # RSpec Matchers
4
5
  module Matchers
5
6
  RSpec::Matchers.define :log do |message|
6
7
  match do |chef_run|
@@ -30,4 +30,24 @@ def define_resource_matchers(actions, resource_types, name_attribute)
30
30
  end
31
31
  end
32
32
  end
33
- end
33
+ end
34
+
35
+ # Render a template.
36
+ #
37
+ # @param [Chef::Resource::Template] template The template to render
38
+ # @param [Chef::Node] node The node which may be required to render the template
39
+ # @return [String] The result result of rendering the template
40
+ def render(template, node)
41
+ # Duplicates functionality in the Chef Template provider
42
+ context = {}; context.merge!(template.variables)
43
+ context[:node] = node
44
+ Erubis::Eruby.new(IO.read(template_path(template))).evaluate(context)
45
+ end
46
+
47
+ # Given a template, return the path on disk.
48
+ #
49
+ # @param [Chef::Resource::Template] template The template
50
+ # @return [String] The path on disk
51
+ def template_path(template)
52
+ File.join("cookbooks/#{template.cookbook || template.cookbook_name}/templates/default", template.source)
53
+ end
@@ -1,9 +1,16 @@
1
1
  # Override Chef LWRP creation to remove existing class to avoid redefinition warnings.
2
2
  class Chef
3
+ # Chef provider for a resource
3
4
  class Provider
4
5
  class << self
5
- alias :old_build_from_file :build_from_file
6
+ alias_method :old_build_from_file, :build_from_file
6
7
 
8
+ # Override Opscode provider to remove any existing LWRP
9
+ #
10
+ # @param [String] cookbook_name The name of the cookbook
11
+ # @param [String] filename File to load as a LWRP
12
+ # @param [Chef::RunContext] run_context Context of a Chef Run
13
+ # @return [Chef::Provider] the created provider
7
14
  def build_from_file(cookbook_name, filename, run_context)
8
15
  remove_existing_lwrp(convert_to_class_name(filename_to_qualified_string(cookbook_name, filename)))
9
16
  old_build_from_file(cookbook_name, filename, run_context)
@@ -1,3 +1,4 @@
1
1
  module ChefSpec
2
- VERSION = '0.2.1'
3
- end
2
+ # The gem version
3
+ VERSION = '0.3.0'
4
+ end
metadata CHANGED
@@ -1,73 +1,63 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: chefspec
3
- version: !ruby/object:Gem::Version
4
- hash: 21
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 2
9
- - 1
10
- version: 0.2.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Andrew Crump
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-09-21 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- version_requirements: &id001 !ruby/object:Gem::Requirement
12
+ date: 2011-10-02 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: chef
16
+ requirement: &2151873320 !ruby/object:Gem::Requirement
22
17
  none: false
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- hash: 35
27
- segments:
28
- - 0
29
- - 9
30
- - 12
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
31
21
  version: 0.9.12
32
22
  - - ~>
33
- - !ruby/object:Gem::Version
34
- hash: 31
35
- segments:
36
- - 0
37
- - 10
38
- version: "0.10"
39
- name: chef
23
+ - !ruby/object:Gem::Version
24
+ version: '0.10'
40
25
  type: :runtime
41
26
  prerelease: false
42
- requirement: *id001
43
- - !ruby/object:Gem::Dependency
44
- version_requirements: &id002 !ruby/object:Gem::Requirement
27
+ version_requirements: *2151873320
28
+ - !ruby/object:Gem::Dependency
29
+ name: erubis
30
+ requirement: &2151885360 !ruby/object:Gem::Requirement
45
31
  none: false
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- hash: 23
50
- segments:
51
- - 2
52
- - 6
53
- - 0
54
- version: 2.6.0
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: *2151885360
39
+ - !ruby/object:Gem::Dependency
55
40
  name: rspec
41
+ requirement: &2151891840 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 2.6.0
56
47
  type: :runtime
57
48
  prerelease: false
58
- requirement: *id002
49
+ version_requirements: *2151891840
59
50
  description: Write RSpec examples for Opscode Chef recipes
60
51
  email:
61
52
  executables: []
62
-
63
53
  extensions: []
64
-
65
54
  extra_rdoc_files: []
66
-
67
- files:
55
+ files:
56
+ - lib/chef/knife/cookbook_create_specs.rb
68
57
  - lib/chefspec/chef_runner.rb
69
58
  - lib/chefspec/matchers/execute.rb
70
59
  - lib/chefspec/matchers/file.rb
60
+ - lib/chefspec/matchers/file_content.rb
71
61
  - lib/chefspec/matchers/log.rb
72
62
  - lib/chefspec/matchers/package.rb
73
63
  - lib/chefspec/matchers/service.rb
@@ -77,37 +67,34 @@ files:
77
67
  - lib/chefspec/version.rb
78
68
  - lib/chefspec.rb
79
69
  homepage: http://acrmp.github.com/chefspec
80
- licenses:
70
+ licenses:
81
71
  - MIT
82
72
  post_install_message:
83
73
  rdoc_options: []
84
-
85
- require_paths:
74
+ require_paths:
86
75
  - lib
87
- required_ruby_version: !ruby/object:Gem::Requirement
76
+ required_ruby_version: !ruby/object:Gem::Requirement
88
77
  none: false
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- hash: 3
93
- segments:
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ segments:
94
83
  - 0
95
- version: "0"
96
- required_rubygems_version: !ruby/object:Gem::Requirement
84
+ hash: 4357686734109657142
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
86
  none: false
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- hash: 3
102
- segments:
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
103
92
  - 0
104
- version: "0"
93
+ hash: 4357686734109657142
105
94
  requirements: []
106
-
107
95
  rubyforge_project:
108
96
  rubygems_version: 1.8.6
109
97
  signing_key:
110
98
  specification_version: 3
111
- summary: chefspec-0.2.1
99
+ summary: chefspec-0.3.0
112
100
  test_files: []
113
-