beaker 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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