openstax_aws 1.4.0 → 1.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75f65f32cd2e572d1e83f624977186c7aee220c6d51924333fa08af2255543ad
4
- data.tar.gz: bf3969a29e8fb4ff94b54bbd9685581cdff28f9c160f3ebe0fa26b92f4875575
3
+ metadata.gz: 7754f428f875d2a03d7e007352ab1c98107838904fd56ec7b0b7e188f62cf3fd
4
+ data.tar.gz: 862cfac082c78ac44a42190634cac16e2d05b2eaf5f9445950928d9883bd53b8
5
5
  SHA512:
6
- metadata.gz: 76287d75f76a51cbeb635e6013f5e896174537fcba6352f5febba64c562c3cb857f82aa2a03f71af9583c5db3e8527bf0298e4e2759db9ac658b7a13c0fa6c14
7
- data.tar.gz: f86924695c16ce1b3729e9a405e36603761477aa4c7af798ea50bd5faeffcaf18d3caca056db5f8d72127c8bf9c7edfd464d46a7e109f8597d1437ecffb2788f
6
+ metadata.gz: dfb2f7012992c090625da1ba7906f475d43042456e8c241e54624123f12a28ac36effa58cab39de0beede13643f4513441da7e1154edfaa2f1783e97ea8927dc
7
+ data.tar.gz: 309ed6f57c82ea3d42a9860f44a7ad80bec3d524ae5deac7546ed870e4cb572b904cba75a76df9e4d80c0834e6393b1b85d41a53d5bb9bc4619da8fc20ea0b1d
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
@@ -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
@@ -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
-
@@ -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
@@ -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
- wait_for_creation if wait
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
- wait_for_update if wait
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
- case stack_resource.resource_type
294
- when "AWS::AutoScaling::AutoScalingGroup"
295
- name = stack_resource.physical_resource_id
296
- client = Aws::AutoScaling::Client.new(region: region)
297
- Aws::AutoScaling::AutoScalingGroup.new(name: name, client: client)
298
- when "AWS::RDS::DBInstance"
299
- db_instance_identifier = stack_resource.physical_resource_id
300
- OpenStax::Aws::RdsInstance.new(db_instance_identifier: db_instance_identifier, region: region)
301
- when "AWS::MSK::Cluster"
302
- msk_cluster_arn = stack_resource.physical_resource_id
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
 
@@ -1,5 +1,5 @@
1
1
  module OpenStax
2
2
  module Aws
3
- VERSION = "1.4.0"
3
+ VERSION = "1.5.0"
4
4
  end
5
5
  end
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/rds_instance"
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.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Slavinsky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-11 00:00:00.000000000 Z
11
+ date: 2022-06-14 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