Class: ChefSpec::Bootstrap

Inherits:
Object
  • Object
show all
Defined in:
lib/chefspec-bootstrap.rb

Instance Method Summary collapse

Constructor Details

#initialize(recipe, template_file, spec_helper_file, output_file) ⇒ Bootstrap

Returns a new instance of Bootstrap.



9
10
11
12
13
14
# File 'lib/chefspec-bootstrap.rb', line 9

def initialize(recipe, template_file, spec_helper_file, output_file)
  @template_file = template_file
  @recipe = recipe
  @spec_helper_file = spec_helper_file || 'spec/spec_helper.rb'
  @output_file = output_file
end

Instance Method Details

#escape_string(string) ⇒ Object



160
161
162
# File 'lib/chefspec-bootstrap.rb', line 160

def escape_string(string)
  string.gsub('\\', '\\\\').gsub("\"", "\\\"")
end

#generateObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/chefspec-bootstrap.rb', line 42

def generate
  setup

  abort 'Output file already exists. Refusing to override.' if @output_file and File.exist?(@output_file)

  erb = ERB.new(File.read(@template_file))

  path, recipe_file = File.split(@recipe)
  recipe = recipe_file.split('.')[0]
  cookbook = path.split(File::SEPARATOR)[1]
  chef_run = get_chef_run(cookbook, recipe)

  puts 'Chefspec execution failed. Generating generic spec.' unless chef_run

  resources = get_resources(chef_run, cookbook, recipe)
  test_cases = generate_test_cases(resources)
  spec_helper = @spec_helper

  spec_output = erb.result(binding)

  if @output_file
    File.open(@output_file, 'w') do |spec_file|
      spec_file.write(spec_output)
    end
  else
    puts spec_output
  end
end

#generate_test_cases(resources) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/chefspec-bootstrap.rb', line 104

def generate_test_cases(resources)
  test_cases = []
  resources.each do |resource|
    verbs = resource.action
    unless verbs.respond_to?(:each)
      verbs = [verbs]
    end

    noun = resource.resource_name
    adjective = resource.name

    verbs.each do |verb|
      unless verb == :nothing
        test_cases.push(
          it: get_it_block(noun, verb, adjective),
          expect: get_expect_block(noun, verb),
          name: adjective
        )
      end
    end
  end
  test_cases
end

#get_all_resources(chef_run) ⇒ Object



85
86
87
# File 'lib/chefspec-bootstrap.rb', line 85

def get_all_resources(chef_run)
  chef_run.resource_collection.all_resources
end

#get_chef_run(cookbook, recipe) ⇒ Object



75
76
77
78
79
# File 'lib/chefspec-bootstrap.rb', line 75

def get_chef_run(cookbook, recipe)
  return ChefSpec::Runner.new.converge("#{cookbook}::#{recipe}")
rescue Exception => e
  return nil
end

#get_expect_block(noun, verb) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/chefspec-bootstrap.rb', line 145

def get_expect_block(noun, verb)
  expect = '%{verb}_%{noun}'
  string_variables = { noun: noun, verb: verb }

  if @api_map[noun] && @api_map[noun][:expect]
    if @api_map[noun][:expect][verb]
      expect = @api_map[noun][:expect][verb]
    elsif @api_map[noun][:expect][:default]
      expect = @api_map[noun][:expect][:default]
    end
  end

  escape_string(expect % string_variables)
end

#get_it_block(noun, verb, adjective) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/chefspec-bootstrap.rb', line 128

def get_it_block(noun, verb, adjective)
  it = '%{verb}s the %{adjective} %{noun}'
  noun_readable = noun.to_s.gsub('_', ' ')
  verb_readable = verb.to_s.gsub('_', ' ')
  string_variables = { noun: noun_readable, verb: verb_readable, adjective: adjective }

  if @api_map[noun] && @api_map[noun][:it]
    if @api_map[noun][:it][verb]
      it = @api_map[noun][:it][verb]
    elsif @api_map[noun][:it][:default]
      it = @api_map[noun][:it][:default]
    end
  end

  escape_string(it  % string_variables)
end

#get_resource_name(resource) ⇒ Object



81
82
83
# File 'lib/chefspec-bootstrap.rb', line 81

def get_resource_name(resource)
  resource.name || resource.identity
end

#get_resources(chef_run, cookbook, recipe) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/chefspec-bootstrap.rb', line 89

def get_resources(chef_run, cookbook, recipe)
  if chef_run
    resources = get_all_resources(chef_run)
    if @recursive
      return resources
    else
      return resources.select do |resource|
        resource.cookbook_name == cookbook.to_sym && resource.recipe_name == recipe
      end
    end
  else
    return []
  end
end

#rootObject



71
72
73
# File 'lib/chefspec-bootstrap.rb', line 71

def root
  @root ||= Pathname.new(File.expand_path('../../', __FILE__))
end

#setupObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/chefspec-bootstrap.rb', line 16

def setup
  unless File.exist?(@recipe)
    abort "Unable to locate recipe file (#{@recipe})"
  end

  unless @template_file
    @template_file = root.join('templates', 'default.erb')
  end

  unless File.exist?(@template_file)
    abort "Unable to locate template file (#{@template_file})"
  end

  @api_map = ChefSpec::APIMap.new.map

  begin
    require File.expand_path(@spec_helper_file)
    @spec_helper = true
  rescue LoadError
    @spec_helper = false
    ::RSpec.configure do |config|
      config.cookbook_path = ['cookbooks']
    end
  end
end