cfn_manage 0.4.3 → 0.5.0

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