chefspec-bootstrap 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -23,10 +23,6 @@ require 'chefspec'
23
23
  describe 'cookbook::recipe' do
24
24
  let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
25
25
 
26
- it 'runs successfully' do
27
- expect{chef_run}.not_to raise_error
28
- end
29
-
30
26
  it "installs the apache2 package" do
31
27
  expect(chef_run).to install_package("apache2")
32
28
  end
@@ -3,11 +3,21 @@
3
3
  require 'chefspec-bootstrap'
4
4
  require 'trollop'
5
5
 
6
+ cookbook_path_help_text = "RSpec config for cookbook path. Defaults to RSpec.configure.cookbook_path from spec_helper.rb."
7
+
6
8
  opts = Trollop::options do
7
9
  opt :cookbooks_dir, "Your site cookbooks directory", :type => :string, :default => "site-cookbooks"
10
+ opt :cookbooks_path, cookbook_path_help_text, :type => :strings
11
+ opt :recursive, "Generate specs for included recipes."
8
12
  opt :spec_dir, "Your spec directory", :type => :string, :default => "spec"
9
13
  opt :template, "ERB template file used to generate specs", :type => :string
10
14
  end
11
15
 
12
- bootstrap = ChefSpec::Bootstrap.new(opts[:cookbooks_dir], opts[:spec_dir], opts[:template])
16
+ bootstrap = ChefSpec::Bootstrap.new(
17
+ opts[:cookbooks_dir],
18
+ opts[:cookbooks_path],
19
+ opts[:spec_dir],
20
+ opts[:template],
21
+ opts[:recursive]
22
+ )
13
23
  bootstrap.generate()
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'chefspec-bootstrap'
3
- s.version = '0.0.2'
3
+ s.version = '0.0.3'
4
4
  s.date = '2014-06-02'
5
5
  s.summary = "Bootstrap your ChefSpec tests."
6
6
  s.description = "Automatically generate ChefSpec tests based on your recipes."
data/lib/api_map.rb ADDED
@@ -0,0 +1,84 @@
1
+ module ChefSpec
2
+ class APIMap
3
+
4
+ IT_CREATE_IF_MISSING = "creates the %{adjective} %{noun} if it is missing"
5
+ IT_MODIFY = "modifies the %{adjective} %{noun}"
6
+ IT_TOUCH = "touches the %{adjective} %{noun}"
7
+ EXPECT_CREATE_IF_MISSING = "create_%{noun}_if_missing"
8
+
9
+ def map
10
+ {
11
+ :cookbook_file => {
12
+ :it => { :create_if_missing => IT_CREATE_IF_MISSING },
13
+ :expect => { :create_if_missing => EXPECT_CREATE_IF_MISSING }
14
+ },
15
+ :deploy => {
16
+ :it => { :force_deploy => "force deploys the %{adjective} %{noun}" }
17
+ },
18
+ :env => {
19
+ :it => { :modify => IT_MODIFY }
20
+ },
21
+ :execute => {
22
+ :it => { :run => "executes %{adjective}" }
23
+ },
24
+ :file => {
25
+ :it => {
26
+ :create_if_missing => IT_CREATE_IF_MISSING,
27
+ :touch => IT_TOUCH
28
+ },
29
+ :expect => { :create_if_missing => EXPECT_CREATE_IF_MISSING }
30
+ },
31
+ :git => {
32
+ :it => {
33
+ :default => "%{verb}s the %{adjective} git repository",
34
+ :checkout => "checks out the %{adjective} git repository"
35
+ }
36
+ },
37
+ :group => {
38
+ :it => { :modify => IT_MODIFY }
39
+ },
40
+ :http_request => {
41
+ :it => {
42
+ :default => "performs a %{verb} HTTP request to %{adjective}"
43
+ }
44
+ },
45
+ :ifconfig => {
46
+ :it => {
47
+ :default => "%{verb}s the %{adjective} network interface using %{noun}"
48
+ }
49
+ },
50
+ :registry_key => {
51
+ :it => {
52
+ :create_if_missing => IT_CREATE_IF_MISSING,
53
+ :delete => "%{verb}s the %{adjective} %{noun} value"
54
+ },
55
+ :expect => { :create_if_missing => EXPECT_CREATE_IF_MISSING }
56
+ },
57
+ :remote_directory => {
58
+ :it => { :create_if_missing => IT_CREATE_IF_MISSING },
59
+ :expect => { :create_if_missing => EXPECT_CREATE_IF_MISSING }
60
+ },
61
+ :remote_file => {
62
+ :it => {
63
+ :create_if_missing => IT_CREATE_IF_MISSING,
64
+ :touch => IT_TOUCH
65
+ },
66
+ :expect => { :create_if_missing => EXPECT_CREATE_IF_MISSING }
67
+ },
68
+ :subversion => {
69
+ :it => {
70
+ :default => "%{verb}s the %{adjective} svn repository",
71
+ :checkout => "checks out the %{adjective} svn repository"
72
+ }
73
+ },
74
+ :template => {
75
+ :it => {
76
+ :create_if_missing => IT_CREATE_IF_MISSING,
77
+ :touch => IT_TOUCH
78
+ },
79
+ :expect => { :create_if_missing => EXPECT_CREATE_IF_MISSING }
80
+ }
81
+ }
82
+ end
83
+ end
84
+ end
@@ -2,14 +2,17 @@ require 'erb'
2
2
  require 'fileutils'
3
3
  require 'ostruct'
4
4
  require 'chefspec'
5
+ require_relative 'api_map'
5
6
 
6
7
  module ChefSpec
7
8
  class Bootstrap
8
9
 
9
- def initialize(cookbooks_dir, spec_dir, template_file)
10
+ def initialize(cookbooks_dir, cookbooks_path, spec_dir, template_file, recursive)
10
11
  @cookbooks_dir = cookbooks_dir
12
+ @cookbooks_path = cookbooks_path
11
13
  @spec_dir = spec_dir
12
14
  @template_file = template_file
15
+ @recursive = recursive
13
16
  end
14
17
 
15
18
  def setup
@@ -24,6 +27,18 @@ module ChefSpec
24
27
  if not File.exist?(@template_file)
25
28
  abort "Unable to locate template file (#{@template_file})"
26
29
  end
30
+
31
+ @api_map = ChefSpec::APIMap.new.map
32
+
33
+ begin
34
+ require File.expand_path("#{@spec_dir}/spec_helper.rb")
35
+ @spec_helper = true
36
+ rescue LoadError
37
+ @spec_helper = false
38
+ ::RSpec.configure do |config|
39
+ config.cookbook_path = @cookbooks_path || [@cookbooks_dir, 'cookbooks']
40
+ end
41
+ end
27
42
  end
28
43
 
29
44
  def generate
@@ -31,14 +46,6 @@ module ChefSpec
31
46
 
32
47
  erb = ERB.new(File.read(@template_file))
33
48
 
34
- # begin
35
- # require "#{@spec_dir}/spec_helper.rb"
36
- # rescue LoadError
37
-
38
- # end
39
-
40
- ::RSpec.configure { |config| config.cookbook_path = [@cookbooks_dir, 'cookbooks'] }
41
-
42
49
  Dir.glob("#{@cookbooks_dir}/*/recipes/*").each do |path|
43
50
  path, recipe_file = File.split(path)
44
51
  recipe = recipe_file.split('.')[0]
@@ -62,7 +69,7 @@ module ChefSpec
62
69
  puts " execution failed. Creating empty spec file."
63
70
  end
64
71
 
65
- resources = get_resources(chef_run)
72
+ resources = get_resources(chef_run, cookbook, recipe)
66
73
  test_cases = generate_test_cases(resources)
67
74
 
68
75
  File.open(filename, "w") do |spec_file|
@@ -79,7 +86,7 @@ module ChefSpec
79
86
  def get_chef_run(cookbook, recipe)
80
87
  begin
81
88
  return ChefSpec::Runner.new.converge("#{cookbook}::#{recipe}")
82
- rescue
89
+ rescue Exception => e
83
90
  return nil
84
91
  end
85
92
  end
@@ -88,9 +95,20 @@ module ChefSpec
88
95
  return resource.name || resource.identity
89
96
  end
90
97
 
91
- def get_resources(chef_run)
98
+ def get_all_resources(chef_run)
99
+ return chef_run.resource_collection.all_resources
100
+ end
101
+
102
+ def get_resources(chef_run, cookbook, recipe)
92
103
  if chef_run
93
- return chef_run.resource_collection.all_resources
104
+ resources = get_all_resources(chef_run)
105
+ if @recursive
106
+ return resources
107
+ else
108
+ return resources.select do |resource|
109
+ resource.cookbook_name == cookbook.to_sym and resource.recipe_name == recipe
110
+ end
111
+ end
94
112
  else
95
113
  return []
96
114
  end
@@ -110,8 +128,8 @@ module ChefSpec
110
128
  verbs.each do |verb|
111
129
  if not verb == :nothing
112
130
  test_cases.push({
113
- :it => "#{verb}s the #{adjective} #{noun}",
114
- :action => "#{verb}_#{noun}",
131
+ :it => get_it_block(noun, verb, adjective),
132
+ :expect => get_expect_block(noun, verb),
115
133
  :name => adjective
116
134
  })
117
135
  end
@@ -119,5 +137,42 @@ module ChefSpec
119
137
  end
120
138
  return test_cases
121
139
  end
140
+
141
+ def get_it_block(noun, verb, adjective)
142
+ it = "%{verb}s the %{adjective} %{noun}"
143
+ noun_readable = noun.to_s.gsub("_", " ")
144
+ verb_readable = verb.to_s.gsub("_", " ")
145
+ string_variables = {:noun => noun_readable, :verb => verb_readable, :adjective => adjective}
146
+
147
+ if @api_map[noun] and @api_map[noun][:it]
148
+ if @api_map[noun][:it][verb]
149
+ it = @api_map[noun][:it][verb]
150
+ elsif @api_map[noun][:it][:default]
151
+ it = @api_map[noun][:it][:default]
152
+ end
153
+ end
154
+
155
+ return escape_string(it % string_variables)
156
+ end
157
+
158
+ def get_expect_block(noun, verb)
159
+ expect = "%{verb}_%{noun}"
160
+ string_variables = {:noun => noun, :verb => verb}
161
+
162
+ if @api_map[noun] and @api_map[noun][:expect]
163
+ if @api_map[noun][:expect][verb]
164
+ expect = @api_map[noun][:expect][verb]
165
+ elsif @api_map[noun][:expect][:default]
166
+ expect = @api_map[noun][:expect][:default]
167
+ end
168
+ end
169
+
170
+ return escape_string(expect % string_variables)
171
+ end
172
+
173
+ def escape_string(string)
174
+ return string.gsub("\\","\\\\").gsub("\"", "\\\"")
175
+ end
176
+
122
177
  end
123
178
  end
@@ -1,13 +1,12 @@
1
1
  require 'chefspec'
2
2
 
3
3
  describe '<%= cookbook %>::<%= recipe %>' do
4
- let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
4
+ let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }<% if not test_cases.empty? %><% test_cases.each do |test_case| %>
5
5
 
6
+ it "<%= test_case[:it] %>" do
7
+ expect(chef_run).to <%= test_case[:expect] %>("<%= test_case[:name] %>")
8
+ end<% end %><% else %>
6
9
  it 'runs successfully' do
7
10
  expect{chef_run}.not_to raise_error
8
- end<% if test_cases %><% test_cases.each do |test_case| %>
9
-
10
- it "<%= test_case[:it] %>" do
11
- expect(chef_run).to <%= test_case[:action] %>("<%= test_case[:name] %>")
12
- end<% end %><% end %>
11
+ end<% end %>
13
12
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chefspec-bootstrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -55,6 +55,7 @@ files:
55
55
  - README.md
56
56
  - bin/chefspec-bootstrap
57
57
  - chefspec-bootstrap.gemspec
58
+ - lib/api_map.rb
58
59
  - lib/chefspec-bootstrap.rb
59
60
  - templates/default.erb
60
61
  homepage: http://rubygems.org/gems/chefspec-bootstrap