Class: Onceover::TestConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/onceover/testconfig.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, opts = {}) ⇒ TestConfig



29
30
31
32
33
34
35
36
37
38
39
40
41
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/onceover/testconfig.rb', line 29

def initialize(file,opts = {})
  begin
    config = YAML.load(File.read(file))
  rescue Errno::ENOENT
    raise "Could not find #{file}"
  rescue Psych::SyntaxError
    raise "Could not parse #{file}, check that it is valid YAML and that the encoding is correct"
  end

  @classes          = []
  @nodes            = []
  @node_groups      = []
  @class_groups     = []
  @spec_tests       = []
  @acceptance_tests = []
  @opts             = opts
  @mock_functions   = config['functions']
  @strict_variables = opts[:strict_variables] ? 'yes' : 'no'

  # Initialise all of the classes and nodes
  config['classes'].each { |clarse| Onceover::Class.new(clarse) } unless config['classes'] == nil
  @classes = Onceover::Class.all

  config['nodes'].each { |node| Onceover::Node.new(node) } unless config['nodes'] == nil
  @nodes = Onceover::Node.all

  # Add the 'all_classes' and 'all_nodes' default groups
  @node_groups << Onceover::Group.new('all_nodes',@nodes)
  @class_groups << Onceover::Group.new('all_classes',@classes)

  # Initialise all of the groups
  config['node_groups'].each { |name, members| @node_groups << Onceover::Group.new(name, members) } unless config['node_groups'] == nil
  config['class_groups'].each { |name, members| @class_groups << Onceover::Group.new(name, members) } unless config['class_groups'] == nil

  @filter_tags      = opts[:tags] ? [opts[:tags].split(',')].flatten : nil
  @filter_classes   = opts[:classes] ? [opts[:classes].split(',')].flatten.map {|x| Onceover::Class.find(x)} : nil
  @filter_nodes     = opts[:nodes] ? [opts[:nodes].split(',')].flatten.map {|x| Onceover::Node.find(x)} : nil
  @skip_r10k        = opts[:skip_r10k] ? true : false

  # Loop over all of the items in the test matrix and add those as test
  # objects to the list of tests
  config['test_matrix'].each do |test_hash|
    test_hash.each do |machines, settings|
      if settings['tests'] == 'spec'
        @spec_tests << Onceover::Test.new(machines,settings['classes'],settings)
      elsif settings['tests'] == 'acceptance'
        @acceptance_tests << Onceover::Test.new(machines,settings['classes'],settings)
      elsif settings['tests'] == 'all_tests'
        tst = Onceover::Test.new(machines,settings['classes'],settings)
        @spec_tests << tst
        @acceptance_tests << tst
      end
    end
  end
end

Instance Attribute Details

#acceptance_testsObject

Returns the value of attribute acceptance_tests.



19
20
21
# File 'lib/onceover/testconfig.rb', line 19

def acceptance_tests
  @acceptance_tests
end

#class_groupsObject

Returns the value of attribute class_groups.



17
18
19
# File 'lib/onceover/testconfig.rb', line 17

def class_groups
  @class_groups
end

#classesObject

Returns the value of attribute classes.



14
15
16
# File 'lib/onceover/testconfig.rb', line 14

def classes
  @classes
end

#environmentObject

Returns the value of attribute environment.



20
21
22
# File 'lib/onceover/testconfig.rb', line 20

def environment
  @environment
end

#filter_classesObject

Returns the value of attribute filter_classes.



23
24
25
# File 'lib/onceover/testconfig.rb', line 23

def filter_classes
  @filter_classes
end

#filter_nodesObject

Returns the value of attribute filter_nodes.



24
25
26
# File 'lib/onceover/testconfig.rb', line 24

def filter_nodes
  @filter_nodes
end

#filter_tagsObject

Returns the value of attribute filter_tags.



22
23
24
# File 'lib/onceover/testconfig.rb', line 22

def filter_tags
  @filter_tags
end

#mock_functionsObject

Returns the value of attribute mock_functions.



25
26
27
# File 'lib/onceover/testconfig.rb', line 25

def mock_functions
  @mock_functions
end

#node_groupsObject

Returns the value of attribute node_groups.



16
17
18
# File 'lib/onceover/testconfig.rb', line 16

def node_groups
  @node_groups
end

#nodesObject

Returns the value of attribute nodes.



15
16
17
# File 'lib/onceover/testconfig.rb', line 15

def nodes
  @nodes
end

#optsObject

Returns the value of attribute opts.



21
22
23
# File 'lib/onceover/testconfig.rb', line 21

def opts
  @opts
end

#skip_r10kObject

Returns the value of attribute skip_r10k.



26
27
28
# File 'lib/onceover/testconfig.rb', line 26

def skip_r10k
  @skip_r10k
end

#spec_testsObject

Returns the value of attribute spec_tests.



18
19
20
# File 'lib/onceover/testconfig.rb', line 18

def spec_tests
  @spec_tests
end

#strict_variablesObject

Returns the value of attribute strict_variables.



27
28
29
# File 'lib/onceover/testconfig.rb', line 27

def strict_variables
  @strict_variables
end

Class Method Details

.find_list(thing) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/onceover/testconfig.rb', line 96

def self.find_list(thing)
  # Takes a string and finds an object or list of objects to match, will
  # take nodes, classes or groups

  # We want to supress warnings for this bit
  old_level = logger.level
  logger.level = :error
  if Onceover::Group.find(thing)
    logger.level = old_level
    return Onceover::Group.find(thing).members
  elsif Onceover::Class.find(thing)
    logger.level = old_level
    return [Onceover::Class.find(thing)]
  elsif Onceover::Node.find(thing)
    logger.level = old_level
    return [Onceover::Node.find(thing)]
  else
    logger.level = old_level
    raise "Could not find #{thing} in list of classes, nodes or groups"
  end
end

.subtractive_to_list(subtractive_hash) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/onceover/testconfig.rb', line 118

def self.subtractive_to_list(subtractive_hash)
  # Take a hash that looks like this:
  # { 'include' => 'somegroup'
  #   'exclude' => 'other'}
  # and return a list of classes/nodes
  include_list = Onceover::TestConfig.find_list(subtractive_hash['include']).flatten
  exclude_list = Onceover::TestConfig.find_list(subtractive_hash['exclude']).flatten
  include_list - exclude_list
end

Instance Method Details



262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/onceover/testconfig.rb', line 262

def create_fixtures_symlinks(repo)
  logger.debug "Creating fixtures symlinks"
  FileUtils.rm_rf("#{repo.tempdir}/spec/fixtures/modules")
  FileUtils.mkdir_p("#{repo.tempdir}/spec/fixtures/modules")
  repo.temp_modulepath.split(':').each do |path|
    Dir["#{path}/*"].each do |mod|
      modulename = File.basename(mod)
      logger.debug "Symlinking #{mod} to #{repo.tempdir}/spec/fixtures/modules/#{modulename}"
      FileUtils.ln_s(mod, "#{repo.tempdir}/spec/fixtures/modules/#{modulename}")
    end
  end
end

#pre_conditionObject



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/onceover/testconfig.rb', line 148

def pre_condition
  # Read all the pre_conditions and return the string
  spec_dir = Onceover::Controlrepo.new.spec_dir
  puppetcode = []
  Dir["#{spec_dir}/pre_conditions/*.pp"].each do |condition_file|
    logger.debug "Reading pre_conditions from #{condition_file}"
    puppetcode << File.read(condition_file)
  end
  return nil if puppetcode.count == 0
  puppetcode.join("\n")
end

#r10k_deploy_local(repo = Onceover::Controlrepo.new) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/onceover/testconfig.rb', line 160

def r10k_deploy_local(repo = Onceover::Controlrepo.new)
  require 'onceover/controlrepo'
  require 'pathname'
  if repo.tempdir == nil
    repo.tempdir = Dir.mktmpdir('r10k')
  else
    logger.debug "Creating #{repo.tempdir}"
    FileUtils.mkdir_p(repo.tempdir)
  end

  # We need to do the copy to a tempdir then move the tempdir to the
  # destination, just in case we get a recursive copy
  # TODO: Improve this to save I/O

  # We might need to exclude some files
  #
  # if we are using bundler to install gems below the controlrepo
  # we don't wan two copies so exclude those
  #
  # If there are more situations like this we can add them to this array as
  # full paths
  excluded_files = []
  if ENV['GEM_HOME']
    logger.debug "Excluding #{ENV['GEM_HOME']} from controlrepo copy"
    excluded_files << Dir.glob("#{ENV['GEM_HOME']}/**/*")
    excluded_files.flatten!
  end

  # Exclude the files we need to
  controlrepo_files = Dir.glob("#{repo.root}/**/*")
  files_to_copy = (controlrepo_files - excluded_files).delete_if { |path| Pathname(path).directory? }
  folders_to_copy = (controlrepo_files - excluded_files).keep_if { |path| Pathname(path).directory? }

  logger.debug "Creating temp dir as a staging directory for copying the controlrepo to #{repo.tempdir}"
  temp_controlrepo = Dir.mktmpdir('controlrepo')

  logger.debug "Creating directories under #{temp_controlrepo}"
  FileUtils.mkdir_p(folders_to_copy.map { |folder| "#{temp_controlrepo}/#{(Pathname(folder).relative_path_from(Pathname(repo.root))).to_s}"})

  logger.debug "Copying files to #{temp_controlrepo}"
  files_to_copy.each do |file|
    FileUtils.cp(file,"#{temp_controlrepo}/#{(Pathname(file).relative_path_from(Pathname(repo.root))).to_s}")
  end
  FileUtils.mkdir_p("#{repo.tempdir}/#{repo.environmentpath}/production")

  logger.debug "Copying #{temp_controlrepo} to #{repo.tempdir}/#{repo.environmentpath}/production"
  FileUtils.cp_r(Dir["#{temp_controlrepo}/*"], "#{repo.tempdir}/#{repo.environmentpath}/production")
  FileUtils.rm_rf(temp_controlrepo)

  # Pull the trigger! If it's not already been pulled
  if repo.tempdir
    if File.directory?(repo.tempdir)
      # TODO: Change this to call out to r10k directly to do this
      # Probably something like:
      # R10K::Settings.global_settings.evaluate(with_overrides)
      # R10K::Action::Deploy::Environment
      Dir.chdir("#{repo.tempdir}/#{repo.environmentpath}/production") do
        logger.debug "Runing r10k puppetfile install --verbose --color --puppetfile #{repo.puppetfile} from #{repo.tempdir}/#{repo.environmentpath}/production"
        system("r10k puppetfile install --verbose --color --puppetfile #{repo.puppetfile}")
      end
    else
      raise "#{repo.tempdir} is not a directory"
    end
  end

  # Return repo.tempdir for use
  repo.tempdir
end

#run_filters(tests) ⇒ Object



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/onceover/testconfig.rb', line 275

def run_filters(tests)
  # All of this needs to be applied AFTER deduplication but BEFORE writing
  filters = {
    'tags'    => @filter_tags,
    'classes' => @filter_classes,
    'nodes'   => @filter_nodes
  }
  filters.each do |method,filter_list|
    if filter_list
      # Remove tests that do not have matching tags
      tests.keep_if do |test|
        filter_list.any? do |filter|
          if test.send(method)
            test.send(method).include?(filter)
          else
            false
          end
        end
      end
    end
  end
  tests
end

#to_sObject



85
86
87
88
89
90
91
92
93
94
# File 'lib/onceover/testconfig.rb', line 85

def to_s
  require 'colored'

  "  \#{'classes'.green}      \#{@classes.map{|c|c.name}}\n  \#{'nodes'.green}        \#{@nodes.map{|n|n.name}}\n  \#{'class_groups'.green} \#{@class_groups}\n  \#{'node_groups'.green}  \#{@node_groups.map{|g|g.name}}\n  END\nend\n".gsub(/^\s{4}/,'')

#verify_acceptance_test(controlrepo, test) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/onceover/testconfig.rb', line 136

def verify_acceptance_test(controlrepo,test)
  warn "[DEPRECATION] #{__method__} is deprecated due to the removal of Beaker"

  require 'yaml'
  nodeset = YAML.load_file(controlrepo.nodeset_file)
  test.nodes.each do |node|
    unless nodeset['HOSTS'].has_key?(node.name)
      raise "Could not find nodeset for node: #{node.name}"
    end
  end
end

#verify_spec_test(controlrepo, test) ⇒ Object



128
129
130
131
132
133
134
# File 'lib/onceover/testconfig.rb', line 128

def verify_spec_test(controlrepo,test)
  test.nodes.each do |node|
    unless controlrepo.facts_files.any? { |file| file =~ /\/#{node.name}\.json/ }
      raise "Could not find factset for node: #{node.name}"
    end
  end
end

#write_acceptance_tests(location, tests) ⇒ Object



234
235
236
237
238
# File 'lib/onceover/testconfig.rb', line 234

def write_acceptance_tests(location, tests)
  warn "[DEPRECATION] #{__method__} is deprecated due to the removal of Beaker"

  File.write("#{location}/acceptance_spec.rb",Onceover::Controlrepo.evaluate_template('acceptance_test_spec.rb.erb',binding))
end

#write_rakefile(location, pattern) ⇒ Object



244
245
246
# File 'lib/onceover/testconfig.rb', line 244

def write_rakefile(location, pattern)
  File.write("#{location}/Rakefile",Onceover::Controlrepo.evaluate_template('testconfig_Rakefile.erb',binding))
end

#write_spec_helper(location, repo) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/onceover/testconfig.rb', line 248

def write_spec_helper(location, repo)
  environmentpath = "#{repo.tempdir}/#{repo.environmentpath}"
  modulepath = repo.config['modulepath']
  modulepath.delete("$basemodulepath")
  modulepath.map! do |path|
    "#{environmentpath}/production/#{path}"
  end
  modulepath = modulepath.join(":")
  repo.temp_modulepath = modulepath

  # Use an ERB template to write a spec test
  File.write("#{location}/spec_helper.rb",Onceover::Controlrepo.evaluate_template('spec_helper.rb.erb',binding))
end

#write_spec_helper_acceptance(location, repo) ⇒ Object



240
241
242
# File 'lib/onceover/testconfig.rb', line 240

def write_spec_helper_acceptance(location, repo)
  File.write("#{location}/spec_helper_acceptance.rb",Onceover::Controlrepo.evaluate_template('spec_helper_acceptance.rb.erb',binding))
end

#write_spec_test(location, test) ⇒ Object



229
230
231
232
# File 'lib/onceover/testconfig.rb', line 229

def write_spec_test(location, test)
  # Use an ERB template to write a spec test
  File.write("#{location}/#{test.to_s}_spec.rb",Onceover::Controlrepo.evaluate_template('test_spec.rb.erb',binding))
end