beaker-hostgenerator 0.9.0 → 0.10.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
- ODVjZTk2ZjQxN2JkMDlkYTMyNDQ3OTU2YTNkNTcyMjQ3MzYyNGQ4Nw==
4
+ OGJmOWNmNjhmMDYwZTBmNjJlMzgxYzk1MjgwNDZmZGVlNDFkZjcxMw==
5
5
  data.tar.gz: !binary |-
6
- MmYzZjJhNWEwYmViZTU2MjY3YmM3MDFjZDE1ODA4OGIwY2ZmMWQxNg==
6
+ MmY3ZGU0MzczN2EyODJlYzgyYzUzMzFmZDIyZmJmNTNiZmE3NjNkNA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YWM2ZjI2MGQ2ODI4MTc1YWY2OTNkZDYxN2E5ZjkwZmQ3NmZlMGUwNjk0Yzg1
10
- YWJjOTc4MWRkYmJiNzA3MGQyNDBmMDE3OGMyN2UzYWUwZWM3NTc5MGE2OWIx
11
- NzJhMmJmYzU4NjYwNmZjYjU0ZGI0ZWJkNWRhNmE1ZGEwODIzNjE=
9
+ NmUxMGVjZTdkODM3ZjM4MDVkMmFkMDlkMjM3Mjk4MTg2ZTY5MDc1NWIxMWI5
10
+ M2ViNGJiMGYwMGNhOTc0MjE1N2MwOWE1NzEwZTU0NGJkZTZmYTRmYmJiZGNk
11
+ MjhiNDZhYmJjOTk4ODcxODk0M2MyMmQ5NTE4ODQ5MjJlMTI5OTk=
12
12
  data.tar.gz: !binary |-
13
- NDIzMzJiZjE2ZDEyNTQxNDIyZDI5MGE4ZThhMGNhNDY2OTc3OWYwYTNkY2Qw
14
- ZDFjYzBkMDlkYTkxMWQwOWFjNWE4MWEwMTVlODk2NjIxYzY0MzI4ZmNjOWQ0
15
- YWUxYjVmY2NkZDFlZjU1YzNlYzkwZjI1NmQzMDQzZGU0ZGEyZWE=
13
+ OTIyNWM4OWFmZTY5N2U4OWI2ZWYzZGMyODY2MWIxOGY0NDMzYmExOGUyZDcy
14
+ NTI4M2Q3YmNkMjdkYzQyN2IwNDExMjNhZDIwN2U4M2Y0NjM0NWZmNjBhMDI4
15
+ NDVhZDk0OTA5MGI3MTk1OWIxN2FhZGI0NjQ0NjI2NDAzOGU2NDI=
@@ -4,7 +4,9 @@ All notable changes to this project will be documented in this file.
4
4
  This project makes a strong effort to adhere to [Semantic
5
5
  Versioning](http://semver.org).
6
6
 
7
- ## [Unreleased][unreleased]
7
+ ## [0.10.0] - 2017-7-7
8
+ - Add map data structure support to arbitrary settings, which previously only
9
+ supported lists and primitives. Maps and lists can be combined.
8
10
 
9
11
  ## [0.9.0] - 2017-6-7
10
12
  - Add list data structure support to arbitrary settings, which previously only
data/README.md CHANGED
@@ -13,6 +13,7 @@ host config files using a compact command line SUT specification.
13
13
  - [Single host with Arbitrary Roles](#single-host-with-arbitrary-roles)
14
14
  - [Two hosts with multiple hypervisors and arbitrary host settings](#two-hosts-with-multiple-hypervisors-and-arbitrary-host-settings)
15
15
  - [Two hosts with arbitrary host settings with arbitrary lists](#two-hosts-with-arbitrary-host-settings-with-arbitrary-lists)
16
+ - [Arbitrary nested hashes and arrays](#arbitrary-nested-hashes-and-arrays)
16
17
  - [Arbitrary global configuration settings](#arbitrary-global-configuration-settings)
17
18
  - [Custom hypervisor](#custom-hypervisor)
18
19
  - [URL-encoded input](#url-encoded-input)
@@ -161,7 +162,7 @@ CONFIG:
161
162
  ### Two hosts with arbitrary host settings with arbitrary lists
162
163
 
163
164
  ```
164
- $ beaker-hostgenerator centos6-64m{disks=\[16\]-redhat7-64a{disks=\[8\,16\]}
165
+ $ beaker-hostgenerator centos6-64m{disks=\[16\]}-redhat7-64a{disks=\[8\,16\]}
165
166
  ```
166
167
 
167
168
  Will generate
@@ -200,6 +201,41 @@ CONFIG:
200
201
  pooling_api: http://vmpooler.delivery.puppetlabs.net/
201
202
  ```
202
203
 
204
+ ### Arbitrary nested hashes and arrays
205
+
206
+ ```
207
+ $ beaker-hostgenerator --global-config {host_tags={lifetime=4h}\,list=[{listkey=listvalue}]\} redhat7-64m{hostlist=\[string\,{key=value}\,1234\]}
208
+ ```
209
+
210
+ Will generate
211
+
212
+ ```yaml
213
+ ---
214
+ HOSTS:
215
+ redhat7-64-1:
216
+ pe_dir:
217
+ pe_ver:
218
+ pe_upgrade_dir:
219
+ pe_upgrade_ver:
220
+ hypervisor: vmpooler
221
+ platform: el-7-x86_64
222
+ template: redhat-7-x86_64
223
+ hostlist:
224
+ - string
225
+ - key: value
226
+ - 1234
227
+ roles:
228
+ - agent
229
+ - master
230
+ CONFIG:
231
+ nfs_server: none
232
+ consoleport: 443
233
+ pooling_api: http://vmpooler.delivery.puppetlabs.net/
234
+ host_tags:
235
+ lifetime: 4h
236
+ list:
237
+ - listkey: listvalue
238
+ ```
203
239
 
204
240
  ### Arbitrary global configuration settings
205
241
 
@@ -74,6 +74,11 @@ module BeakerHostGenerator
74
74
  # Merge in global configuration settings after the hypervisor defaults
75
75
  if options[:global_config]
76
76
  decoded = prepare(options[:global_config])
77
+ # Support for strings without '{}' was introduced, so just double
78
+ # check here to ensure that we pass in values surrounded by '{}'.
79
+ if !decoded.start_with?('{')
80
+ decoded = "{#{decoded}}"
81
+ end
77
82
  global_config = settings_string_to_map(decoded)
78
83
  config['CONFIG'].deep_merge!(global_config)
79
84
  end
@@ -195,9 +195,10 @@ module BeakerHostGenerator
195
195
 
196
196
  # Transforms the arbitrary host settings map from a string representation
197
197
  # to a proper hash map data structure for merging into the host
198
- # configuration.
198
+ # configuration. Supports arbitrary nested hashes and arrays.
199
199
  #
200
200
  # The string is expected to be of the form "{key1=value1,key2=[v2,v3],...}".
201
+ # Nesting looks like "{key1={nested_key=nested_value},list=[[list1, list2]]}".
201
202
  # Whitespace is expected to be properly quoted as it will not be treated
202
203
  # any different than non-whitespace characters.
203
204
  #
@@ -206,38 +207,120 @@ module BeakerHostGenerator
206
207
  # @param host_settings [String] Non-nil user input string that defines host
207
208
  # specific settings.
208
209
  #
209
- # @returns [Hash{String=>String|Array}] The host_settings string as a map.
210
+ # @returns [Hash{String=>String|Array|Hash}] The host_settings string as a map.
210
211
  def settings_string_to_map(host_settings)
211
- # Strip it down to a list of pairs
212
- # Splitting on all commas except inside `[]`
213
- settings_pairs =
214
- host_settings.
215
- delete('{}').
216
- split(/,(?=[^\]]*(?:\[|$))/).
217
- map { |keyvalue| keyvalue.split('=') }
218
-
219
- # Validate they're actually pairs, and that all keys are non-empty
220
- settings_pairs.each do |pair|
221
- if pair.length != 2
222
- raise BeakerHostGenerator::Exceptions::InvalidNodeSpecError,
223
- "Malformed host settings: #{host_settings}"
212
+
213
+ stringscan = StringScanner.new(host_settings)
214
+ object = nil
215
+ object_depth = []
216
+ current_depth = 0
217
+
218
+ # This loop scans until the next delimiter character is found. When
219
+ # the next delimiter is recognized, there is enough context in the
220
+ # substring to determine a course of action to modify the primary
221
+ # object. The `object_depth` object tracks which current object is
222
+ # being modified, and pops it off the end of the array when that
223
+ # data structure is completed.
224
+ #
225
+ # This algorithm would also support a base array, but since there
226
+ # is no need for that functionality, we just assume the string is
227
+ # always a representation of a hash.
228
+ loop do
229
+ blob = stringscan.scan_until(/\[|{|}|\]|,/)
230
+
231
+ break if blob.nil?
232
+
233
+ if stringscan.pos() == 1
234
+ object = {}
235
+ object_depth.push(object)
236
+ next
224
237
  end
225
- if pair.first.nil? || pair.first.empty?
226
- raise BeakerHostGenerator::Exceptions::InvalidNodeSpecError,
227
- "Malformed host settings: #{host_settings}"
238
+
239
+ current_type = object_depth[current_depth].class
240
+ current_object = object_depth[current_depth]
241
+
242
+ if blob == '['
243
+ current_object.push([])
244
+ object_depth.push(current_object.last)
245
+ current_depth = current_depth.next
246
+ next
228
247
  end
229
- end
230
248
 
231
- # Replace the remaining `,` to make array for arbitrary list if brackets exist
232
- settings_pairs.each do |pair|
233
- if pair[1].include?("[")
234
- pair[1] = pair[1].
235
- delete('[]').
236
- split(',')
249
+ if blob.start_with?('{')
250
+ current_object.push({})
251
+ object_depth.push(current_object.last)
252
+ current_depth = current_depth.next
253
+ next
254
+ end
255
+
256
+
257
+
258
+ if blob == ']' or blob == '}'
259
+ object_depth.pop
260
+ current_depth = current_depth.pred
261
+ next
262
+ end
263
+
264
+ # When there is assignment happening, we need to create a new
265
+ # corresponding data structure, add it to the object depth, and
266
+ # then change the current depth
267
+ if blob[-2] == '='
268
+ raise Beaker::HostGenerator::Exceptions::InvalidNodeSpecError unless blob.end_with?('{','[')
269
+ if blob[-1] == '{'
270
+ current_object[blob[0..-3]] = {}
271
+ else
272
+ current_object[blob[0..-3]] = []
273
+ end
274
+ object_depth.push(current_object[blob[0..-3]])
275
+ current_depth = current_depth.next
276
+ next
277
+ end
278
+
279
+ if blob[-1] == '}'
280
+ raise Beaker::HostGenerator::Exceptions::InvalidNodeSpecError if blob.count('=') != 1
281
+ key_pair = blob[0..-2].split('=')
282
+ raise Beaker::HostGenerator::Exceptions::InvalidNodeSpecError if key_pair.size != 2
283
+ key_pair.each do |element|
284
+ raise Beaker::HostGenerator::Exceptions::InvalidNodeSpecError if element.empty?
285
+ end
286
+ current_object[key_pair[0]] = key_pair[1]
287
+ object_depth.pop
288
+ current_depth = current_depth.pred
289
+ next
290
+ end
291
+
292
+ if blob == ','
293
+ next
294
+ end
295
+
296
+ if blob[-1] == ','
297
+ if current_type == Hash
298
+ key_pair = blob[0..-2].split('=')
299
+ raise Beaker::HostGenerator::Exceptions::InvalidNodeSpecError if key_pair.size != 2
300
+ key_pair.each do |element|
301
+ raise Beaker::HostGenerator::Exceptions::InvalidNodeSpecError if element.empty?
302
+ end
303
+ current_object[key_pair[0]] = key_pair[1]
304
+ next
305
+ elsif current_type == Array
306
+ current_object.push(blob[0..-2])
307
+ next
308
+ end
309
+ end
310
+
311
+ if blob[-1] == ']'
312
+ current_object.push(blob[0..-2])
313
+ object_depth.pop
314
+ current_depth = current_depth.pred
315
+ next
237
316
  end
238
317
  end
239
318
 
240
- Hash[settings_pairs]
319
+ object
320
+ rescue Exception => e
321
+ raise BeakerHostGenerator::Exceptions::InvalidNodeSpecError,
322
+ "Malformed host settings: #{host_settings}"
241
323
  end
324
+
242
325
  end
243
326
  end
@@ -1,5 +1,5 @@
1
1
  module BeakerHostGenerator
2
2
  module Version
3
- STRING = '0.9.0'
3
+ STRING = '0.10.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beaker-hostgenerator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Branan Purvine-Riley
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-06-07 00:00:00.000000000 Z
13
+ date: 2017-07-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: minitest
@@ -197,7 +197,6 @@ files:
197
197
  - Gemfile
198
198
  - HISTORY.md
199
199
  - LICENSE
200
- - MAINTAINERS
201
200
  - README.md
202
201
  - Rakefile
203
202
  - beaker-hostgenerator.gemspec
@@ -1,18 +0,0 @@
1
- {
2
- "version": 1,
3
- "file_format": "This MAINTAINERS file format is described at http://pup.pt/maintainers",
4
- "issues": "https://tickets.puppetlabs.com/browse/QENG",
5
- "internal_list": "https://groups.google.com/a/puppet.com/forum/?hl=en#!forum/discuss-quality-engineering",
6
- "people": [
7
- {
8
- "github": "nwolfe",
9
- "email": "nwolfe@puppet.com",
10
- "name": "Nate Wolfe"
11
- },
12
- {
13
- "github": "waynr",
14
- "email": "wayne@puppet.com",
15
- "name": "Wayne Warren"
16
- }
17
- ]
18
- }