openstax_aws 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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