cfn_manage 0.4.3 → 0.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.
@@ -1,16 +1,17 @@
1
- require_relative '../lib/aws_credentials'
1
+ require 'cfn_manage/aws_credentials'
2
2
 
3
- module Base2
3
+ module CfnManage
4
4
 
5
5
  class Ec2StartStopHandler
6
6
 
7
7
  @instance
8
8
 
9
- def initialize(instance_id)
10
- credentials = Base2::AWSCredentials.get_session_credentials("stoprun_#{instance_id}")
9
+ def initialize(instance_id, skip_wait)
10
+ credentials = CfnManage::AWSCredentials.get_session_credentials("stoprun_#{instance_id}")
11
11
  ec2_client = Aws::EC2::Client.new(credentials: credentials, retry_limit: 20)
12
12
  @instance = Aws::EC2::Resource.new(client: ec2_client, retry_limit: 20).instance(instance_id)
13
13
  @instance_id = instance_id
14
+ @skip_wait = skip_wait
14
15
  end
15
16
 
16
17
  def start(configuration)
@@ -34,8 +35,9 @@ module Base2
34
35
  return {}
35
36
  end
36
37
 
37
-
38
-
38
+ def wait(wait_states=[])
39
+ $log.debug("Not waiting for EC2 instance #{@instance_id}")
40
+ end
39
41
 
40
42
  end
41
- end
43
+ end
@@ -0,0 +1,66 @@
1
+ require 'cfn_manage/aws_credentials'
2
+
3
+ module CfnManage
4
+ class EcsClusterStartStopHandler
5
+
6
+ def initialize(cluster_id, skip_wait)
7
+ credentials = CfnManage::AWSCredentials.get_session_credentials("stoprun_#{cluster_id}")
8
+ @ecs_client = Aws::ECS::Client.new(credentials: credentials, retry_limit: 20)
9
+ @services = @ecs_client.list_services(cluster: cluster_id).service_arns
10
+ $log.info("Found #{@services.count} services in ECS cluster #{cluster_id}")
11
+ @cluster = cluster_id
12
+ @skip_wait = skip_wait
13
+ end
14
+
15
+ def start(configuration)
16
+ @services.each do |service_arn|
17
+
18
+ $log.info("Searching for ECS service #{service_arn} in cluster #{@cluster}")
19
+ service = @ecs_client.describe_services(services:[service_arn], cluster: @cluster).services[0]
20
+
21
+ if service.desired_count != 0
22
+ $log.info("ECS service #{service.service_name} is already running")
23
+ next
24
+ end
25
+
26
+ $log.info("Starting ECS service #{service.service_name} with desired count of #{configuration[service.service_name]['desired_count']}")
27
+ @ecs_client.update_service({
28
+ desired_count: configuration[service.service_name]['desired_count'],
29
+ service: service_arn,
30
+ cluster: @cluster
31
+ })
32
+
33
+ end
34
+ end
35
+
36
+ def stop
37
+ configuration = {}
38
+ @services.each do |service_arn|
39
+
40
+ $log.info("Searching for ECS service #{service_arn} in cluster #{@cluster}")
41
+ service = @ecs_client.describe_services(services:[service_arn], cluster: @cluster).services[0]
42
+
43
+ if service.desired_count == 0
44
+ $log.info("ECS service #{service.service_name} is already stopped")
45
+ next
46
+ end
47
+
48
+ configuration[service.service_name] = { desired_count: service.desired_count }
49
+ $log.info("Stopping ECS service #{service.service_name}")
50
+ @ecs_client.update_service({
51
+ desired_count: 0,
52
+ service: service_arn,
53
+ cluster: @cluster
54
+ })
55
+
56
+ end
57
+
58
+ return configuration
59
+ end
60
+
61
+ def wait(completed_status)
62
+ $log.debug("Not waiting for ECS Services in cluster #{@cluster}")
63
+ end
64
+
65
+ end
66
+ end
@@ -1,13 +1,14 @@
1
- require_relative '../lib/aws_credentials'
1
+ require 'cfn_manage/aws_credentials'
2
2
 
3
- module Base2
3
+ module CfnManage
4
4
 
5
5
  class RdsStartStopHandler
6
6
 
7
- def initialize(instance_id)
7
+ def initialize(instance_id, skip_wait)
8
8
  @instance_id = instance_id
9
-
10
- credentials = Base2::AWSCredentials.get_session_credentials("startstoprds_#{instance_id}")
9
+ @skip_wait = skip_wait
10
+ @excluded_engines = %w(aurora aurora-mysql aurora-postgresql) # RDS list of exluded engines that don't support RDS stop start
11
+ credentials = CfnManage::AWSCredentials.get_session_credentials("startstoprds_#{instance_id}")
11
12
  @rds_client = Aws::RDS::Client.new(retry_limit: 20)
12
13
  if credentials != nil
13
14
  @rds_client = Aws::RDS::Client.new(credentials: credentials, retry_limit: 20)
@@ -18,9 +19,7 @@ module Base2
18
19
  end
19
20
 
20
21
  def start(configuration)
21
- # RDS list of exluded engines that don't support RDS stop start
22
- excluded_engines = %w(aurora aurora-mysql aurora-postgresql)
23
- if excluded_engines.include? @rds_instance.engine
22
+ if @excluded_engines.include? @rds_instance.engine
24
23
  $log.info("RDS Instance #{@instance_id} engine is #{@rds_instance.engine} and cannot be started by instance.")
25
24
  return
26
25
  end
@@ -35,10 +34,12 @@ module Base2
35
34
  @rds_client.start_db_instance({ db_instance_identifier: @instance_id })
36
35
 
37
36
  # wait instance to become available
38
- $log.info("Waiting db instance to become available #{@instance_id}")
39
- wait_rds_instance_states( %w(starting available))
37
+ unless @skip_wait
38
+ $log.info("Waiting db instance to become available #{@instance_id}")
39
+ wait('available')
40
+ end
40
41
  else
41
- wait_rds_instance_states( %w(available))
42
+ wait('available') unless @skip_wait
42
43
  end
43
44
 
44
45
  # convert rds instance to mutli-az if required
@@ -54,8 +55,7 @@ module Base2
54
55
  is_multi_az: @rds_instance.multi_az
55
56
  }
56
57
  # RDS list of exluded engines that don't support RDS stop start
57
- excluded_engines = %w(aurora aurora-mysql aurora-postgresql)
58
- if excluded_engines.include? @rds_instance.engine
58
+ if @excluded_engines.include? @rds_instance.engine
59
59
  $log.info("RDS Instance #{@instance_id} engine is #{@rds_instance.engine} and cannot be stoped by instance.")
60
60
  return configuration
61
61
  end
@@ -82,8 +82,10 @@ module Base2
82
82
  # stop rds instance and wait for it to be fully stopped
83
83
  $log.info("Stopping instance #{@instance_id}")
84
84
  @rds_client.stop_db_instance({ db_instance_identifier: @instance_id })
85
- $log.info("Waiting db instance to be stopped #{@instance_id}")
86
- wait_rds_instance_states(%w(stopping stopped))
85
+ unless @skip_wait
86
+ $log.info("Waiting db instance to be stopped #{@instance_id}")
87
+ wait('stopped')
88
+ end
87
89
 
88
90
  return configuration
89
91
  end
@@ -95,40 +97,37 @@ module Base2
95
97
  end
96
98
  @rds_instance.modify({ multi_az: multi_az, apply_immediately: true })
97
99
  # allow half an hour for instance to be converted
98
- wait_states = %w(modifying available)
99
- wait_rds_instance_states( wait_states)
100
+ wait('available')
100
101
  end
101
102
 
102
- def wait_rds_instance_states(wait_states)
103
- wait_states.each do |state|
104
- # reached state must be steady, at least a minute. Modifying an instance to/from MultiAZ can't be shorter
105
- # than 40 seconds, hence steady count is 4
106
- state_count = 0
107
- steady_count = 4
108
- attempts = 0
109
- rds = Aws::RDS::Resource.new(client: @rds_client)
110
- until attempts == (max_attempts = 60*6) do
111
- instance = rds.db_instance(@instance_id)
112
- $log.info("Instance #{instance.db_instance_identifier} state: #{instance.db_instance_status}, waiting for #{state}")
113
-
114
- if instance.db_instance_status == "#{state}"
115
- state_count = state_count + 1
116
- $log.info("#{state_count}/#{steady_count}")
117
- else
118
- state_count = 0
119
- end
120
- break if state_count == steady_count
121
- attempts = attempts + 1
122
- sleep(15)
103
+ def wait(completed_state)
104
+ # reached state must be steady, at least a minute. Modifying an instance to/from MultiAZ can't be shorter
105
+ # than 40 seconds, hence steady count is 4
106
+ state_count = 0
107
+ steady_count = 4
108
+ attempts = 0
109
+ rds = Aws::RDS::Resource.new(client: @rds_client)
110
+ until attempts == (max_attempts = 60*6) do
111
+ instance = rds.db_instance(@instance_id)
112
+ $log.info("Instance #{instance.db_instance_identifier} state: #{instance.db_instance_status}, waiting for #{completed_state}")
113
+
114
+ if instance.db_instance_status == "#{completed_state}"
115
+ state_count = state_count + 1
116
+ $log.info("#{state_count}/#{steady_count}")
117
+ else
118
+ state_count = 0
123
119
  end
120
+ break if state_count == steady_count
121
+ attempts = attempts + 1
122
+ sleep(15)
123
+ end
124
124
 
125
- if attempts == max_attempts
126
- $log.error("RDS Database Instance #{@instance_id} did not enter #{state} state, however continuing operations...")
127
- end
125
+ if attempts == max_attempts
126
+ $log.error("RDS Database Instance #{@instance_id} did not enter #{state} state, however continuing operations...")
128
127
  end
129
128
  end
130
129
 
131
- private :set_rds_instance_multi_az, :wait_rds_instance_states
130
+ private :set_rds_instance_multi_az
132
131
 
133
132
  end
134
133
 
@@ -1,13 +1,13 @@
1
- require_relative '../lib/aws_credentials'
1
+ require 'cfn_manage/aws_credentials'
2
2
 
3
- module Base2
3
+ module CfnManage
4
4
 
5
5
  class SpotFleetStartStopHandler
6
6
 
7
- def initialize(fleet_id)
7
+ def initialize(fleet_id, skip_wait)
8
8
  @fleet_id = fleet_id
9
-
10
- credentials = Base2::AWSCredentials.get_session_credentials("startstopfleet_#{fleet_id}")
9
+ @skip_wait = skip_wait
10
+ credentials = CfnManage::AWSCredentials.get_session_credentials("startstopfleet_#{fleet_id}")
11
11
  @ec2_client = Aws::EC2::Client.new(retry_limit: 20)
12
12
  if credentials != nil
13
13
  @ec2_client = Aws::EC2::Client.new(credentials: credentials, retry_limit: 20)
@@ -48,6 +48,10 @@ module Base2
48
48
  return configuration
49
49
  end
50
50
 
51
+ def wait(wait_states=[])
52
+ $log.debug("Not waiting for spot fleet #{@fleet_id}")
53
+ end
54
+
51
55
  end
52
56
 
53
- end
57
+ end
@@ -0,0 +1,44 @@
1
+ require 'cfn_manage/asg_start_stop_handler'
2
+ require 'cfn_manage/ec2_start_stop_handler'
3
+ require 'cfn_manage/rds_start_stop_handler'
4
+ require 'cfn_manage/aurora_cluster_start_stop_handler'
5
+ require 'cfn_manage/alarm_start_stop_handler'
6
+ require 'cfn_manage/spot_fleet_start_stop_handler'
7
+ require 'cfn_manage/ecs_cluster_start_stop_handler'
8
+
9
+ module CfnManage
10
+
11
+ class StartStopHandlerFactory
12
+
13
+ # Factory method to get start/stop handler based on CloudFormation
14
+ # resource type. If resource_id passed in does not exist, it is
15
+ # very likely that exception will be raised
16
+ def self.get_start_stop_handler(resource_type, resource_id, skip_wait)
17
+ case resource_type
18
+ when 'AWS::AutoScaling::AutoScalingGroup'
19
+ return CfnManage::AsgStartStopHandler.new(resource_id, skip_wait)
20
+
21
+ when 'AWS::EC2::Instance'
22
+ return CfnManage::Ec2StartStopHandler.new(resource_id, skip_wait)
23
+
24
+ when 'AWS::RDS::DBInstance'
25
+ return CfnManage::RdsStartStopHandler.new(resource_id, skip_wait)
26
+
27
+ when 'AWS::RDS::DBCluster'
28
+ return CfnManage::AuroraClusterStartStopHandler.new(resource_id, skip_wait)
29
+
30
+ when 'AWS::CloudWatch::Alarm'
31
+ return CfnManage::AlarmStartStopHandler.new(resource_id)
32
+
33
+ when 'AWS::EC2::SpotFleet'
34
+ return CfnManage::SpotFleetStartStopHandler.new(resource_id, skip_wait)
35
+
36
+ when 'AWS::ECS::Cluster'
37
+ return CfnManage::EcsClusterStartStopHandler.new(resource_id, skip_wait)
38
+
39
+ else
40
+ return nil
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module CfnManage
2
+ VERSION="0.5.0".freeze
3
+ end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn_manage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Base2Services
8
8
  - Nikola Tosic
9
+ - Angus Vine
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2018-10-18 00:00:00.000000000 Z
13
+ date: 2018-10-26 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: aws-sdk-core
@@ -171,6 +172,124 @@ dependencies:
171
172
  - - "<"
172
173
  - !ruby/object:Gem::Version
173
174
  version: '2'
175
+ - !ruby/object:Gem::Dependency
176
+ name: aws-sdk-ecs
177
+ requirement: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - "~>"
180
+ - !ruby/object:Gem::Version
181
+ version: '1'
182
+ - - "<"
183
+ - !ruby/object:Gem::Version
184
+ version: '2'
185
+ type: :runtime
186
+ prerelease: false
187
+ version_requirements: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - "~>"
190
+ - !ruby/object:Gem::Version
191
+ version: '1'
192
+ - - "<"
193
+ - !ruby/object:Gem::Version
194
+ version: '2'
195
+ - !ruby/object:Gem::Dependency
196
+ name: bundler
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.16'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.16'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rake
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '10.0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: '10.0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: rspec
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: '0.9'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: '0.9'
237
+ - !ruby/object:Gem::Dependency
238
+ name: rspec-core
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - "~>"
242
+ - !ruby/object:Gem::Version
243
+ version: '3.8'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - "~>"
249
+ - !ruby/object:Gem::Version
250
+ version: '3.8'
251
+ - !ruby/object:Gem::Dependency
252
+ name: rspec-expectations
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - "~>"
256
+ - !ruby/object:Gem::Version
257
+ version: '3.8'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - "~>"
263
+ - !ruby/object:Gem::Version
264
+ version: '3.8'
265
+ - !ruby/object:Gem::Dependency
266
+ name: rspec-mocks
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '3.8'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '3.8'
279
+ - !ruby/object:Gem::Dependency
280
+ name: simplecov
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - "~>"
284
+ - !ruby/object:Gem::Version
285
+ version: '0.16'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - "~>"
291
+ - !ruby/object:Gem::Version
292
+ version: '0.16'
174
293
  description: ''
175
294
  email: itsupport@base2services.com
176
295
  executables:
@@ -179,20 +298,22 @@ extensions: []
179
298
  extra_rdoc_files: []
180
299
  files:
181
300
  - bin/cfn_manage
182
- - bin/cfn_manage.rb
183
301
  - bin/usage.txt
184
- - lib/alarm_start_stop_handler.rb
185
- - lib/asg_start_stop_handler.rb
186
- - lib/aurora_cluster_start_stop_handler.rb
187
- - lib/aws_credentials.rb
188
- - lib/cf_common.rb
189
- - lib/cf_progress_tracker.rb
190
- - lib/cf_start_stop_environment.rb
191
- - lib/ec2_start_stop_handler.rb
192
- - lib/rds_start_stop_handler.rb
193
- - lib/spot_fleet_start_stop_handler.rb
194
- - lib/start_stop_handler_factory.rb
195
- homepage: https://github.com/base2Services/cfn-library/blob/master/README.md
302
+ - lib/cfn_manage.rb
303
+ - lib/cfn_manage/alarm_start_stop_handler.rb
304
+ - lib/cfn_manage/asg_start_stop_handler.rb
305
+ - lib/cfn_manage/aurora_cluster_start_stop_handler.rb
306
+ - lib/cfn_manage/aws_credentials.rb
307
+ - lib/cfn_manage/cf_common.rb
308
+ - lib/cfn_manage/cf_progress_tracker.rb
309
+ - lib/cfn_manage/cf_start_stop_environment.rb
310
+ - lib/cfn_manage/ec2_start_stop_handler.rb
311
+ - lib/cfn_manage/ecs_cluster_start_stop_handler.rb
312
+ - lib/cfn_manage/rds_start_stop_handler.rb
313
+ - lib/cfn_manage/spot_fleet_start_stop_handler.rb
314
+ - lib/cfn_manage/start_stop_handler_factory.rb
315
+ - lib/cfn_manage/version.rb
316
+ homepage: https://github.com/base2Services/cfn-start-stop-stack/blob/master/README.md
196
317
  licenses:
197
318
  - MIT
198
319
  metadata: {}
@@ -212,7 +333,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
333
  version: '0'
213
334
  requirements: []
214
335
  rubyforge_project:
215
- rubygems_version: 2.6.13
336
+ rubygems_version: 2.7.7
216
337
  signing_key:
217
338
  specification_version: 4
218
339
  summary: Manage AWS Cloud Formation stacks