openstax_aws 1.3.0 → 1.6.0
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/.github/workflows/tests.yml +3 -5
- data/CHANGELOG.md +9 -0
- data/lib/openstax/aws/alarm.rb +48 -0
- data/lib/openstax/aws/auto_scaling_group.rb +18 -1
- data/lib/openstax/aws/build_image_command_1.rb +5 -0
- data/lib/openstax/aws/deployment_base.rb +39 -2
- data/lib/openstax/aws/distribution.rb +2 -1
- data/lib/openstax/aws/event_rule.rb +34 -0
- data/lib/openstax/aws/git_helper.rb +5 -2
- data/lib/openstax/aws/image.rb +5 -2
- data/lib/openstax/aws/msk_cluster.rb +4 -1
- data/lib/openstax/aws/packer_1_4_1.rb +54 -28
- data/lib/openstax/aws/rds_instance.rb +6 -3
- data/lib/openstax/aws/resource_factory.rb +36 -0
- data/lib/openstax/aws/sam_stack.rb +6 -2
- data/lib/openstax/aws/stack.rb +33 -17
- data/lib/openstax/aws/template.rb +1 -1
- data/lib/openstax/aws/version.rb +1 -1
- data/lib/openstax_aws.rb +6 -1
- data/openstax_aws.gemspec +2 -0
- metadata +37 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7ed7cb99a4131a436325e8766d03f6a62accbd62a700a6238a0a6278ae1e6e5
|
4
|
+
data.tar.gz: 46f26ea0c266cf1c1ca1b0cf7c5307848bf8be3c5097c7fe16472a1fe3115f81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1871bbb908ecbfb58eb782fae57f960cf1db1a066adf8003c14115756273656a51aa2c32e061bb8fcc6607fe06633fd6936b7d71da38c907d313aa9d5509ad8b
|
7
|
+
data.tar.gz: 82108d04dde247454dfeafe8450a2bfed4ffe40d8d00c45dea2693501ae9693e7e77be618605cf3f49cb647bdb6cdf0b78e1cac71b37f3fe0fbe94543a1ffac8
|
data/.github/workflows/tests.yml
CHANGED
@@ -4,9 +4,7 @@ on:
|
|
4
4
|
pull_request:
|
5
5
|
push:
|
6
6
|
branches:
|
7
|
-
-
|
8
|
-
schedule:
|
9
|
-
- cron: '0 0 * * 0' # weekly
|
7
|
+
- master
|
10
8
|
|
11
9
|
jobs:
|
12
10
|
tests:
|
@@ -17,7 +15,7 @@ jobs:
|
|
17
15
|
- uses: actions/checkout@v2
|
18
16
|
- uses: actions/setup-ruby@v1
|
19
17
|
with:
|
20
|
-
ruby-version: 2.
|
18
|
+
ruby-version: 2.6
|
21
19
|
- uses: actions/cache@v2
|
22
20
|
with:
|
23
21
|
path: vendor/bundle
|
@@ -30,4 +28,4 @@ jobs:
|
|
30
28
|
bundle config path vendor/bundle
|
31
29
|
bundle config jobs 2
|
32
30
|
bundle install
|
33
|
-
bundle exec
|
31
|
+
bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.5.0] - 2022-06-14
|
10
|
+
- Automatically tag CloudWatch alarms and EventBridge rules after stacks are created or updated
|
11
|
+
|
12
|
+
## [1.4.0] - 2022-05-11
|
13
|
+
- ???
|
14
|
+
|
15
|
+
## [1.3.0] - 2021-03-23
|
16
|
+
- ???
|
17
|
+
|
9
18
|
## [1.2.0] - 2021-01-12
|
10
19
|
|
11
20
|
- Added additional method to MskCluster resource, to return sorted list of bootstrap brokers
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module OpenStax::Aws
|
2
|
+
class Alarm
|
3
|
+
attr_reader :raw_alarm
|
4
|
+
|
5
|
+
delegate_missing_to :@raw_alarm
|
6
|
+
|
7
|
+
def self.physical_resource_id_attribute
|
8
|
+
:name
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(region:, name:)
|
12
|
+
@raw_alarm = ::Aws::CloudWatch::Alarm.new(
|
13
|
+
name: name,
|
14
|
+
client: Aws::CloudWatch::Client.new(region: region)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def tags
|
19
|
+
client.list_tags_for_resource(resource_arn: raw_alarm.alarm_arn).tags
|
20
|
+
end
|
21
|
+
|
22
|
+
def tag_resource(new_tags)
|
23
|
+
client.tag_resource resource_arn: raw_alarm.alarm_arn, tags: new_tags
|
24
|
+
end
|
25
|
+
|
26
|
+
def logger
|
27
|
+
OpenStax::Aws.configuration.logger
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_tags_not_handled_by_cloudformation(stack_tags)
|
31
|
+
missing_tags = stack_tags.map(&:to_h) - tags.map(&:to_h)
|
32
|
+
|
33
|
+
return if missing_tags.empty?
|
34
|
+
|
35
|
+
logger.debug "Tagging #{name}..."
|
36
|
+
attempt = 1
|
37
|
+
begin
|
38
|
+
tag_resource missing_tags
|
39
|
+
rescue Aws::CloudWatch::Errors::Throttling
|
40
|
+
retry_in = attempt**2
|
41
|
+
logger.debug "Tagging #{name} failed... retrying in #{retry_in} seconds"
|
42
|
+
sleep retry_in
|
43
|
+
attempt += 1
|
44
|
+
retry
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,14 +1,19 @@
|
|
1
1
|
module OpenStax::Aws
|
2
2
|
class AutoScalingGroup
|
3
|
-
attr_reader :raw_asg
|
3
|
+
attr_reader :raw_asg, :region
|
4
4
|
|
5
5
|
delegate_missing_to :@raw_asg
|
6
6
|
|
7
|
+
def self.physical_resource_id_attribute
|
8
|
+
:name
|
9
|
+
end
|
10
|
+
|
7
11
|
def initialize(name:, region:)
|
8
12
|
@raw_asg = Aws::AutoScaling::AutoScalingGroup.new(
|
9
13
|
name: name,
|
10
14
|
client: Aws::AutoScaling::Client.new(region: region)
|
11
15
|
)
|
16
|
+
@region = region
|
12
17
|
end
|
13
18
|
|
14
19
|
def increase_desired_capacity(by:)
|
@@ -24,5 +29,17 @@ module OpenStax::Aws
|
|
24
29
|
def desired_capacity
|
25
30
|
raw_asg.desired_capacity
|
26
31
|
end
|
32
|
+
|
33
|
+
def alarms
|
34
|
+
client.describe_policies(
|
35
|
+
auto_scaling_group_name: raw_asg.name
|
36
|
+
).flat_map(&:scaling_policies).flat_map(&:alarms).map do |alarm|
|
37
|
+
OpenStax::Aws::Alarm.new region: region, name: alarm.alarm_name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_tags_not_handled_by_cloudformation(stack_tags)
|
42
|
+
alarms.each { |alarm| alarm.add_tags_not_handled_by_cloudformation stack_tags }
|
43
|
+
end
|
27
44
|
end
|
28
45
|
end
|
@@ -7,6 +7,7 @@ module OpenStax
|
|
7
7
|
def initialize(ami_name_base:, region:,
|
8
8
|
verbose: false, debug: false,
|
9
9
|
github_org:, repo:, branch: nil, sha: nil,
|
10
|
+
deployment_sha: nil,
|
10
11
|
packer_absolute_file_path: , playbook_absolute_file_path:,
|
11
12
|
dry_run: true)
|
12
13
|
if sha.nil?
|
@@ -18,6 +19,8 @@ module OpenStax
|
|
18
19
|
)
|
19
20
|
end
|
20
21
|
|
22
|
+
deployment_sha ||= OpenStax::Aws::GitHelper.current_sha
|
23
|
+
|
21
24
|
ami_name = "#{ami_name_base}@#{sha[0..6]} #{Time.now.utc.strftime("%y%m%d%H%MZ")}"
|
22
25
|
|
23
26
|
@packer = OpenStax::Aws::PackerFactory.new_packer(
|
@@ -30,9 +33,11 @@ module OpenStax
|
|
30
33
|
@packer.var("region", region)
|
31
34
|
@packer.var("ami_name", ami_name)
|
32
35
|
@packer.var("sha", sha)
|
36
|
+
@packer.var("deployment_sha", deployment_sha)
|
33
37
|
@packer.var("playbook_file", playbook_absolute_file_path)
|
34
38
|
@packer.var("ami_description", {
|
35
39
|
sha: sha,
|
40
|
+
deployment_sha: deployment_sha,
|
36
41
|
github_org: github_org,
|
37
42
|
repo: repo
|
38
43
|
}.to_json)
|
@@ -260,6 +260,32 @@ module OpenStax::Aws
|
|
260
260
|
nil # can be overridden by the DSL
|
261
261
|
end
|
262
262
|
|
263
|
+
def failed_statuses_table
|
264
|
+
rows = []
|
265
|
+
|
266
|
+
stacks.each do |stack|
|
267
|
+
stack.status(reload: false).failed_events_since_last_user_event.each do |event|
|
268
|
+
rows.push([stack.name, event.status_text, event.status_reason])
|
269
|
+
end if stack.status.failed?
|
270
|
+
end
|
271
|
+
|
272
|
+
column_widths = [
|
273
|
+
2 + rows.reduce(0) { |result, rowdata| [result, rowdata[0].length].max },
|
274
|
+
2 + rows.reduce(0) { |result, rowdata| [result, rowdata[1].length].max },
|
275
|
+
0
|
276
|
+
]
|
277
|
+
|
278
|
+
output = []
|
279
|
+
|
280
|
+
output.push(["Stack", "Status", "Reason"].each_with_index.map { |header, index| header.ljust(column_widths[index]) }.join(''))
|
281
|
+
|
282
|
+
rows.each { |rowdata|
|
283
|
+
output.push(rowdata.each_with_index.map { |value, index| value.ljust(column_widths[index]) }.join(''))
|
284
|
+
}
|
285
|
+
|
286
|
+
output.join("\n")
|
287
|
+
end
|
288
|
+
|
263
289
|
protected
|
264
290
|
|
265
291
|
def parameter_default(parameter_name)
|
@@ -360,13 +386,24 @@ module OpenStax::Aws
|
|
360
386
|
get_image_tag(image_id: image_id, key: "sha")
|
361
387
|
end
|
362
388
|
|
363
|
-
protected
|
364
|
-
|
365
389
|
def secrets_namespace(id: 'default')
|
366
390
|
raise "Override this method in your deployment class and provide a namespace " \
|
367
391
|
"for secrets data in the AWS Parameter Store. The key there will be this namespace " \
|
368
392
|
"prefixed by the environment name and suffixed with the secret name."
|
369
393
|
end
|
370
394
|
|
395
|
+
def log_and_exit_if_failed_status
|
396
|
+
begin
|
397
|
+
yield
|
398
|
+
rescue
|
399
|
+
if status.failed?
|
400
|
+
logger.fatal("The following errors have occurred: \n#{failed_statuses_table}")
|
401
|
+
exit(1)
|
402
|
+
else
|
403
|
+
raise
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
371
408
|
end
|
372
409
|
end
|
@@ -34,7 +34,8 @@ module OpenStax::Aws
|
|
34
34
|
begin
|
35
35
|
Aws::CloudFront::Waiters::InvalidationCompleted.new(
|
36
36
|
client: client,
|
37
|
-
before_attempt: ->(*) { wait_message.say_it }
|
37
|
+
before_attempt: ->(*) { wait_message.say_it },
|
38
|
+
max_attempts: 60
|
38
39
|
).wait(
|
39
40
|
distribution_id: id,
|
40
41
|
id: invalidation_id
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module OpenStax::Aws
|
2
|
+
class EventRule
|
3
|
+
attr_reader :raw_rule, :client
|
4
|
+
|
5
|
+
delegate_missing_to :@raw_rule
|
6
|
+
|
7
|
+
def self.physical_resource_id_attribute
|
8
|
+
:name
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(name:, region:)
|
12
|
+
@client = Aws::EventBridge::Client.new region: region
|
13
|
+
# There is no real rule wrapper in the SDK but the DescribeRuleResponse can be used
|
14
|
+
@raw_rule = client.describe_rule name: name
|
15
|
+
end
|
16
|
+
|
17
|
+
def tags
|
18
|
+
client.list_tags_for_resource(resource_arn: raw_rule.arn).tags
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_resource(new_tags)
|
22
|
+
client.tag_resource resource_arn: raw_rule.arn, tags: new_tags
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_tags_not_handled_by_cloudformation(stack_tags)
|
26
|
+
missing_tags = stack_tags.map(&:to_h) - tags.map(&:to_h)
|
27
|
+
|
28
|
+
return if missing_tags.empty?
|
29
|
+
|
30
|
+
OpenStax::Aws.configuration.logger.debug "Tagging #{name}..."
|
31
|
+
tag_resource missing_tags
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -3,7 +3,6 @@ require 'open-uri'
|
|
3
3
|
|
4
4
|
module OpenStax::Aws
|
5
5
|
module GitHelper
|
6
|
-
|
7
6
|
def self.sha_for_branch_name(org_slash_repo:, branch:)
|
8
7
|
::Git.ls_remote("https://github.com/#{org_slash_repo}")["branches"][branch][:sha]
|
9
8
|
end
|
@@ -11,7 +10,7 @@ module OpenStax::Aws
|
|
11
10
|
def self.file_content_at_sha(org_slash_repo:, sha:, path:, github_token: nil )
|
12
11
|
if github_token.blank?
|
13
12
|
location = "https://raw.githubusercontent.com/#{org_slash_repo}/#{sha}/#{path}"
|
14
|
-
file = open(location)
|
13
|
+
file = URI.open(location)
|
15
14
|
file.read
|
16
15
|
else
|
17
16
|
uri = URI("https://raw.githubusercontent.com/#{org_slash_repo}/#{sha}/#{path}")
|
@@ -23,5 +22,9 @@ module OpenStax::Aws
|
|
23
22
|
end
|
24
23
|
end
|
25
24
|
end
|
25
|
+
|
26
|
+
def self.current_sha
|
27
|
+
::Git.revparse('HEAD')
|
28
|
+
end
|
26
29
|
end
|
27
30
|
end
|
data/lib/openstax/aws/image.rb
CHANGED
@@ -25,9 +25,12 @@ module OpenStax::Aws
|
|
25
25
|
get_tag(key: "sha")
|
26
26
|
end
|
27
27
|
|
28
|
-
def self.find_by_sha(sha:, region:)
|
28
|
+
def self.find_by_sha(sha:, region:, deployment_sha: nil)
|
29
|
+
filters = [{name: "tag:sha", values: [sha]}]
|
30
|
+
filters << {name: "tag:deployment_sha", values: [deployment_sha]} unless deployment_sha.nil?
|
31
|
+
|
29
32
|
Aws::EC2::Client.new(region: region).describe_images({
|
30
|
-
owners: ['self'], filters:
|
33
|
+
owners: ['self'], filters: filters
|
31
34
|
}).images.map{|aws_image| new(aws_image: aws_image)}
|
32
35
|
end
|
33
36
|
end
|
@@ -5,6 +5,10 @@ module OpenStax::Aws
|
|
5
5
|
|
6
6
|
delegate_missing_to :@client
|
7
7
|
|
8
|
+
def self.physical_resource_id_attribute
|
9
|
+
:cluster_arn
|
10
|
+
end
|
11
|
+
|
8
12
|
def initialize(cluster_arn:, region:)
|
9
13
|
@cluster_arn = cluster_arn
|
10
14
|
@client = ::Aws::Kafka::Client.new(region: region)
|
@@ -20,4 +24,3 @@ module OpenStax::Aws
|
|
20
24
|
|
21
25
|
end
|
22
26
|
end
|
23
|
-
|
@@ -41,54 +41,80 @@ module OpenStax::Aws
|
|
41
41
|
cmd = "PACKER_LOG=1 #{cmd}" if @verbose
|
42
42
|
cmd = "#{cmd} --debug" if @debug
|
43
43
|
|
44
|
-
cmd
|
44
|
+
cmd
|
45
45
|
end
|
46
46
|
|
47
47
|
def run
|
48
48
|
@logger.info("**** DRY RUN ****") if @dry_run
|
49
|
-
@logger.info("Running: #{command}")
|
49
|
+
@logger.info("Running: #{command} #{@absolute_file_path}")
|
50
50
|
|
51
51
|
if !@dry_run
|
52
52
|
@logger.info("Printing stderr for desired verbosity")
|
53
|
-
ami = ""
|
54
53
|
|
55
|
-
|
56
|
-
begin
|
57
|
-
previous_interrupt_handler = Signal.trap 'INT' do
|
58
|
-
# Interrupt Packer
|
59
|
-
Process.kill 'INT', wait_thr.pid
|
54
|
+
tmpdir = nil
|
60
55
|
|
61
|
-
|
62
|
-
|
56
|
+
begin
|
57
|
+
config_path = @absolute_file_path
|
63
58
|
|
64
|
-
|
65
|
-
|
59
|
+
# Can't handle modifying HCL2 templates yet
|
60
|
+
if config_path.ends_with?('.json')
|
61
|
+
config = JSON.parse(File.read(config_path))
|
62
|
+
config['post-processors'] ||= []
|
63
|
+
manifest_config = (config['post-processors']).find do |processor|
|
64
|
+
processor['type'] == 'manifest'
|
66
65
|
end
|
67
66
|
|
68
|
-
|
67
|
+
# Configure a manifest post-processor if not already configured
|
68
|
+
if manifest_config.nil?
|
69
|
+
tmpdir = Dir.mktmpdir
|
69
70
|
|
70
|
-
|
71
|
+
manifest_config = { 'type' => 'manifest', 'output' => "#{tmpdir}/manifest.json" }
|
71
72
|
|
72
|
-
|
73
|
-
line << char
|
74
|
-
STDERR.print char
|
73
|
+
config['post-processors'] << manifest_config
|
75
74
|
|
76
|
-
|
75
|
+
config_path = "#{tmpdir}/packer.json"
|
77
76
|
|
78
|
-
|
79
|
-
ami = matchami.captures[0] if matchami
|
80
|
-
|
81
|
-
line = ''
|
77
|
+
File.write(config_path, JSON.dump(config))
|
82
78
|
end
|
83
|
-
ensure
|
84
|
-
# Restore previous interrupt unless we did so already
|
85
|
-
Signal.trap 'INT', previous_interrupt_handler unless previous_interrupt_handler.nil?
|
86
79
|
end
|
87
80
|
|
88
|
-
|
81
|
+
Open3.popen2e("#{command} #{config_path}") do |stdin, stdout_err, wait_thr|
|
82
|
+
begin
|
83
|
+
previous_interrupt_handler = Signal.trap 'INT' do
|
84
|
+
# Interrupt Packer
|
85
|
+
Process.kill 'INT', wait_thr.pid
|
86
|
+
|
87
|
+
# Restore previous interrupt handler so we don't interrupt Packer again
|
88
|
+
Signal.trap 'INT', previous_interrupt_handler
|
89
|
+
|
90
|
+
# Disable other code that restores previous interrupt
|
91
|
+
previous_interrupt_handler = nil
|
92
|
+
end
|
93
|
+
|
94
|
+
stdout_err.sync = true
|
95
|
+
|
96
|
+
# Send all packer output to STDERR
|
97
|
+
while char = stdout_err.getc do
|
98
|
+
STDERR.print char
|
99
|
+
end
|
100
|
+
ensure
|
101
|
+
# Restore previous interrupt unless we did so already
|
102
|
+
Signal.trap 'INT', previous_interrupt_handler unless previous_interrupt_handler.nil?
|
103
|
+
end
|
104
|
+
|
105
|
+
# Read the AMI ID from the manifest file and output it to STDOUT
|
106
|
+
unless manifest_config.nil?
|
107
|
+
manifest = File.read(manifest_config['output']) rescue nil
|
89
108
|
|
90
|
-
|
91
|
-
|
109
|
+
puts JSON.parse(manifest)['builds'].last['artifact_id'].split(':', 2).last \
|
110
|
+
unless manifest.nil?
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return Packer's exit status wrapped in a Process::Status object
|
114
|
+
wait_thr.value
|
115
|
+
end
|
116
|
+
ensure
|
117
|
+
FileUtils.remove_entry(tmpdir) unless tmpdir.nil?
|
92
118
|
end
|
93
119
|
end
|
94
120
|
end
|
@@ -5,6 +5,10 @@ module OpenStax::Aws
|
|
5
5
|
|
6
6
|
delegate_missing_to :@raw
|
7
7
|
|
8
|
+
def self.physical_resource_id_attribute
|
9
|
+
:db_instance_identifier
|
10
|
+
end
|
11
|
+
|
8
12
|
def initialize(db_instance_identifier:, region:)
|
9
13
|
@raw = Aws::RDS::DBInstance.new(
|
10
14
|
db_instance_identifier,
|
@@ -14,12 +18,11 @@ module OpenStax::Aws
|
|
14
18
|
|
15
19
|
def set_master_password(password:)
|
16
20
|
raw.modify({
|
17
|
-
apply_immediately: true,
|
21
|
+
apply_immediately: true,
|
18
22
|
master_user_password: password
|
19
23
|
})
|
20
|
-
|
24
|
+
|
21
25
|
end
|
22
26
|
|
23
27
|
end
|
24
28
|
end
|
25
|
-
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module OpenStax::Aws
|
2
|
+
class ResourceFactory
|
3
|
+
# All classes listed here should implement the self.physical_resource_id method
|
4
|
+
ALL_TYPES = {
|
5
|
+
'AWS::AutoScaling::AutoScalingGroup' => OpenStax::Aws::AutoScalingGroup,
|
6
|
+
'AWS::CloudWatch::Alarm' => OpenStax::Aws::Alarm,
|
7
|
+
'AWS::Events::Rule' => OpenStax::Aws::EventRule,
|
8
|
+
'AWS::RDS::DBInstance' => OpenStax::Aws::RdsInstance,
|
9
|
+
'AWS::MSK::Cluster' => OpenStax::Aws::MskCluster
|
10
|
+
}
|
11
|
+
|
12
|
+
attr_reader :region, :types
|
13
|
+
|
14
|
+
def initialize(region:, types: nil)
|
15
|
+
@region = region
|
16
|
+
@types = types.nil? ? ALL_TYPES : ALL_TYPES.select { |type, _| types.include? type }
|
17
|
+
end
|
18
|
+
|
19
|
+
def from_stack_resource_or_summary(stack_resource)
|
20
|
+
klass = types[stack_resource.resource_type]
|
21
|
+
return if klass.nil?
|
22
|
+
|
23
|
+
klass.new(
|
24
|
+
region: region,
|
25
|
+
klass.physical_resource_id_attribute => stack_resource.physical_resource_id
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def from_stack_resource_or_summary!(stack_resource)
|
30
|
+
from_stack_resource_or_summary(stack_resource).tap do |resource|
|
31
|
+
raise "'#{stack_resource.resource_type}' is not yet implemented in `ResourceFactory`" \
|
32
|
+
if resource.nil?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -32,9 +32,12 @@ module OpenStax::Aws
|
|
32
32
|
dry_run: dry_run)
|
33
33
|
end
|
34
34
|
|
35
|
-
def build
|
35
|
+
def build(debug: false, env_vars: {})
|
36
36
|
# SAM doesn't have an API or SDK - we have to make calls to its CLI
|
37
|
+
env_vars_prefix = env_vars.map { |variable, value| "#{variable}=#{value}" }.join(' ')
|
37
38
|
command = "sam build -t #{absolute_template_path} -b #{build_directory}"
|
39
|
+
command += ' --debug' if debug
|
40
|
+
command = "#{env_vars_prefix} #{command}" if env_vars_prefix.present?
|
38
41
|
System.call(command, logger: logger, dry_run: dry_run)
|
39
42
|
end
|
40
43
|
|
@@ -50,7 +53,8 @@ module OpenStax::Aws
|
|
50
53
|
" --capabilities CAPABILITY_IAM" \
|
51
54
|
" --s3-bucket #{bucket_name}" \
|
52
55
|
" --s3-prefix #{name}" \
|
53
|
-
" --stack-name #{name}"
|
56
|
+
" --stack-name #{name}" \
|
57
|
+
" --region #{region}"
|
54
58
|
|
55
59
|
if params.any?
|
56
60
|
command += " --parameter-overrides #{self.class.format_hash_as_cli_stack_parameters(params)}"
|
data/lib/openstax/aws/stack.rb
CHANGED
@@ -86,9 +86,15 @@ module OpenStax::Aws
|
|
86
86
|
}
|
87
87
|
|
88
88
|
logger.info("Creating #{name} stack...")
|
89
|
-
client.create_stack(options) if !dry_run
|
90
89
|
|
91
|
-
|
90
|
+
if !dry_run
|
91
|
+
client.create_stack(options)
|
92
|
+
|
93
|
+
if wait
|
94
|
+
wait_for_creation
|
95
|
+
tag_resources_not_handled_by_cloudformation
|
96
|
+
end
|
97
|
+
end
|
92
98
|
end
|
93
99
|
|
94
100
|
def parameters_for_update(overrides: {})
|
@@ -218,14 +224,24 @@ module OpenStax::Aws
|
|
218
224
|
logger.info("Executing change set")
|
219
225
|
change_set.execute
|
220
226
|
reset_cached_remote_state
|
221
|
-
end
|
222
227
|
|
223
|
-
|
228
|
+
wait_for_update if wait
|
229
|
+
end
|
224
230
|
end
|
225
231
|
|
232
|
+
# We can still tag resources even if there are no changes according to CloudFormation
|
233
|
+
tag_resources_not_handled_by_cloudformation if wait && !dry_run
|
234
|
+
|
226
235
|
change_set
|
227
236
|
end
|
228
237
|
|
238
|
+
def tag_resources_not_handled_by_cloudformation
|
239
|
+
stack_tags = self.class.format_hash_as_tag_parameters @tags
|
240
|
+
resources(
|
241
|
+
[ 'AWS::CloudWatch::Alarm', 'AWS::Events::Rule', 'AWS::AutoScaling::AutoScalingGroup' ]
|
242
|
+
).each { |resource| resource.add_tags_not_handled_by_cloudformation(stack_tags) }
|
243
|
+
end
|
244
|
+
|
229
245
|
def delete(retain_resources: [], wait: false)
|
230
246
|
logger.info("**** DRY RUN ****") if dry_run
|
231
247
|
|
@@ -289,20 +305,20 @@ module OpenStax::Aws
|
|
289
305
|
|
290
306
|
def resource(logical_id)
|
291
307
|
stack_resource = aws_stack.resource(logical_id)
|
308
|
+
resource_factory = OpenStax::Aws::ResourceFactory.new region: region
|
309
|
+
resource_factory.from_stack_resource_or_summary! stack_resource
|
310
|
+
end
|
292
311
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
OpenStax::Aws::MskCluster.new(cluster_arn: msk_cluster_arn, region: region)
|
304
|
-
else
|
305
|
-
raise "'#{stack_resource.resource_type}' is not yet implemented in `Stack#resource`"
|
312
|
+
def resources(types = nil)
|
313
|
+
resource_factory = OpenStax::Aws::ResourceFactory.new region: region, types: types
|
314
|
+
|
315
|
+
Enumerator.new do |yielder|
|
316
|
+
client.list_stack_resources(stack_name: name).each do |response|
|
317
|
+
response.stack_resource_summaries.each do |stack_resource_summary|
|
318
|
+
resource = resource_factory.from_stack_resource_or_summary stack_resource_summary
|
319
|
+
yielder << resource unless resource.nil?
|
320
|
+
end
|
321
|
+
end
|
306
322
|
end
|
307
323
|
end
|
308
324
|
|
data/lib/openstax/aws/version.rb
CHANGED
data/lib/openstax_aws.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require "aws-sdk-autoscaling"
|
2
2
|
require "aws-sdk-cloudformation"
|
3
3
|
require "aws-sdk-cloudfront"
|
4
|
+
require "aws-sdk-cloudwatch"
|
4
5
|
require "aws-sdk-ec2"
|
6
|
+
require "aws-sdk-eventbridge"
|
5
7
|
require "aws-sdk-kafka"
|
6
8
|
require "aws-sdk-rds"
|
7
9
|
require "aws-sdk-s3"
|
@@ -143,10 +145,13 @@ require "openstax/aws/stack_status"
|
|
143
145
|
require "openstax/aws/stack_factory"
|
144
146
|
require "openstax/aws/deployment_base"
|
145
147
|
require "openstax/aws/ec2_instance_data"
|
148
|
+
require "openstax/aws/alarm"
|
146
149
|
require "openstax/aws/auto_scaling_group"
|
147
150
|
require "openstax/aws/auto_scaling_instance"
|
148
|
-
require "openstax/aws/
|
151
|
+
require "openstax/aws/event_rule"
|
149
152
|
require "openstax/aws/msk_cluster"
|
153
|
+
require "openstax/aws/rds_instance"
|
154
|
+
require "openstax/aws/resource_factory"
|
150
155
|
require "openstax/aws/packer_1_2_5"
|
151
156
|
require "openstax/aws/packer_1_4_1"
|
152
157
|
require "openstax/aws/packer_factory"
|
data/openstax_aws.gemspec
CHANGED
@@ -32,7 +32,9 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_dependency "aws-sdk-autoscaling", "~> 1"
|
33
33
|
spec.add_dependency "aws-sdk-cloudformation", "~> 1"
|
34
34
|
spec.add_dependency "aws-sdk-cloudfront", "~> 1"
|
35
|
+
spec.add_dependency "aws-sdk-cloudwatch", "~> 1"
|
35
36
|
spec.add_dependency "aws-sdk-ec2", "~> 1"
|
37
|
+
spec.add_dependency "aws-sdk-eventbridge", "~> 1"
|
36
38
|
spec.add_dependency "aws-sdk-kafka", "~> 1"
|
37
39
|
spec.add_dependency "aws-sdk-rds", "~> 1"
|
38
40
|
spec.add_dependency "aws-sdk-s3", "~> 1"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: openstax_aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JP Slavinsky
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-autoscaling
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: aws-sdk-cloudwatch
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: aws-sdk-ec2
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: aws-sdk-eventbridge
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: aws-sdk-kafka
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -289,6 +317,7 @@ files:
|
|
289
317
|
- bin/templates/aws_ruby_development.yml
|
290
318
|
- examples/deployment.rb
|
291
319
|
- ideas.md
|
320
|
+
- lib/openstax/aws/alarm.rb
|
292
321
|
- lib/openstax/aws/auto_scaling_group.rb
|
293
322
|
- lib/openstax/aws/auto_scaling_instance.rb
|
294
323
|
- lib/openstax/aws/build_image_command_1.rb
|
@@ -296,6 +325,7 @@ files:
|
|
296
325
|
- lib/openstax/aws/deployment_base.rb
|
297
326
|
- lib/openstax/aws/distribution.rb
|
298
327
|
- lib/openstax/aws/ec2_instance_data.rb
|
328
|
+
- lib/openstax/aws/event_rule.rb
|
299
329
|
- lib/openstax/aws/extensions.rb
|
300
330
|
- lib/openstax/aws/git_helper.rb
|
301
331
|
- lib/openstax/aws/image.rb
|
@@ -304,6 +334,7 @@ files:
|
|
304
334
|
- lib/openstax/aws/packer_1_4_1.rb
|
305
335
|
- lib/openstax/aws/packer_factory.rb
|
306
336
|
- lib/openstax/aws/rds_instance.rb
|
337
|
+
- lib/openstax/aws/resource_factory.rb
|
307
338
|
- lib/openstax/aws/s3_text_file.rb
|
308
339
|
- lib/openstax/aws/sam_stack.rb
|
309
340
|
- lib/openstax/aws/secrets.rb
|
@@ -327,7 +358,7 @@ licenses:
|
|
327
358
|
- MIT
|
328
359
|
metadata:
|
329
360
|
allowed_push_host: https://rubygems.org
|
330
|
-
post_install_message:
|
361
|
+
post_install_message:
|
331
362
|
rdoc_options: []
|
332
363
|
require_paths:
|
333
364
|
- lib
|
@@ -342,8 +373,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
342
373
|
- !ruby/object:Gem::Version
|
343
374
|
version: '0'
|
344
375
|
requirements: []
|
345
|
-
rubygems_version: 3.
|
346
|
-
signing_key:
|
376
|
+
rubygems_version: 3.1.4
|
377
|
+
signing_key:
|
347
378
|
specification_version: 4
|
348
379
|
summary: openstax IaC
|
349
380
|
test_files: []
|