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,128 @@
|
|
1
|
+
module CFnDK
|
2
|
+
class StackCommand < 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 :stack_names, type: :array, aliases: 's', desc: 'Target stack names'
|
11
|
+
|
12
|
+
desc 'create', 'Create stack'
|
13
|
+
option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
|
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
|
+
stacks = CFnDK::Stacks.new(data, options, credentials)
|
21
|
+
|
22
|
+
global_config.pre_command_execute
|
23
|
+
stacks.pre_command_execute
|
24
|
+
stacks.validate
|
25
|
+
stacks.create
|
26
|
+
stacks.post_command_execute
|
27
|
+
global_config.post_command_execute
|
28
|
+
return 0
|
29
|
+
rescue => e
|
30
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
31
|
+
e.backtrace_locations.each do |line|
|
32
|
+
CFnDK.logger.debug line
|
33
|
+
end
|
34
|
+
return 1
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'update', 'Update stack'
|
38
|
+
option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
|
39
|
+
option :properties, type: :hash, aliases: 'p', default: {}, desc: 'Set property'
|
40
|
+
def update
|
41
|
+
CFnDK.logger.info 'update...'.color(:green)
|
42
|
+
data = load_config_data(options)
|
43
|
+
credentials = resolve_credential(data, options)
|
44
|
+
global_config = CFnDK::GlobalConfig.new(data, options)
|
45
|
+
stacks = CFnDK::Stacks.new(data, options, credentials)
|
46
|
+
|
47
|
+
global_config.pre_command_execute
|
48
|
+
stacks.pre_command_execute
|
49
|
+
stacks.validate
|
50
|
+
stacks.update
|
51
|
+
stacks.post_command_execute
|
52
|
+
global_config.post_command_execute
|
53
|
+
return 0
|
54
|
+
rescue => e
|
55
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
56
|
+
e.backtrace_locations.each do |line|
|
57
|
+
CFnDK.logger.debug line
|
58
|
+
end
|
59
|
+
return 1
|
60
|
+
end
|
61
|
+
|
62
|
+
desc 'destroy', 'Destroy stack'
|
63
|
+
option :force, type: :boolean, aliases: 'f', default: false, desc: 'Say yes to all prompts for confirmation'
|
64
|
+
option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
|
65
|
+
def destroy
|
66
|
+
CFnDK.logger.info 'destroy...'.color(:green)
|
67
|
+
data = load_config_data(options)
|
68
|
+
credentials = resolve_credential(data, options)
|
69
|
+
|
70
|
+
stacks = CFnDK::Stacks.new(data, options, credentials)
|
71
|
+
|
72
|
+
if options[:force] || yes?('Are you sure you want to destroy? (y/n)', :yellow)
|
73
|
+
stacks.destroy
|
74
|
+
return 0
|
75
|
+
else
|
76
|
+
CFnDK.logger.info 'destroy command was canceled'.color(:green)
|
77
|
+
return 2
|
78
|
+
end
|
79
|
+
rescue => e
|
80
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
81
|
+
e.backtrace_locations.each do |line|
|
82
|
+
CFnDK.logger.debug line
|
83
|
+
end
|
84
|
+
return 1
|
85
|
+
end
|
86
|
+
|
87
|
+
desc 'validate', 'Validate stack'
|
88
|
+
def validate
|
89
|
+
CFnDK.logger.info 'validate...'.color(:green)
|
90
|
+
data = load_config_data(options)
|
91
|
+
credentials = resolve_credential(data, options)
|
92
|
+
global_config = CFnDK::GlobalConfig.new(data, options)
|
93
|
+
stacks = CFnDK::Stacks.new(data, options, credentials)
|
94
|
+
|
95
|
+
global_config.pre_command_execute
|
96
|
+
stacks.pre_command_execute
|
97
|
+
stacks.validate
|
98
|
+
stacks.post_command_execute
|
99
|
+
global_config.post_command_execute
|
100
|
+
return 0
|
101
|
+
rescue => e
|
102
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
103
|
+
e.backtrace_locations.each do |line|
|
104
|
+
CFnDK.logger.debug line
|
105
|
+
end
|
106
|
+
return 1
|
107
|
+
end
|
108
|
+
|
109
|
+
desc 'report', 'Report stack'
|
110
|
+
option :uuid, type: :string, aliases: 'u', default: ENV['CFNDK_UUID'] || nil, desc: 'Use UUID'
|
111
|
+
option :types, type: :array, default: %w(tag output parameter resource event), desc: 'Report type'
|
112
|
+
def report
|
113
|
+
CFnDK.logger.info 'report...'.color(:green)
|
114
|
+
data = load_config_data(options)
|
115
|
+
credentials = resolve_credential(data, options)
|
116
|
+
|
117
|
+
stacks = CFnDK::Stacks.new(data, options, credentials)
|
118
|
+
stacks.report
|
119
|
+
return 0
|
120
|
+
rescue => e
|
121
|
+
CFnDK.logger.error "#{e.class}: #{e.message}".color(:red)
|
122
|
+
e.backtrace_locations.each do |line|
|
123
|
+
CFnDK.logger.debug line
|
124
|
+
end
|
125
|
+
return 1
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/cfndk/stacks.rb
CHANGED
@@ -3,8 +3,7 @@ module CFnDK
|
|
3
3
|
def initialize(data, option, credentials)
|
4
4
|
@option = option
|
5
5
|
@credentials = credentials
|
6
|
-
@
|
7
|
-
|
6
|
+
@global_config = CFnDK::GlobalConfig.new(data, option)
|
8
7
|
prepare_stack(data)
|
9
8
|
prepare_sequence
|
10
9
|
end
|
@@ -52,48 +51,74 @@ module CFnDK
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
|
-
def
|
54
|
+
def create_change_set
|
56
55
|
@sequence.each do |stacks|
|
57
|
-
|
58
|
-
changeset_stacks = []
|
56
|
+
wait_until_stacks = []
|
59
57
|
stacks.each do |name|
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
wait_until_stacks.push(@stacks[name].create_change_set)
|
59
|
+
end
|
60
|
+
wait_until_stacks.compact!
|
61
|
+
wait_until_stacks.each do |name|
|
62
|
+
@stacks[name].wait_until_create_change_set
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute_change_set
|
68
|
+
@sequence.each do |stacks|
|
69
|
+
created_stacks = []
|
70
|
+
wait_until_stacks = []
|
71
|
+
stacks.each do |name|
|
72
|
+
created_stacks.push(name) if @stacks[name].created?
|
73
|
+
wait_until_stacks.push(@stacks[name].execute_change_set)
|
74
|
+
end
|
75
|
+
wait_until_stacks.compact!
|
76
|
+
wait_until_stacks.each do |name|
|
77
|
+
if created_stacks.include?(name)
|
78
|
+
@stacks[name].wait_until_update
|
63
79
|
else
|
64
|
-
@stacks[name].
|
65
|
-
create_stacks.push name
|
80
|
+
@stacks[name].wait_until_create
|
66
81
|
end
|
67
82
|
end
|
68
|
-
|
69
|
-
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete_change_set
|
87
|
+
@sequence.reverse_each do |stacks|
|
88
|
+
stacks.each do |name|
|
89
|
+
@stacks[name].delete_change_set
|
70
90
|
end
|
71
|
-
|
72
|
-
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def report_change_set
|
95
|
+
@sequence.each do |stacks|
|
96
|
+
stacks.each do |name|
|
97
|
+
@stacks[name].report_change_set
|
73
98
|
end
|
74
99
|
end
|
75
100
|
end
|
76
101
|
|
77
|
-
def
|
102
|
+
def report
|
78
103
|
@sequence.each do |stacks|
|
79
104
|
stacks.each do |name|
|
80
|
-
@stacks[name].
|
105
|
+
@stacks[name].report
|
81
106
|
end
|
82
107
|
end
|
83
108
|
end
|
84
109
|
|
85
|
-
def
|
110
|
+
def pre_command_execute
|
86
111
|
@sequence.each do |stacks|
|
87
112
|
stacks.each do |name|
|
88
|
-
@stacks[name].
|
113
|
+
@stacks[name].pre_command_execute
|
89
114
|
end
|
90
115
|
end
|
91
116
|
end
|
92
117
|
|
93
|
-
def
|
118
|
+
def post_command_execute
|
94
119
|
@sequence.each do |stacks|
|
95
120
|
stacks.each do |name|
|
96
|
-
@stacks[name].
|
121
|
+
@stacks[name].post_command_execute
|
97
122
|
end
|
98
123
|
end
|
99
124
|
end
|
@@ -102,8 +127,9 @@ module CFnDK
|
|
102
127
|
|
103
128
|
def prepare_stack(data)
|
104
129
|
@stacks = {}
|
130
|
+
return unless data['stacks'].is_a?(Hash)
|
105
131
|
data['stacks'].each do |name, properties|
|
106
|
-
@stacks[name] = Stack.new(name, properties, @option, @credentials)
|
132
|
+
@stacks[name] = Stack.new(name, properties, @option, @global_config, @credentials)
|
107
133
|
end
|
108
134
|
end
|
109
135
|
|
@@ -117,7 +143,7 @@ module CFnDK
|
|
117
143
|
names_of_processed_stack.include? depend_name
|
118
144
|
end
|
119
145
|
end
|
120
|
-
raise
|
146
|
+
raise "There are cyclic dependency or stack doesn't exist. unprocessed_stack: " + names_of_upprocessed_stack.join(',') if names.empty?
|
121
147
|
names_of_processed_stack += names
|
122
148
|
names_of_upprocessed_stack -= names
|
123
149
|
@sequence.push names
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CFnDK
|
2
|
+
module SubcommandHelpReturnable
|
3
|
+
module ClassMethods
|
4
|
+
def subcommand_help(cmd)
|
5
|
+
desc 'help [COMMAND]', 'Describe subcommands or one specific subcommand'
|
6
|
+
class_eval "
|
7
|
+
def help(command = nil, subcommand = true); super; return 2; end
|
8
|
+
"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
extend ClassMethods
|
12
|
+
def self.included(klass)
|
13
|
+
klass.extend ClassMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
using Polyfill(
|
2
|
+
String: %w[#delete_prefix]
|
3
|
+
)
|
4
|
+
|
5
|
+
module CFnDK
|
6
|
+
class TemplatePackager
|
7
|
+
def initialize(template_file, region, package, global_config, s3_client, sts_client)
|
8
|
+
@template_file = template_file
|
9
|
+
@region = region
|
10
|
+
@package = package
|
11
|
+
@global_config = global_config
|
12
|
+
@s3_client = s3_client
|
13
|
+
@sts_client = sts_client
|
14
|
+
@template_body = nil
|
15
|
+
@is_uploaded = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def large_template?
|
19
|
+
template_body.size > 51200
|
20
|
+
end
|
21
|
+
|
22
|
+
def template_body
|
23
|
+
package_templte
|
24
|
+
end
|
25
|
+
|
26
|
+
def upload_template_file
|
27
|
+
key = [@global_config.s3_template_hash, @template_file].compact.join('/')
|
28
|
+
url = "https://s3.amazonaws.com/#{bucket_name}/#{key}"
|
29
|
+
|
30
|
+
unless @is_uploaded
|
31
|
+
create_bucket
|
32
|
+
@s3_client.put_object(
|
33
|
+
body: template_body,
|
34
|
+
bucket: bucket_name,
|
35
|
+
key: key
|
36
|
+
)
|
37
|
+
@is_uploaded = true
|
38
|
+
CFnDK.logger.info('Put S3 object: ' + url + ' Size: ' + template_body.size.to_s)
|
39
|
+
end
|
40
|
+
url
|
41
|
+
end
|
42
|
+
|
43
|
+
def package_templte
|
44
|
+
if !@template_body
|
45
|
+
if !@package
|
46
|
+
@template_body = File.open(@template_file, 'r').read
|
47
|
+
return @template_body
|
48
|
+
end
|
49
|
+
orgTemplate = File.open(@template_file, 'r').read
|
50
|
+
CFnDK.logger.debug('Original Template:' + orgTemplate)
|
51
|
+
if is_json?(orgTemplate)
|
52
|
+
data = JSON.parse(orgTemplate)
|
53
|
+
else
|
54
|
+
data = YAML.load(orgTemplate.gsub(/!/, '____CFNDK!____'))
|
55
|
+
end
|
56
|
+
|
57
|
+
if data['Resources']
|
58
|
+
data['Resources'].each do |k, v|
|
59
|
+
next unless v.key?('Type')
|
60
|
+
t = v['Type']
|
61
|
+
properties = v['Properties'] || {}
|
62
|
+
case t
|
63
|
+
when 'AWS::CloudFormation::Stack' then
|
64
|
+
if properties['TemplateURL'] =~ /^\s*./
|
65
|
+
tp = TemplatePackager.new(File.dirname(@template_file) + '/' + properties['TemplateURL'].sub(/^\s*.\//, ''), @region, @package, @global_config, @s3_client, @sts_client)
|
66
|
+
v['Properties']['TemplateURL'] = tp.upload_template_file
|
67
|
+
end
|
68
|
+
when 'AWS::Lambda::Function' then
|
69
|
+
if properties['Code'].kind_of?(String)
|
70
|
+
result = upload_zip_file(File.dirname(@template_file) + '/' + properties['Code'].sub(/^\s*.\//, ''))
|
71
|
+
v['Properties']['Code'] = {
|
72
|
+
'S3Bucket' => result['bucket'],
|
73
|
+
'S3Key' => result['key']
|
74
|
+
}
|
75
|
+
end
|
76
|
+
when 'AWS::Serverless::Function' then
|
77
|
+
if properties['CodeUri'].kind_of?(String)
|
78
|
+
result = upload_zip_file(File.dirname(@template_file) + '/' + properties['CodeUri'].sub(/^\s*.\//, ''))
|
79
|
+
v['Properties']['CodeUri'] = {
|
80
|
+
'Bucket' => result['bucket'],
|
81
|
+
'Key' => result['key']
|
82
|
+
}
|
83
|
+
end
|
84
|
+
when 'AWS::Serverless::Api' then
|
85
|
+
if properties['DefinitionUri'].kind_of?(String)
|
86
|
+
result = upload_file(File.dirname(@template_file) + '/' + properties['DefinitionUri'].sub(/^\s*.\//, ''))
|
87
|
+
v['Properties']['DefinitionUri'] = {
|
88
|
+
'Bucket' => result['bucket'],
|
89
|
+
'Key' => result['key']
|
90
|
+
}
|
91
|
+
end
|
92
|
+
when 'AWS::ApiGateway::RestApi' then
|
93
|
+
if properties['BodyS3Location'].kind_of?(String)
|
94
|
+
result = upload_file(File.dirname(@template_file) + '/' + properties['BodyS3Location'].sub(/^\s*.\//, ''))
|
95
|
+
v['Properties']['BodyS3Location'] = {
|
96
|
+
'Bucket' => result['bucket'],
|
97
|
+
'Key' => result['key']
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
## TODO support resources
|
102
|
+
# * AWS::AppSync::GraphQLSchema DefinitionS3Location
|
103
|
+
# * AWS::AppSync::Resolver RequestMappingTemplateS3Location
|
104
|
+
# * AWS::AppSync::Resolver ResponseMappingTemplateS3Location
|
105
|
+
# * AWS::ElasticBeanstalk::ApplicationVersion SourceBundle
|
106
|
+
# * AWS::Glue::Job Command ScriptLocation
|
107
|
+
# * AWS::Include Location
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
if is_json?(orgTemplate)
|
112
|
+
@template_body = JSON.dump(data)
|
113
|
+
else
|
114
|
+
@template_body = YAML.dump_stream(data).gsub(/____CFNDK!____/, '!')
|
115
|
+
end
|
116
|
+
CFnDK.logger.info('Template Packager diff: ' + @template_file)
|
117
|
+
CFnDK.logger.info(CFnDK.diff(orgTemplate, @template_body).to_s)
|
118
|
+
CFnDK.logger.debug('Package Template size: ' + @template_body.size.to_s)
|
119
|
+
CFnDK.logger.debug('Package Template:' + @template_body)
|
120
|
+
end
|
121
|
+
@template_body
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def upload_zip_file(path)
|
127
|
+
create_bucket
|
128
|
+
key = [@global_config.s3_template_hash, path.sub(/^.\//, '') + ".zip"].compact.join('/')
|
129
|
+
|
130
|
+
|
131
|
+
buffer = Zip::OutputStream.write_buffer do |out|
|
132
|
+
Dir.glob(path + '/**/*') do |file|
|
133
|
+
if (!File.directory?(file))
|
134
|
+
out.put_next_entry(file.delete_prefix(path + '/'))
|
135
|
+
out.write(File.open(file, 'r').read)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
@s3_client.put_object(
|
141
|
+
body: buffer.string,
|
142
|
+
bucket: bucket_name,
|
143
|
+
key: key
|
144
|
+
)
|
145
|
+
url = "https://s3.amazonaws.com/#{bucket_name}/#{key}"
|
146
|
+
CFnDK.logger.info('Put S3 object: ' + url)
|
147
|
+
{
|
148
|
+
'bucket' => bucket_name,
|
149
|
+
'key' => key
|
150
|
+
}
|
151
|
+
end
|
152
|
+
|
153
|
+
def upload_file(path)
|
154
|
+
create_bucket
|
155
|
+
key = [@global_config.s3_template_hash, path.sub(/^.\//, '')].compact.join('/')
|
156
|
+
|
157
|
+
@s3_client.put_object(
|
158
|
+
body: File.open(path, 'r').read,
|
159
|
+
bucket: bucket_name,
|
160
|
+
key: key
|
161
|
+
)
|
162
|
+
url = "https://s3.amazonaws.com/#{bucket_name}/#{key}"
|
163
|
+
CFnDK.logger.info('Put S3 object: ' + url)
|
164
|
+
{
|
165
|
+
'bucket' => bucket_name,
|
166
|
+
'key' => key
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
def create_bucket
|
171
|
+
begin
|
172
|
+
@s3_client.head_bucket(bucket: bucket_name)
|
173
|
+
rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::Forbidden
|
174
|
+
@s3_client.create_bucket(bucket: bucket_name)
|
175
|
+
CFnDK.logger.info('Creatt S3 bucket: ' + bucket_name)
|
176
|
+
@s3_client.put_bucket_lifecycle_configuration(
|
177
|
+
bucket: bucket_name,
|
178
|
+
lifecycle_configuration: {
|
179
|
+
rules: [
|
180
|
+
{
|
181
|
+
expiration: {
|
182
|
+
days: 1,
|
183
|
+
},
|
184
|
+
status: 'Enabled',
|
185
|
+
id: 'Delete Old Files',
|
186
|
+
prefix: '',
|
187
|
+
abort_incomplete_multipart_upload: {
|
188
|
+
days_after_initiation: 1,
|
189
|
+
},
|
190
|
+
},
|
191
|
+
],
|
192
|
+
}
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def bucket_name
|
198
|
+
resp = @sts_client.get_caller_identity({})
|
199
|
+
resp.account + '-' + @region + '-' + @global_config.s3_template_bucket
|
200
|
+
end
|
201
|
+
|
202
|
+
def is_json?(str)
|
203
|
+
begin
|
204
|
+
!!JSON.parse(str)
|
205
|
+
rescue
|
206
|
+
false
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|