license-acceptance 0.0.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +97 -0
- data/config/product_info.toml +1 -0
- data/lib/license_acceptance/acceptor.rb +117 -0
- data/lib/license_acceptance/arg_acceptance.rb +33 -0
- data/lib/license_acceptance/cli_flags/mixlib_cli.rb +22 -0
- data/lib/license_acceptance/cli_flags/thor.rb +21 -0
- data/lib/license_acceptance/config.rb +65 -0
- data/lib/license_acceptance/env_acceptance.rb +19 -0
- data/lib/license_acceptance/file_acceptance.rb +97 -0
- data/lib/license_acceptance/logger.rb +19 -0
- data/lib/license_acceptance/product.rb +23 -0
- data/lib/license_acceptance/product_reader.rb +108 -0
- data/lib/license_acceptance/product_relationship.rb +13 -0
- data/lib/license_acceptance/prompt_acceptance.rb +104 -0
- data/lib/license_acceptance/version.rb +3 -0
- data/spec/license_acceptance/acceptor_spec.rb +222 -0
- data/spec/license_acceptance/arg_acceptance_spec.rb +37 -0
- data/spec/license_acceptance/cli_flags/mixlib_cli_spec.rb +14 -0
- data/spec/license_acceptance/cli_flags/thor_spec.rb +14 -0
- data/spec/license_acceptance/config_spec.rb +113 -0
- data/spec/license_acceptance/env_acceptance_spec.rb +43 -0
- data/spec/license_acceptance/file_acceptance_spec.rb +121 -0
- data/spec/license_acceptance/product_reader_spec.rb +139 -0
- data/spec/license_acceptance/product_spec.rb +13 -0
- data/spec/license_acceptance/prompt_acceptance_spec.rb +100 -0
- data/spec/spec_helper.rb +25 -0
- metadata +184 -22
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/LICENSE +0 -1
- data/README.md +0 -35
- data/lib/license/acceptance/version.rb +0 -5
- data/lib/license/acceptance.rb +0 -8
- data/license-acceptance.gemspec +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ae4a25ff89f94b78498d69d0d5805a243e065cc2e622e4ec08f2acf8294345d
|
4
|
+
data.tar.gz: b994a62576a2e0c24694f916d3e4672f556077d8882bb52aa853706ef1e4e9c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6d8d023638ba548846b92b27e166a7ff2683b96b59eb5513b71c28ebbd46792dfd755e46893409e02dfbf4ce83dcee28e60e4c26716078fbe122b465553d399
|
7
|
+
data.tar.gz: d4501d2b154e6fcf8dabdc1a40c689d2bb575ea09f0f61b1f3ccbb5775609808ac6543fc6f9ed9bbee262fc085ddc634ecc4f3732a01cc17e951422162fdcded
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
license-acceptance (0.1.0)
|
5
|
+
pastel (>= 0.7)
|
6
|
+
tomlrb (~> 1.2)
|
7
|
+
tty-box (>= 0.3)
|
8
|
+
tty-platform (>= 0.2)
|
9
|
+
tty-prompt (>= 0.18)
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: https://rubygems.org/
|
13
|
+
specs:
|
14
|
+
binding_of_caller (0.8.0)
|
15
|
+
debug_inspector (>= 0.0.1)
|
16
|
+
byebug (11.0.1)
|
17
|
+
climate_control (0.2.0)
|
18
|
+
coderay (1.1.2)
|
19
|
+
debug_inspector (0.0.3)
|
20
|
+
diff-lcs (1.3)
|
21
|
+
equatable (0.5.0)
|
22
|
+
method_source (0.9.2)
|
23
|
+
mixlib-cli (2.0.3)
|
24
|
+
necromancer (0.4.0)
|
25
|
+
pastel (0.7.2)
|
26
|
+
equatable (~> 0.5.0)
|
27
|
+
tty-color (~> 0.4.0)
|
28
|
+
pry (0.12.2)
|
29
|
+
coderay (~> 1.1.0)
|
30
|
+
method_source (~> 0.9.0)
|
31
|
+
pry-byebug (3.7.0)
|
32
|
+
byebug (~> 11.0)
|
33
|
+
pry (~> 0.10)
|
34
|
+
pry-stack_explorer (0.4.9.3)
|
35
|
+
binding_of_caller (>= 0.7)
|
36
|
+
pry (>= 0.9.11)
|
37
|
+
rake (12.3.2)
|
38
|
+
rspec (3.8.0)
|
39
|
+
rspec-core (~> 3.8.0)
|
40
|
+
rspec-expectations (~> 3.8.0)
|
41
|
+
rspec-mocks (~> 3.8.0)
|
42
|
+
rspec-core (3.8.0)
|
43
|
+
rspec-support (~> 3.8.0)
|
44
|
+
rspec-expectations (3.8.2)
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
+
rspec-support (~> 3.8.0)
|
47
|
+
rspec-mocks (3.8.0)
|
48
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
49
|
+
rspec-support (~> 3.8.0)
|
50
|
+
rspec-support (3.8.0)
|
51
|
+
strings (0.1.4)
|
52
|
+
strings-ansi (~> 0.1.0)
|
53
|
+
unicode-display_width (~> 1.4.0)
|
54
|
+
unicode_utils (~> 1.4.0)
|
55
|
+
strings-ansi (0.1.0)
|
56
|
+
thor (0.20.3)
|
57
|
+
timers (4.3.0)
|
58
|
+
tomlrb (1.2.8)
|
59
|
+
tty-box (0.3.0)
|
60
|
+
pastel (~> 0.7.2)
|
61
|
+
strings (~> 0.1.4)
|
62
|
+
tty-cursor (~> 0.6.0)
|
63
|
+
tty-color (0.4.3)
|
64
|
+
tty-cursor (0.6.1)
|
65
|
+
tty-platform (0.2.0)
|
66
|
+
tty-prompt (0.18.1)
|
67
|
+
necromancer (~> 0.4.0)
|
68
|
+
pastel (~> 0.7.0)
|
69
|
+
timers (~> 4.0)
|
70
|
+
tty-cursor (~> 0.6.0)
|
71
|
+
tty-reader (~> 0.5.0)
|
72
|
+
tty-reader (0.5.0)
|
73
|
+
tty-cursor (~> 0.6.0)
|
74
|
+
tty-screen (~> 0.6.4)
|
75
|
+
wisper (~> 2.0.0)
|
76
|
+
tty-screen (0.6.5)
|
77
|
+
unicode-display_width (1.4.1)
|
78
|
+
unicode_utils (1.4.0)
|
79
|
+
wisper (2.0.0)
|
80
|
+
|
81
|
+
PLATFORMS
|
82
|
+
ruby
|
83
|
+
|
84
|
+
DEPENDENCIES
|
85
|
+
bundler (>= 1.17)
|
86
|
+
climate_control (>= 0.2)
|
87
|
+
license-acceptance!
|
88
|
+
mixlib-cli (>= 1.7)
|
89
|
+
pry (>= 0.12)
|
90
|
+
pry-byebug (>= 3.6)
|
91
|
+
pry-stack_explorer (>= 0.4)
|
92
|
+
rake (>= 10.0)
|
93
|
+
rspec (>= 3.0)
|
94
|
+
thor (>= 0.20)
|
95
|
+
|
96
|
+
BUNDLED WITH
|
97
|
+
1.17.3
|
@@ -0,0 +1 @@
|
|
1
|
+
# DO NOT CHANGE - overwritten by expeditor at build time
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "license_acceptance/config"
|
3
|
+
require "license_acceptance/logger"
|
4
|
+
require "license_acceptance/product_reader"
|
5
|
+
require "license_acceptance/product_relationship"
|
6
|
+
require "license_acceptance/file_acceptance"
|
7
|
+
require "license_acceptance/arg_acceptance"
|
8
|
+
require "license_acceptance/prompt_acceptance"
|
9
|
+
require "license_acceptance/env_acceptance"
|
10
|
+
|
11
|
+
module LicenseAcceptance
|
12
|
+
class Acceptor
|
13
|
+
extend Forwardable
|
14
|
+
include Logger
|
15
|
+
|
16
|
+
attr_reader :config, :product_reader, :env_acceptance, :file_acceptance, :arg_acceptance, :prompt_acceptance
|
17
|
+
|
18
|
+
def initialize(opts={})
|
19
|
+
@config = Config.new(opts)
|
20
|
+
Logger.initialize(config.logger)
|
21
|
+
@product_reader = ProductReader.new
|
22
|
+
@env_acceptance = EnvAcceptance.new
|
23
|
+
@file_acceptance = FileAcceptance.new(config)
|
24
|
+
@arg_acceptance = ArgAcceptance.new
|
25
|
+
@prompt_acceptance = PromptAcceptance.new(config)
|
26
|
+
end
|
27
|
+
|
28
|
+
def_delegator :@config, :output
|
29
|
+
|
30
|
+
# For applications that just need simple logic to handle a failed license acceptance flow we include this small
|
31
|
+
# wrapper. Apps with more complex logic (like logging to a logging engine) should call the non-bang version and
|
32
|
+
# handle the exception.
|
33
|
+
def check_and_persist!(product_name, version)
|
34
|
+
check_and_persist(product_name, version)
|
35
|
+
rescue LicenseNotAcceptedError
|
36
|
+
output.puts "#{product_name} cannot execute without accepting the license"
|
37
|
+
exit 172
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_and_persist(product_name, version)
|
41
|
+
if env_acceptance.check_no_persist(ENV) || arg_acceptance.check_no_persist(ARGV)
|
42
|
+
logger.debug("Chef License accepted with no persistence")
|
43
|
+
return true
|
44
|
+
end
|
45
|
+
|
46
|
+
product_reader.read
|
47
|
+
product_relationship = product_reader.lookup(product_name, version)
|
48
|
+
|
49
|
+
missing_licenses = file_acceptance.check(product_relationship)
|
50
|
+
|
51
|
+
# They have already accepted all licenses and stored their acceptance in the persistent files
|
52
|
+
if missing_licenses.empty?
|
53
|
+
logger.debug("All licenses present")
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
|
57
|
+
if env_acceptance.check(ENV) || arg_acceptance.check(ARGV)
|
58
|
+
if config.persist
|
59
|
+
errs = file_acceptance.persist(product_relationship, missing_licenses)
|
60
|
+
if errs.empty?
|
61
|
+
output_num_persisted(missing_licenses.size)
|
62
|
+
else
|
63
|
+
output_persist_failed(errs)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
return true
|
67
|
+
elsif config.output.isatty && prompt_acceptance.request(missing_licenses) do
|
68
|
+
if config.persist
|
69
|
+
file_acceptance.persist(product_relationship, missing_licenses)
|
70
|
+
else
|
71
|
+
[]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
return true
|
75
|
+
else
|
76
|
+
raise LicenseNotAcceptedError.new(missing_licenses)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.check_and_persist!(product_name, version, opts={})
|
81
|
+
new(opts).check_and_persist!(product_name, version)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.check_and_persist(product_name, version, opts={})
|
85
|
+
new(opts).check_and_persist(product_name, version)
|
86
|
+
end
|
87
|
+
|
88
|
+
# In the case where users accept with a command line argument or environment variable
|
89
|
+
# we still want to output the fact that the filesystem was changed.
|
90
|
+
def output_num_persisted(count)
|
91
|
+
s = count > 1 ? "s": ""
|
92
|
+
output.puts <<~EOM
|
93
|
+
#{PromptAcceptance::BORDER}
|
94
|
+
#{PromptAcceptance::CHECK} #{count} product license#{s} accepted.
|
95
|
+
#{PromptAcceptance::BORDER}
|
96
|
+
EOM
|
97
|
+
end
|
98
|
+
|
99
|
+
def output_persist_failed(errs)
|
100
|
+
output.puts <<~EOM
|
101
|
+
#{PromptAcceptance::BORDER}
|
102
|
+
#{PromptAcceptance::CHECK} Product license accepted.
|
103
|
+
Could not persist acceptance:\n\t* #{errs.map(&:message).join("\n\t* ")}
|
104
|
+
#{PromptAcceptance::BORDER}
|
105
|
+
EOM
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class LicenseNotAcceptedError < RuntimeError
|
111
|
+
def initialize(missing_licenses)
|
112
|
+
msg = "Missing licenses for the following:\n* " + missing_licenses.join("\n* ")
|
113
|
+
super(msg)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module LicenseAcceptance
|
2
|
+
class ArgAcceptance
|
3
|
+
|
4
|
+
def check(argv)
|
5
|
+
if argv.include?("--chef-license=accept")
|
6
|
+
return true
|
7
|
+
end
|
8
|
+
i = argv.index("--chef-license")
|
9
|
+
unless i.nil?
|
10
|
+
val = argv[i+1]
|
11
|
+
if val != nil && val.downcase == "accept"
|
12
|
+
return true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_no_persist(argv)
|
19
|
+
if argv.include?("--chef-license=accept-no-persist")
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
i = argv.index("--chef-license")
|
23
|
+
unless i.nil?
|
24
|
+
val = argv[i+1]
|
25
|
+
if val != nil && val.downcase == "accept-no-persist"
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
begin
|
2
|
+
require 'mixlib/cli'
|
3
|
+
rescue => exception
|
4
|
+
raise "Must have mixlib-cli gem installed to use this mixin"
|
5
|
+
end
|
6
|
+
|
7
|
+
module LicenseAcceptance
|
8
|
+
module CLIFlags
|
9
|
+
|
10
|
+
module MixlibCLI
|
11
|
+
|
12
|
+
def self.included(klass)
|
13
|
+
klass.option :chef_license,
|
14
|
+
long: "--chef-license ACCEPTANCE",
|
15
|
+
description: "Accept the license for this product and any contained products ('accept' or 'accept-no-persist')",
|
16
|
+
required: false
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'thor'
|
3
|
+
rescue => exception
|
4
|
+
raise "Must have thor gem installed to use this mixin"
|
5
|
+
end
|
6
|
+
|
7
|
+
module LicenseAcceptance
|
8
|
+
module CLIFlags
|
9
|
+
|
10
|
+
module Thor
|
11
|
+
|
12
|
+
def self.included(klass)
|
13
|
+
klass.class_option :chef_license,
|
14
|
+
type: :string,
|
15
|
+
desc: 'Accept the license for this product and any contained products: accept, accept-no-persist'
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'tty-platform'
|
3
|
+
|
4
|
+
module LicenseAcceptance
|
5
|
+
class Config
|
6
|
+
attr_accessor :output, :logger, :license_locations, :persist_location, :persist
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@output = opts.fetch(:output, $stdout)
|
10
|
+
@logger = opts.fetch(:logger, ::Logger.new(IO::NULL))
|
11
|
+
@license_locations = opts.fetch(:license_locations, default_license_locations)
|
12
|
+
@license_locations = [ @license_locations ].flatten
|
13
|
+
@persist_location = opts.fetch(:persist_location, default_persist_location)
|
14
|
+
@persist = opts.fetch(:persist, true)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def platform
|
20
|
+
@platform ||= TTY::Platform.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_root?
|
24
|
+
Process.uid == 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_license_locations
|
28
|
+
if platform.windows?
|
29
|
+
l = [ File.join(ENV["HOMEDRIVE"], "chef/accepted_licenses/") ]
|
30
|
+
unless is_root?
|
31
|
+
# Look through a list of possible user locations and pick the first one that exists
|
32
|
+
# copied from path_helper.rb in chef-config gem
|
33
|
+
possible_dirs = []
|
34
|
+
possible_dirs << ENV["HOME"] if ENV["HOME"]
|
35
|
+
possible_dirs << ENV["HOMEDRIVE"] + ENV["HOMEPATH"] if ENV["HOMEDRIVE"] && ENV["HOMEPATH"]
|
36
|
+
possible_dirs << ENV["HOMESHARE"] + ENV["HOMEPATH"] if ENV["HOMESHARE"] && ENV["HOMEPATH"]
|
37
|
+
possible_dirs << ENV["USERPROFILE"] if ENV["USERPROFILE"]
|
38
|
+
raise NoValidEnvironmentVar if possible_dirs.empty?
|
39
|
+
possible_dirs.each do |possible_dir|
|
40
|
+
if Dir.exist?(possible_dir)
|
41
|
+
full_possible_dir = File.join(possible_dir, ".chef/accepted_licenses/")
|
42
|
+
l << full_possible_dir
|
43
|
+
break
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
l = [ "/etc/chef/accepted_licenses/" ]
|
49
|
+
l << File.join(ENV['HOME'], ".chef/accepted_licenses/") unless is_root?
|
50
|
+
end
|
51
|
+
l
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_persist_location
|
55
|
+
license_locations[-1]
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class NoValidEnvironmentVar < StandardError
|
61
|
+
def initialize
|
62
|
+
super("no valid environment variables set on Windows")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LicenseAcceptance
|
2
|
+
class EnvAcceptance
|
3
|
+
|
4
|
+
def check(env)
|
5
|
+
if env['CHEF_LICENSE'] && env['CHEF_LICENSE'].downcase == 'accept'
|
6
|
+
return true
|
7
|
+
end
|
8
|
+
return false
|
9
|
+
end
|
10
|
+
|
11
|
+
def check_no_persist(env)
|
12
|
+
if env['CHEF_LICENSE'] && env['CHEF_LICENSE'].downcase == 'accept-no-persist'
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'yaml'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'etc'
|
5
|
+
require "license_acceptance/logger"
|
6
|
+
|
7
|
+
module LicenseAcceptance
|
8
|
+
class FileAcceptance
|
9
|
+
include Logger
|
10
|
+
|
11
|
+
attr_reader :config
|
12
|
+
|
13
|
+
def initialize(config)
|
14
|
+
@config = config
|
15
|
+
end
|
16
|
+
|
17
|
+
INVOCATION_TIME = DateTime.now.freeze
|
18
|
+
|
19
|
+
# For all the given products in the product set, search all possible locations for the
|
20
|
+
# license acceptance files.
|
21
|
+
def check(product_relationship)
|
22
|
+
searching = [product_relationship.parent] + product_relationship.children
|
23
|
+
missing_licenses = searching.clone
|
24
|
+
logger.debug("Searching for the following licenses: #{missing_licenses.map(&:name)}")
|
25
|
+
|
26
|
+
searching.each do |product|
|
27
|
+
found = false
|
28
|
+
config.license_locations.each do |loc|
|
29
|
+
f = File.join(loc, product.filename)
|
30
|
+
if File.exist?(f)
|
31
|
+
found = true
|
32
|
+
logger.debug("Found license #{product.filename} at #{f}")
|
33
|
+
missing_licenses.delete(product)
|
34
|
+
break
|
35
|
+
end
|
36
|
+
end
|
37
|
+
break if missing_licenses.empty?
|
38
|
+
end
|
39
|
+
logger.debug("Missing licenses remaining: #{missing_licenses.map(&:name)}")
|
40
|
+
missing_licenses
|
41
|
+
end
|
42
|
+
|
43
|
+
def persist(product_relationship, missing_licenses)
|
44
|
+
parent = product_relationship.parent
|
45
|
+
parent_version = product_relationship.parent_version
|
46
|
+
root_dir = config.persist_location
|
47
|
+
|
48
|
+
if !Dir.exist?(root_dir)
|
49
|
+
begin
|
50
|
+
FileUtils.mkdir_p(root_dir)
|
51
|
+
rescue StandardError => e
|
52
|
+
msg = "Could not create license directory #{root_dir}"
|
53
|
+
logger.info "#{msg}\n\t#{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
54
|
+
return [e]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
errs = []
|
59
|
+
if missing_licenses.include?(parent)
|
60
|
+
err = persist_license(root_dir, parent, parent, parent_version)
|
61
|
+
errs << err unless err.nil?
|
62
|
+
end
|
63
|
+
product_relationship.children.each do |child|
|
64
|
+
if missing_licenses.include?(child)
|
65
|
+
err = persist_license(root_dir, child, parent, parent_version)
|
66
|
+
errs << err unless err.nil?
|
67
|
+
end
|
68
|
+
end
|
69
|
+
return errs
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def persist_license(folder_path, product, parent, parent_version)
|
75
|
+
path = File.join(folder_path, product.filename)
|
76
|
+
logger.info("Persisting a license for #{product.name} at path #{path}")
|
77
|
+
File.open(path, File::WRONLY | File::CREAT | File::EXCL) do |license_file|
|
78
|
+
contents = {
|
79
|
+
name: product.name,
|
80
|
+
date_accepted: INVOCATION_TIME.iso8601,
|
81
|
+
accepting_product: parent.name,
|
82
|
+
accepting_product_version: parent_version,
|
83
|
+
user: Etc.getlogin,
|
84
|
+
file_format: 1,
|
85
|
+
}
|
86
|
+
contents = Hash[contents.map { |k, v| [k.to_s, v] }]
|
87
|
+
license_file << YAML.dump(contents)
|
88
|
+
end
|
89
|
+
return nil
|
90
|
+
rescue StandardError => e
|
91
|
+
msg = "Could not persist license to #{path}"
|
92
|
+
logger.info "#{msg}\n\t#{e.message}\n\t#{e.backtrace.join("\n\t")}"
|
93
|
+
return e
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|