beaker 1.2.0 → 1.3.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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MWYxNzhkNWRkYTM2NzkxODFjODhjMDlhMmE2YWZhOWI0OWU1NjM3ZQ==
4
+ NzRhYTI0NDgzNDBlZWRjMWU3YzVlZGQyMTY0MGZiNzQ2M2I3NDljMg==
5
5
  data.tar.gz: !binary |-
6
- ZWM4OWNhOTU3NzRlZGU1ZmUzODkyN2M5MmI1ZTRmYWEzYmNlY2I5Mw==
6
+ NTE0ZTIyNGY4ZDc0NjZlYWJhNjc0YTQyZjA3NjVjM2U4OTdhZTlmYw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NmZiYzYyYWQ5MDY1NGE0MmI2ZjZhY2QxZWVkZmE4OTY0MWI0ZjA2MDlkYjQx
10
- ZTczY2E5ODUzMzcyY2QxNjg1YzllNjNiZDIzNjQwNDRlODRiNzJmMGZjZWY0
11
- YTI4ZGEyN2FjOWEzOGI1MDI3MmY2ZGE0Mzk5MDcwMDlhMzZmOTA=
9
+ MWQyNGMyM2EyNGRkNGY1NTYyNGQ0NjgxOGY3ZmE2NzhiM2ExNzVlMDYyMzg2
10
+ ZmE3Y2E3NzZkYmIyY2I0ZGZiYTk0ZDA3MGM2Y2RhOWI5MDQ2Y2Q2YjJkNzA1
11
+ NmI2MzI0ODQ2MDM4NWNmMjcwNmU1NTQyMTc4YTA4YjExNzdlYzE=
12
12
  data.tar.gz: !binary |-
13
- NzgxNDdiNjYyMDEwMTYzM2I0M2RlZWU2NmMzNTVhZGQxMGZkMWUzOGQ5Mjc0
14
- M2Q0YmIyMzZmOGQzZDVlYzZiMzRiOTJiZmQyYmJhNDJmNDhjMTczNjg4NDk1
15
- MmFhMjM1YjUwYzRmNTBkOTkxMDZiM2M2ZDM3OTE1YmRhYTNkMzI=
13
+ ZWJhMDExYmVmYTU0MzE0ZWJhZTUzODJjZDIxMjMwNTMyYjRkMTE4NTYyYTk4
14
+ NDQ5ZDI4NTA3NzI3YWMwM2MxYmQyZjRkNGZiZWNmNzFlZDFlMWI1ZTg4ZDNj
15
+ NzkyZDMzNGMzNmQwNjk2NDVmMDI5Mzk3OTNlMWIzMzNiOWJjMGE=
data/README.md CHANGED
@@ -101,7 +101,7 @@ Additionaly, Beaker supports the following host options:
101
101
  * snapshot
102
102
  * the name of the snapshot to revert to before testing
103
103
  * roles
104
- * the 'job' of this host, an array of `master`, `agent`, `dashboard`, `database`, `default` or any user-defined string
104
+ * the 'job' of this host, an array of `master`, `agent`, `frictionless`, `dashboard`, `database`, `default` or any user-defined string
105
105
  * pe_dir
106
106
  * the directory where PE builds are located, may be local directory or a URL
107
107
  * pe_ver
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "beaker"
5
- s.version = '1.2.0'
5
+ s.version = '1.3.0'
6
6
  s.authors = ["Puppetlabs"]
7
7
  s.email = ["delivery@puppetlabs.com"]
8
8
  s.homepage = "https://github.com/puppetlabs/beaker"
@@ -26,7 +26,7 @@ module Beaker
26
26
  @logger.notify(VERSION_STRING % spec.version)
27
27
  exit
28
28
  end
29
- @logger.notify(@options.dump)
29
+ @logger.info(@options.dump)
30
30
 
31
31
  #add additional paths to the LOAD_PATH
32
32
  if not @options[:load_path].empty?
@@ -646,14 +646,18 @@ module Beaker
646
646
  # @options opts [Hash] :environment Additional environment variables to be
647
647
  # passed to the 'puppet apply' command
648
648
  #
649
- # @option opts [Boolean] :catch_failures (false) By default
650
- # `puppet --apply` will exit with 0,
651
- # which does not count as a test
652
- # failure, even if there were errors applying
653
- # the manifest. This option enables detailed
654
- # exit codes and causes a test failure if
655
- # `puppet --apply` indicates there was a
656
- # failure during its execution.
649
+ # @option opts [Boolean] :catch_failures (false) By default `puppet
650
+ # --apply` will exit with 0, which does not count
651
+ # as a test failure, even if there were errors or
652
+ # changes when applying the manifest. This option
653
+ # enables detailed exit codes and causes a test
654
+ # failure if `puppet --apply` indicates there was
655
+ # a failure during its execution.
656
+ #
657
+ # @option opts [Boolean] :catch_changes (false) This option enables
658
+ # detailed exit codes and causes a test failure
659
+ # if `puppet --apply` indicates that there were
660
+ # changes or failures during its execution.
657
661
  #
658
662
  # @option opts [Boolean] :expect_failures (false) This option enables
659
663
  # detailed exit codes and causes a test failure
@@ -666,7 +670,7 @@ module Beaker
666
670
  #
667
671
  def apply_manifest_on(host, manifest, opts = {}, &block)
668
672
  on_options = {:stdin => manifest + "\n"}
669
- on_options[:acceptable_exit_codes] = Array(opts.delete(:acceptable_exit_codes))
673
+ on_options[:acceptable_exit_codes] = Array(opts.delete(:acceptable_exit_codes))
670
674
  args = ["--verbose"]
671
675
  args << "--parseonly" if opts[:parseonly]
672
676
  args << "--trace" if opts[:trace]
@@ -675,10 +679,15 @@ module Beaker
675
679
  # "... an exit code of '2' means there were changes, an exit code of
676
680
  # '4' means there were failures during the transaction, and an exit
677
681
  # code of '6' means there were both changes and failures."
678
- if opts[:catch_failures] and opts[:expect_failures]
679
- raise(ArgumentError, "Cannot specify both `catch_failures` and `expect_failures` for a single manifest")
682
+ if [opts[:catch_changes],opts[:catch_failures],opts[:expect_failures]].select{|x|x}.length > 1
683
+ raise(ArgumentError, "Cannot specify more than one of `catch_failures`, `catch_changes`, or `expect_failures` for a single manifest")
680
684
  end
681
- if opts[:catch_failures]
685
+ if opts[:catch_changes]
686
+ args << '--detailed-exitcodes'
687
+
688
+ # We're after idempotency so allow exit code 0 only.
689
+ on_options[:acceptable_exit_codes] |= [0]
690
+ elsif opts[:catch_failures]
682
691
  args << '--detailed-exitcodes'
683
692
 
684
693
  # We're after only complete success so allow exit codes 0 and 2 only.
@@ -878,7 +887,7 @@ module Beaker
878
887
  #
879
888
  # @param [Host] host The host to sign for
880
889
  #
881
- # @returns nil
890
+ # @return nil
882
891
  # @raise [FailTest] if process times out
883
892
  def sign_certificate_for(host)
884
893
  if [master, dashboard, database].include? host
@@ -916,7 +925,7 @@ module Beaker
916
925
  # @param [String] name The name of the fact to query for
917
926
  # @!macro common_opts
918
927
  #
919
- # @returns String The value of the fact 'name' on the provided host
928
+ # @return String The value of the fact 'name' on the provided host
920
929
  # @raise [FailTest] Raises an exception if call to facter fails
921
930
  def fact_on(host, name, opts = {})
922
931
  result = on host, facter(name, opts)
@@ -144,9 +144,11 @@ module Beaker
144
144
  if host['platform'] =~ /windows/
145
145
  version = options[:pe_ver_win] || host['pe_ver']
146
146
  "cd #{host['working_dir']} && msiexec.exe /qn /i puppet-enterprise-#{version}.msi"
147
- else
147
+ elsif host['roles'].include? 'frictionless'
148
148
  version = options[:pe_ver] || host['pe_ver']
149
- "cd #{host['working_dir']}/#{host['dist']} && ./#{options[:installer]}"
149
+ "cd #{host['working_dir']} && curl -kO https://#{master}:8140/packages/#{version}/#{host['platform']}.bash && bash #{host['platform']}.bash"
150
+ else
151
+ "cd #{host['working_dir']}/#{host['dist']} && ./#{options[:installer]} -a #{host['working_dir']}/answers"
150
152
  end
151
153
  end
152
154
 
@@ -178,6 +180,9 @@ module Beaker
178
180
  # @api private
179
181
  def fetch_puppet(hosts, options)
180
182
  hosts.each do |host|
183
+ # We install Puppet from the master for frictionless installs, so we don't need to *fetch* anything
184
+ next if host['roles'].include? 'frictionless'
185
+
181
186
  windows = host['platform'] =~ /windows/
182
187
  path = options[:pe_dir] || host['pe_dir']
183
188
  local = File.directory?(path)
@@ -262,10 +267,13 @@ module Beaker
262
267
  if host['platform'] =~ /windows/
263
268
  on host, "#{installer_cmd(host, options)} PUPPET_MASTER_SERVER=#{master} PUPPET_AGENT_CERTNAME=#{host}"
264
269
  else
265
- answers = Beaker::Answers.answers(options[:pe_ver] || host['pe_ver'], hosts, master_certname, options)
266
- create_remote_file host, "#{host['working_dir']}/answers", Beaker::Answers.answer_string(host, answers)
270
+ # We only need answers if we're using the classic installer
271
+ if ! host['roles'].include? 'frictionless'
272
+ answers = Beaker::Answers.answers(options[:pe_ver] || host['pe_ver'], hosts, master_certname, options)
273
+ create_remote_file host, "#{host['working_dir']}/answers", Beaker::Answers.answer_string(host, answers)
274
+ end
267
275
 
268
- on host, "#{installer_cmd(host, options)} -a #{host['working_dir']}/answers"
276
+ on host, installer_cmd(host, options)
269
277
  end
270
278
  end
271
279
 
@@ -133,8 +133,17 @@ module Beaker
133
133
 
134
134
  def vagrant_cmd(args)
135
135
  Dir.chdir(@vagrant_path) do
136
- run = system("vagrant #{args}")
137
- if not run
136
+ exit_status = 1
137
+ Open3.popen3("vagrant #{args}") {|stdin, stdout, stderr, wait_thr|
138
+ while line = stdout.gets
139
+ @logger.debug(line)
140
+ end
141
+ if not wait_thr.value.success?
142
+ raise "Failed to exec 'vagrant #{args}'"
143
+ end
144
+ exit_status = wait_thr.value
145
+ }
146
+ if exit_status != 0
138
147
  raise "Failed to execute vagrant_cmd ( #{args} )"
139
148
  end
140
149
  end
@@ -26,6 +26,31 @@ module Beaker
26
26
  raise 'You must specify a folder for vCloud instances!' unless @options['folder']
27
27
  end
28
28
 
29
+ def check_url url
30
+ begin
31
+ URI.parse(url)
32
+ rescue
33
+ return false
34
+ end
35
+ true
36
+ end
37
+
38
+ def get_template_url pooling_api, template
39
+ if not check_url(pooling_api)
40
+ raise ArgumentError, "Invalid pooling_api URL: #{pooling_api}"
41
+ end
42
+ scheme = ''
43
+ if not URI.parse(pooling_api).scheme
44
+ scheme = 'http://'
45
+ end
46
+ #check that you have a valid uri
47
+ template_url = scheme + pooling_api + '/vm/' + template
48
+ if not check_url(template_url)
49
+ raise ArgumentError, "Invalid full template URL: #{template_url}"
50
+ end
51
+ template_url
52
+ end
53
+
29
54
  def provision
30
55
  start = Time.now
31
56
  try = 1
@@ -38,7 +63,7 @@ module Beaker
38
63
  @logger.notify "Requesting '#{h['template']}' VM from vCloud host pool"
39
64
 
40
65
  begin
41
- uri = URI.parse(@options['pooling_api']+'/vm/'+h['template'])
66
+ uri = URI.parse(get_template_url(@options['pooling_api'], h['template']))
42
67
 
43
68
  http = Net::HTTP.new( uri.host, uri.port )
44
69
  request = Net::HTTP::Post.new(uri.request_uri)
@@ -78,7 +103,7 @@ module Beaker
78
103
  vm_names.each do |name|
79
104
  @logger.notify "Handing '#{name}' back to pooling API for VM destruction"
80
105
 
81
- uri = URI.parse(@options['pooling_api']+'/vm/'+name)
106
+ uri = URI.parse(get_template_url(@options['pooling_api'], name))
82
107
 
83
108
  http = Net::HTTP.new( uri.host, uri.port )
84
109
  request = Net::HTTP::Delete.new(uri.request_uri)
@@ -1,4 +1,8 @@
1
1
  module Beaker
2
+ # The Beaker Logger class
3
+ # This class handles message reporting for Beaker, it reports based upon a provided log level
4
+ # to a given destination (be it a string or file)
5
+ #
2
6
  class Logger
3
7
  NORMAL = "\e[00;00m"
4
8
  BRIGHT_NORMAL = "\e[00;01m"
@@ -19,19 +23,47 @@ module Beaker
19
23
  BRIGHT_CYAN = "\e[01;36m"
20
24
  BRIGHT_WHITE = "\e[01;37m"
21
25
 
26
+ # The defined log levels. Each log level also reports messages at levels lower than itself
22
27
  LOG_LEVELS = {
23
- :debug => 1,
24
- :warn => 2,
25
- :normal => 3,
26
- :info => 4
28
+ :debug => 5,
29
+ :verbose => 3,
30
+ :info => 2,
31
+ :notify => 1,
32
+ :warn => 0,
27
33
  }
28
34
 
29
35
  attr_accessor :color, :log_level, :destinations
30
36
 
37
+ # Initialization of the Logger class
38
+ # @overload initialize(dests)
39
+ # Initialize a Logger object that reports to the provided destinations, use default options
40
+ # @param [Array<String, IO>] Array of IO and strings (assumed to be file paths) to be reported to
41
+ # @overload initialize(dests, options)
42
+ # Initialize a Logger object that reports to the provided destinations, use options from provided option hash
43
+ # @param [Array<String, IO>] Array of IO and strings (assumed to be file paths) to be reported to
44
+ # @param [Hash] options Hash of options
45
+ # @option options [Boolean] :color (true) Print color code before log messages
46
+ # @option options [Boolean] :quiet (false) Do not log messages to STDOUT
47
+ # @option options [String] :log_level ("info") Log level (one of "debug" - highest level, "verbose", "info",
48
+ # "notify" and "warn" - lowest level (see {LOG_LEVELS})) The log level indicates that messages at that
49
+ # log_level and lower will be reported.
31
50
  def initialize(*args)
32
51
  options = args.last.is_a?(Hash) ? args.pop : {}
33
52
  @color = options[:color]
34
- @log_level = options[:debug] ? :debug : :normal
53
+ case options[:log_level]
54
+ when /debug/i
55
+ @log_level = :debug
56
+ when /verbose/i
57
+ @log_level = :verbose
58
+ when /info/i
59
+ @log_level = :info
60
+ when /notify/i
61
+ @log_level = :notify
62
+ when /warn/i
63
+ @log_level = :warn
64
+ else
65
+ @log_level = :info
66
+ end
35
67
  @destinations = []
36
68
 
37
69
  dests = args
@@ -40,6 +72,8 @@ module Beaker
40
72
  dests.each {|dest| add_destination(dest)}
41
73
  end
42
74
 
75
+ # Construct an array of open steams for printing log messages to
76
+ # @param [Array<IO, String>] dest Array of strings (each used as a file path) and IO steams that messages will be printed to
43
77
  def add_destination(dest)
44
78
  case dest
45
79
  when IO
@@ -51,6 +85,8 @@ module Beaker
51
85
  end
52
86
  end
53
87
 
88
+ # Remove a steam from the destinations array based upon it's name or file path
89
+ # @param [String, IO] dest String representing a file path or IO stream
54
90
  def remove_destination(dest)
55
91
  case dest
56
92
  when IO
@@ -62,14 +98,40 @@ module Beaker
62
98
  end
63
99
  end
64
100
 
101
+ # Are we at {LOG_LEVELS} debug?
102
+ # @return [Boolean] true if 'debug' or higher, false if not 'debug' {LOG_LEVELS} or lower
65
103
  def is_debug?
66
- LOG_LEVELS[@log_level] <= LOG_LEVELS[:debug]
104
+ LOG_LEVELS[@log_level] >= LOG_LEVELS[:debug]
105
+ end
106
+
107
+ # Are we at {LOG_LEVELS} verbose?
108
+ # @return [Boolean] true if 'verbose' or higher, false if not 'verbose' {LOG_LEVELS} or lower
109
+ def is_verbose?
110
+ LOG_LEVELS[@log_level] >= LOG_LEVELS[:verbose]
67
111
  end
68
112
 
113
+ # Are we at {LOG_LEVELS} warn?
114
+ # @return [Boolean] true if 'warn' or higher, false if not 'warn' {LOG_LEVELS} or lower
69
115
  def is_warn?
70
- LOG_LEVELS[@log_level] <= LOG_LEVELS[:warn]
116
+ LOG_LEVELS[@log_level] >= LOG_LEVELS[:warn]
117
+ end
118
+
119
+ # Are we at {LOG_LEVELS} info?
120
+ # @return [Boolean] true if 'info' or higher, false if not 'info' {LOG_LEVELS} or lower
121
+ def is_info?
122
+ LOG_LEVELS[@log_level] >= LOG_LEVELS[:info]
71
123
  end
72
124
 
125
+ # Are we at {LOG_LEVELS} notify?
126
+ # @return [Boolean] true if 'notify' or higher, false if not 'notify' {LOG_LEVELS} or lower
127
+ def is_notify?
128
+ LOG_LEVELS[@log_level] >= LOG_LEVELS[:notify]
129
+ end
130
+
131
+ # Custom reporting for messages generated by host SUTs.
132
+ # Will not print unless we are at {LOG_LEVELS} 'debug' or higher.
133
+ # Strips any color codes already in the provided messages, then adds logger color codes before reporting
134
+ # @param args[Array<String>] Strings to be reported
73
135
  def host_output *args
74
136
  return unless is_debug?
75
137
  strings = strip_colors_from args
@@ -77,35 +139,67 @@ module Beaker
77
139
  optionally_color GREY, string, false
78
140
  end
79
141
 
142
+ # Report a debug message.
143
+ # Will not print unless we are at {LOG_LEVELS} 'debug' or higher.
144
+ # @param args[Array<String>] Strings to be reported
80
145
  def debug *args
81
- return unless is_debug?
146
+ return unless is_verbose?
82
147
  optionally_color WHITE, args
83
148
  end
84
149
 
150
+ # Report a warning message.
151
+ # Will not print unless we are at {LOG_LEVELS} 'warn' or higher.
152
+ # Will pre-pend the message with "Warning: ".
153
+ # @param args[Array<String>] Strings to be reported
85
154
  def warn *args
86
155
  return unless is_warn?
87
156
  strings = args.map {|msg| "Warning: #{msg}" }
88
157
  optionally_color YELLOW, strings
89
158
  end
90
159
 
160
+ # Report an info message.
161
+ # Will not print unless we are at {LOG_LEVELS} 'info' or higher.
162
+ # @param args[Array<String>] Strings to be reported
163
+ def info *args
164
+ return unless is_info?
165
+ optionally_color BLUE, args
166
+ end
167
+
168
+ # Report a success message.
169
+ # Will always be reported.
170
+ # @param args[Array<String>] Strings to be reported
91
171
  def success *args
92
172
  optionally_color GREEN, args
93
173
  end
94
174
 
175
+ # Report a notify message.
176
+ # Will not print unless we are at {LOG_LEVELS} 'notify' or higher.
177
+ # @param args[Array<String>] Strings to be reported
95
178
  def notify *args
179
+ return unless is_notify?
96
180
  optionally_color BRIGHT_WHITE, args
97
181
  end
98
182
 
183
+ # Report an error message.
184
+ # Will always be reported.
185
+ # @param args[Array<String>] Strings to be reported
99
186
  def error *args
100
187
  optionally_color BRIGHT_RED, args
101
188
  end
102
189
 
190
+ # Strip any color codes from provided string(s)
191
+ # @param [String] lines A single or array of lines to removed color codes from
192
+ # @return [Array<String>] An array of strings that do not have color codes
103
193
  def strip_colors_from lines
104
194
  Array(lines).map do |line|
105
195
  line.gsub /\e\[(\d+;)?\d+m/, ''
106
196
  end
107
197
  end
108
198
 
199
+ # Print the provided message to the set destination streams, using color codes if appropriate
200
+ # @param [String] color_code The color code to pre-pend to the message
201
+ # @param [String] msg The message to be reported
202
+ # @param [Boolean] add_newline (true) Add newlines between the color codes and the message
109
203
  def optionally_color color_code, msg, add_newline = true
110
204
  print_statement = add_newline ? :puts : :print
111
205
  @destinations.each do |to|
@@ -115,15 +209,22 @@ module Beaker
115
209
  end
116
210
  end
117
211
 
118
- # utility method to get the current call stack and format it
212
+ # Utility method to get the current call stack and format it
119
213
  # to a human-readable string (which some IDEs/editors
120
- # will recognize as links to the line numbers in the trace)
214
+ # will recognize as links to the line numbers in the trace).
215
+ # Beaker associated files will be purged from backtrace unless log level is 'debug' or higher
216
+ # @param [String] backtrace (caller(1)) The backtrace to format
217
+ # @return [String] The formatted backtrace
121
218
  def pretty_backtrace backtrace = caller(1)
122
- trace = purge_harness_files_from( Array( backtrace ) )
219
+ trace = is_debug? ? backtrace : purge_harness_files_from( backtrace )
123
220
  expand_symlinks( trace ).join "\n"
124
221
  end
125
222
 
126
- private
223
+ private
224
+ # Expand each symlink found to its full path
225
+ # Lines are assumed to be in the format "String : Integer"
226
+ # @param [String] backtrace The string to search and expand symlinks in
227
+ # @return [String] The backtrace with symlinks expanded
127
228
  def expand_symlinks backtrace
128
229
  backtrace.collect do |line|
129
230
  file_path, line_num = line.split( ":" )
@@ -132,6 +233,9 @@ module Beaker
132
233
  end
133
234
  end
134
235
 
236
+ # Remove Beaker associated lines from a given String
237
+ # @param [String] backtrace The string to remove Beaker associated lines from
238
+ # @return [String] The cleaned backtrace
135
239
  def purge_harness_files_from backtrace
136
240
  mostly_purged = backtrace.reject do |line|
137
241
  # LOADED_FEATURES is an array of anything `require`d, i.e. everything
@@ -145,9 +249,11 @@ module Beaker
145
249
  completely_purged = mostly_purged.reject {|line| line.include? $0 }
146
250
  end
147
251
 
148
- # utility method that takes a path as input, checks each component
252
+ # Utility method that takes a path as input, checks each component
149
253
  # of the path to see if it is a symlink, and expands
150
- # it if it is. returns the expanded path.
254
+ # it if it is.
255
+ # @param [String] file_path The path to be examined
256
+ # @return [String] The fully expanded file_path
151
257
  def expand_symlink file_path
152
258
  file_path.split( "/" ).inject do |full_path, next_dir|
153
259
  next_path = full_path + "/" + next_dir
@@ -118,10 +118,21 @@ module Beaker
118
118
  @cmd_options[:color] = bool
119
119
  end
120
120
 
121
+ opts.on '--log-level LEVEL',
122
+ 'Log level',
123
+ 'Supported LEVEL keywords:',
124
+ 'debug : all messages, plus full stack trace of errors',
125
+ 'verbose : all messages',
126
+ 'info : info messages, notifications and warnings',
127
+ 'notify : notifications and warnings',
128
+ 'warn : warnings only',
129
+ '(default: info)' do |val|
130
+ @cmd_options[:log_level] = val
131
+ end
132
+
121
133
  opts.on '--[no-]debug',
122
- 'Enable full debugging',
123
- '(default: false)' do |bool|
124
- @cmd_options[:debug] = bool
134
+ 'DEPRECATED, use --log-level' do |bool|
135
+ @cmd_options[:log_level] = bool ? 'debug' : 'info'
125
136
  end
126
137
 
127
138
  opts.on '-d', '--[no-]dry-run',
@@ -80,7 +80,7 @@ module Beaker
80
80
  if discover_files.empty?
81
81
  parser_error "empty directory used as an option (#{root})!"
82
82
  end
83
- files += discover_files
83
+ files += discover_files.sort
84
84
  end
85
85
  end
86
86
  end
@@ -269,6 +269,9 @@ module Beaker
269
269
  if role_array.include?('master')
270
270
  master += 1
271
271
  end
272
+ if role_array.include?('frictionless') and !(role_array & ['master', 'database', 'dashboard', 'console']).empty?
273
+ parser_error "Only agent nodes may have the role 'frictionless', fix #{@options[:hosts_file]}"
274
+ end
272
275
  end
273
276
  if master > 1 or master < 1
274
277
  parser_error "One and only one host/node may have the role 'master', fix #{@options[:hosts_file]}"
@@ -29,6 +29,7 @@ module Beaker
29
29
  def self.presets
30
30
  h = Beaker::Options::OptionsHash.new
31
31
  h.merge({
32
+ :log_level => 'info',
32
33
  :hosts_file => 'sample.cfg',
33
34
  :options_file => nil,
34
35
  :type => 'pe',
@@ -38,7 +39,6 @@ module Beaker
38
39
  :quiet => false,
39
40
  :xml => false,
40
41
  :color => true,
41
- :debug => false,
42
42
  :dry_run => false,
43
43
  :timeout => 300,
44
44
  :fail_mode => nil,
@@ -30,7 +30,6 @@ module Beaker
30
30
 
31
31
  report_and_raise(@logger, RuntimeError.new("#{@name}: no test files found..."), "TestSuite: initialize") if @test_files.empty?
32
32
 
33
- @test_files = @test_files.sort
34
33
  rescue => e
35
34
  report_and_raise(@logger, e, "TestSuite: initialize")
36
35
  end
@@ -340,6 +340,25 @@ describe ClassMixedWithDSLHelpers do
340
340
  :trace => true,
341
341
  :catch_failures => true )
342
342
  end
343
+ it 'enforces a 0 exit code through :catch_changes' do
344
+ subject.should_receive( :puppet ).
345
+ with( 'apply', '--verbose', '--trace', '--detailed-exitcodes' ).
346
+ and_return( 'puppet_command' )
347
+
348
+ subject.should_receive( :on ).with(
349
+ 'my_host',
350
+ 'puppet_command',
351
+ :acceptable_exit_codes => [0],
352
+ :stdin => "class { \"boo\": }\n"
353
+ )
354
+
355
+ subject.apply_manifest_on(
356
+ 'my_host',
357
+ 'class { "boo": }',
358
+ :trace => true,
359
+ :catch_changes => true
360
+ )
361
+ end
343
362
  it 'enforces exit codes through :expect_failures' do
344
363
  subject.should_receive( :puppet ).
345
364
  with( 'apply', '--verbose', '--trace', '--detailed-exitcodes' ).
@@ -130,7 +130,7 @@ describe ClassMixedWithDSLInstallUtils do
130
130
  end
131
131
 
132
132
  it 'generates a unix PE install command for a unix host' do
133
- expect( subject.installer_cmd( unixhost, { :installer => 'puppet-enterprise-installer' } ) ).to be === "cd /tmp/puppet-enterprise-3.1.0-rc0-230-g36c9e5c-debian-7-i386 && ./puppet-enterprise-installer"
133
+ expect( subject.installer_cmd( unixhost, { :installer => 'puppet-enterprise-installer' } ) ).to be === "cd /tmp/puppet-enterprise-3.1.0-rc0-230-g36c9e5c-debian-7-i386 && ./puppet-enterprise-installer -a /tmp/answers"
134
134
  end
135
135
  end
136
136
 
@@ -199,6 +199,14 @@ describe ClassMixedWithDSLInstallUtils do
199
199
  subject.fetch_puppet( [winhost], {} )
200
200
 
201
201
  end
202
+
203
+ it "does nothing for a frictionless agent" do
204
+ unixhost['roles'] << 'frictionless'
205
+
206
+ subject.should_not_receive(:scp_to)
207
+ subject.should_not_receive(:on)
208
+ subject.fetch_puppet( [unixhost], {} )
209
+ end
202
210
  end
203
211
 
204
212
  describe 'do_install' do
@@ -15,6 +15,32 @@ module Beaker
15
15
  Socket.stub( :getaddrinfo ).and_return( true )
16
16
  end
17
17
 
18
+ describe '#get_template_url' do
19
+
20
+ it 'works returns the valid url when passed valid pooling_api and template name' do
21
+ vcloud = Beaker::VcloudPooled.new( make_hosts, make_opts )
22
+ uri = vcloud.get_template_url("http://pooling.com", "template")
23
+ expect( uri ).to be === "http://pooling.com/vm/template"
24
+ end
25
+
26
+ it 'adds a missing scheme to a given URL' do
27
+ vcloud = Beaker::VcloudPooled.new( make_hosts, make_opts )
28
+ uri = vcloud.get_template_url("pooling.com", "template")
29
+ expect( URI.parse(uri).scheme ).to_not be === nil
30
+ end
31
+
32
+ it 'raises an error on an invalid pooling api url' do
33
+ vcloud = Beaker::VcloudPooled.new( make_hosts, make_opts )
34
+ expect{ vcloud.get_template_url("pooling### ", "template")}.to raise_error ArgumentError
35
+ end
36
+
37
+ it 'raises an error on an invalide template name' do
38
+ vcloud = Beaker::VcloudPooled.new( make_hosts, make_opts )
39
+ expect{ vcloud.get_template_url("pooling.com", "t!e&m*p(l\\a/t e")}.to raise_error ArgumentError
40
+ end
41
+
42
+ end
43
+
18
44
  describe "#provision" do
19
45
 
20
46
  it 'provisions hosts from the pool' do
@@ -16,7 +16,7 @@ module Beaker
16
16
  context 'default for' do
17
17
  its(:destinations) { should include(STDOUT) }
18
18
  its(:color) { should be_nil }
19
- its(:log_level) { should be :normal }
19
+ its(:log_level) { should be :info }
20
20
  end
21
21
  end
22
22
 
@@ -57,7 +57,7 @@ module Beaker
57
57
 
58
58
  context 'at debug log_level' do
59
59
  subject( :debug_logger ) { Logger.new( my_io,
60
- :debug => true,
60
+ :log_level => 'debug',
61
61
  :quiet => true,
62
62
  :color => true )
63
63
  }
@@ -80,14 +80,13 @@ module Beaker
80
80
  end
81
81
  end
82
82
 
83
- context 'at normal log_level' do
84
- subject( :normal_logger ) { Logger.new( my_io,
83
+ context 'at info log_level' do
84
+ subject( :info_logger ) { Logger.new( my_io,
85
85
  :quiet => true,
86
86
  :color => true )
87
87
  }
88
88
 
89
89
  its( :is_debug? ) { should be_false }
90
- its( :is_warn? ) { should be_false }
91
90
 
92
91
 
93
92
  context 'skip' do
@@ -96,8 +95,7 @@ module Beaker
96
95
  my_io.should_not_receive :print
97
96
  end
98
97
 
99
- it( 'warnings' ) { normal_logger.warn 'NOT A WARNING!' }
100
- it( 'debugs' ) { normal_logger.debug 'NOT DEBUGGING!' }
98
+ it( 'debugs' ) { info_logger.debug 'NOT DEBUGGING!' }
101
99
  end
102
100
 
103
101
 
@@ -107,9 +105,9 @@ module Beaker
107
105
  my_io.should_receive( :print ).twice
108
106
  end
109
107
 
110
- it( 'successes' ) { normal_logger.success 'SUCCESS!' }
111
- it( 'notifications' ) { normal_logger.notify 'NOTFIY!' }
112
- it( 'errors' ) { normal_logger.error 'ERROR!' }
108
+ it( 'successes' ) { info_logger.success 'SUCCESS!' }
109
+ it( 'notifications' ) { info_logger.notify 'NOTFIY!' }
110
+ it( 'errors' ) { info_logger.error 'ERROR!' }
113
111
  end
114
112
  end
115
113
  end
@@ -6,14 +6,14 @@ module Beaker
6
6
 
7
7
  let(:parser) {Beaker::Options::CommandLineParser.new}
8
8
  let(:test_opts) {["-h", "vcloud.cfg", "--debug", "--tests", "test.rb", "--help"]}
9
- let(:full_opts) {["--hosts", "host.cfg", "--options", "opts_file", "--type", "pe", "--helper", "path_to_helper", "--load-path", "load_path", "--tests", "test1.rb,test2.rb,test3.rb", "--pre-suite", "pre_suite.rb", "--post-suite", "post_suite.rb", "--no-provision", "--preserve-hosts", "--root-keys", "--keyfile", "../.ssh/id_rsa", "--install", "gitrepopath", "-m", "module", "-q", "--no-xml", "--dry-run", "--no-ntp", "--repo-proxy", "--add-el-extras", "--config", "anotherfile.cfg", "--fail-mode", "fast", "--no-color", "--version"]}
9
+ let(:full_opts) {["--hosts", "host.cfg", "--options", "opts_file", "--type", "pe", "--helper", "path_to_helper", "--load-path", "load_path", "--tests", "test1.rb,test2.rb,test3.rb", "--pre-suite", "pre_suite.rb", "--post-suite", "post_suite.rb", "--no-provision", "--preserve-hosts", "--root-keys", "--keyfile", "../.ssh/id_rsa", "--install", "gitrepopath", "-m", "module", "-q", "--no-xml", "--dry-run", "--no-ntp", "--repo-proxy", "--add-el-extras", "--config", "anotherfile.cfg", "--fail-mode", "fast", "--no-color", "--version", "--log-level", "info"]}
10
10
 
11
11
  it "can correctly read command line input" do
12
- expect(parser.parse!(test_opts)).to be === {:hosts_file=>"vcloud.cfg", :debug=>true, :tests=>"test.rb", :help=>true}
12
+ expect(parser.parse!(test_opts)).to be === {:hosts_file=>"vcloud.cfg", :log_level=>"debug", :tests=>"test.rb", :help=>true}
13
13
  end
14
14
 
15
15
  it "supports all our command line options" do
16
- expect(parser.parse!(full_opts)).to be === {:hosts_file=>"anotherfile.cfg", :options_file=>"opts_file", :type=>"pe", :helper=>"path_to_helper", :load_path=>"load_path", :tests=>"test1.rb,test2.rb,test3.rb", :pre_suite=>"pre_suite.rb", :post_suite=>"post_suite.rb", :provision=>false, :preserve_hosts=>true, :root_keys=>true, :keyfile=>"../.ssh/id_rsa", :install=>"gitrepopath", :modules=>"module", :quiet=>true, :xml=>false, :dry_run=>true, :timesync=>false, :repo_proxy=>true, :add_el_extras=>true, :fail_mode=>"fast", :color=>false, :version=>true}
16
+ expect(parser.parse!(full_opts)).to be === {:hosts_file=>"anotherfile.cfg", :options_file=>"opts_file", :type=>"pe", :helper=>"path_to_helper", :load_path=>"load_path", :tests=>"test1.rb,test2.rb,test3.rb", :pre_suite=>"pre_suite.rb", :post_suite=>"post_suite.rb", :provision=>false, :preserve_hosts=>true, :root_keys=>true, :keyfile=>"../.ssh/id_rsa", :install=>"gitrepopath", :modules=>"module", :quiet=>true, :xml=>false, :dry_run=>true, :timesync=>false, :repo_proxy=>true, :add_el_extras=>true, :fail_mode=>"fast", :color=>false, :version=>true, :log_level=>"info"}
17
17
  end
18
18
 
19
19
  it "can produce a usage description" do
@@ -44,23 +44,23 @@ module Beaker
44
44
  #test parse_install_options
45
45
  it "can transform --install PUPPET/3.1 into #{repo}/puppet.git#3.1" do
46
46
  opts = ["PUPPET/3.1"]
47
- expect(parser.parse_git_repos(opts)).to be === ["#{repo}/puppet.git#3.1"]
47
+ expect(parser.parse_git_repos(opts)).to be === ["#{repo}/puppet.git#3.1"]
48
48
  end
49
49
  it "can transform --install FACTER/v.1.0 into #{repo}/facter.git#v.1.0" do
50
50
  opts = ["FACTER/v.1.0"]
51
- expect(parser.parse_git_repos(opts)).to be === ["#{repo}/facter.git#v.1.0"]
51
+ expect(parser.parse_git_repos(opts)).to be === ["#{repo}/facter.git#v.1.0"]
52
52
  end
53
53
  it "can transform --install HIERA/xyz into #{repo}/hiera.git#xyz" do
54
54
  opts = ["HIERA/xyz"]
55
- expect(parser.parse_git_repos(opts)).to be === ["#{repo}/hiera.git#xyz"]
55
+ expect(parser.parse_git_repos(opts)).to be === ["#{repo}/hiera.git#xyz"]
56
56
  end
57
57
  it "can transform --install HIERA-PUPPET/path/to/repo into #{repo}/hiera-puppet.git#path/to/repo" do
58
58
  opts = ["HIERA-PUPPET/path/to/repo"]
59
- expect(parser.parse_git_repos(opts)).to be === ["#{repo}/hiera-puppet.git#path/to/repo"]
59
+ expect(parser.parse_git_repos(opts)).to be === ["#{repo}/hiera-puppet.git#path/to/repo"]
60
60
  end
61
61
  it "can transform --install PUPPET/3.1,FACTER/v.1.0 into #{repo}/puppet.git#3.1,#{repo}/facter.git#v.1.0" do
62
62
  opts = ["PUPPET/3.1", "FACTER/v.1.0"]
63
- expect(parser.parse_git_repos(opts)).to be === ["#{repo}/puppet.git#3.1", "#{repo}/facter.git#v.1.0"]
63
+ expect(parser.parse_git_repos(opts)).to be === ["#{repo}/puppet.git#3.1", "#{repo}/facter.git#v.1.0"]
64
64
  end
65
65
  it "can leave --install git://github.com/puppetlabs/puppet.git#my/full/path alone" do
66
66
  opts = ["git://github.com/puppetlabs/puppet.git#my/full/path"]
@@ -98,7 +98,7 @@ module Beaker
98
98
  it 'raises an error when no ruby files are found' do
99
99
  @files = [ pl_test, sh_test ]
100
100
  paths
101
- expect{parser.file_list([File.expand_path(test_dir)])}.to raise_error(ArgumentError)
101
+ expect{parser.file_list([File.expand_path(test_dir)])}.to raise_error(ArgumentError)
102
102
  end
103
103
  it 'raises an error when no paths are specified for searching' do
104
104
  @files = ''
@@ -107,6 +107,40 @@ module Beaker
107
107
 
108
108
  end
109
109
 
110
+ context 'combining split_arg and file_list maintain test file ordering', :use_fakefs => true do
111
+ let(:test_dir) { 'tmp/tests/' }
112
+ let(:other_test_dir) {'tmp/tests2/' }
113
+
114
+ before :each do
115
+ @files = ['00_EnvSetup.rb', '035_StopFirewall.rb', '05_HieraSetup.rb', '01_TestSetup.rb', '03_PuppetMasterSanity.rb', '06_InstallModules.rb', '02_PuppetUserAndGroup.rb', '04_ValidateSignCert.rb', '07_InstallCACerts.rb'].shuffle!.map!{|x| test_dir + x }
116
+ @other_files = ['00_EnvSetup.rb', '035_StopFirewall.rb', '05_HieraSetup.rb', '01_TestSetup.rb', '03_PuppetMasterSanity.rb', '06_InstallModules.rb', '02_PuppetUserAndGroup.rb', '04_ValidateSignCert.rb', '07_InstallCACerts.rb'].shuffle!.map!{|x| other_test_dir + x }
117
+ create_files(@files)
118
+ create_files(@other_files)
119
+ create_files(['08_foss.rb'])
120
+ end
121
+
122
+ it "when provided a file followed by dir, runs the file first" do
123
+ arg = "08_foss.rb,#{test_dir}"
124
+ expect(parser.file_list(parser.split_arg(arg))).to be === ["08_foss.rb", "#{File.expand_path(test_dir)}/00_EnvSetup.rb", "#{File.expand_path(test_dir)}/01_TestSetup.rb", "#{File.expand_path(test_dir)}/02_PuppetUserAndGroup.rb", "#{File.expand_path(test_dir)}/035_StopFirewall.rb", "#{File.expand_path(test_dir)}/03_PuppetMasterSanity.rb", "#{File.expand_path(test_dir)}/04_ValidateSignCert.rb", "#{File.expand_path(test_dir)}/05_HieraSetup.rb", "#{File.expand_path(test_dir)}/06_InstallModules.rb", "#{File.expand_path(test_dir)}/07_InstallCACerts.rb"]
125
+ end
126
+
127
+ it "when provided a dir followed by a file, runs the file last" do
128
+ arg = "#{test_dir},08_foss.rb"
129
+ expect(parser.file_list(parser.split_arg(arg))).to be === ["#{File.expand_path(test_dir)}/00_EnvSetup.rb", "#{File.expand_path(test_dir)}/01_TestSetup.rb", "#{File.expand_path(test_dir)}/02_PuppetUserAndGroup.rb", "#{File.expand_path(test_dir)}/035_StopFirewall.rb", "#{File.expand_path(test_dir)}/03_PuppetMasterSanity.rb", "#{File.expand_path(test_dir)}/04_ValidateSignCert.rb", "#{File.expand_path(test_dir)}/05_HieraSetup.rb", "#{File.expand_path(test_dir)}/06_InstallModules.rb", "#{File.expand_path(test_dir)}/07_InstallCACerts.rb", "08_foss.rb"]
130
+ end
131
+
132
+ it "correctly orders files in a directory" do
133
+ arg = "#{test_dir}"
134
+ expect(parser.file_list(parser.split_arg(arg))).to be === ["#{File.expand_path(test_dir)}/00_EnvSetup.rb", "#{File.expand_path(test_dir)}/01_TestSetup.rb", "#{File.expand_path(test_dir)}/02_PuppetUserAndGroup.rb", "#{File.expand_path(test_dir)}/035_StopFirewall.rb", "#{File.expand_path(test_dir)}/03_PuppetMasterSanity.rb", "#{File.expand_path(test_dir)}/04_ValidateSignCert.rb", "#{File.expand_path(test_dir)}/05_HieraSetup.rb", "#{File.expand_path(test_dir)}/06_InstallModules.rb", "#{File.expand_path(test_dir)}/07_InstallCACerts.rb"]
135
+ end
136
+
137
+ it "when provided two directories orders each directory separately" do
138
+ arg = "#{test_dir}/,#{other_test_dir}/"
139
+ expect(parser.file_list(parser.split_arg(arg))).to be === ["#{File.expand_path(test_dir)}/00_EnvSetup.rb", "#{File.expand_path(test_dir)}/01_TestSetup.rb", "#{File.expand_path(test_dir)}/02_PuppetUserAndGroup.rb", "#{File.expand_path(test_dir)}/035_StopFirewall.rb", "#{File.expand_path(test_dir)}/03_PuppetMasterSanity.rb", "#{File.expand_path(test_dir)}/04_ValidateSignCert.rb", "#{File.expand_path(test_dir)}/05_HieraSetup.rb", "#{File.expand_path(test_dir)}/06_InstallModules.rb", "#{File.expand_path(test_dir)}/07_InstallCACerts.rb", "#{File.expand_path(other_test_dir)}/00_EnvSetup.rb", "#{File.expand_path(other_test_dir)}/01_TestSetup.rb", "#{File.expand_path(other_test_dir)}/02_PuppetUserAndGroup.rb", "#{File.expand_path(other_test_dir)}/035_StopFirewall.rb", "#{File.expand_path(other_test_dir)}/03_PuppetMasterSanity.rb", "#{File.expand_path(other_test_dir)}/04_ValidateSignCert.rb", "#{File.expand_path(other_test_dir)}/05_HieraSetup.rb", "#{File.expand_path(other_test_dir)}/06_InstallModules.rb", "#{File.expand_path(other_test_dir)}/07_InstallCACerts.rb"]
140
+ end
141
+
142
+ end
143
+
110
144
  #test yaml file checking
111
145
  it "raises error on improperly formatted yaml file" do
112
146
  FakeFS.deactivate!
@@ -119,19 +153,19 @@ module Beaker
119
153
 
120
154
  it "can correctly combine arguments from different sources" do
121
155
  FakeFS.deactivate!
122
- args = ["-h", hosts_path, "--debug", "--type", "git", "--install", "PUPPET/1.0,HIERA/hello"]
123
- expect(parser.parse_args(args)).to be === {:hosts_file=>hosts_path, :options_file=>nil, :type=>"git", :provision=>true, :preserve_hosts=>false, :root_keys=>false, :quiet=>false, :xml=>false, :color=>true, :debug=>true, :dry_run=>false, :timeout=>300, :fail_mode=>nil, :timesync=>false, :repo_proxy=>false, :add_el_extras=>false, :consoleport=>443, :pe_dir=>"/opt/enterprise/dists", :pe_version_file=>"LATEST", :pe_version_file_win=>"LATEST-win", :dot_fog=>"#{home}/.fog", :help=>false, :ec2_yaml=>"config/image_templates/ec2.yaml", :ssh=>{:config=>false, :paranoid=>false, :timeout=>300, :auth_methods=>["publickey"], :port=>22, :forward_agent=>true, :keys=>["#{home}/.ssh/id_rsa"], :user_known_hosts_file=>"#{home}/.ssh/known_hosts"}, :install=>["git://github.com/puppetlabs/puppet.git#1.0", "git://github.com/puppetlabs/hiera.git#hello"], :HOSTS=>{:"pe-ubuntu-lucid"=>{:roles=>["agent", "dashboard", "database", "master"], :vmname=>"pe-ubuntu-lucid", :platform=>"ubuntu-10.04-i386", :snapshot=>"clean-w-keys", :hypervisor=>"fusion"}, :"pe-centos6"=>{:roles=>["agent"], :vmname=>"pe-centos6", :platform=>"el-6-i386", :hypervisor=>"fusion", :snapshot=>"clean-w-keys"}}, :nfs_server=>"none", :helper=>[], :load_path=>[], :tests=>[], :pre_suite=>[], :post_suite=>[], :modules=>[]}
156
+ args = ["-h", hosts_path, "--log-level", "debug", "--type", "git", "--install", "PUPPET/1.0,HIERA/hello"]
157
+ expect(parser.parse_args(args)).to be === {:log_level=>"debug", :hosts_file=>hosts_path, :options_file=>nil, :type=>"git", :provision=>true, :preserve_hosts=>false, :root_keys=>false, :quiet=>false, :xml=>false, :color=>true, :dry_run=>false, :timeout=>300, :fail_mode=>nil, :timesync=>false, :repo_proxy=>false, :add_el_extras=>false, :consoleport=>443, :pe_dir=>"/opt/enterprise/dists", :pe_version_file=>"LATEST", :pe_version_file_win=>"LATEST-win", :dot_fog=>"#{home}/.fog", :help=>false, :ec2_yaml=>"config/image_templates/ec2.yaml", :ssh=>{:config=>false, :paranoid=>false, :timeout=>300, :auth_methods=>["publickey"], :port=>22, :forward_agent=>true, :keys=>["#{home}/.ssh/id_rsa"], :user_known_hosts_file=>"#{home}/.ssh/known_hosts"}, :install=>["git://github.com/puppetlabs/puppet.git#1.0", "git://github.com/puppetlabs/hiera.git#hello"], :HOSTS=>{:"pe-ubuntu-lucid"=>{:roles=>["agent", "dashboard", "database", "master"], :vmname=>"pe-ubuntu-lucid", :platform=>"ubuntu-10.04-i386", :snapshot=>"clean-w-keys", :hypervisor=>"fusion"}, :"pe-centos6"=>{:roles=>["agent"], :vmname=>"pe-centos6", :platform=>"el-6-i386", :hypervisor=>"fusion", :snapshot=>"clean-w-keys"}}, :nfs_server=>"none", :helper=>[], :load_path=>[], :tests=>[], :pre_suite=>[], :post_suite=>[], :modules=>[]}
124
158
  end
125
159
 
126
160
  it "ensures that file-mode is one of fast/stop" do
127
161
  FakeFS.deactivate!
128
- args = ["-h", hosts_path, "--debug", "--fail-mode", "slow"]
162
+ args = ["-h", hosts_path, "--log-level", "debug", "--fail-mode", "slow"]
129
163
  expect{parser.parse_args(args)}.to raise_error(ArgumentError)
130
164
  end
131
165
 
132
166
  it "ensures that type is one of pe/git" do
133
167
  FakeFS.deactivate!
134
- args = ["-h", hosts_path, "--debug", "--type", "unkowns"]
168
+ args = ["-h", hosts_path, "--log-level", "debug", "--type", "unkowns"]
135
169
  expect{parser.parse_args(args)}.to raise_error(ArgumentError)
136
170
  end
137
171
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beaker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppetlabs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-06 00:00:00.000000000 Z
11
+ date: 2013-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec