chefspec-bootstrap 0.0.1 → 0.0.2
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.
- data/README.md +61 -5
- data/bin/chefspec-bootstrap +2 -3
- data/chefspec-bootstrap.gemspec +2 -3
- data/lib/chefspec-bootstrap.rb +91 -15
- data/templates/default.erb +5 -1
- metadata +3 -19
data/README.md
CHANGED
@@ -1,11 +1,67 @@
|
|
1
1
|
chefspec-bootstrap
|
2
2
|
==================
|
3
3
|
|
4
|
-
A tool to get started with ChefSpec.
|
4
|
+
A command line tool to get started with ChefSpec. Generates spec files for your untested recipes.
|
5
5
|
|
6
|
-
|
6
|
+
Given a cookbook called `cookbook` with a recipe called `recipe.rb`:
|
7
|
+
```ruby
|
8
|
+
package "apache2"
|
9
|
+
|
10
|
+
file "/etc/apache2/sites-available/default" do
|
11
|
+
action :delete
|
12
|
+
end
|
13
|
+
|
14
|
+
template "/etc/apache2/sites-available/mysite" do
|
15
|
+
source "mysite.conf.erb"
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
The command line tool will generate the following spec file at `spec/cookbook/recipe_spec.rb`:
|
20
|
+
```ruby
|
21
|
+
require 'chefspec'
|
22
|
+
|
23
|
+
describe 'cookbook::recipe' do
|
24
|
+
let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
|
25
|
+
|
26
|
+
it 'runs successfully' do
|
27
|
+
expect{chef_run}.not_to raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "installs the apache2 package" do
|
31
|
+
expect(chef_run).to install_package("apache2")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "deletes the /etc/apache2/conf.d/python.conf file" do
|
35
|
+
expect(chef_run).to delete_file("/etc/apache2/conf.d/python.conf")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "creates the /etc/apache2/sites-available/mysite template" do
|
39
|
+
expect(chef_run).to create_template("/etc/apache2/sites-available/mysite")
|
40
|
+
end
|
41
|
+
end
|
7
42
|
```
|
8
|
-
|
9
|
-
|
10
|
-
|
43
|
+
|
44
|
+
|
45
|
+
Getting Started
|
46
|
+
---
|
47
|
+
Install the gem
|
11
48
|
```
|
49
|
+
gem install chefspec-bootstrap
|
50
|
+
```
|
51
|
+
|
52
|
+
Run the command-line tool
|
53
|
+
```
|
54
|
+
chefspec-bootstrap
|
55
|
+
```
|
56
|
+
|
57
|
+
Options
|
58
|
+
---
|
59
|
+
```
|
60
|
+
--cookbooks-dir, -c <s>: Your site cookbooks directory (default: site-cookbooks)
|
61
|
+
--spec-dir, -s <s>: Your spec directory (default: spec)
|
62
|
+
--template, -t <s>: ERB template file used to generate specs
|
63
|
+
```
|
64
|
+
|
65
|
+
Creating a custom template
|
66
|
+
---
|
67
|
+
A custom erb template can be passsed using the `-t` flag. See the included default template for an example.
|
data/bin/chefspec-bootstrap
CHANGED
@@ -9,6 +9,5 @@ opts = Trollop::options do
|
|
9
9
|
opt :template, "ERB template file used to generate specs", :type => :string
|
10
10
|
end
|
11
11
|
|
12
|
-
bootstrap = ChefSpec::Bootstrap.new
|
13
|
-
|
14
|
-
bootstrap.generate(opts[:cookbooks_dir], opts[:spec_dir], opts[:template])
|
12
|
+
bootstrap = ChefSpec::Bootstrap.new(opts[:cookbooks_dir], opts[:spec_dir], opts[:template])
|
13
|
+
bootstrap.generate()
|
data/chefspec-bootstrap.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'chefspec-bootstrap'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.2'
|
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."
|
@@ -12,7 +12,6 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.executables = ["chefspec-bootstrap"]
|
13
13
|
s.required_ruby_version = '>= 1.9'
|
14
14
|
|
15
|
-
s.add_dependency '
|
16
|
-
s.add_dependency 'chefspec', '~> 3.1.0'
|
15
|
+
s.add_dependency 'chefspec', '~> 3.4.0'
|
17
16
|
s.add_dependency 'trollop', '~> 2.0.0'
|
18
17
|
end
|
data/lib/chefspec-bootstrap.rb
CHANGED
@@ -1,37 +1,69 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
1
|
require 'erb'
|
4
2
|
require 'fileutils'
|
5
3
|
require 'ostruct'
|
4
|
+
require 'chefspec'
|
6
5
|
|
7
6
|
module ChefSpec
|
8
7
|
class Bootstrap
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
|
9
|
+
def initialize(cookbooks_dir, spec_dir, template_file)
|
10
|
+
@cookbooks_dir = cookbooks_dir
|
11
|
+
@spec_dir = spec_dir
|
12
|
+
@template_file = template_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
if not Dir.exist?(@cookbooks_dir)
|
17
|
+
abort "Unable to locate your cookbooks directory (#{@cookbooks_dir})"
|
12
18
|
end
|
13
19
|
|
14
|
-
if not template_file
|
15
|
-
template_file = root.join('templates', 'default.erb')
|
20
|
+
if not @template_file
|
21
|
+
@template_file = root.join('templates', 'default.erb')
|
16
22
|
end
|
17
23
|
|
18
|
-
if not File.exist?(template_file)
|
19
|
-
abort "Unable to locate template file (#{template_file})"
|
24
|
+
if not File.exist?(@template_file)
|
25
|
+
abort "Unable to locate template file (#{@template_file})"
|
20
26
|
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate
|
30
|
+
setup()
|
31
|
+
|
32
|
+
erb = ERB.new(File.read(@template_file))
|
33
|
+
|
34
|
+
# begin
|
35
|
+
# require "#{@spec_dir}/spec_helper.rb"
|
36
|
+
# rescue LoadError
|
21
37
|
|
22
|
-
|
38
|
+
# end
|
23
39
|
|
24
|
-
|
40
|
+
::RSpec.configure { |config| config.cookbook_path = [@cookbooks_dir, 'cookbooks'] }
|
41
|
+
|
42
|
+
Dir.glob("#{@cookbooks_dir}/*/recipes/*").each do |path|
|
25
43
|
path, recipe_file = File.split(path)
|
26
44
|
recipe = recipe_file.split('.')[0]
|
27
45
|
cookbook = path.split(File::SEPARATOR)[1]
|
28
46
|
|
29
|
-
filename = "#{spec_dir}/#{cookbook}/#{recipe}_spec.rb"
|
47
|
+
filename = "#{@spec_dir}/#{cookbook}/#{recipe}_spec.rb"
|
48
|
+
|
49
|
+
puts filename
|
30
50
|
|
31
|
-
if
|
32
|
-
|
51
|
+
if File.exist?(filename)
|
52
|
+
puts " spec already exists. Skipping."
|
53
|
+
else
|
54
|
+
FileUtils.mkdir_p "#{@spec_dir}/#{cookbook}"
|
33
55
|
|
34
|
-
puts "
|
56
|
+
puts " executing recipe with ChefSpec..."
|
57
|
+
chef_run = get_chef_run(cookbook, recipe)
|
58
|
+
|
59
|
+
if chef_run
|
60
|
+
puts " execution suceeded. Creating spec file."
|
61
|
+
else
|
62
|
+
puts " execution failed. Creating empty spec file."
|
63
|
+
end
|
64
|
+
|
65
|
+
resources = get_resources(chef_run)
|
66
|
+
test_cases = generate_test_cases(resources)
|
35
67
|
|
36
68
|
File.open(filename, "w") do |spec_file|
|
37
69
|
spec_file.write(erb.result(binding))
|
@@ -43,5 +75,49 @@ module ChefSpec
|
|
43
75
|
def root
|
44
76
|
@root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
45
77
|
end
|
78
|
+
|
79
|
+
def get_chef_run(cookbook, recipe)
|
80
|
+
begin
|
81
|
+
return ChefSpec::Runner.new.converge("#{cookbook}::#{recipe}")
|
82
|
+
rescue
|
83
|
+
return nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_resource_name(resource)
|
88
|
+
return resource.name || resource.identity
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_resources(chef_run)
|
92
|
+
if chef_run
|
93
|
+
return chef_run.resource_collection.all_resources
|
94
|
+
else
|
95
|
+
return []
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def generate_test_cases(resources)
|
100
|
+
test_cases = []
|
101
|
+
resources.each do |resource|
|
102
|
+
verbs = resource.action
|
103
|
+
if not verbs.respond_to?(:each)
|
104
|
+
verbs = [verbs]
|
105
|
+
end
|
106
|
+
|
107
|
+
noun = resource.resource_name
|
108
|
+
adjective = resource.name
|
109
|
+
|
110
|
+
verbs.each do |verb|
|
111
|
+
if not verb == :nothing
|
112
|
+
test_cases.push({
|
113
|
+
:it => "#{verb}s the #{adjective} #{noun}",
|
114
|
+
:action => "#{verb}_#{noun}",
|
115
|
+
:name => adjective
|
116
|
+
})
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return test_cases
|
121
|
+
end
|
46
122
|
end
|
47
123
|
end
|
data/templates/default.erb
CHANGED
@@ -5,5 +5,9 @@ describe '<%= cookbook %>::<%= recipe %>' do
|
|
5
5
|
|
6
6
|
it 'runs successfully' do
|
7
7
|
expect{chef_run}.not_to raise_error
|
8
|
-
end
|
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 %>
|
9
13
|
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.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,22 +11,6 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2014-06-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
name: chef
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '11.0'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '11.0'
|
30
14
|
- !ruby/object:Gem::Dependency
|
31
15
|
name: chefspec
|
32
16
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +18,7 @@ dependencies:
|
|
34
18
|
requirements:
|
35
19
|
- - ~>
|
36
20
|
- !ruby/object:Gem::Version
|
37
|
-
version: 3.
|
21
|
+
version: 3.4.0
|
38
22
|
type: :runtime
|
39
23
|
prerelease: false
|
40
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +26,7 @@ dependencies:
|
|
42
26
|
requirements:
|
43
27
|
- - ~>
|
44
28
|
- !ruby/object:Gem::Version
|
45
|
-
version: 3.
|
29
|
+
version: 3.4.0
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: trollop
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|