beaker 3.12.0 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/acceptance/tests/subcommands/init.rb +17 -15
  3. data/acceptance/tests/subcommands/provision.rb +45 -0
  4. data/beaker.gemspec +5 -9
  5. data/bin/beaker +1 -1
  6. data/docs/concepts/test_tagging.md +27 -14
  7. data/docs/how_to/archive_sut_files.md +19 -1
  8. data/docs/how_to/hypervisors/README.md +20 -3
  9. data/docs/how_to/hypervisors/ec2.md +4 -0
  10. data/docs/how_to/hypervisors/vmpooler.md +24 -0
  11. data/docs/how_to/hypervisors/vsphere.md +0 -3
  12. data/docs/tutorials/installation.md +22 -7
  13. data/lib/beaker/cli.rb +28 -12
  14. data/lib/beaker/dsl.rb +2 -1
  15. data/lib/beaker/dsl/helpers/puppet_helpers.rb +1 -1
  16. data/lib/beaker/dsl/helpers/tk_helpers.rb +1 -1
  17. data/lib/beaker/dsl/structure.rb +0 -130
  18. data/lib/beaker/dsl/test_tagging.rb +157 -0
  19. data/lib/beaker/host/unix/exec.rb +9 -1
  20. data/lib/beaker/host_prebuilt_steps.rb +1 -1
  21. data/lib/beaker/hypervisor/openstack.rb +8 -9
  22. data/lib/beaker/options/command_line_parser.rb +19 -4
  23. data/lib/beaker/options/parser.rb +18 -9
  24. data/lib/beaker/options/presets.rb +6 -4
  25. data/lib/beaker/options/validator.rb +11 -5
  26. data/lib/beaker/subcommand.rb +84 -6
  27. data/lib/beaker/subcommands/subcommand_util.rb +58 -7
  28. data/lib/beaker/version.rb +1 -1
  29. data/spec/beaker/cli_spec.rb +44 -1
  30. data/spec/beaker/dsl/structure_spec.rb +1 -214
  31. data/spec/beaker/dsl/test_tagging_spec.rb +274 -0
  32. data/spec/beaker/host/cisco_spec.rb +4 -4
  33. data/spec/beaker/host/unix/exec_spec.rb +2 -2
  34. data/spec/beaker/host_prebuilt_steps_spec.rb +1 -1
  35. data/spec/beaker/options/command_line_parser_spec.rb +2 -2
  36. data/spec/beaker/options/parser_spec.rb +33 -24
  37. data/spec/beaker/options/validator_spec.rb +18 -3
  38. data/spec/beaker/subcommand/subcommand_util_spec.rb +121 -10
  39. metadata +12 -8
@@ -245,12 +245,27 @@ module Beaker
245
245
  @cmd_options[:type] = type
246
246
  end
247
247
 
248
- opts.on '--tag TAGS', 'Run the set of tests matching ALL of the provided single or comma separated list of tags' do |value|
249
- @cmd_options[:tag_includes] = value
248
+ opts.on '--tag TAGS',
249
+ 'DEPRECATED - use --test-tag-and instead' do |value|
250
+ @cmd_options[:test_tag_and] = value
251
+ end
252
+ opts.on '--test-tag-and TAGS',
253
+ 'Run the set of tests matching ALL of the provided single or comma separated list of tags' do |value|
254
+ @cmd_options[:test_tag_and] = value
255
+ end
256
+
257
+ opts.on '--test-tag-or TAGS',
258
+ 'Run the set of tests matching ANY of the provided single or comma separated list of tags' do |value|
259
+ @cmd_options[:test_tag_or] = value
250
260
  end
251
261
 
252
- opts.on '--exclude-tag TAGS', 'Run the set of tests that do not contain ANY of the provided single or command separated list of tags' do |value|
253
- @cmd_options[:tag_excludes] = value
262
+ opts.on '--exclude-tag TAGS',
263
+ 'DEPRECATED - use --test-tag-exclude instead' do |value|
264
+ @cmd_options[:test_tag_exclude] = value
265
+ end
266
+ opts.on '--test-tag-exclude TAGS',
267
+ 'Run the set of tests that do not contain ANY of the provided single or comma separated list of tags' do |value|
268
+ @cmd_options[:test_tag_exclude] = value
254
269
  end
255
270
 
256
271
  opts.on '--xml-time-order',
@@ -363,8 +363,12 @@ module Beaker
363
363
  host[:host_tags] = @options[:host_tags].merge(host[:host_tags] || {})
364
364
  end
365
365
 
366
- normalize_tags!
367
- @validator.validate_tags(@options[:tag_includes], @options[:tag_excludes])
366
+ normalize_test_tags!
367
+ @validator.validate_test_tags(
368
+ @options[:test_tag_and],
369
+ @options[:test_tag_or],
370
+ @options[:test_tag_exclude]
371
+ )
368
372
  resolve_symlinks!
369
373
 
370
374
  #set the default role
@@ -411,13 +415,18 @@ module Beaker
411
415
 
412
416
  # Normalize include and exclude tags. This modifies @options.
413
417
  #
414
- def normalize_tags!
415
- @options[:tag_includes] ||= ''
416
- @options[:tag_excludes] ||= ''
417
- @options[:tag_includes] = @options[:tag_includes].split(',') if @options[:tag_includes].respond_to?(:split)
418
- @options[:tag_excludes] = @options[:tag_excludes].split(',') if @options[:tag_excludes].respond_to?(:split)
419
- @options[:tag_includes].map!(&:downcase)
420
- @options[:tag_excludes].map!(&:downcase)
418
+ # @note refer to {Beaker::DSL::TestTagging} for test tagging implementation
419
+ #
420
+ def normalize_test_tags!
421
+ @options[:test_tag_and] ||= ''
422
+ @options[:test_tag_or] ||= ''
423
+ @options[:test_tag_exclude] ||= ''
424
+ @options[:test_tag_and] = @options[:test_tag_and].split(',') if @options[:test_tag_and].respond_to?(:split)
425
+ @options[:test_tag_or] = @options[:test_tag_or].split(',') if @options[:test_tag_or].respond_to?(:split)
426
+ @options[:test_tag_exclude] = @options[:test_tag_exclude].split(',') if @options[:test_tag_exclude].respond_to?(:split)
427
+ @options[:test_tag_and].map!(&:downcase)
428
+ @options[:test_tag_or].map!(&:downcase)
429
+ @options[:test_tag_exclude].map!(&:downcase)
421
430
  end
422
431
 
423
432
  private
@@ -34,8 +34,9 @@ module Beaker
34
34
  :release_yum_repo_url => ['BEAKER_RELEASE_YUM_REPO', 'RELEASE_YUM_REPO'],
35
35
  :dev_builds_url => ['BEAKER_DEV_BUILDS_URL', 'DEV_BUILDS_URL'],
36
36
  :vbguest_plugin => ['BEAKER_VB_GUEST_PLUGIN', 'BEAKER_vb_guest_plugin'],
37
- :tag_includes => ['BEAKER_TAG'],
38
- :tag_excludes => ['BEAKER_EXCLUDE_TAG'],
37
+ :test_tag_and => ['BEAKER_TAG', 'BEAKER_TEST_TAG_AND'],
38
+ :test_tag_or => ['BEAKER_TEST_TAG_OR'],
39
+ :test_tag_exclude => ['BEAKER_EXCLUDE_TAG', 'BEAKER_TEST_TAG_EXCLUDE'],
39
40
  :run_in_parallel => ['BEAKER_RUN_IN_PARALLEL'],
40
41
  }
41
42
 
@@ -157,8 +158,9 @@ module Beaker
157
158
  :log_sut_event => 'sut.log',
158
159
  :color => true,
159
160
  :dry_run => false,
160
- :tag_includes => '',
161
- :tag_excludes => '',
161
+ :test_tag_and => '',
162
+ :test_tag_or => '',
163
+ :test_tag_exclude => '',
162
164
  :timeout => 900, # 15 minutes
163
165
  :fail_mode => 'slow',
164
166
  :accept_all_exit_codes => false,
@@ -81,14 +81,20 @@ module Beaker
81
81
 
82
82
  # Raise an error if an item exists in both the include and exclude lists.
83
83
  #
84
- # @param [Array] include included items
85
- # @param [Array] exclude excluded items
84
+ # @note see test tagging logic at {Beaker::DSL::TestTagging} module
85
+ #
86
+ # @param [Array] tags_and included items
87
+ # @param [Array] tags_exclude excluded items
86
88
  # @return [nil] Does not return anything
87
- def validate_tags(include, exclude)
88
- include.each do |included_tag|
89
+ def validate_test_tags(tags_and, tags_or, tags_exclude)
90
+ if tags_and.length > 0 && tags_or.length > 0
91
+ validator_error "cannot have values for both test tagging operands (AND and OR)"
92
+ end
93
+
94
+ tags_and.each do |included_tag|
89
95
  # select items from exclude set that match included_tag
90
96
  # no match is an empty list/array/[]
91
- if exclude.select { |ex| ex == included_tag } != []
97
+ if tags_exclude.select { |ex| ex == included_tag } != []
92
98
  validator_error "tag '#{included_tag}' cannot be in both the included and excluded tag sets"
93
99
  end
94
100
  end
@@ -6,20 +6,98 @@ module Beaker
6
6
  class Subcommand < Thor
7
7
  SubcommandUtil = Beaker::Subcommands::SubcommandUtil
8
8
 
9
- desc "init", "Initialises the beaker test environment configuration"
10
- option :hypervisor, :type => :string, :enum => %w{vagrant vmpooler}
9
+ def initialize(*args)
10
+ super
11
+ @@config = SubcommandUtil.init_config()
12
+ end
13
+
14
+ # Options listed in this group 'Beaker run' are options that can be set on subcommands
15
+ # but are not processed by the subcommand itself. They are passed through so that when
16
+ # a Beaker::CLI object executes, it can pick up these options. Notably excluded from this
17
+ # group are `help` and `version`. Please note that whenever the command_line_parser.rb is
18
+ # updated, this list should also be updated as well.
19
+ class_option :hosts, :aliases => '-h', :type => :string, :group => 'Beaker run'
20
+ class_option :'options-file', :aliases => '-o', :type => :string, :group => 'Beaker run'
21
+ class_option :helper, :type => :string, :group => 'Beaker run'
22
+ class_option :'load-path', :type => :string, :group => 'Beaker run'
23
+ class_option :tests, :aliases => '-t', :type => :string, :group => 'Beaker run'
24
+ class_option :'pre-suite', :type => :string, :group => 'Beaker run'
25
+ class_option :'post-suite', :type => :string, :group => 'Beaker run'
26
+ class_option :'pre-cleanup', :type => :string, :group => 'Beaker run'
27
+ class_option :'provision', :type => :boolean, :group => 'Beaker run'
28
+ class_option :'preserve-hosts', :type => :string, :group => 'Beaker run'
29
+ class_option :'root-keys', :type => :boolean, :group => 'Beaker run'
30
+ class_option :keyfile, :type => :string, :group => 'Beaker run'
31
+ class_option :timeout, :type => :string, :group => 'Beaker run'
32
+ class_option :install, :aliases => '-i', :type => :string, :group => 'Beaker run'
33
+ class_option :modules, :aliases => '-m', :type => :string, :group => 'Beaker run'
34
+ class_option :quiet, :aliases => '-q', :type => :boolean, :group => 'Beaker run'
35
+ class_option :color, :type => :boolean, :group => 'Beaker run'
36
+ class_option :'color-host-output', :type => :boolean, :group => 'Beaker run'
37
+ class_option :'log-level', :type => :string, :group => 'Beaker run'
38
+ class_option :'log-prefix', :type => :string, :group => 'Beaker run'
39
+ class_option :'dry-run', :type => :boolean, :group => 'Beaker run'
40
+ class_option :'fail-mode', :type => :string, :group => 'Beaker run'
41
+ class_option :ntp, :type => :boolean, :group => 'Beaker run'
42
+ class_option :'repo-proxy', :type => :boolean, :group => 'Beaker run'
43
+ class_option :'add-el-extras', :type => :boolean, :group => 'Beaker run'
44
+ class_option :'package-proxy', :type => :string, :group => 'Beaker run'
45
+ class_option :'validate', :type => :boolean, :group => 'Beaker run'
46
+ class_option :'collect-perf-data', :type => :boolean, :group => 'Beaker run'
47
+ class_option :'parse-only', :type => :boolean, :group => 'Beaker run'
48
+ class_option :tag, :type => :string, :group => 'Beaker run'
49
+ class_option :'exclude-tags', :type => :string, :group => 'Beaker run'
50
+ class_option :'xml-time-order', :type => :boolean, :group => 'Beaker run'
51
+
52
+ desc "init HYPERVISOR", "Initialises the beaker test environment configuration"
11
53
  option :help, :type => :boolean, :hide => true
12
54
  long_desc <<-LONGDESC
13
- Initialises a beaker environment configuration
55
+
56
+ Initialises a test environment configuration for a specific hypervisor
57
+
58
+ Supported hypervisors are: vagrant (default), vmpooler
59
+
14
60
  LONGDESC
15
- def init()
61
+ def init(hypervisor='vagrant')
16
62
  if options[:help]
17
63
  invoke :help, [], ["init"]
18
64
  return
19
65
  end
66
+ SubcommandUtil.verify_init_args(hypervisor)
20
67
  SubcommandUtil.require_tasks()
21
- SubcommandUtil.init_hypervisor(options)
22
- say "Writing host config to .beaker/acceptance/config/default_#{options[:hypervisor]}_hosts.yaml"
68
+ SubcommandUtil.init_hypervisor(hypervisor)
69
+ say "Writing host config to .beaker/acceptance/config/default_#{hypervisor}_hosts.yaml"
70
+ SubcommandUtil.store_config({:hypervisor => hypervisor})
71
+ SubcommandUtil.delete_config([:provisioned])
72
+ end
73
+
74
+ desc "provision", "Provisions the beaker test configuration"
75
+ option :validate, :type => :boolean, :default => true
76
+ option :configure, :type => :boolean, :default => true
77
+ option :help, :type => :boolean, :hide => true
78
+ long_desc <<-LONGDESC
79
+ Provisions a beaker configuration
80
+ LONGDESC
81
+ def provision()
82
+ if options[:help]
83
+ invoke :help, [], ["provision"]
84
+ return
85
+ end
86
+
87
+ hypervisor = @@config.transaction { @@config[:hypervisor] }
88
+
89
+ unless hypervisor
90
+ SubcommandUtil.error_with("Please initialise a configuration")
91
+ end
92
+
93
+ provisioned = @@config.transaction { @@config[:provisioned] }
94
+
95
+ if !provisioned or options[:force]
96
+ SubcommandUtil.provision(hypervisor, options)
97
+ SubcommandUtil.store_config({:provisioned => true})
98
+ else
99
+ say "Hosts have already been provisioned"
100
+ end
23
101
  end
24
102
  end
25
103
  end
@@ -1,5 +1,7 @@
1
1
  require 'rake'
2
2
  require 'stringio'
3
+ require 'yaml/store'
4
+ require 'fileutils'
3
5
 
4
6
  module Beaker
5
7
  module Subcommands
@@ -18,6 +20,8 @@ module Beaker
18
20
  module SubcommandUtil
19
21
  BEAKER_REQUIRE = "require 'beaker/tasks/quick_start'"
20
22
  HYPERVISORS = ["vagrant", "vmpooler"]
23
+ CONFIG_DIR = ".beaker"
24
+ CONFIG_KEYS = [:hypervisor, :provisioned]
21
25
 
22
26
  # Check if the first argument to the beaker execution is a subcommand
23
27
  # @return [Boolean] true if argv[0] is "help" or a method defined in the Subcommands class, false otherwise
@@ -86,17 +90,20 @@ module Beaker
86
90
  execute_rake_task("beaker_quickstart:gen_hosts[vmpooler]")
87
91
  end
88
92
 
89
- # Print a message to the console and exit with 0
90
- # @param [String] msg the message to print
91
- def self.exit_with(msg)
93
+ # Print a message to the console and exit with specified exit code, defaults to 1
94
+ # @param [String] msg the message to output
95
+ # @param [Hash<Object>] options to specify exit code or output stack trace
96
+ def self.error_with(msg, options={})
92
97
  puts msg
93
- exit(0)
98
+ puts options[:stack_trace] if options[:stack_trace]
99
+ exit_code = options[:exit_code] ? options[:exit_code] : 1
100
+ exit(exit_code)
94
101
  end
95
102
 
96
103
  # Call the quick start task for the specified hypervisor
97
- # @param [Array<Object>] options the options we want to query
98
- def self.init_hypervisor(options)
99
- case options[:hypervisor]
104
+ # @param [String] hypervisor the hypervisor we want to query
105
+ def self.init_hypervisor(hypervisor)
106
+ case hypervisor
100
107
  when "vagrant"
101
108
  init_vagrant
102
109
  when "vmpooler"
@@ -104,6 +111,14 @@ module Beaker
104
111
  end
105
112
  end
106
113
 
114
+ # Verify that a valid hypervisor has been specified
115
+ # @param [String] hypervisor the hypervisor we want to validate
116
+ def self.verify_init_args(hypervisor)
117
+ unless HYPERVISORS.include?(hypervisor)
118
+ error_with("Invalid hypervisor. Currently supported hypervisors are: #{HYPERVISORS.join(', ')}")
119
+ end
120
+ end
121
+
107
122
  # Execute a task but capture stdout and stderr to a buffer
108
123
  def self.with_captured_output
109
124
  begin
@@ -117,6 +132,42 @@ module Beaker
117
132
  $stderr = old_stderr
118
133
  end
119
134
  end
135
+
136
+ # Initialise the beaker config
137
+ def self.init_config()
138
+ FileUtils.mkdir_p CONFIG_DIR
139
+ @@store = YAML::Store.new("#{CONFIG_DIR}/config")
140
+ end
141
+
142
+ # Store values from a hash into the beaker config
143
+ # @param [Hash{Symbol=>String}] config values we want to store
144
+ def self.store_config(config)
145
+ @@store.transaction do
146
+ CONFIG_KEYS.each do |key|
147
+ @@store[key] = config[key] unless config[key].nil?
148
+ end
149
+ end
150
+ end
151
+
152
+ # Delete keys from the beaker configi
153
+ # @param [Array<Object>] keys the keys we want to delete from the config
154
+ def self.delete_config(keys)
155
+ @@store.transaction {
156
+ keys.each do |key|
157
+ @@store.delete(key)
158
+ end
159
+ }
160
+ end
161
+
162
+ # Reset args and provision nodes
163
+ # @param [String] hypervisor the hypervisor to use
164
+ # @param [Array<Object>] options the options to use when provisioning
165
+ def self.provision(hypervisor, options)
166
+ reset_argv(["--hosts", "#{CONFIG_DIR}/acceptance/config/default_#{hypervisor}_hosts.yaml", "--validate", options[:validate], "--configure", options[:configure]])
167
+ beaker = Beaker::CLI.new.parse_options
168
+ beaker.provision
169
+ beaker.preserve_hosts_file
170
+ end
120
171
  end
121
172
  end
122
173
  end
@@ -1,5 +1,5 @@
1
1
  module Beaker
2
2
  module Version
3
- STRING = '3.12.0'
3
+ STRING = '3.13.0'
4
4
  end
5
5
  end
@@ -2,9 +2,52 @@ require 'spec_helper'
2
2
 
3
3
  module Beaker
4
4
  describe CLI do
5
+
6
+ context 'initializing and parsing' do
7
+ let( :cli ) {
8
+ Beaker::CLI.new
9
+ }
10
+
11
+ describe 'instance variable initialization' do
12
+ it 'creates a logger for use before parse is called' do
13
+ expect(Beaker::Logger).to receive(:new).once.and_call_original
14
+ expect(cli.logger).to be_instance_of(Beaker::Logger)
15
+ end
16
+
17
+ it 'generates the timestamp' do
18
+ expect(Time).to receive(:now).once
19
+ cli
20
+ end
21
+ end
22
+
23
+ describe '#parse_options' do
24
+ it 'returns self' do
25
+ expect(cli.parse_options).to be_instance_of(Beaker::CLI)
26
+ end
27
+
28
+ it 'replaces the logger object with a new one' do
29
+ expect(Beaker::Logger).to receive(:new).with(no_args).once.and_call_original
30
+ expect(Beaker::Logger).to receive(:new).once.and_call_original
31
+ cli.parse_options
32
+ end
33
+ end
34
+
35
+ describe '#print_version_and_options' do
36
+ before do
37
+ options = Beaker::Options::OptionsHash.new
38
+ options[:beaker_version] = 'version_number'
39
+ cli.instance_variable_set('@options', options)
40
+ end
41
+ it 'prints the version and dumps the options' do
42
+ expect(cli.logger).to receive(:info).exactly(3).times
43
+ cli.print_version_and_options
44
+ end
45
+ end
46
+ end
47
+
5
48
  let(:cli) {
6
49
  allow(File).to receive(:exists?).and_return(true)
7
- Beaker::CLI.new
50
+ Beaker::CLI.new.parse_options
8
51
  }
9
52
 
10
53
  context 'execute!' do
@@ -280,217 +280,4 @@ describe ClassMixedWithDSLStructure do
280
280
  end
281
281
  end
282
282
 
283
- describe '#tag' do
284
- let ( :tag_includes ) { @tag_includes || [] }
285
- let ( :tag_excludes ) { @tag_excludes || [] }
286
- let ( :options ) {
287
- opts = Beaker::Options::OptionsHash.new
288
- opts[:tag_includes] = tag_includes
289
- opts[:tag_excludes] = tag_excludes
290
- opts
291
- }
292
-
293
- before :each do
294
- allow( subject ).to receive( :platform_specific_tag_confines )
295
- end
296
-
297
- it 'sets tags on the TestCase\'s metadata object' do
298
- subject.instance_variable_set(:@options, options)
299
- tags = ['pants', 'jayjay', 'moguely']
300
- subject.tag(*tags)
301
- expect( metadata[:case][:tags] ).to be === tags
302
- end
303
-
304
- it 'lowercases the tags' do
305
- subject.instance_variable_set(:@options, options)
306
- tags_upper = ['pANTs', 'jAYJAy', 'moGUYly']
307
- tags_lower = tags_upper.map(&:downcase)
308
- subject.tag(*tags_upper)
309
- expect( metadata[:case][:tags] ).to be === tags_lower
310
- end
311
-
312
- it 'skips the test if any of the requested tags isn\'t included in this test' do
313
- test_tags = ['pants', 'jayjay', 'moguely']
314
- @tag_includes = test_tags.compact.push('needed_tag_not_in_test')
315
- subject.instance_variable_set(:@options, options)
316
-
317
- allow( subject ).to receive( :path )
318
- expect( subject ).to receive( :skip_test )
319
- subject.tag(*test_tags)
320
- end
321
-
322
- it 'runs the test if all requested tags are included in this test' do
323
- @tag_includes = ['pants_on_head', 'jayjay_jayjay', 'mo']
324
- test_tags = @tag_includes.compact.push('extra_asdf')
325
- subject.instance_variable_set(:@options, options)
326
-
327
- allow( subject ).to receive( :path )
328
- expect( subject ).to receive( :skip_test ).never
329
- subject.tag(*test_tags)
330
- end
331
-
332
- it 'skips the test if any of the excluded tags are included in this test' do
333
- test_tags = ['ports', 'jay_john_mary', 'mog_the_dog']
334
- @tag_excludes = [test_tags[0]]
335
- subject.instance_variable_set(:@options, options)
336
-
337
- allow( subject ).to receive( :path )
338
- expect( subject ).to receive( :skip_test )
339
- subject.tag(*test_tags)
340
- end
341
-
342
- it 'runs the test if none of the excluded tags are included in this test' do
343
- @tag_excludes = ['pants_on_head', 'jayjay_jayjay', 'mo']
344
- test_tags = ['pants_at_head', 'jayj00_jayjay', 'motly_crew']
345
- subject.instance_variable_set(:@options, options)
346
-
347
- allow( subject ).to receive( :path )
348
- expect( subject ).to receive( :skip_test ).never
349
- subject.tag(*test_tags)
350
- end
351
-
352
- end
353
- end
354
-
355
- describe Beaker::DSL::Structure::PlatformTagConfiner do
356
- let ( :confines_array ) { @confines_array || [] }
357
- let ( :confiner ) {
358
- Beaker::DSL::Structure::PlatformTagConfiner.new( confines_array )
359
- }
360
-
361
- describe '#initialize' do
362
- it 'transforms one entry' do
363
- platform_regex = /^ubuntu$/
364
- tag_reason_hash = {
365
- 'tag1' => 'reason1',
366
- 'tag2' => 'reason2'
367
- }
368
- @confines_array = [ {
369
- :platform => platform_regex,
370
- :tag_reason_hash => tag_reason_hash
371
- }
372
- ]
373
-
374
- internal_hash = confiner.instance_variable_get( :@tag_confine_details_hash )
375
- expect( internal_hash.keys() ).to include( 'tag1' )
376
- expect( internal_hash.keys() ).to include( 'tag2' )
377
- expect( internal_hash.keys().length() ).to be === 2
378
-
379
- tag_reason_hash.each do |tag, reason|
380
- tag_array = internal_hash[tag]
381
- expect( tag_array.length() ).to be === 1
382
- tag_hash = tag_array[0]
383
- expect( tag_hash[:platform_regex] ).to eql( platform_regex )
384
- expect( tag_hash[:log_message] ).to match( /#{reason}/ )
385
- expect( tag_hash[:type] ).to be === :except
386
- end
387
- end
388
-
389
- it 'deals with the same tag being used on multiple platforms correctly' do
390
- @confines_array = [
391
- {
392
- :platform => /^el-/,
393
- :tag_reason_hash => {
394
- 'tag1' => 'reason el 1',
395
- 'tag2' => 'reason2'
396
- }
397
- }, {
398
- :platform => /^cisco-/,
399
- :tag_reason_hash => {
400
- 'tag1' => 'reason cisco 1',
401
- 'tag3' => 'reason3'
402
- }
403
- }
404
- ]
405
-
406
- internal_hash = confiner.instance_variable_get( :@tag_confine_details_hash )
407
- expect( internal_hash.keys() ).to include( 'tag1' )
408
- expect( internal_hash.keys() ).to include( 'tag2' )
409
- expect( internal_hash.keys() ).to include( 'tag3' )
410
- expect( internal_hash.keys().length() ).to be === 3
411
-
412
- shared_tag_array = internal_hash['tag1']
413
- expect( shared_tag_array.length() ).to be === 2
414
-
415
- platform_el_found = false
416
- platform_cisco_found = false
417
- shared_tag_array.each do |confine_details|
418
- case confine_details[:log_message]
419
- when /\ el\ 1/
420
- platform_el_found = true
421
- platform_to_match = /^el-/
422
- reason_to_match = /reason\ el\ 1/
423
- when /\ cisco\ 1/
424
- platform_cisco_found = true
425
- platform_to_match = /^cisco-/
426
- reason_to_match = /reason\ cisco\ 1/
427
- else
428
- log_msg = "unexpected log message for confine_details: "
429
- log_msg << confine_details[:log_message]
430
- fail( log_msg )
431
- end
432
-
433
- expect( confine_details[:platform_regex] ).to eql( platform_to_match )
434
- expect( confine_details[:log_message] ).to match( reason_to_match )
435
- end
436
- expect( platform_el_found ).to be === true
437
- expect( platform_cisco_found ).to be === true
438
- end
439
- end
440
-
441
- describe '#confine_details' do
442
- it 'returns an empty array if no tags match' do
443
- fake_confine_details_hash = { 'tag1' => [ {:type => 1}, {:type => 2} ]}
444
- confiner.instance_variable_set(
445
- :@tag_confine_details_hash, fake_confine_details_hash
446
- )
447
- expect( confiner.confine_details( [ 'tag2', 'tag3' ] ) ).to be === []
448
- end
449
-
450
- context 'descriminates on tag name' do
451
- fake_confine_details_hash = {
452
- 'tag0' => [ 10, 20, 30, 40 ],
453
- 'tag1' => [ 41, 51, 61, 71 ],
454
- 'tag2' => [ 22, 32, 42, 52 ],
455
- 'tag3' => [ 63, 73, 83, 93 ],
456
- 'tag4' => [ 34, 44, 54, 64 ],
457
- }
458
-
459
- key_combos_to_test = fake_confine_details_hash.keys.map { |key| [key] }
460
- key_combos_to_test << [ 'tag0', 'tag2' ]
461
- key_combos_to_test << [ 'tag1', 'tag4' ]
462
- key_combos_to_test << [ 'tag2', 'tag3', 'tag4' ]
463
- key_combos_to_test << fake_confine_details_hash.keys()
464
-
465
- before :each do
466
- confiner.instance_variable_set(
467
- :@tag_confine_details_hash, fake_confine_details_hash
468
- )
469
- end
470
-
471
- key_combos_to_test.each do |key_combo_to_have|
472
- it "selects key(s) #{key_combo_to_have} from #{fake_confine_details_hash.keys}" do
473
- haves = []
474
- key_combo_to_have.each do |key_to_have|
475
- haves += fake_confine_details_hash[key_to_have]
476
- end
477
- keys_not_to_have = fake_confine_details_hash.keys.reject { |key_trial|
478
- key_combo_to_have.include?( key_trial )
479
- }
480
- have_nots = []
481
- keys_not_to_have.each do |key_not_to_have|
482
- have_nots += fake_confine_details_hash[key_not_to_have]
483
- end
484
-
485
- details = confiner.confine_details( key_combo_to_have )
486
- have_nots.each do |confine_details|
487
- expect( details ).to_not include( confine_details )
488
- end
489
- haves.each do |confine_details|
490
- expect( details ).to include( confine_details )
491
- end
492
- end
493
- end
494
- end
495
- end
496
- end
283
+ end