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, cookbook_path) ⇒ Bootstrap

Returns a new instance of Bootstrap.



9
10
11
12
13
14
15
# File 'lib/chefspec_bootstrap.rb', line 9

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

Instance Method Details

#escape_string(string) ⇒ Object



166
167
168
# File 'lib/chefspec_bootstrap.rb', line 166

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

#generateObject



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

def generate
  setup

  abort 'Output file already exists. Refusing to override.' if @output_file && 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)[-2]
  chef_run = get_chef_run(cookbook, recipe)

  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
    generate_spec_file(spec_output)
  else
    puts spec_output
  end
end

#generate_spec_file(output) ⇒ Object



72
73
74
75
76
77
78
79
80
81
# File 'lib/chefspec_bootstrap.rb', line 72

def generate_spec_file(output)
  output_path = @output_file.split(File::SEPARATOR)
  output_path.pop

  FileUtils.mkpath(output_path.join(File::SEPARATOR)) if output_path

  File.open(@output_file, 'w') do |spec_file|
    spec_file.write(output)
  end
end

#generate_test_cases(resources) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/chefspec_bootstrap.rb', line 112

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

    noun = resource.resource_name
    adjective = resource.name

    verbs.each do |verb|
      next if verb == :nothing

      test_cases.push(
        it: get_it_block(noun, verb, adjective),
        expect: get_expect_block(noun, verb),
        name: adjective
      )
    end
  end
  test_cases
end

#get_all_resources(chef_run) ⇒ Object



93
94
95
# File 'lib/chefspec_bootstrap.rb', line 93

def get_all_resources(chef_run)
  chef_run.resource_collection.all_resources
end

#get_chef_run(cookbook, recipe) ⇒ Object



83
84
85
86
87
# File 'lib/chefspec_bootstrap.rb', line 83

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

#get_expect_block(noun, verb) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/chefspec_bootstrap.rb', line 151

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



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/chefspec_bootstrap.rb', line 134

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



89
90
91
# File 'lib/chefspec_bootstrap.rb', line 89

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

#get_resources(chef_run, cookbook, recipe) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/chefspec_bootstrap.rb', line 97

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



68
69
70
# File 'lib/chefspec_bootstrap.rb', line 68

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

#setupObject



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

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 = [@cookbook_path]
    end
  end
end