abide_dev_utils 0.6.0 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
3
4
  require 'yaml'
4
5
  require 'selenium-webdriver'
5
6
  require 'abide_dev_utils/errors/comply'
6
7
  require 'abide_dev_utils/gcloud'
7
8
  require 'abide_dev_utils/output'
8
9
  require 'abide_dev_utils/prompt'
10
+ require 'pry'
9
11
 
10
12
  module AbideDevUtils
11
13
  # Holds module methods and a class for dealing with Puppet Comply
@@ -16,56 +18,55 @@ module AbideDevUtils
16
18
  ReportScraper.new(url, config, **opts).build_report(password)
17
19
  end
18
20
 
19
- def self.check_for_regressions(url, password, config = nil, **opts)
20
- current_report = build_report(url, password, config, **opts)
21
- last_report = if opts.fetch(:remote_report_storage, '') == 'gcloud'
22
- fetch_report
21
+ def self.compare_reports(report_a, report_b, **opts)
22
+ report_name = opts.fetch(:report_name, nil)
23
+ current_report = ScanReport.new.from_yaml(report_a)
24
+ last_report = if opts.fetch(:remote_storage, '') == 'gcloud'
25
+ report_name = report_b if report_name.nil?
26
+ ScanReport.new.from_yaml(ScanReport.fetch_report(name: report_b))
23
27
  else
24
- File.open(opts[:last_report], 'r', &:read)
28
+ report_name = File.basename(report_b) if report_name.nil?
29
+ ScanReport.new.from_yaml(File.read(report_b))
25
30
  end
26
- result, details = good_comparison?(report_comparison(current_report, last_report))
31
+ result, details = current_report.report_comparison(last_report, check_goodness: true)
27
32
  if result
28
- puts 'A-OK'
33
+ AbideDevUtils::Output.simple('No negative differences detected...')
34
+ AbideDevUtils::Output.simple(JSON.pretty_generate(details))
29
35
  else
30
- puts 'Uh-Oh'
31
- puts details
36
+ AbideDevUtils::Output.simple('Negative differences detected!', stream: $stderr)
37
+ AbideDevUtils::Output.simple(JSON.pretty_generate(details), stream: $stderr)
32
38
  end
39
+ if opts.fetch(:upload, false) && !opts.fetch(:remote_storage, '').empty? && !report_name.nil?
40
+ AbideDevUtils::Output.simple('Uploading current report...')
41
+ ScanReport.upload_report(File.expand_path(report_a), name: report_name)
42
+ AbideDevUtils::Output.simple('Successfully uploaded report.')
43
+ end
44
+ result
33
45
  end
34
46
 
35
47
  # Class that uses Selenium WebDriver to gather scan reports from Puppet Comply
36
48
  class ReportScraper
49
+ attr_reader :timeout,
50
+ :username,
51
+ :status,
52
+ :ignorelist,
53
+ :onlylist,
54
+ :max_pagination,
55
+ :screenshot_on_error,
56
+ :page_source_on_error
57
+
37
58
  def initialize(url, config = nil, **opts)
38
59
  @url = url
39
60
  @config = config
40
61
  @opts = opts
41
- end
42
-
43
- def timeout
44
- @timeout ||= fetch_option(:timeout, 10).to_i
45
- end
46
-
47
- def username
48
- @username ||= fetch_option(:username, 'comply')
49
- end
50
-
51
- def status
52
- @status ||= fetch_option(:status)
53
- end
54
-
55
- def ignorelist
56
- @ignorelist ||= fetch_option(:ignorelist, [])
57
- end
58
-
59
- def onlylist
60
- @onlylist ||= fetch_option(:onlylist, [])
61
- end
62
-
63
- def screenshot_on_error
64
- @screenshot_on_error ||= fetch_option(:screenshot_on_error, true)
65
- end
66
-
67
- def page_source_on_error
68
- @page_source_on_error ||= fetch_option(:page_source_on_error, true)
62
+ @timeout = fetch_option(:timeout, 10).to_i
63
+ @username = fetch_option(:username, 'comply')
64
+ @status = fetch_option(:status)
65
+ @ignorelist = fetch_option(:ignorelist, [])
66
+ @onlylist = fetch_option(:onlylist, [])
67
+ @max_pagination = fetch_option(:max_pagination, 5).to_i
68
+ @screenshot_on_error = fetch_option(:screenshot_on_error, false)
69
+ @page_source_on_error = fetch_option(:page_source_on_error, false)
69
70
  end
70
71
 
71
72
  def build_report(password)
@@ -119,6 +120,7 @@ module AbideDevUtils
119
120
  --headless
120
121
  --test-type
121
122
  --disable-gpu
123
+ --no-sandbox
122
124
  --no-first-run
123
125
  --no-default-browser-check
124
126
  --ignore-certificate-errors
@@ -133,27 +135,37 @@ module AbideDevUtils
133
135
  subject.find_element(**kwargs)
134
136
  end
135
137
 
136
- def wait_on(ignore_nse: false, ignore: [Selenium::WebDriver::Error::NoSuchElementError], &block)
138
+ def find_elements(subject = driver, **kwargs)
139
+ driver.manage.window.resize_to(1920, 1080)
140
+ subject.find_elements(**kwargs)
141
+ end
142
+
143
+ def wait_on(timeout: @timeout,
144
+ ignore_nse: false,
145
+ quit_driver: true,
146
+ quiet: false,
147
+ ignore: [Selenium::WebDriver::Error::NoSuchElementError],
148
+ &block)
137
149
  raise 'wait_on must be passed a block' unless block
138
150
 
139
151
  value = nil
140
152
  if ignore_nse
141
153
  begin
142
- Selenium::WebDriver::Wait.new(ignore: [], timeout: timeout).until do
154
+ Selenium::WebDriver::Wait.new(ignore: [], timeout: timeout, interval: 1).until do
143
155
  value = yield
144
156
  end
145
157
  rescue Selenium::WebDriver::Error::NoSuchElementError
146
158
  return value
147
- rescue => e
148
- raise_error(e)
159
+ rescue StandardError => e
160
+ raise_error(e, AbideDevUtils::Comply::WaitOnError, quit_driver: quit_driver, quiet: quiet)
149
161
  end
150
162
  else
151
163
  begin
152
- Selenium::WebDriver::Wait.new(ignore: ignore, timeout: timeout).until do
164
+ Selenium::WebDriver::Wait.new(ignore: ignore, timeout: timeout, interval: 1).until do
153
165
  value = yield
154
166
  end
155
- rescue => e
156
- raise_error(e)
167
+ rescue StandardError => e
168
+ raise_error(e, AbideDevUtils::Comply::WaitOnError, quit_driver: quit_driver, quiet: quiet)
157
169
  end
158
170
  end
159
171
  value
@@ -169,20 +181,21 @@ module AbideDevUtils
169
181
  FileUtils.mkdir_p path
170
182
  end
171
183
 
172
- def raise_error(err)
173
- output.simple 'Something went wrong!'
184
+ def raise_error(original, err_class = nil, quit_driver: true, quiet: false)
185
+ output.simple 'Something went wrong!' unless quiet
174
186
  if screenshot_on_error
175
- output.simple 'Taking a screenshot of current page state...'
187
+ output.simple 'Taking a screenshot of current page state...' unless quiet
176
188
  screenshot
177
189
  end
178
190
 
179
191
  if page_source_on_error
180
- output.simple 'Saving page source of current page...'
192
+ output.simple 'Saving page source of current page...' unless quiet
181
193
  page_source
182
194
  end
183
195
 
184
- driver.quit
185
- raise err
196
+ driver.quit if quit_driver
197
+ actual_err_class = err_class.nil? ? original.class : err_class
198
+ raise actual_err_class, original.message
186
199
  end
187
200
 
188
201
  def screenshot
@@ -223,15 +236,59 @@ module AbideDevUtils
223
236
  error_text = wait_on(ignore_nse: true) { find_element(class: 'kc-feedback-text').text }
224
237
  return if error_text.nil? || error_text.empty?
225
238
 
226
- raise ComplyLoginFailedError, error_text
239
+ raise AbideDevUtils::Comply::ComplyLoginFailedError, error_text
240
+ end
241
+
242
+ def filter_node_report_links(node_report_links)
243
+ if onlylist.empty? && ignorelist.empty?
244
+ output.simple 'No filters set, using all node reports...'
245
+ return node_report_links
246
+ end
247
+
248
+ unless onlylist.empty?
249
+ output.simple 'Onlylist found, filtering node reports...'
250
+ return node_report_links.select { |l| onlylist.include?(l[:name]) }
251
+ end
252
+
253
+ output.simple 'Ignorelist found, filtering node reports...'
254
+ node_report_links.reject { |l| ignorelist.include?(l[:name]) }
255
+ end
256
+
257
+ def find_node_report_table(subject)
258
+ wait_on { find_element(subject, class: 'metric-containers-failed-hosts-count') }
259
+ hosts = find_element(subject, class: 'metric-containers-failed-hosts-count')
260
+ table = find_element(hosts, class: 'rc-table')
261
+ wait_on { find_element(table, tag_name: 'tbody') }
262
+ find_element(table, tag_name: 'tbody')
263
+ end
264
+
265
+ def wait_for_node_report_links(table_body)
266
+ wait_on(timeout: 2, quit_driver: false, quiet: true) { table_body.find_element(tag_name: 'a') }
267
+ output.simple 'Found node report links...'
268
+ table_body.find_elements(tag_name: 'a')
269
+ rescue AbideDevUtils::Comply::WaitOnError
270
+ []
227
271
  end
228
272
 
229
273
  def find_node_report_links
230
274
  output.simple 'Finding nodes with scan reports...'
231
- hosts = wait_on { find_element(class: 'metric-containers-failed-hosts-count') }
232
- table = find_element(hosts, class: 'rc-table')
233
- table_body = find_element(table, tag_name: 'tbody')
234
- wait_on { table_body.find_elements(tag_name: 'a') }
275
+ node_report_links = []
276
+ (1..max_pagination).each do |page|
277
+ output.simple "Trying page #{page}..."
278
+ driver.get("#{@url}/dashboard?page=#{page}&limit=50")
279
+ table_body = find_node_report_table(driver)
280
+ elems = wait_for_node_report_links(table_body)
281
+ if elems.empty?
282
+ output.simple "No links found on page #{page}, stopping search..."
283
+ break
284
+ end
285
+
286
+ elems.each do |elem|
287
+ node_report_links << { name: elem.text, url: elem.attribute('href') }
288
+ end
289
+ end
290
+ driver.get(@url)
291
+ filter_node_report_links(node_report_links)
235
292
  end
236
293
 
237
294
  def connect(password)
@@ -249,67 +306,69 @@ module AbideDevUtils
249
306
  nstr
250
307
  end
251
308
 
309
+ def wait_on_element_and_increment(subject = driver, **element_id)
310
+ element = wait_on { find_element(subject, **element_id) }
311
+ progress.increment
312
+ element
313
+ end
314
+
315
+ def wait_on_elements_and_increment(subject = driver, **element_id)
316
+ elements = wait_on { find_elements(subject, **element_id) }
317
+ progress.increment
318
+ elements
319
+ end
320
+
252
321
  def scrape_report
253
322
  output.simple 'Building scan reports, this may take a while...'
254
323
  all_checks = {}
255
324
  original_window = driver.window_handle
256
- if !onlylist.empty?
257
- node_report_links.reject! { |l| !onlylist.include?(l.text) }
258
- elsif !ignorelist.empty?
259
- node_report_links.reject! { |l| ignorelist.include?(l.text) }
260
- end
261
325
  node_report_links.each do |link|
262
- begin
263
- node_name = link.text
264
- new_progress(node_name)
265
- link_url = link.attribute('href')
266
- driver.manage.new_window(:tab)
326
+ node_name = link[:name]
327
+ link_url = link[:url]
328
+ new_progress(node_name)
329
+ driver.manage.new_window(:tab)
330
+ progress.increment
331
+ wait_on { driver.window_handles.length == 2 }
332
+ progress.increment
333
+ driver.switch_to.window driver.window_handles[1]
334
+ driver.get(link_url)
335
+ wait_on_element_and_increment(class: 'details-header')
336
+ wait_on_element_and_increment(class: 'details-scan-info')
337
+ wait_on_element_and_increment(class: 'details-table')
338
+ report = { 'scan_results' => {} }
339
+ scan_info_table = wait_on_element_and_increment(class: 'details-scan-info')
340
+ scan_info_table_rows = wait_on_elements_and_increment(scan_info_table, tag_name: 'tr')
341
+ check_table_body = wait_on_element_and_increment(tag_name: 'tbody')
342
+ check_table_rows = wait_on_elements_and_increment(check_table_body, tag_name: 'tr')
343
+ scan_info_table_rows.each do |row|
344
+ key = find_element(row, tag_name: 'h5').text
345
+ value = find_element(row, tag_name: 'strong').text
346
+ report[key.downcase.tr(':', '').tr(' ', '_')] = value
267
347
  progress.increment
268
- wait_on { driver.window_handles.length == 2 }
269
- progress.increment
270
- driver.switch_to.window driver.window_handles[1]
271
- driver.get(link_url)
272
- wait_on { find_element(class: 'details-scan-info') }
273
- progress.increment
274
- wait_on { find_element(class: 'details-table') }
275
- progress.increment
276
- report = { 'scan_results' => {} }
277
- scan_info_table = find_element(class: 'details-scan-info')
278
- scan_info_table_rows = scan_info_table.find_elements(tag_name: 'tr')
279
- progress.increment
280
- check_table_body = find_element(tag_name: 'tbody')
281
- check_table_rows = check_table_body.find_elements(tag_name: 'tr')
282
- progress.increment
283
- scan_info_table_rows.each do |row|
284
- key = find_element(row, tag_name: 'h5').text
285
- value = find_element(row, tag_name: 'strong').text
286
- report[key.downcase.tr(':', '').tr(' ', '_')] = value
287
- progress.increment
288
- end
289
- check_table_rows.each do |row|
290
- chk_objs = row.find_elements(tag_name: 'td')
291
- chk_objs.map!(&:text)
292
- if status.nil? || status.include?(chk_objs[1].downcase)
293
- name_parts = chk_objs[0].match(/^([0-9.]+) (.+)$/)
294
- key = normalize_cis_rec_name(name_parts[2])
295
- unless report['scan_results'].key?(chk_objs[1])
296
- report['scan_results'][chk_objs[1]] = {}
297
- end
298
- report['scan_results'][chk_objs[1]][key] = {
299
- 'name' => name_parts[2].chomp,
300
- 'number' => name_parts[1].chomp
301
- }
348
+ end
349
+ check_table_rows.each do |row|
350
+ chk_objs = row.find_elements(tag_name: 'td')
351
+ chk_objs.map!(&:text)
352
+ if status.nil? || status.include?(chk_objs[1].downcase)
353
+ name_parts = chk_objs[0].match(/^([0-9.]+) (.+)$/)
354
+ key = normalize_cis_rec_name(name_parts[2])
355
+ unless report['scan_results'].key?(chk_objs[1])
356
+ report['scan_results'][chk_objs[1]] = {}
302
357
  end
303
- progress.increment
358
+ report['scan_results'][chk_objs[1]][key] = {
359
+ 'name' => name_parts[2].chomp,
360
+ 'number' => name_parts[1].chomp
361
+ }
304
362
  end
305
- all_checks[node_name] = report
306
- driver.close
307
- output.simple "Created report for #{node_name}"
308
- rescue => e
309
- raise_error(e)
310
- ensure
311
- driver.switch_to.window original_window
363
+ progress.increment
312
364
  end
365
+ all_checks[node_name] = report
366
+ driver.close
367
+ output.simple "Created report for #{node_name}"
368
+ rescue ::StandardError => e
369
+ raise_error(e)
370
+ ensure
371
+ driver.switch_to.window original_window
313
372
  end
314
373
  all_checks
315
374
  end
@@ -317,6 +376,8 @@ module AbideDevUtils
317
376
 
318
377
  # Contains multiple NodeScanReport objects
319
378
  class ScanReport
379
+ attr_reader :node_scan_reports
380
+
320
381
  def from_yaml(report)
321
382
  @scan_report = if report.is_a? Hash
322
383
  report
@@ -325,7 +386,65 @@ module AbideDevUtils
325
386
  else
326
387
  YAML.safe_load(report)
327
388
  end
328
- build_node_scan_reports
389
+ @node_scan_reports = build_node_scan_reports
390
+ self
391
+ end
392
+
393
+ def to_h
394
+ node_scan_reports.each_with_object({}) do |node, h|
395
+ h[node.name] = node.hash
396
+ end
397
+ end
398
+
399
+ def to_yaml
400
+ to_h.to_yaml
401
+ end
402
+
403
+ def self.storage_bucket
404
+ @storage_bucket ||= AbideDevUtils::GCloud.storage_bucket
405
+ end
406
+
407
+ def self.fetch_report(name: 'comply_report.yaml')
408
+ report = storage_bucket.file(name)
409
+ report.download.read
410
+ end
411
+
412
+ def self.upload_report(report, name: 'comply_report.yaml')
413
+ storage_bucket.create_file(report, name)
414
+ end
415
+
416
+ def report_comparison(other, check_goodness: false)
417
+ comparison = []
418
+ node_scan_reports.zip(other.node_scan_reports).each do |cr, lr|
419
+ comparison << { cr.name => { diff: {}, node_presense: :new } } if lr.nil?
420
+ comparison << { lr.name => { diff: {}, node_presense: :dropped } } if cr.nil?
421
+ comparison << { cr.name => { diff: cr.diff(lr), node_presence: :same } } unless cr.nil? || lr.nil?
422
+ end
423
+ comparison.inject(&:merge)
424
+ return good_comparison?(comparison) if check_goodness
425
+
426
+ compairison
427
+ end
428
+
429
+ def good_comparison?(report_comparison)
430
+ good = true
431
+ not_good = {}
432
+ report_comparison.each do |node_report|
433
+ node_name = node_report.keys[0]
434
+ report = node_report[node_name]
435
+ next if report[:diff].empty?
436
+
437
+ not_good[node_name] = {}
438
+ unless report.dig(:diff, :passing, :other).nil?
439
+ good = false
440
+ not_good[node_name][:new_not_passing] = report[:diff][:passing][:other]
441
+ end
442
+ unless report.dig(:diff, :failing, :self).nil?
443
+ good = false
444
+ not_good[node_name][:new_failing] = report[:diff][:failing][:self]
445
+ end
446
+ end
447
+ [good, not_good]
329
448
  end
330
449
 
331
450
  private
@@ -341,20 +460,22 @@ module AbideDevUtils
341
460
 
342
461
  # Class representation of a Comply node scan report
343
462
  class NodeScanReport
344
- attr_reader :name, :passing, :failing, :not_checked, :informational, :benchmark, :last_scan, :profile
463
+ attr_reader :name, :passing, :failing, :error, :not_checked, :informational, :benchmark, :last_scan, :profile
345
464
 
346
- DIFF_PROPERTIES = %i[passing failing not_checked informational].freeze
465
+ DIFF_PROPERTIES = %i[passing failing error not_checked informational].freeze
347
466
 
348
467
  def initialize(node_name, node_hash)
349
468
  @name = node_name
350
469
  @hash = node_hash
351
470
  @passing = node_hash.dig('scan_results', 'Pass') || {}
352
471
  @failing = node_hash.dig('scan_results', 'Fail') || {}
472
+ @error = node_hash.dig('scan_results', 'Error') || {}
353
473
  @not_checked = node_hash.dig('scan_results', 'Not checked') || {}
354
474
  @informational = node_hash.dig('scan_results', 'Informational') || {}
355
475
  @benchmark = node_hash['benchmark']
356
476
  @last_scan = node_hash['last_scan']
357
477
  @profile = node_hash.fetch('custom_profile', nil) || node_hash.fetch('profile', nil)
478
+ create_equality_methods
358
479
  end
359
480
 
360
481
  def diff(other)
@@ -365,21 +486,17 @@ module AbideDevUtils
365
486
  diff
366
487
  end
367
488
 
368
- def method_missing(method_name, *args, &_block)
369
- case method_name
370
- when method_name.match?(/^(passing|failing|not_checked|informational)_equal?$/)
371
- property_equal?(method_name.delete_suffix('_equal?'), *args)
372
- when method_name.match?(/^(to_h|to_yaml)$/)
373
- @hash.send(method_name.to_sym)
374
- end
375
- end
489
+ private
376
490
 
377
- def respond_to_missing?(method_name, _include_private = false)
378
- method_name.match?(/^(((passing|failing|not_checked|informational)_equal?)|to_h|to_yaml)$/)
491
+ def create_equality_methods
492
+ DIFF_PROPERTIES.each do |prop|
493
+ meth_name = "#{prop.to_s}_equal?"
494
+ self.class.define_method(meth_name) do |other|
495
+ property_equal?(prop, other)
496
+ end
497
+ end
379
498
  end
380
499
 
381
- private
382
-
383
500
  def property_diff(property, other)
384
501
  {
385
502
  self: send(property).keys - other.send(property).keys,
@@ -388,54 +505,8 @@ module AbideDevUtils
388
505
  end
389
506
 
390
507
  def property_equal?(property, other_property)
391
- send(property.to_sym) == other_property
392
- end
393
- end
394
-
395
- def self.storage_bucket
396
- @storage_bucket ||= AbideDevUtils::GCloud.storage_bucket
397
- end
398
-
399
- def self.fetch_report
400
- report = storage_bucket.file('comply_report.yaml')
401
- report.download.read
402
- end
403
-
404
- def self.upload_report(report)
405
- file_to_upload = report.is_a?(Hash) ? report.to_yaml : report
406
- storage_bucket.create_file(file_to_upload, 'comply_report.yaml')
407
- end
408
-
409
- def self.report_comparison(current, last)
410
- current_report = ScanReport.new.from_yaml(current)
411
- last_report = ScanReport.new.from_yaml(last)
412
-
413
- comparison = []
414
- current_report.zip(last_report).each do |cr, lr|
415
- comparison << { cr.name => { diff: {}, node_presense: :new } } if lr.nil?
416
- comparison << { lr.name => { diff: {}, node_presense: :dropped } } if cr.nil?
417
- comparison << { cr.name => { diff: cr.diff(lr), node_presence: :same } } unless cr.nil? || lr.nil?
418
- end
419
- comparison.inject(&:merge)
420
- end
421
-
422
- def self.good_comparison?(report_comparison)
423
- good = true
424
- not_good = {}
425
- report_comparison.each do |node_name, report|
426
- next if report[:diff].empty?
427
-
428
- not_good[node_name] = {}
429
- unless report[:diff][:passing][:other].empty?
430
- good = false
431
- not_good[node_name][:new_not_passing] = report[:diff][:passing][:other]
432
- end
433
- unless report[:diff][:failing][:self].empty?
434
- good = false
435
- not_good[node_name][:new_failing] = report[:diff][:failing][:self]
436
- end
508
+ send(property) == other_property
437
509
  end
438
- [good, not_good]
439
510
  end
440
511
  end
441
512
  end
@@ -8,6 +8,10 @@ module AbideDevUtils
8
8
  class ComplyLoginFailedError < GenericError
9
9
  @default = 'Failed to login to Comply:'
10
10
  end
11
+
12
+ class WaitOnError < GenericError
13
+ @default = 'wait_on failed due to error:'
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -29,6 +29,11 @@ module AbideDevUtils
29
29
  @default = 'Path is not a directory:'
30
30
  end
31
31
 
32
+ # Raised when a file extension is not correct
33
+ class FileExtensionIncorrectError < GenericError
34
+ @default = 'File extension does not match specified extension:'
35
+ end
36
+
32
37
  # Raised when a searched for service is not found in the parser
33
38
  class ServiceNotFoundError < GenericError
34
39
  @default = 'Service not found:'
@@ -48,5 +53,9 @@ module AbideDevUtils
48
53
  class NotHashableError < GenericError
49
54
  @default = 'Object does not respond to #to_hash or #to_h:'
50
55
  end
56
+
57
+ class CliOptionsConflict < GenericError
58
+ @default = "Console options conflict."
59
+ end
51
60
  end
52
61
  end
@@ -12,5 +12,17 @@ module AbideDevUtils
12
12
  class StrategyInvalidError < GenericError
13
13
  @default = 'Invalid strategy selected. Should be either \'name\' or \'num\''
14
14
  end
15
+
16
+ class ControlPartsError < GenericError
17
+ @default = 'Failed to extract parts from control name:'
18
+ end
19
+
20
+ class ProfilePartsError < GenericError
21
+ @default = 'Failed to extract parts from profile name:'
22
+ end
23
+
24
+ class UnsupportedXCCDFError < GenericError
25
+ @default = "XCCDF type is unsupported!"
26
+ end
15
27
  end
16
28
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
3
4
  require 'abide_dev_utils/errors/gcloud'
4
5
 
5
6
  module AbideDevUtils
@@ -14,7 +15,7 @@ module AbideDevUtils
14
15
  require 'google/cloud/storage'
15
16
  @bucket = Google::Cloud::Storage.new(
16
17
  project_id: project || ENV['ABIDE_GCLOUD_PROJECT'],
17
- credentials: credentials || ENV['ABIDE_GCLOUD_CREDENTIALS']
18
+ credentials: credentials || JSON.parse(ENV['ABIDE_GCLOUD_CREDENTIALS'])
18
19
  ).bucket(name || ENV['ABIDE_GCLOUD_BUCKET'])
19
20
  end
20
21
  end
@@ -22,9 +22,13 @@ module AbideDevUtils
22
22
  end
23
23
 
24
24
  def self.yaml(in_obj, console: false, file: nil)
25
- AbideDevUtils::Validate.hashable(in_obj)
26
- # Use object's #to_yaml method if it exists, convert to hash if not
27
- yaml_out = in_obj.respond_to?(:to_yaml) ? in_obj.to_yaml : in_obj.to_h.to_yaml
25
+ yaml_out = if in_obj.is_a? String
26
+ in_obj
27
+ else
28
+ AbideDevUtils::Validate.hashable(in_obj)
29
+ # Use object's #to_yaml method if it exists, convert to hash if not
30
+ in_obj.respond_to?(:to_yaml) ? in_obj.to_yaml : in_obj.to_h.to_yaml
31
+ end
28
32
  simple(yaml_out) if console
29
33
  FWRITER.write_yaml(yaml_out, file: file) unless file.nil?
30
34
  end