cfndk 0.0.7 → 0.1.2
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 +5 -5
- data/.circleci/config.yml +79 -0
- data/.gitignore +1 -1
- data/.rspec +2 -0
- data/.rspec_parallel +6 -0
- data/.simplecov +9 -0
- data/Gemfile +11 -1
- data/Gemfile.lock +815 -0
- data/README.md +269 -76
- data/bin/cfndk +3 -18
- data/cfndk.gemspec +15 -6
- data/docker/Dockerfile +8 -0
- data/docker/build.sh +3 -0
- data/docker/cfndk.sh +14 -0
- data/lib/cfndk.rb +36 -0
- data/lib/cfndk/change_set_command.rb +103 -0
- data/lib/cfndk/command.rb +125 -119
- data/lib/cfndk/config_file_loadable.rb +13 -0
- data/lib/cfndk/credential_provider_chain.rb +12 -42
- data/lib/cfndk/credential_resolvable.rb +10 -0
- data/lib/cfndk/diff.rb +38 -0
- data/lib/cfndk/global_config.rb +46 -0
- data/lib/cfndk/key_pair.rb +66 -14
- data/lib/cfndk/key_pair_command.rb +60 -0
- data/lib/cfndk/key_pairs.rb +22 -5
- data/lib/cfndk/logger.rb +12 -3
- data/lib/cfndk/stack.rb +427 -126
- data/lib/cfndk/stack_command.rb +128 -0
- data/lib/cfndk/stacks.rb +48 -22
- data/lib/cfndk/subcommand_help_returnable.rb +16 -0
- data/lib/cfndk/template_packager.rb +210 -0
- data/lib/cfndk/uuid.rb +10 -0
- data/lib/cfndk/version.rb +1 -1
- data/skel/cfndk.yml +4 -0
- data/spec/.gitignore +1 -0
- data/spec/cfndk_change_set_create_spec.rb +436 -0
- data/spec/cfndk_change_set_destroy_spec.rb +160 -0
- data/spec/cfndk_change_set_execute_spec.rb +179 -0
- data/spec/cfndk_change_set_report_spec.rb +107 -0
- data/spec/cfndk_change_set_spec.rb +37 -0
- data/spec/cfndk_create_spec.rb +504 -0
- data/spec/cfndk_destroy_spec.rb +148 -0
- data/spec/cfndk_keypiar_spec.rb +397 -0
- data/spec/cfndk_report_spec.rb +164 -0
- data/spec/cfndk_spec.rb +103 -0
- data/spec/cfndk_stack_create_spec.rb +814 -0
- data/spec/cfndk_stack_destroy_spec.rb +225 -0
- data/spec/cfndk_stack_report_spec.rb +181 -0
- data/spec/cfndk_stack_spec.rb +133 -0
- data/spec/cfndk_stack_update_spec.rb +553 -0
- data/spec/fixtures/big_vpc.yaml +533 -0
- data/spec/fixtures/empty_resource.yaml +2 -0
- data/spec/fixtures/iam.json +8 -0
- data/spec/fixtures/iam.yaml +38 -0
- data/spec/fixtures/iam_different.json +8 -0
- data/spec/fixtures/invalid_vpc.yaml +21 -0
- data/spec/fixtures/lambda_function/index.js +4 -0
- data/spec/fixtures/lambda_function/lambda_function.json +4 -0
- data/spec/fixtures/lambda_function/lambda_function.yaml +28 -0
- data/spec/fixtures/nested_stack.json +35 -0
- data/spec/fixtures/nested_stack.yaml +20 -0
- data/spec/fixtures/serverless_function/index.js +4 -0
- data/spec/fixtures/serverless_function/serverless_function.json +4 -0
- data/spec/fixtures/serverless_function/serverless_function.yaml +21 -0
- data/spec/fixtures/sg.json +8 -0
- data/spec/fixtures/sg.yaml +27 -0
- data/spec/fixtures/sg_different.yaml +22 -0
- data/spec/fixtures/stack.json +8 -0
- data/spec/fixtures/stack.template.json +39 -0
- data/spec/fixtures/stack.yaml +22 -0
- data/spec/fixtures/vpc.json +8 -0
- data/spec/fixtures/vpc.template.json +40 -0
- data/spec/fixtures/vpc.yaml +21 -0
- data/spec/fixtures/vpc_different.yaml +21 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/aruba.rb +6 -0
- data/vagrant/Vagrantfile +89 -0
- metadata +259 -31
@@ -0,0 +1,13 @@
|
|
1
|
+
module CFnDK
|
2
|
+
module ConfigFileLoadable
|
3
|
+
private
|
4
|
+
|
5
|
+
def load_config_data(options)
|
6
|
+
raise "File does not exist. #{options[:config_path]}" unless File.file?(options[:config_path])
|
7
|
+
data = open(options[:config_path], 'r') { |f| YAML.load(f) }
|
8
|
+
return data if data
|
9
|
+
CFnDK.logger.error "File is empty. #{options[:config_path]}".color(:red)
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module CFnDK
|
2
2
|
class CredentialProviderChain
|
3
|
-
def initialize(
|
4
|
-
@
|
3
|
+
def initialize(profile = nil)
|
4
|
+
@profile = profile
|
5
5
|
end
|
6
6
|
|
7
7
|
def resolve
|
8
8
|
providers.each do |method_name, options|
|
9
|
-
|
9
|
+
CFnDK.logger.debug "resolving: #{method_name}"
|
10
|
+
provider = send(method_name, options)
|
11
|
+
CFnDK.logger.debug "resolved: #{method_name}" if provider && provider.set?
|
10
12
|
return provider if provider && provider.set?
|
11
13
|
end
|
12
14
|
nil
|
@@ -16,30 +18,17 @@ module CFnDK
|
|
16
18
|
|
17
19
|
def providers
|
18
20
|
[
|
19
|
-
[:static_credentials, {}],
|
20
21
|
[:env_credentials, {}],
|
21
22
|
[:assume_role_credentials, {}],
|
22
|
-
[:shared_credentials, {}],
|
23
|
-
[:process_credentials, {}],
|
23
|
+
[:shared_credentials, {profile: @profile}],
|
24
24
|
[:instance_profile_credentials, {
|
25
|
-
retries:
|
26
|
-
http_open_timeout:
|
27
|
-
http_read_timeout:
|
25
|
+
retries: 0,
|
26
|
+
http_open_timeout: 1,
|
27
|
+
http_read_timeout: 1,
|
28
28
|
}],
|
29
29
|
]
|
30
30
|
end
|
31
31
|
|
32
|
-
def static_credentials(options)
|
33
|
-
if options[:config]
|
34
|
-
::Aws::Credentials.new(
|
35
|
-
options[:config].access_key_id,
|
36
|
-
options[:config].secret_access_key,
|
37
|
-
options[:config].session_token)
|
38
|
-
else
|
39
|
-
nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
32
|
def env_credentials(options)
|
44
33
|
key = %w(AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY)
|
45
34
|
secret = %w(AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY)
|
@@ -55,8 +44,8 @@ module CFnDK
|
|
55
44
|
end
|
56
45
|
|
57
46
|
def shared_credentials(options)
|
58
|
-
if options[:
|
59
|
-
::Aws::SharedCredentials.new(profile_name: options[:
|
47
|
+
if options[:profile]
|
48
|
+
::Aws::SharedCredentials.new(profile_name: options[:profile])
|
60
49
|
else
|
61
50
|
::Aws::SharedCredentials.new(
|
62
51
|
profile_name: ENV['AWS_PROFILE'].nil? ? 'default' : ENV['AWS_PROFILE'])
|
@@ -65,29 +54,10 @@ module CFnDK
|
|
65
54
|
nil
|
66
55
|
end
|
67
56
|
|
68
|
-
def process_credentials(options)
|
69
|
-
profile_name = options[:config].profile if options[:config]
|
70
|
-
profile_name ||= ENV['AWS_PROFILE'].nil? ? 'default' : ENV['AWS_PROFILE']
|
71
|
-
|
72
|
-
config = ::Aws.shared_config
|
73
|
-
if config.config_enabled? && process_provider = config.credentials_process(profile_name)
|
74
|
-
::Aws::ProcessCredentials.new(process_provider)
|
75
|
-
else
|
76
|
-
nil
|
77
|
-
end
|
78
|
-
rescue ::Aws::Errors::NoSuchProfileError
|
79
|
-
nil
|
80
|
-
end
|
81
|
-
|
82
57
|
def assume_role_credentials(options)
|
83
58
|
if ::Aws.shared_config.config_enabled?
|
84
59
|
profile = nil
|
85
60
|
region = nil
|
86
|
-
if options[:config]
|
87
|
-
profile = options[:config].profile
|
88
|
-
region = options[:config].region
|
89
|
-
assume_role_with_profile(options[:config].profile, options[:config].region)
|
90
|
-
end
|
91
61
|
assume_role_with_profile(profile, region)
|
92
62
|
else
|
93
63
|
nil
|
@@ -106,7 +76,7 @@ module CFnDK
|
|
106
76
|
::Aws.shared_config.assume_role_credentials_from_config(
|
107
77
|
profile: prof,
|
108
78
|
region: region,
|
109
|
-
chain_config:
|
79
|
+
chain_config: nil
|
110
80
|
)
|
111
81
|
end
|
112
82
|
end
|
data/lib/cfndk/diff.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module CFnDK
|
2
|
+
FORMAT = :unified
|
3
|
+
LINES = 3
|
4
|
+
|
5
|
+
def self.diff(data_old, data_new)
|
6
|
+
result = ''
|
7
|
+
|
8
|
+
file_length_difference = 0
|
9
|
+
|
10
|
+
data_old = data_old.split($/).map { |e| e.chomp }
|
11
|
+
data_new = data_new.split($/).map { |e| e.chomp }
|
12
|
+
|
13
|
+
diffs = Diff::LCS.diff(data_old, data_new)
|
14
|
+
diffs = nil if diffs.empty?
|
15
|
+
|
16
|
+
return '' unless diffs
|
17
|
+
|
18
|
+
oldhunk = hunk = nil
|
19
|
+
|
20
|
+
diffs.each do |piece|
|
21
|
+
begin
|
22
|
+
hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, LINES, file_length_difference)
|
23
|
+
file_length_difference = hunk.file_length_difference
|
24
|
+
|
25
|
+
next unless oldhunk
|
26
|
+
next if LINES.positive? and hunk.merge(oldhunk)
|
27
|
+
|
28
|
+
result << oldhunk.diff(FORMAT) << "\n"
|
29
|
+
ensure
|
30
|
+
oldhunk = hunk
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
last = oldhunk.diff(FORMAT)
|
35
|
+
last << "\n" if last.respond_to?(:end_with?) && !last.end_with?("\n")
|
36
|
+
result << last
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module CFnDK
|
2
|
+
class GlobalConfig
|
3
|
+
attr_reader :timeout_in_minutes, :s3_template_bucket, :s3_template_hash, :region, :role_arn, :package, :profile, :pre_command, :post_command
|
4
|
+
def initialize(data, option)
|
5
|
+
@timeout_in_minutes = 1
|
6
|
+
@s3_template_bucket = 'cfndk-templates'
|
7
|
+
@s3_template_hash = Uuid.instance.uuid
|
8
|
+
@region = ENV['AWS_REGION'] || 'us-east-1'
|
9
|
+
@package = false
|
10
|
+
@profile = ENV['AWS_PROFILE'] || nil
|
11
|
+
return unless data['global'].is_a?(Hash)
|
12
|
+
@timeout_in_minutes = data['global']['timeout_in_minutes'] || 1
|
13
|
+
@s3_template_bucket = data['global']['s3_template_bucket'] || 'cfndk-templates'
|
14
|
+
@region = data['global']['region'] || ENV['AWS_REGION'] || 'us-east-1'
|
15
|
+
@package = data['global']['package'] === 'true' ? true : false
|
16
|
+
@role_arn = data['global']['role_arn'] || nil
|
17
|
+
@profile = ENV['AWS_PROFILE'] || data['global']['default_profile'] || nil
|
18
|
+
@pre_command = data['global']['pre_command'] || nil
|
19
|
+
@post_command = data['global']['post_command'] || nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def pre_command_execute
|
23
|
+
if @pre_command
|
24
|
+
CFnDK.logger.info(('execute global pre command: ' + @pre_command).color(:green))
|
25
|
+
IO.popen(@pre_command, :err => [:child, :out]) do |io|
|
26
|
+
io.each_line do |line|
|
27
|
+
CFnDK.logger.info((line).color(:green))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
raise 'global pre command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @pre_command if $?.exitstatus != 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def post_command_execute
|
35
|
+
if @post_command
|
36
|
+
CFnDK.logger.info(('execute global post command: ' + @post_command).color(:green))
|
37
|
+
IO.popen(@post_command, :err => [:child, :out]) do |io|
|
38
|
+
io.each_line do |line|
|
39
|
+
CFnDK.logger.info((line).color(:green))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
raise 'global post command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @post_command if $?.exitstatus != 0
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/cfndk/key_pair.rb
CHANGED
@@ -1,43 +1,95 @@
|
|
1
1
|
module CFnDK
|
2
2
|
class KeyPair
|
3
|
-
attr_reader :key_file
|
4
|
-
def initialize(name, data, option, credentials)
|
3
|
+
attr_reader :key_file, :enabled, :pre_command, :post_command
|
4
|
+
def initialize(name, data, option, global_config, credentials)
|
5
|
+
@global_config = global_config
|
5
6
|
@name = name
|
6
|
-
|
7
|
-
@key_file = data['key_file'] || nil
|
7
|
+
data = {} unless data
|
8
|
+
@key_file = data['key_file'] || nil
|
9
|
+
@region = data['region'] || @global_config.region
|
10
|
+
@pre_command = data['pre_command'] || nil
|
11
|
+
@post_command = data['post_command'] || nil
|
12
|
+
@enabled = true
|
13
|
+
@enabled = false if data['enabled'] === false
|
8
14
|
@option = option
|
9
|
-
@
|
10
|
-
@client = Aws::EC2::Client.new(credentials: credentials)
|
15
|
+
@client = Aws::EC2::Client.new(credentials: credentials, region: @region)
|
11
16
|
end
|
12
17
|
|
13
18
|
def create
|
14
|
-
|
19
|
+
return unless @enabled
|
20
|
+
CFnDK.logger.info(('creating keypair: ' + name).color(:green))
|
15
21
|
key_pair = @client.create_key_pair(
|
16
22
|
key_name: name
|
17
23
|
)
|
18
|
-
|
24
|
+
CFnDK.logger.info(('created keypair: ' + name).color(:green))
|
19
25
|
|
20
26
|
create_key_file(key_pair)
|
21
27
|
end
|
22
28
|
|
23
29
|
def destroy
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
return unless @enabled
|
31
|
+
if exists?
|
32
|
+
CFnDK.logger.info(('deleting keypair: ' + name).color(:green))
|
33
|
+
@client.delete_key_pair(
|
34
|
+
key_name: name
|
35
|
+
)
|
36
|
+
CFnDK.logger.info(('deleted keypair: ' + name).color(:green))
|
37
|
+
else
|
38
|
+
CFnDK.logger.info(('do not delete keypair: ' + name).color(:red))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def exists?
|
43
|
+
!@client.describe_key_pairs(
|
44
|
+
key_names: [
|
45
|
+
name,
|
46
|
+
]
|
47
|
+
).key_pairs.empty?
|
48
|
+
rescue Aws::EC2::Errors::InvalidKeyPairNotFound
|
49
|
+
false
|
29
50
|
end
|
30
51
|
|
31
52
|
def name
|
32
53
|
[@name, @option[:uuid]].compact.join('-')
|
33
54
|
end
|
34
55
|
|
56
|
+
def original_name
|
57
|
+
@name
|
58
|
+
end
|
59
|
+
|
60
|
+
def pre_command_execute
|
61
|
+
return unless @enabled
|
62
|
+
if @pre_command
|
63
|
+
CFnDK.logger.info(('execute pre command: ' + @pre_command).color(:green))
|
64
|
+
IO.popen(@pre_command, :err => [:child, :out]) do |io|
|
65
|
+
io.each_line do |line|
|
66
|
+
CFnDK.logger.info((line).color(:green))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
raise 'pre command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @pre_command if $?.exitstatus != 0
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def post_command_execute
|
74
|
+
return unless @enabled
|
75
|
+
if @post_command
|
76
|
+
CFnDK.logger.info(('execute post command: ' + @post_command).color(:green))
|
77
|
+
IO.popen(@post_command, :err => [:child, :out]) do |io|
|
78
|
+
io.each_line do |line|
|
79
|
+
CFnDK.logger.info((line).color(:green))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
raise 'post command is error. status: ' + $?.exitstatus.to_s + ' command: ' + @post_command if $?.exitstatus != 0
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
35
86
|
private
|
36
87
|
|
37
88
|
def create_key_file(key_pair)
|
38
89
|
return unless @key_file
|
39
90
|
key_file = CFnDK::ErbString.new(@key_file, @option).value
|
40
|
-
|
91
|
+
CFnDK.logger.info(('create key file: ' + key_file).color(:green))
|
92
|
+
FileUtils.mkdir_p(File.dirname(key_file))
|
41
93
|
File.write(key_file, key_pair.key_material)
|
42
94
|
end
|
43
95
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module CFnDK
|
2
|
+
class KeyPairCommand < Thor
|
3
|
+
include SubcommandHelpReturnable
|
4
|
+
include ConfigFileLoadable
|
5
|
+
include CredentialResolvable
|
6
|
+
|
7
|
+
class_option :verbose, type: :boolean, aliases: 'v', desc: 'More verbose output.'
|
8
|
+
class_option :color, type: :boolean, default: true, desc: 'Use colored output'
|
9
|
+
class_option :config_path, type: :string, aliases: 'c', default: "#{Dir.getwd}/cfndk.yml", desc: 'The configuration file to use'
|
10
|
+
class_option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
|
11
|
+
class_option :keypair_names, type: :array, desc: 'Target keypair names'
|
12
|
+
|
13
|
+
desc 'create', 'Create keypair'
|
14
|
+
option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
|
15
|
+
def create
|
16
|
+
CFnDK.logger.info 'create...'.color(:green)
|
17
|
+
data = load_config_data(options)
|
18
|
+
credentials = resolve_credential(data, options)
|
19
|
+
global_config = CFnDK::GlobalConfig.new(data, options)
|
20
|
+
keypairs = CFnDK::KeyPairs.new(data, options, credentials)
|
21
|
+
|
22
|
+
global_config.pre_command_execute
|
23
|
+
keypairs.pre_command_execute
|
24
|
+
keypairs.create
|
25
|
+
keypairs.post_command_execute
|
26
|
+
global_config.post_command_execute
|
27
|
+
return 0
|
28
|
+
rescue => e
|
29
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
30
|
+
e.backtrace_locations.each do |line|
|
31
|
+
CFnDK.logger.debug line
|
32
|
+
end
|
33
|
+
return 1
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'destroy', 'Destroy keypair'
|
37
|
+
option :force, type: :boolean, aliases: 'f', default: false, desc: 'Say yes to all prompts for confirmation'
|
38
|
+
def destroy
|
39
|
+
CFnDK.logger.info 'destroy...'.color(:green)
|
40
|
+
data = load_config_data(options)
|
41
|
+
credentials = resolve_credential(data, options)
|
42
|
+
|
43
|
+
keypairs = CFnDK::KeyPairs.new(data, options, credentials)
|
44
|
+
|
45
|
+
if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
|
46
|
+
keypairs.destroy
|
47
|
+
return 0
|
48
|
+
else
|
49
|
+
CFnDK.logger.info 'destroy command was canceled'.color(:green)
|
50
|
+
return 2
|
51
|
+
end
|
52
|
+
rescue => e
|
53
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
54
|
+
e.backtrace_locations.each do |line|
|
55
|
+
CFnDK.logger.debug line
|
56
|
+
end
|
57
|
+
return 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/cfndk/key_pairs.rb
CHANGED
@@ -3,17 +3,34 @@ module CFnDK
|
|
3
3
|
def initialize(data, option, credentials)
|
4
4
|
@option = option
|
5
5
|
@credentials = credentials
|
6
|
+
@global_config = CFnDK::GlobalConfig.new(data, option)
|
6
7
|
prepare_keypairs(data)
|
7
8
|
end
|
8
9
|
|
9
10
|
def create
|
10
|
-
|
11
|
-
|
11
|
+
@keypairs.each_value do |keypair|
|
12
|
+
next if @option[:keypair_names].instance_of?(Array) && !@option[:keypair_names].include?(keypair.original_name)
|
13
|
+
keypair.create
|
14
|
+
end
|
12
15
|
end
|
13
16
|
|
14
17
|
def destroy
|
15
|
-
|
16
|
-
|
18
|
+
@keypairs.each_value do |keypair|
|
19
|
+
next if @option[:keypair_names].instance_of?(Array) && !@option[:keypair_names].include?(keypair.original_name)
|
20
|
+
keypair.destroy
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def pre_command_execute
|
25
|
+
@keypairs.each_value do |keypair|
|
26
|
+
keypair.pre_command_execute
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def post_command_execute
|
31
|
+
@keypairs.each_value do |keypair|
|
32
|
+
keypair.post_command_execute
|
33
|
+
end
|
17
34
|
end
|
18
35
|
|
19
36
|
private
|
@@ -22,7 +39,7 @@ module CFnDK
|
|
22
39
|
@keypairs = {}
|
23
40
|
return unless data['keypairs']
|
24
41
|
data['keypairs'].each do |name, properties|
|
25
|
-
@keypairs[name] = KeyPair.new(name, properties, @option, @credentials)
|
42
|
+
@keypairs[name] = KeyPair.new(name, properties, @option, @global_config, @credentials)
|
26
43
|
end
|
27
44
|
end
|
28
45
|
end
|
data/lib/cfndk/logger.rb
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
module CFnDK
|
2
|
-
|
3
|
-
|
2
|
+
def self.logger
|
3
|
+
@logger = CFnDKLogger.new({}) if @logger.nil?
|
4
|
+
@logger
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.logger=(logger)
|
8
|
+
@logger = logger
|
9
|
+
end
|
10
|
+
|
11
|
+
class CFnDKLogger < Logger
|
12
|
+
def initialize(options)
|
4
13
|
super(STDOUT)
|
5
|
-
self.level = Logger::INFO unless
|
14
|
+
self.level = Logger::INFO unless options[:verbose]
|
6
15
|
self.formatter = proc { |severity, datetime, progname, message|
|
7
16
|
message.to_s.split(/\n/).map do |line|
|
8
17
|
"#{datetime} #{severity} #{line}\n"
|