hygroscope 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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6843b8aec13ea4cea7186e3e0d303bf9fb9a3fcc
4
- data.tar.gz: e8892054ee9e904e1c3d668c56866d01d5f9e624
3
+ metadata.gz: d0c04fe1271358a786c6d3a11bf560b6dd3b473c
4
+ data.tar.gz: 651417b88a81f851051083505ef069f1a74f11f3
5
5
  SHA512:
6
- metadata.gz: cd09dd561634d91ce8ed58851c58b58e445cfb5e275119923ee6fb7a977d66e486d96143e035ac8566d70a257cc3f51c07e2adfacb9a165724e424fbde5d6552
7
- data.tar.gz: 8b508549617eee3670492368d9616bba7293e6072d6199ebe944fe9553b74e8a487b03fa4e4ac7f8d06caecf989639ad8cf1024481d30c686002c157be657248
6
+ metadata.gz: 0cc74e488efa5facd0b5f460a0035a5da03055324ede819b25333f969d45b815a41452199bc966cb83377decddba2ceac2675e1691ef346ae4d3ab66d4cb57be
7
+ data.tar.gz: dde59539318ab9315129291de3ceed29c7e7e5ba52efcfca38059e5d94bf8aa92bd230a397d87a8b1bbd87289dfc87ff104d7d4f46c1121e19ead89e2206bfb6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 1.3.0 (2016-08-12)
2
+ - Support passing capabilities using new --capabilities option. No longer set
3
+ CAPABILITY_IAM by default.
4
+ - When performing updates use existing parameters by default
5
+ - Do not compress template by default (readability vs slight space savings)
6
+ - Rubocop code cleanup
7
+
1
8
  ## 1.2.0 (2015-10-08)
2
9
  - Support AWS credential profiles and multiple regions using new --region and
3
10
  --profile options.
data/hygroscope.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'hygroscope'
3
- s.version = '1.2.0'
3
+ s.version = '1.3.0'
4
4
  s.summary = 'CloudFormation launcher'
5
5
  s.description = 'A tool for managing the launch of complex CloudFormation stacks'
6
6
  s.authors = ['Daniel Silverman']
@@ -81,18 +81,18 @@ module Hygroscope
81
81
  # NOTE: Profiles cannot assume roles, see:
82
82
  # https://github.com/aws/aws-sdk-ruby/issues/910
83
83
  class_option :profile,
84
- aliases: '-p',
85
- type: :string,
86
- default: 'default',
87
- desc: 'AWS account credentials profile name'
84
+ aliases: '-p',
85
+ type: :string,
86
+ default: 'default',
87
+ desc: 'AWS account credentials profile name'
88
88
  class_option :region,
89
- aliases: '-r',
90
- type: :string,
91
- default: 'us-east-1',
92
- desc: 'AWS region'
89
+ aliases: '-r',
90
+ type: :string,
91
+ default: 'us-east-1',
92
+ desc: 'AWS region'
93
93
 
94
94
  desc 'prepare', 'Prepare to create or update a stack by generating the template, assembling parameters, and managing payload upload', hide: true
95
- def prepare
95
+ def prepare(action = 'create')
96
96
  # Generate the template
97
97
  t = Hygroscope::Template.new(template_path, options[:region], options[:profile])
98
98
 
@@ -132,49 +132,57 @@ module Hygroscope
132
132
  end
133
133
  end if options[:existing].is_a?(Array)
134
134
 
135
- # Prompt for each missing parameter and save it in the paramset object
136
- missing.each do |key|
137
- # Do not prompt for keys prefixed with the "Hygroscope" reserved word.
138
- # These parameters are populated internally without user input.
139
- next if key =~ /^Hygroscope/
140
-
141
- type = t.parameters[key]['Type']
142
- default = p.get(key) ? p.get(key) : t.parameters[key]['Default'] || ''
143
- description = t.parameters[key]['Description'] || false
144
- values = t.parameters[key]['AllowedValues'] || false
145
- no_echo = t.parameters[key]['NoEcho'] || false
146
-
147
- # Thor conveniently provides some nice logic for formatting,
148
- # allowing defaults, and validating user input
149
- ask_opts = {}
150
- ask_opts[:default] = default unless default.to_s.empty?
151
- ask_opts[:limited_to] = values if values
152
- ask_opts[:echo] = false if no_echo
153
-
154
- puts
155
- say("#{description} (#{type})") if description
156
- # Make sure user enters a value
157
- # TODO: Better input validation
158
- answer = ''
159
- answer = ask(key, :cyan, ask_opts) until answer != ''
160
-
161
- # Save answer to paramset object
162
- p.set(key, answer)
163
-
164
- # Add a line break
165
- say if no_echo
166
- end
135
+ # If this is an update and ask was not specified, set any missing
136
+ # parameters to use_previous_value
137
+ if action == 'update' && !options[:ask]
138
+ missing.each do |key|
139
+ p.set(key, nil, use_previous_value: true)
140
+ end
141
+ else
142
+ # Prompt for each missing parameter and save it in the paramset object
143
+ missing.each do |key|
144
+ # Do not prompt for keys prefixed with the "Hygroscope" reserved word.
145
+ # These parameters are populated internally without user input.
146
+ next if key =~ /^Hygroscope/
147
+
148
+ type = t.parameters[key]['Type']
149
+ default = p.get(key) ? p.get(key) : t.parameters[key]['Default'] || ''
150
+ description = t.parameters[key]['Description'] || false
151
+ values = t.parameters[key]['AllowedValues'] || false
152
+ no_echo = t.parameters[key]['NoEcho'] || false
153
+
154
+ # Thor conveniently provides some nice logic for formatting,
155
+ # allowing defaults, and validating user input
156
+ ask_opts = {}
157
+ ask_opts[:default] = default unless default.to_s.empty?
158
+ ask_opts[:limited_to] = values if values
159
+ ask_opts[:echo] = false if no_echo
160
+
161
+ puts
162
+ say("#{description} (#{type})") if description
163
+ # Make sure user enters a value
164
+ # TODO: Better input validation
165
+ answer = ''
166
+ answer = ask(key, :cyan, ask_opts) until answer != ''
167
+
168
+ # Save answer to paramset object
169
+ p.set(key, answer)
167
170
 
168
- # Offer to save paramset if it was modified
169
- # Filter out keys beginning with "Hygroscope" since they are not visible
170
- # to the user and may be modified on each invocation.
171
- unless missing.reject { |k| k =~ /^Hygroscope/ }.empty?
172
- puts
173
- if yes?('Save changes to paramset?')
174
- unless options[:paramset]
175
- p.name = ask('Paramset name', :cyan, default: options[:name])
171
+ # Add a line break
172
+ say if no_echo
173
+ end
174
+
175
+ # Offer to save paramset if it was modified
176
+ # Filter out keys beginning with "Hygroscope" since they are not visible
177
+ # to the user and may be modified on each invocation.
178
+ unless missing.reject { |k| k =~ /^Hygroscope/ }.empty?
179
+ puts
180
+ if yes?('Save changes to paramset?')
181
+ unless options[:paramset]
182
+ p.name = ask('Paramset name', :cyan, default: options[:name])
183
+ end
184
+ p.save!
176
185
  end
177
- p.save!
178
186
  end
179
187
  end
180
188
 
@@ -196,39 +204,51 @@ module Hygroscope
196
204
 
197
205
  desc 'create', "Create a new stack.\nUse the --name option to launch more than one stack from the same template.\nCommand prompts for parameters unless --paramset is specified.\nUse --existing to set parameters from an existing stack's outputs."
198
206
  method_option :name,
199
- aliases: '-n',
200
- default: File.basename(Dir.pwd),
201
- desc: 'Name of stack'
207
+ aliases: '-n',
208
+ default: File.basename(Dir.pwd),
209
+ desc: 'Name of stack'
202
210
  method_option :paramset,
203
- aliases: '-s',
204
- required: false,
205
- desc: 'Name of saved paramset to use (optional)'
211
+ aliases: '-s',
212
+ required: false,
213
+ desc: 'Name of saved paramset to use (optional)'
206
214
  method_option :existing,
207
- aliases: '-e',
208
- type: :array,
209
- required: false,
210
- desc: 'Name of one or more existing stacks from which to retrieve outputs as parameters (optional)'
215
+ aliases: '-e',
216
+ type: :array,
217
+ required: false,
218
+ desc: 'Name of one or more existing stacks from which to retrieve outputs as parameters (optional)'
211
219
  method_option :ask,
212
- aliases: '-a',
213
- type: :boolean,
214
- default: false,
215
- desc: 'Still prompt for parameters even when using a paramset'
220
+ aliases: '-a',
221
+ type: :boolean,
222
+ default: false,
223
+ desc: 'Still prompt for parameters even when using a paramset'
216
224
  method_option :tags,
217
- aliases: '-t',
218
- type: :array,
219
- required: false,
220
- default: [],
221
- desc: 'One or more parameters to apply as tags to all stack resources'
225
+ aliases: '-t',
226
+ type: :array,
227
+ required: false,
228
+ default: [],
229
+ desc: 'One or more parameters to apply as tags to all stack resources'
230
+ method_option :capabilities,
231
+ aliases: '-c',
232
+ type: :array,
233
+ required: false,
234
+ default: [],
235
+ desc: 'One or more capabilities to pass to CloudFormation (i.e. CAPABILITY_IAM)'
236
+ method_option :compress,
237
+ type: :boolean,
238
+ default: false,
239
+ desc: 'Whether to compress the CloudFormation template slightly at the expense of readability by removing extra spaces'
222
240
  def create
223
241
  check_path
224
242
  validate
225
243
 
226
244
  # Prepare task takes care of shared logic between "create" and "update"
227
- template, paramset = prepare
245
+ template, paramset = prepare('create')
228
246
 
229
- stack = Hygroscope::Stack.new(options[:name], options[:region], options[:profile])
230
- stack.parameters = paramset.parameters
231
- stack.template = template.compress
247
+ stack = Hygroscope::Stack.new(options[:name], options[:region], options[:profile])
248
+ stack.parameters = paramset.parameters
249
+ stack.template = options[:compress] ? template.compress : template.process
250
+ stack.capabilities = options[:capabilities]
251
+ stack.timeout = 60
232
252
 
233
253
  stack.tags['X-Hygroscope-Template'] = hygro_name
234
254
  options[:tags].each do |tag|
@@ -239,58 +259,67 @@ module Hygroscope
239
259
  end
240
260
  end
241
261
 
242
- stack.capabilities = ['CAPABILITY_IAM']
243
- stack.timeout = 60
244
-
245
262
  stack.create!
246
-
247
263
  status
248
264
  end
249
265
 
250
- desc 'update', "Update a running stack.\nCommand prompts for parameters unless a --paramset is specified."
266
+ desc 'update', "Update an existing stack.\nUse the --name option to specify the stack name if it differs from the template name.\nBy default parameters are set to existing values, unless --paramset or --ask is specified."
251
267
  method_option :name,
252
- aliases: '-n',
253
- default: File.basename(Dir.pwd),
254
- desc: 'Name of stack'
268
+ aliases: '-n',
269
+ default: File.basename(Dir.pwd),
270
+ desc: 'Name of stack'
255
271
  method_option :paramset,
256
- aliases: '-s',
257
- required: false,
258
- desc: 'Name of saved paramset to use (optional)'
272
+ aliases: '-s',
273
+ required: false,
274
+ desc: 'Name of saved paramset to use (optional)'
275
+ method_option :existing,
276
+ aliases: '-e',
277
+ type: :array,
278
+ required: false,
279
+ desc: 'Name of one or more existing stacks from which to retrieve outputs as parameters (optional)'
259
280
  method_option :ask,
260
- aliases: '-a',
261
- type: :boolean,
262
- default: false,
263
- desc: 'Still prompt for parameters even when using a paramset'
281
+ aliases: '-a',
282
+ type: :boolean,
283
+ default: false,
284
+ desc: 'Still prompt for parameters even when using a paramset'
285
+ method_option :capabilities,
286
+ aliases: '-c',
287
+ type: :array,
288
+ required: false,
289
+ default: [],
290
+ desc: 'One or more capabilities to pass to CloudFormation (i.e. CAPABILITY_NAMED_IAM)'
291
+ method_option :compress,
292
+ type: :boolean,
293
+ default: false,
294
+ desc: 'Whether to compress the CloudFormation template slightly at the expense of readability by removing extra spaces'
264
295
  def update
265
- # TODO: Right now update just does the same thing as create, not taking
266
- # into account the complications of updating (which params to keep,
267
- # whether to re-upload the payload, etc.)
296
+ # TODO: Make re-uploading the payload optional
268
297
  check_path
269
298
  validate
270
299
 
271
300
  # Prepare task takes care of shared logic between "create" and "update"
272
- template, paramset = prepare
301
+ template, paramset = prepare('update')
273
302
 
274
- s = Hygroscope::Stack.new(options[:name], options[:region], options[:profile])
275
- s.parameters = paramset.parameters
276
- s.template = template.compress
277
- s.capabilities = ['CAPABILITY_IAM']
278
- s.timeout = 60
279
- s.update!
303
+ stack = Hygroscope::Stack.new(options[:name], options[:region], options[:profile])
304
+ stack.parameters = paramset.parameters
305
+ stack.template = options[:compress] ? template.compress : template.process
306
+ stack.capabilities = options[:capabilities]
307
+ stack.timeout = 60
280
308
 
309
+ stack.update!
281
310
  status
282
311
  end
283
312
 
284
313
  desc 'delete', 'Delete a running stack after asking for confirmation.'
285
314
  method_option :name,
286
- aliases: '-n',
287
- default: File.basename(Dir.pwd),
288
- desc: 'Name of stack'
315
+ aliases: '-n',
316
+ default: File.basename(Dir.pwd),
317
+ desc: 'Name of stack'
289
318
  method_option :force,
290
- aliases: '-f',
291
- type: :boolean,
292
- default: false,
293
- desc: 'Delete without asking for confirmation'
319
+ aliases: '-f',
320
+ type: :boolean,
321
+ default: false,
322
+ desc: 'Delete without asking for confirmation'
294
323
  def delete
295
324
  check_path
296
325
  abort unless options[:force] ||
@@ -304,76 +333,78 @@ module Hygroscope
304
333
 
305
334
  desc 'status', 'View status of stack create/update/delete action.\nUse the --name option to change which stack is reported upon.'
306
335
  method_option :name,
307
- aliases: '-n',
308
- default: File.basename(Dir.pwd),
309
- desc: 'Name of stack'
336
+ aliases: '-n',
337
+ default: File.basename(Dir.pwd),
338
+ desc: 'Name of stack'
310
339
  def status
311
340
  check_path
312
341
  stack = Hygroscope::Stack.new(options[:name], options[:region], options[:profile])
313
342
 
314
343
  # Query and display the status of the stack and its resources. Refresh
315
344
  # every 10 seconds until the user aborts or an error is encountered.
316
- begin
317
- s = stack.describe
318
-
319
- system('clear') || system('cls')
320
-
321
- header = {
322
- 'Name:' => s.stack_name,
323
- 'Created:' => s.creation_time,
324
- 'Status:' => colorize_status(s.stack_status)
325
- }
326
-
327
- print_table header
328
- puts
329
-
330
- # Fancy acrobatics to fit output to terminal width. If the terminal
331
- # window is too small, fallback to something appropriate for ~80 chars
332
- term_width = `stty size 2>/dev/null`.split[1].to_i || `tput cols 2>/dev/null`.to_i
333
- type_width = term_width < 80 ? 30 : term_width - 50
334
- output_width = term_width < 80 ? 54 : term_width - 31
335
-
336
- # Header row
337
- puts set_color(sprintf(' %-28s %-*s %-18s ', 'Resource', type_width, 'Type', 'Status'), :white, :on_blue)
338
- resources = stack.list_resources
339
- resources.each do |r|
340
- puts sprintf(' %-28s %-*s %-18s ', r[:name][0..26], type_width, r[:type][0..type_width], colorize_status(r[:status]))
341
- end
345
+ loop do
346
+ begin
347
+ s = stack.describe
348
+
349
+ system('clear') || system('cls')
350
+
351
+ header = {
352
+ 'Name:' => s.stack_name,
353
+ 'Created:' => s.creation_time,
354
+ 'Status:' => colorize_status(s.stack_status)
355
+ }
342
356
 
343
- if s.stack_status.downcase =~ /complete$/
344
- # If the stack is complete display any available outputs and stop refreshing
357
+ print_table header
345
358
  puts
346
- puts set_color(sprintf(' %-28s %-*s ', 'Output', output_width, 'Value'), :white, :on_yellow)
347
- s.outputs.each do |o|
348
- puts sprintf(' %-28s %-*s ', o.output_key, output_width, o.output_value)
359
+
360
+ # Fancy acrobatics to fit output to terminal width. If the terminal
361
+ # window is too small, fallback to something appropriate for ~80 chars
362
+ term_width = `stty size 2>/dev/null`.split[1].to_i || `tput cols 2>/dev/null`.to_i
363
+ type_width = term_width < 80 ? 30 : term_width - 50
364
+ output_width = term_width < 80 ? 54 : term_width - 31
365
+
366
+ # Header row
367
+ puts set_color(format(' %-28s %-*s %-18s ', 'Resource', type_width, 'Type', 'Status'), :white, :on_blue)
368
+ resources = stack.list_resources
369
+ resources.each do |r|
370
+ puts format(' %-28s %-*s %-18s ', r[:name][0..26], type_width, r[:type][0..type_width], colorize_status(r[:status]))
349
371
  end
350
372
 
351
- puts "\nMore information: https://console.aws.amazon.com/cloudformation/home"
352
- break
353
- elsif s.stack_status.downcase =~ /failed$/
354
- # If the stack failed to create, stop refreshing
355
- puts "\nMore information: https://console.aws.amazon.com/cloudformation/home"
356
- break
357
- else
358
- puts "\nMore information: https://console.aws.amazon.com/cloudformation/home"
359
- countdown('Updating in', 9)
360
- puts
373
+ if s.stack_status.downcase =~ /complete$/
374
+ # If the stack is complete display any available outputs and stop refreshing
375
+ puts
376
+ puts set_color(format(' %-28s %-*s ', 'Output', output_width, 'Value'), :white, :on_yellow)
377
+ s.outputs.each do |o|
378
+ puts format(' %-28s %-*s ', o.output_key, output_width, o.output_value)
379
+ end
380
+
381
+ puts "\nMore information: https://console.aws.amazon.com/cloudformation/home"
382
+ break
383
+ elsif s.stack_status.downcase =~ /failed$/
384
+ # If the stack failed to create, stop refreshing
385
+ puts "\nMore information: https://console.aws.amazon.com/cloudformation/home"
386
+ break
387
+ else
388
+ puts "\nMore information: https://console.aws.amazon.com/cloudformation/home"
389
+ countdown('Updating in', 9)
390
+ puts
391
+ end
392
+ rescue Aws::CloudFormation::Errors::ValidationError
393
+ say_fail('Stack not found')
394
+ rescue Interrupt
395
+ abort
361
396
  end
362
- rescue Aws::CloudFormation::Errors::ValidationError
363
- say_fail('Stack not found')
364
- rescue Interrupt
365
- abort
366
- end while true
397
+ end
367
398
  end
368
399
 
369
400
  desc 'generate',
370
- "Generate and display JSON output from template files.\n" \
371
- "To validate that the template is well-formed use the 'validate' command."
401
+ "Generate and display JSON output from template files.\n" \
402
+ "To validate that the template is well-formed use the 'validate' command."
372
403
  method_option :color,
373
- aliases: '-c',
374
- type: :boolean,
375
- default: true,
376
- desc: 'Colorize JSON output'
404
+ aliases: '-c',
405
+ type: :boolean,
406
+ default: true,
407
+ desc: 'Colorize JSON output'
377
408
  def generate
378
409
  check_path
379
410
  t = Hygroscope::Template.new(template_path, options[:region], options[:profile])
@@ -405,9 +436,9 @@ module Hygroscope
405
436
 
406
437
  desc 'paramset', "List saved paramsets.\nIf --name is passed, shows all parameters in the named set."
407
438
  method_option :name,
408
- aliases: '-n',
409
- required: false,
410
- desc: 'Name of a paramset'
439
+ aliases: '-n',
440
+ required: false,
441
+ desc: 'Name of a paramset'
411
442
  def paramset
412
443
  if options[:name]
413
444
  say_paramset(options[:name])
@@ -12,20 +12,19 @@ module Hygroscope
12
12
  @parameters = {}
13
13
  @path = File.join(Dir.pwd, 'paramsets')
14
14
 
15
- if name
16
- @name = name
17
- self.load!
18
- end
15
+ return unless name
16
+
17
+ @name = name
18
+ load!
19
19
  end
20
20
 
21
21
  def load!
22
22
  files = Dir.glob(File.join(@path, @name + '.{yml,yaml}'))
23
- if files.empty?
24
- fail Hygroscope::ParamSetNotFoundError
25
- else
26
- @file = files.first
27
- @parameters = YAML.load_file(@file)
28
- end
23
+
24
+ raise Hygroscope::ParamSetNotFoundError if files.empty?
25
+
26
+ @file = files.first
27
+ @parameters = YAML.load_file(@file)
29
28
  end
30
29
 
31
30
  def save!
@@ -40,8 +39,12 @@ module Hygroscope
40
39
  @parameters[key]
41
40
  end
42
41
 
43
- def set(key, value)
44
- @parameters[key] = value
42
+ def set(key, value, use_previous_value: false)
43
+ @parameters[key] = if use_previous_value
44
+ 'HYGROSCOPE_USE_PREVIOUS_VALUE'
45
+ else
46
+ value
47
+ end
45
48
  end
46
49
  end
47
50
  end
@@ -47,8 +47,8 @@ module Hygroscope
47
47
  def send
48
48
  @client.put_object(
49
49
  bucket: @bucket,
50
- key: key,
51
- body: @archive
50
+ key: key,
51
+ body: @archive
52
52
  )
53
53
  end
54
54
 
@@ -25,7 +25,7 @@ module Hygroscope
25
25
  stack_parameters = []
26
26
  @parameters.each do |k, v|
27
27
  stack_parameters << {
28
- parameter_key: k,
28
+ parameter_key: k,
29
29
  parameter_value: v.to_s
30
30
  }
31
31
  end
@@ -33,17 +33,17 @@ module Hygroscope
33
33
  stack_tags = []
34
34
  @tags.each do |k, v|
35
35
  stack_tags << {
36
- key: k,
36
+ key: k,
37
37
  value: v.to_s
38
38
  }
39
39
  end
40
40
 
41
41
  stack_opts = {
42
- stack_name: @name,
43
- template_body: @template,
44
- parameters: stack_parameters,
42
+ stack_name: @name,
43
+ template_body: @template,
44
+ parameters: stack_parameters,
45
45
  timeout_in_minutes: @timeout,
46
- on_failure: @on_failure
46
+ on_failure: @on_failure
47
47
  }
48
48
 
49
49
  stack_opts['capabilities'] = @capabilities unless @capabilities.empty?
@@ -61,16 +61,23 @@ module Hygroscope
61
61
  def update!
62
62
  stack_parameters = []
63
63
  @parameters.each do |k, v|
64
- stack_parameters << {
65
- parameter_key: k,
66
- parameter_value: v.to_s
67
- }
64
+ stack_parameters << if v == 'HYGROSCOPE_USE_PREVIOUS_VALUE'
65
+ {
66
+ parameter_key: k,
67
+ use_previous_value: true
68
+ }
69
+ else
70
+ {
71
+ parameter_key: k,
72
+ parameter_value: v.to_s
73
+ }
74
+ end
68
75
  end
69
76
 
70
77
  stack_opts = {
71
- stack_name: @name,
78
+ stack_name: @name,
72
79
  template_body: @template,
73
- parameters: stack_parameters
80
+ parameters: stack_parameters
74
81
  }
75
82
 
76
83
  stack_opts['capabilities'] = @capabilities unless @capabilities.empty?
@@ -106,8 +113,8 @@ module Hygroscope
106
113
  resources = []
107
114
  resp.stack_resources.each do |r|
108
115
  resources << {
109
- name: r.logical_resource_id,
110
- type: r.resource_type,
116
+ name: r.logical_resource_id,
117
+ type: r.resource_type,
111
118
  status: r.resource_status
112
119
  }
113
120
  end
@@ -28,7 +28,7 @@ module Hygroscope
28
28
  cfoo.process(*files)
29
29
  end
30
30
 
31
- fail(TemplateYamlParseError, err.string) unless err.string.empty?
31
+ raise(TemplateYamlParseError, err.string) unless err.string.empty?
32
32
 
33
33
  @template = out.string
34
34
  @template
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hygroscope
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
  - Daniel Silverman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-08 00:00:00.000000000 Z
11
+ date: 2016-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor