chefspec-bootstrap 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,11 +1,67 @@
1
1
  chefspec-bootstrap
2
2
  ==================
3
3
 
4
- A tool to get started with ChefSpec. The script will look up all your recipes and create a spec file for each one.
4
+ A command line tool to get started with ChefSpec. Generates spec files for your untested recipes.
5
5
 
6
- From within your chef project directory:
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
- wget https://raw.githubusercontent.com/AMeng/chefspec-bootstrap/master/bootstrap.rb
9
- chmod +x bootstrap.rb
10
- ./bootstrap.rb
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.
@@ -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()
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'chefspec-bootstrap'
3
- s.version = '0.0.1'
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 'chef', '~> 11.0'
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
@@ -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
- def generate(cookbooks_dir, spec_dir, template_file)
10
- if not Dir.exist?(cookbooks_dir)
11
- abort "Unable to locate your cookbooks directory (#{cookbooks_dir})"
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
- erb = ERB.new(File.read(template_file))
38
+ # end
23
39
 
24
- Dir.glob("#{cookbooks_dir}/*/recipes/*").each do |path|
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 not File.exist?(filename)
32
- FileUtils.mkdir_p "#{spec_dir}/#{cookbook}"
51
+ if File.exist?(filename)
52
+ puts " spec already exists. Skipping."
53
+ else
54
+ FileUtils.mkdir_p "#{@spec_dir}/#{cookbook}"
33
55
 
34
- puts "Creating spec file: #{filename}"
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
@@ -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.1
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.1.0
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.1.0
29
+ version: 3.4.0
46
30
  - !ruby/object:Gem::Dependency
47
31
  name: trollop
48
32
  requirement: !ruby/object:Gem::Requirement