cfn_manage 0.7.0 → 0.8.3
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/.gitignore +8 -0
- data/.rspec +2 -0
- data/.travis.yml +20 -0
- data/Dockerfile +7 -0
- data/Gemfile +9 -0
- data/LICENSE +21 -0
- data/README.md +311 -0
- data/Rakefile +9 -0
- data/cfn_manage.gemspec +58 -0
- data/{bin → exe}/cfn_manage +78 -7
- data/{bin → exe}/usage.txt +31 -0
- data/lib/cfn_manage/cf_start_stop_environment.rb +84 -56
- data/lib/cfn_manage/globals.rb +90 -0
- data/lib/cfn_manage/handlers/alarm.rb +45 -0
- data/lib/cfn_manage/handlers/asg.rb +311 -0
- data/lib/cfn_manage/handlers/aurora_cluster.rb +97 -0
- data/lib/cfn_manage/handlers/documentdb.rb +89 -0
- data/lib/cfn_manage/handlers/ec2.rb +42 -0
- data/lib/cfn_manage/handlers/ecs_cluster.rb +219 -0
- data/lib/cfn_manage/handlers/rds.rb +142 -0
- data/lib/cfn_manage/handlers/spot_fleet.rb +56 -0
- data/lib/cfn_manage/handlers/transfer.rb +96 -0
- data/lib/cfn_manage/start_stop_handler_factory.rb +19 -19
- data/lib/cfn_manage/tag_finder.rb +77 -0
- data/lib/cfn_manage/version.rb +1 -1
- metadata +56 -21
- data/lib/cfn_manage/alarm_start_stop_handler.rb +0 -44
- data/lib/cfn_manage/asg_start_stop_handler.rb +0 -181
- data/lib/cfn_manage/aurora_cluster_start_stop_handler.rb +0 -97
- data/lib/cfn_manage/documentdb_cluster_start_stop_handler.rb +0 -89
- data/lib/cfn_manage/ec2_start_stop_handler.rb +0 -43
- data/lib/cfn_manage/ecs_cluster_start_stop_handler.rb +0 -80
- data/lib/cfn_manage/rds_start_stop_handler.rb +0 -134
- data/lib/cfn_manage/spot_fleet_start_stop_handler.rb +0 -57
- data/lib/cfn_manage/transfer_start_stop_handler.rb +0 -97
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'cfn_manage/aws_credentials'
|
2
|
-
|
3
|
-
module CfnManage
|
4
|
-
|
5
|
-
class AlarmStartStopHandler
|
6
|
-
|
7
|
-
def initialize(alarm_name)
|
8
|
-
@alarm_id = alarm_name
|
9
|
-
credentials = CfnManage::AWSCredentials.get_session_credentials("startstopalarm_#{@asg_name}")
|
10
|
-
@cwclient = Aws::CloudWatch::Client.new(retry_limit: 20)
|
11
|
-
if credentials != nil
|
12
|
-
@cwclient = Aws::CloudWatch::Client.new(credentials: credentials, retry_limit: 20)
|
13
|
-
end
|
14
|
-
|
15
|
-
@cwresource = Aws::CloudWatch::Resource.new(client: @cwclient)
|
16
|
-
@alarm = @cwresource.alarm(alarm_name)
|
17
|
-
end
|
18
|
-
|
19
|
-
def start(configuration)
|
20
|
-
if @alarm.actions_enabled
|
21
|
-
$log.info("Alarm #{@alarm.alarm_arn} actions already enabled")
|
22
|
-
return
|
23
|
-
end
|
24
|
-
$log.info("Enabling alarm #{@alarm.alarm_arn}")
|
25
|
-
@alarm.enable_actions({})
|
26
|
-
end
|
27
|
-
|
28
|
-
def stop
|
29
|
-
if not @alarm.actions_enabled
|
30
|
-
$log.info("Alarm #{@alarm.alarm_arn} actions already disabled")
|
31
|
-
return {}
|
32
|
-
end
|
33
|
-
$log.info("Disabling actions on alarm #{@alarm.alarm_arn}")
|
34
|
-
@alarm.disable_actions({})
|
35
|
-
return {}
|
36
|
-
end
|
37
|
-
|
38
|
-
def wait(wait_states=[])
|
39
|
-
$log.debug("Not waiting for alarm #{@alarm_id}")
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
@@ -1,181 +0,0 @@
|
|
1
|
-
require 'cfn_manage/aws_credentials'
|
2
|
-
|
3
|
-
module CfnManage
|
4
|
-
|
5
|
-
class AsgStartStopHandler
|
6
|
-
|
7
|
-
def initialize(asg_id, skip_wait)
|
8
|
-
@asg_name = asg_id
|
9
|
-
@skip_wait = skip_wait
|
10
|
-
@asg_suspend_termination = (ENV.key?('ASG_SUSPEND_TERMINATION') and ENV['ASG_SUSPEND_TERMINATION'] == '1')
|
11
|
-
credentials = CfnManage::AWSCredentials.get_session_credentials("stopasg_#{@asg_name}")
|
12
|
-
@asg_client = Aws::AutoScaling::Client.new(retry_limit: 20)
|
13
|
-
@ec2_client = Aws::EC2::Client.new(retry_limit: 20)
|
14
|
-
if credentials != nil
|
15
|
-
@asg_client = Aws::AutoScaling::Client.new(credentials: credentials, retry_limit: 20)
|
16
|
-
@ec2_client = Aws::EC2::Client.new(credentials: credentials, retry_limit: 20)
|
17
|
-
end
|
18
|
-
|
19
|
-
asg_details = @asg_client.describe_auto_scaling_groups(
|
20
|
-
auto_scaling_group_names: [@asg_name]
|
21
|
-
)
|
22
|
-
if asg_details.auto_scaling_groups.size() == 0
|
23
|
-
raise "Couldn't find ASG #{@asg_name}"
|
24
|
-
end
|
25
|
-
@asg = asg_details.auto_scaling_groups[0]
|
26
|
-
end
|
27
|
-
|
28
|
-
def stop
|
29
|
-
# check if already stopped
|
30
|
-
if @asg.min_size == @asg.max_size and @asg.max_size == @asg.desired_capacity and @asg.min_size == 0
|
31
|
-
$log.info("ASG #{@asg_name} already stopped")
|
32
|
-
# nil and false configurations are not saved
|
33
|
-
return nil
|
34
|
-
else
|
35
|
-
|
36
|
-
puts @asg.auto_scaling_group_name
|
37
|
-
|
38
|
-
unless @asg_suspend_termination
|
39
|
-
# store asg configuration to S3
|
40
|
-
configuration = {
|
41
|
-
desired_capacity: @asg.desired_capacity,
|
42
|
-
min_size: @asg.min_size,
|
43
|
-
max_size: @asg.max_size
|
44
|
-
}
|
45
|
-
|
46
|
-
$log.info("Setting desired capacity to 0/0/0 for ASG #{@asg.auto_scaling_group_name}A")
|
47
|
-
|
48
|
-
puts @asg.auto_scaling_group_name
|
49
|
-
@asg_client.update_auto_scaling_group({
|
50
|
-
auto_scaling_group_name: "#{@asg.auto_scaling_group_name}",
|
51
|
-
min_size: 0,
|
52
|
-
max_size: 0,
|
53
|
-
desired_capacity: 0
|
54
|
-
})
|
55
|
-
return configuration
|
56
|
-
else
|
57
|
-
|
58
|
-
configuration = {
|
59
|
-
desired_capacity: @asg.desired_capacity,
|
60
|
-
min_size: @asg.min_size,
|
61
|
-
max_size: @asg.max_size,
|
62
|
-
suspended_processes: @asg.suspended_processes
|
63
|
-
}
|
64
|
-
|
65
|
-
$log.info("Suspending processes for ASG #{@asg.auto_scaling_group_name}A")
|
66
|
-
|
67
|
-
@asg_client.suspend_processes({
|
68
|
-
auto_scaling_group_name: "#{@asg.auto_scaling_group_name}",
|
69
|
-
})
|
70
|
-
|
71
|
-
$log.info("Stopping all instances in ASG #{@asg.auto_scaling_group_name}A")
|
72
|
-
|
73
|
-
@asg.instances.each do |instance|
|
74
|
-
@instance_id = instance.instance_id
|
75
|
-
@instance = Aws::EC2::Resource.new(client: @ec2_client, retry_limit: 20).instance(@instance_id)
|
76
|
-
|
77
|
-
if %w(stopped stopping).include?(@instance.state.name)
|
78
|
-
$log.info("Instance #{@instance_id} already stopping or stopped")
|
79
|
-
return
|
80
|
-
end
|
81
|
-
|
82
|
-
$log.info("Stopping instance #{@instance_id}")
|
83
|
-
@instance.stop()
|
84
|
-
end
|
85
|
-
|
86
|
-
return configuration
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
def start(configuration)
|
95
|
-
if configuration.nil?
|
96
|
-
$log.warn("No configuration found for #{@asg_name}, skipping..")
|
97
|
-
return
|
98
|
-
end
|
99
|
-
$log.info("Starting ASG #{@asg_name} with following configuration\n#{configuration}")
|
100
|
-
|
101
|
-
unless @asg_suspend_termination
|
102
|
-
# restore asg sizes
|
103
|
-
@asg_client.update_auto_scaling_group({
|
104
|
-
auto_scaling_group_name: @asg_name,
|
105
|
-
min_size: configuration['min_size'],
|
106
|
-
max_size: configuration['max_size'],
|
107
|
-
desired_capacity: configuration['desired_capacity']
|
108
|
-
})
|
109
|
-
else
|
110
|
-
|
111
|
-
$log.info("Starting instances for ASG #{@asg_name}...")
|
112
|
-
|
113
|
-
@asg.instances.each do |instance|
|
114
|
-
@instance_id = instance.instance_id
|
115
|
-
@instance = Aws::EC2::Resource.new(client: @ec2_client, retry_limit: 20).instance(@instance_id)
|
116
|
-
|
117
|
-
if %w(running).include?(@instance.state.name)
|
118
|
-
$log.info("Instance #{@instance_id} already running")
|
119
|
-
return
|
120
|
-
end
|
121
|
-
$log.info("Starting instance #{@instance_id}")
|
122
|
-
@instance.start()
|
123
|
-
end
|
124
|
-
|
125
|
-
unhealthy = true
|
126
|
-
|
127
|
-
$log.info("Checking health status for instances for ASG #{@asg_name}")
|
128
|
-
|
129
|
-
while unhealthy do
|
130
|
-
|
131
|
-
asg_curr_details = @asg_client.describe_auto_scaling_groups(
|
132
|
-
auto_scaling_group_names: [@asg_name]
|
133
|
-
)
|
134
|
-
@asg_status = asg_curr_details.auto_scaling_groups[0]
|
135
|
-
|
136
|
-
allHealthy = 0
|
137
|
-
|
138
|
-
@asg_status.instances.each do |instance|
|
139
|
-
@instance_health = instance.health_status
|
140
|
-
if @instance_health == "Healthy"
|
141
|
-
allHealthy += 1
|
142
|
-
else
|
143
|
-
$log.info("Instance #{instance.instance_id} not currently healthy...")
|
144
|
-
sleep(15)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
if allHealthy == @asg_status.instances.length
|
149
|
-
$log.info("All instances healthy in ASG #{@asg_name}")
|
150
|
-
unhealthy = false
|
151
|
-
break
|
152
|
-
end
|
153
|
-
|
154
|
-
end
|
155
|
-
|
156
|
-
$log.info("Resuming all processes for ASG #{@asg_name}")
|
157
|
-
|
158
|
-
@asg_client.resume_processes({
|
159
|
-
auto_scaling_group_name: "#{@asg.auto_scaling_group_name}",
|
160
|
-
})
|
161
|
-
|
162
|
-
if configuration['suspended_processes'].any?
|
163
|
-
|
164
|
-
$log.info("Suspending processes stored in configuration for ASG #{@asg_name}")
|
165
|
-
|
166
|
-
@asg_client.suspend_processes({
|
167
|
-
auto_scaling_group_name: "#{@asg.auto_scaling_group_name}",
|
168
|
-
scaling_processes: configuration['suspended_processes'],
|
169
|
-
})
|
170
|
-
end
|
171
|
-
|
172
|
-
end
|
173
|
-
|
174
|
-
end
|
175
|
-
|
176
|
-
def wait(wait_states=[])
|
177
|
-
$log.debug("Not waiting for ASG #{@asg_name}")
|
178
|
-
end
|
179
|
-
|
180
|
-
end
|
181
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'cfn_manage/aws_credentials'
|
2
|
-
|
3
|
-
module CfnManage
|
4
|
-
|
5
|
-
class AuroraClusterStartStopHandler
|
6
|
-
|
7
|
-
def initialize(cluster_id, skip_wait)
|
8
|
-
@cluster_id = cluster_id
|
9
|
-
@skip_wait = skip_wait
|
10
|
-
credentials = CfnManage::AWSCredentials.get_session_credentials("startstopcluster_#{cluster_id}")
|
11
|
-
@rds_client = Aws::RDS::Client.new(retry_limit: 20)
|
12
|
-
if credentials != nil
|
13
|
-
@rds_client = Aws::RDS::Client.new(credentials: credentials, retry_limit: 20)
|
14
|
-
end
|
15
|
-
rds = Aws::RDS::Resource.new(client: @rds_client)
|
16
|
-
@rds_cluster = rds.db_cluster(cluster_id)
|
17
|
-
end
|
18
|
-
|
19
|
-
def start(configuration)
|
20
|
-
if @rds_cluster.status == 'available'
|
21
|
-
$log.info("Aurora Cluster #{@cluster_id} is already in available state")
|
22
|
-
return
|
23
|
-
end
|
24
|
-
|
25
|
-
if @rds_cluster.engine_mode != 'provisioned'
|
26
|
-
$log.info("Aurora Cluster #{@cluster_id} is not a provisioned cluster and cannot be started using this method.")
|
27
|
-
return
|
28
|
-
end
|
29
|
-
|
30
|
-
# start rds cluster
|
31
|
-
if @rds_cluster.status == 'stopped'
|
32
|
-
$log.info("Starting Aurora cluster #{@cluster_id}")
|
33
|
-
@rds_client.start_db_cluster({ db_cluster_identifier: @cluster_id })
|
34
|
-
unless @skip_wait
|
35
|
-
# wait cluster to become available
|
36
|
-
$log.info("Waiting Aurora cluster to become available #{@cluster_id}")
|
37
|
-
wait('available')
|
38
|
-
end
|
39
|
-
else
|
40
|
-
$log.info("Aurora Cluster #{@cluster_id} is not in a stopped state. State: #{@rds_cluster.status}")
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def stop
|
45
|
-
if @rds_cluster.status == 'stopped'
|
46
|
-
$log.info("Aurora Cluster #{@cluster_id} is already stopped")
|
47
|
-
return {}
|
48
|
-
end
|
49
|
-
|
50
|
-
if @rds_cluster.status != 'available'
|
51
|
-
$log.info("Aurora Cluster #{@cluster_id} is not in a available state. State: #{@rds_cluster.status}")
|
52
|
-
return {}
|
53
|
-
end
|
54
|
-
|
55
|
-
if @rds_cluster.engine_mode != 'provisioned'
|
56
|
-
$log.info("Aurora Cluster #{@cluster_id} is not a provisioned cluster and cannot be stopped using this method.")
|
57
|
-
return {}
|
58
|
-
end
|
59
|
-
# stop rds cluster and wait for it to be fully stopped
|
60
|
-
$log.info("Stopping aurora cluster #{@cluster_id}")
|
61
|
-
@rds_client.stop_db_cluster({ db_cluster_identifier: @cluster_id })
|
62
|
-
unless @skip_wait
|
63
|
-
$log.info("Waiting aurora cluster to be stopped #{@cluster_id}")
|
64
|
-
wait('stopped')
|
65
|
-
end
|
66
|
-
return {}
|
67
|
-
end
|
68
|
-
|
69
|
-
def wait(completed_state)
|
70
|
-
# reached state must be steady, at least a minute.
|
71
|
-
state_count = 0
|
72
|
-
steady_count = 4
|
73
|
-
attempts = 0
|
74
|
-
rds = Aws::RDS::Resource.new(client: @rds_client)
|
75
|
-
until attempts == (max_attempts = 60*6) do
|
76
|
-
cluster = rds.db_cluster(@cluster_id)
|
77
|
-
$log.info("Aurora Cluster #{cluster.db_cluster_identifier} state: #{cluster.status}, waiting for #{completed_state}")
|
78
|
-
|
79
|
-
if cluster.status == "#{completed_state}"
|
80
|
-
state_count = state_count + 1
|
81
|
-
$log.info("#{state_count}/#{steady_count}")
|
82
|
-
else
|
83
|
-
state_count = 0
|
84
|
-
end
|
85
|
-
break if state_count == steady_count
|
86
|
-
attempts = attempts + 1
|
87
|
-
sleep(15)
|
88
|
-
end
|
89
|
-
|
90
|
-
if attempts == max_attempts
|
91
|
-
$log.error("RDS Aurora Cluster #{@cluster_id} did not enter #{state} state, however continuing operations...")
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
require 'cfn_manage/aws_credentials'
|
2
|
-
|
3
|
-
module CfnManage
|
4
|
-
|
5
|
-
class DocumentDbClusterStartStopHandler
|
6
|
-
|
7
|
-
def initialize(cluster_id, skip_wait)
|
8
|
-
@cluster_id = cluster_id
|
9
|
-
@skip_wait = skip_wait
|
10
|
-
credentials = CfnManage::AWSCredentials.get_session_credentials("startstopcluster_#{cluster_id}")
|
11
|
-
@docdb_client = Aws::DocDB::Client.new(retry_limit: 20)
|
12
|
-
if credentials != nil
|
13
|
-
@docdb_client = Aws::DocDB::Client.new(credentials: credentials, retry_limit: 20)
|
14
|
-
end
|
15
|
-
cluster = @docdb_client.describe_db_clusters({ db_cluster_identifier: @cluster_id })
|
16
|
-
@docdb_cluster = cluster.db_clusters.first
|
17
|
-
end
|
18
|
-
|
19
|
-
def start(configuration)
|
20
|
-
if @docdb_cluster.status == 'available'
|
21
|
-
$log.info("DocDB Cluster #{@cluster_id} is already in available state")
|
22
|
-
return
|
23
|
-
end
|
24
|
-
|
25
|
-
# start docdb cluster
|
26
|
-
if @docdb_cluster.status == 'stopped'
|
27
|
-
$log.info("Starting DocDB cluster #{@cluster_id}")
|
28
|
-
@docdb_client.start_db_cluster({ db_cluster_identifier: @cluster_id })
|
29
|
-
unless @skip_wait
|
30
|
-
# wait cluster to become available
|
31
|
-
$log.info("Waiting DocDB cluster to become available #{@cluster_id}")
|
32
|
-
wait('available')
|
33
|
-
end
|
34
|
-
else
|
35
|
-
$log.info("DocDB Cluster #{@cluster_id} is not in a stopped state. State: #{@docdb_cluster.status}")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def stop
|
40
|
-
if @docdb_cluster.status == 'stopped'
|
41
|
-
$log.info("DocDB Cluster #{@cluster_id} is already stopped")
|
42
|
-
return {}
|
43
|
-
end
|
44
|
-
|
45
|
-
if @docdb_cluster.status != 'available'
|
46
|
-
$log.info("DocDB Cluster #{@cluster_id} is not in a available state. State: #{@docdb_cluster.status}")
|
47
|
-
return {}
|
48
|
-
end
|
49
|
-
# stop docdb cluster and wait for it to be fully stopped
|
50
|
-
$log.info("Stopping DocDB cluster #{@cluster_id}")
|
51
|
-
@docdb_client.stop_db_cluster({ db_cluster_identifier: @cluster_id })
|
52
|
-
unless @skip_wait
|
53
|
-
$log.info("Waiting DocDB cluster to be stopped #{@cluster_id}")
|
54
|
-
wait('stopped')
|
55
|
-
end
|
56
|
-
return {}
|
57
|
-
end
|
58
|
-
|
59
|
-
def wait(completed_state)
|
60
|
-
# reached state must be steady, at least a minute.
|
61
|
-
state_count = 0
|
62
|
-
steady_count = 4
|
63
|
-
attempts = 0
|
64
|
-
|
65
|
-
until attempts == (max_attempts = 60*6) do
|
66
|
-
# Declare client and cluster variable a second time inside the loop so it re-evaluates each time.
|
67
|
-
docdb = @docdb_client.describe_db_clusters({ db_cluster_identifier: @cluster_id })
|
68
|
-
cluster = docdb.db_clusters.first
|
69
|
-
$log.info("DocDB Cluster #{cluster.db_cluster_identifier} state: #{cluster.status}, waiting for #{completed_state}")
|
70
|
-
|
71
|
-
if cluster.status == "#{completed_state}"
|
72
|
-
state_count = state_count + 1
|
73
|
-
$log.info("#{state_count}/#{steady_count}")
|
74
|
-
else
|
75
|
-
state_count = 0
|
76
|
-
end
|
77
|
-
break if state_count == steady_count
|
78
|
-
attempts = attempts + 1
|
79
|
-
sleep(15)
|
80
|
-
end
|
81
|
-
|
82
|
-
if attempts == max_attempts
|
83
|
-
$log.error("DocDB Cluster #{@cluster_id} did not enter #{completed_state} state, however continuing operations...")
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'cfn_manage/aws_credentials'
|
2
|
-
|
3
|
-
module CfnManage
|
4
|
-
|
5
|
-
class Ec2StartStopHandler
|
6
|
-
|
7
|
-
@instance
|
8
|
-
|
9
|
-
def initialize(instance_id, skip_wait)
|
10
|
-
credentials = CfnManage::AWSCredentials.get_session_credentials("stoprun_#{instance_id}")
|
11
|
-
ec2_client = Aws::EC2::Client.new(credentials: credentials, retry_limit: 20)
|
12
|
-
@instance = Aws::EC2::Resource.new(client: ec2_client, retry_limit: 20).instance(instance_id)
|
13
|
-
@instance_id = instance_id
|
14
|
-
@skip_wait = skip_wait
|
15
|
-
end
|
16
|
-
|
17
|
-
def start(configuration)
|
18
|
-
if %w(running).include?(@instance.state.name)
|
19
|
-
$log.info("Instance #{@instance_id} already running")
|
20
|
-
return
|
21
|
-
end
|
22
|
-
$log.info("Starting instance #{@instance_id}")
|
23
|
-
@instance.start()
|
24
|
-
end
|
25
|
-
|
26
|
-
def stop
|
27
|
-
if %w(stopped stopping).include?(@instance.state.name)
|
28
|
-
$log.info("Instance #{@instance_id} already stopping or stopped")
|
29
|
-
return
|
30
|
-
end
|
31
|
-
$log.info("Stopping instance #{@instance_id}")
|
32
|
-
@instance.stop()
|
33
|
-
|
34
|
-
# empty configuration for ec2 instances
|
35
|
-
return {}
|
36
|
-
end
|
37
|
-
|
38
|
-
def wait(wait_states=[])
|
39
|
-
$log.debug("Not waiting for EC2 instance #{@instance_id}")
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|