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
# 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 #{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'

  # 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)

  config['classes'].each { |clarse| @classes << Onceover::Class.new(clarse) } unless config['classes'] == nil
  config['nodes'].each { |node| @nodes << Onceover::Node.new(node) } unless config['nodes'] == nil
  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

  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



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/onceover/testconfig.rb', line 77

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

Instance Method Details



229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/onceover/testconfig.rb', line 229

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



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

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



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
# File 'lib/onceover/testconfig.rb', line 129

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



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/onceover/testconfig.rb', line 242

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

#verify_acceptance_test(controlrepo, test) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/onceover/testconfig.rb', line 107

def verify_acceptance_test(controlrepo,test)
  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



99
100
101
102
103
104
105
# File 'lib/onceover/testconfig.rb', line 99

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



203
204
205
# File 'lib/onceover/testconfig.rb', line 203

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

#write_rakefile(location, pattern) ⇒ Object



211
212
213
# File 'lib/onceover/testconfig.rb', line 211

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

#write_spec_helper(location, repo) ⇒ Object



215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/onceover/testconfig.rb', line 215

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



207
208
209
# File 'lib/onceover/testconfig.rb', line 207

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



198
199
200
201
# File 'lib/onceover/testconfig.rb', line 198

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