cfn_manage 0.7.1 → 0.8.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 +4 -4
- data/bin/cfn_manage +78 -7
- data/bin/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 +207 -0
- data/lib/cfn_manage/handlers/rds.rb +134 -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 +36 -14
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 343401ecc1402d26222f76e4bcff786ee798fcede9d1b67f6e37dc4a99527886
|
4
|
+
data.tar.gz: 95dfb13ac573a995ad875f341043b451d428b568f78f50496c95044cd2ccf1f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f52ec460cd5f1ded3b1fb7080b82f309d508d25fac2e5e6cc05f6f4c0334f1858f72dd694a2f5f1529a9088f61cfc74c3d3f874b1fe07df9a011d800dd6ca2e5
|
7
|
+
data.tar.gz: 4d73d61e515e309ea5ee40b22728ce539b466319b10dcceef7a4106a1bf24cf06b2edfc43141fda9fee8656bfc00e5a7cdb3147bdac6e9145d7545836015b640
|
data/bin/cfn_manage
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require 'optparse'
|
3
3
|
require 'cfn_manage/version'
|
4
4
|
require 'cfn_manage/cf_common'
|
5
|
+
require 'cfn_manage/globals'
|
5
6
|
require 'cfn_manage/cf_start_stop_environment'
|
6
7
|
require 'logger'
|
7
8
|
|
@@ -18,6 +19,7 @@ $options['AWS_ASSUME_ROLE'] = ENV['AWS_ASSUME_ROLE']
|
|
18
19
|
|
19
20
|
# global logger
|
20
21
|
$log = Logger.new(STDOUT)
|
22
|
+
$log.level = Logger::INFO
|
21
23
|
|
22
24
|
# always flush output
|
23
25
|
STDOUT.sync = true
|
@@ -77,6 +79,24 @@ OptionParser.new do |opts|
|
|
77
79
|
opts.on('--alarm [ALARM]') do |alarm|
|
78
80
|
$options['ALARM'] = alarm
|
79
81
|
end
|
82
|
+
|
83
|
+
opts.on('--asg-wait-state [WAIT_STATE]') do |state|
|
84
|
+
allows_values = ['HealthyInASG','Running','HealthyInTargetGroup']
|
85
|
+
if !allows_values.include? state
|
86
|
+
STDERR.puts("#{type} is not a valid value for `--asg-wait-state`. Use one of #{allows_values.join(',')}")
|
87
|
+
exit 1
|
88
|
+
end
|
89
|
+
CfnManage.asg_wait_state = state
|
90
|
+
end
|
91
|
+
|
92
|
+
opts.on('--ecs-wait-state [WAIT_STATE]') do |state|
|
93
|
+
allows_values = ['Running','HealthyInTargetGroup']
|
94
|
+
if !allows_values.include? state
|
95
|
+
STDERR.puts("#{type} is not a valid value for `--ecs-wait-state`. Use one of #{allows_values.join(',')}")
|
96
|
+
exit 1
|
97
|
+
end
|
98
|
+
CfnManage.ecs_wait_state = state
|
99
|
+
end
|
80
100
|
|
81
101
|
opts.on('-r [AWS_REGION]', '--region [AWS_REGION]') do |region|
|
82
102
|
ENV['AWS_REGION'] = region
|
@@ -86,29 +106,80 @@ OptionParser.new do |opts|
|
|
86
106
|
ENV['CFN_AWS_PROFILE'] = profile
|
87
107
|
end
|
88
108
|
|
109
|
+
# Boolean options with support for command line and environment variables
|
110
|
+
|
89
111
|
opts.on('--dry-run') do
|
90
|
-
|
112
|
+
CfnManage.dry_run
|
113
|
+
end
|
114
|
+
|
115
|
+
if ENV['DRY_RUN'] == '1'
|
116
|
+
CfnManage.dry_run
|
117
|
+
end
|
118
|
+
|
119
|
+
opts.on('--debug') do
|
120
|
+
$log.level = Logger::DEBUG
|
121
|
+
end
|
122
|
+
|
123
|
+
if ENV['CFN_DEBUG'] == '1'
|
124
|
+
$log.level = Logger::DEBUGß
|
91
125
|
end
|
92
126
|
|
93
127
|
opts.on('--continue-on-error') do
|
94
|
-
|
128
|
+
CfnManage.continue_on_error
|
129
|
+
end
|
130
|
+
|
131
|
+
if ENV['CFN_CONTINUE_ON_ERROR'] == '1'
|
132
|
+
CfnManage.continue_on_error
|
95
133
|
end
|
96
134
|
|
97
135
|
opts.on('--wait-async') do
|
98
|
-
|
99
|
-
|
136
|
+
CfnManage.skip_wait
|
137
|
+
CfnManage.wait_async
|
138
|
+
end
|
139
|
+
|
140
|
+
if ENV['WAIT_ASYNC'] == '1'
|
141
|
+
CfnManage.skip_wait
|
142
|
+
CfnManage.wait_async
|
100
143
|
end
|
101
144
|
|
102
145
|
opts.on('--skip-wait') do
|
103
|
-
|
146
|
+
CfnManage.skip_wait
|
147
|
+
end
|
148
|
+
|
149
|
+
if ENV['SKIP_WAIT'] == '1'
|
150
|
+
CfnManage.skip_wait
|
104
151
|
end
|
105
152
|
|
106
153
|
opts.on('--ignore-missing-ecs-config') do
|
107
|
-
|
154
|
+
CfnManage.ignore_missing_ecs_config
|
155
|
+
end
|
156
|
+
|
157
|
+
if ENV['IGNORE_MISSING_ECS_CONFIG'] == '1'
|
158
|
+
CfnManage.ignore_missing_ecs_config
|
108
159
|
end
|
109
160
|
|
110
161
|
opts.on('--asg-suspend-termination') do
|
111
|
-
|
162
|
+
CfnManage.asg_suspend_termination
|
163
|
+
end
|
164
|
+
|
165
|
+
if ENV['ASG_SUSPEND_TERMINATION'] == '1'
|
166
|
+
CfnManage.asg_suspend_termination
|
167
|
+
end
|
168
|
+
|
169
|
+
opts.on('--tags') do
|
170
|
+
CfnManage.find_tags
|
171
|
+
end
|
172
|
+
|
173
|
+
if ENV['CFN_TAGS'] == '1'
|
174
|
+
CfnManage.find_tags
|
175
|
+
end
|
176
|
+
|
177
|
+
opts.on('--ecs-wait-container-instances') do
|
178
|
+
CfnManage.ecs_wait_container_instances
|
179
|
+
end
|
180
|
+
|
181
|
+
if ENV['ECS_WAIT_CONTAINER_INSTANCES'] == '1'
|
182
|
+
CfnManage.ecs_wait_container_instances
|
112
183
|
end
|
113
184
|
|
114
185
|
end.parse!
|
data/bin/usage.txt
CHANGED
@@ -71,6 +71,10 @@ General options:
|
|
71
71
|
Applicable only to [start|stop-environment] commands. If dry run is enabled
|
72
72
|
info about assets being started / stopped will ne only printed to standard output,
|
73
73
|
without any action taken.
|
74
|
+
|
75
|
+
--debug
|
76
|
+
|
77
|
+
Displays debug logs
|
74
78
|
|
75
79
|
--continue-on-error
|
76
80
|
|
@@ -96,3 +100,30 @@ General options:
|
|
96
100
|
--asg-suspend-termination
|
97
101
|
|
98
102
|
Will stop instances in the autoscaling group(s) instead of the default behaviour of termination.
|
103
|
+
|
104
|
+
--asg-wait-state
|
105
|
+
|
106
|
+
Allowed values ['HealthyInASG','Running','HealthyInTargetGroup']
|
107
|
+
Default: 'HealthyInASG'
|
108
|
+
|
109
|
+
'HealthyInASG' - waits for all instances to reach a healthy state in the asg
|
110
|
+
'Running' - waits for all instances to reach the EC2 running state
|
111
|
+
'HealthyInTargetGroup' - waits for all instances to reach a healthy state in all asg assocated target groups
|
112
|
+
|
113
|
+
--ecs-wait-state
|
114
|
+
|
115
|
+
Allowed values ['Running','HealthyInTargetGroup']
|
116
|
+
Default: 'Skip'
|
117
|
+
|
118
|
+
'Running' - waits for all ecs services in cluster to reach the running state
|
119
|
+
'HealthyInTargetGroup' - waits for all ecs services in cluster to reach a healthy state in all assocated target groups
|
120
|
+
|
121
|
+
--tags
|
122
|
+
|
123
|
+
will query resource tags for individual resource settings.
|
124
|
+
`cfn_manage:priority` for prefered starting order
|
125
|
+
will default to defined resource order if no tag is found or resource doesn't support tags
|
126
|
+
|
127
|
+
--ecs-wait-container-instances
|
128
|
+
|
129
|
+
waits for a container instance to be active in the ecs cluster before starting services
|
@@ -1,41 +1,35 @@
|
|
1
|
-
require '
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
|
2
4
|
require 'aws-sdk-s3'
|
3
|
-
require 'aws-sdk-ec2'
|
4
5
|
require 'aws-sdk-cloudformation'
|
5
|
-
require 'aws-sdk-rds'
|
6
|
-
require 'aws-sdk-cloudwatch'
|
7
|
-
require 'aws-sdk-autoscaling'
|
8
|
-
require 'aws-sdk-ecs'
|
9
|
-
require 'aws-sdk-docdb'
|
10
6
|
|
11
7
|
require 'cfn_manage/cf_common'
|
12
8
|
require 'cfn_manage/aws_credentials'
|
13
|
-
require '
|
14
|
-
require 'yaml'
|
9
|
+
require 'cfn_manage/tag_finder'
|
15
10
|
require 'cfn_manage/start_stop_handler_factory'
|
16
11
|
|
17
12
|
module CfnManage
|
18
13
|
module CloudFormation
|
19
14
|
class EnvironmentRunStop
|
20
15
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
'AWS::DocDB::DBCluster' => '100',
|
32
|
-
'AWS::AutoScaling::AutoScalingGroup' => '200',
|
33
|
-
'AWS::EC2::Instance' => '200',
|
34
|
-
'AWS::EC2::SpotFleet' => '200',
|
35
|
-
'AWS::Transfer::Server' => '200',
|
36
|
-
'AWS::ECS::Cluster' => '250',
|
37
|
-
'AWS::CloudWatch::Alarm' => '300'
|
16
|
+
DEFAULT_PRIORITIES = {
|
17
|
+
'AWS::RDS::DBInstance' => '100',
|
18
|
+
'AWS::RDS::DBCluster' => '100',
|
19
|
+
'AWS::DocDB::DBCluster' => '100',
|
20
|
+
'AWS::AutoScaling::AutoScalingGroup' => '200',
|
21
|
+
'AWS::EC2::Instance' => '200',
|
22
|
+
'AWS::EC2::SpotFleet' => '200',
|
23
|
+
'AWS::Transfer::Server' => '200',
|
24
|
+
'AWS::ECS::Cluster' => '250',
|
25
|
+
'AWS::CloudWatch::Alarm' => '300'
|
38
26
|
}
|
27
|
+
|
28
|
+
TAGGED_RESOURCES = %w(
|
29
|
+
AWS::AutoScaling::AutoScalingGroup
|
30
|
+
AWS::EC2::Instance
|
31
|
+
AWS::ECS::Cluster
|
32
|
+
)
|
39
33
|
|
40
34
|
def initialize()
|
41
35
|
@environment_resources = []
|
@@ -46,10 +40,6 @@ module CfnManage
|
|
46
40
|
if not @credentials.nil?
|
47
41
|
@cf_client = Aws::CloudFormation::Client.new(credentials: @credentials, retry_limit: 20)
|
48
42
|
end
|
49
|
-
@dry_run = (ENV.key?('DRY_RUN') and ENV['DRY_RUN'] == '1')
|
50
|
-
@skip_wait = (ENV.key?('SKIP_WAIT') and ENV['SKIP_WAIT'] == '1')
|
51
|
-
@wait_async = (ENV.key?('WAIT_ASYNC') and ENV['WAIT_ASYNC'] == '1')
|
52
|
-
@continue_on_error = (ENV.key? 'CFN_CONTINUE_ON_ERROR' and ENV['CFN_CONTINUE_ON_ERROR'] == '1')
|
53
43
|
rescue NoMethodError => e
|
54
44
|
puts "Got No Method Error on CloudFormation::initialize, this often means that you're missing a AWS_DEFAULT_REGION"
|
55
45
|
rescue Aws::Sigv4::Errors::MissingCredentialsError => e
|
@@ -62,7 +52,7 @@ module CfnManage
|
|
62
52
|
Common.visit_stack(@cf_client, stack_name, method(:collect_resources), true)
|
63
53
|
do_start_assets
|
64
54
|
configuration = { stack_running: true }
|
65
|
-
save_item_configuration("environment_data/stack-#{stack_name}", configuration) unless
|
55
|
+
save_item_configuration("environment_data/stack-#{stack_name}", configuration) unless CfnManage.dry_run?
|
66
56
|
$log.info("Environment #{stack_name} started")
|
67
57
|
end
|
68
58
|
|
@@ -72,19 +62,31 @@ module CfnManage
|
|
72
62
|
Common.visit_stack(@cf_client, stack_name, method(:collect_resources), true)
|
73
63
|
do_stop_assets
|
74
64
|
configuration = { stack_running: false }
|
75
|
-
save_item_configuration("environment_data/stack-#{stack_name}", configuration) unless
|
65
|
+
save_item_configuration("environment_data/stack-#{stack_name}", configuration) unless CfnManage.dry_run?
|
76
66
|
$log.info("Environment #{stack_name} stopped")
|
77
67
|
end
|
78
68
|
|
79
69
|
def start_resource(resource_id,resource_type)
|
70
|
+
priority = DEFAULT_PRIORITIES[resource_type]
|
71
|
+
options = {}
|
72
|
+
|
73
|
+
if CfnManage.find_tags?
|
74
|
+
tags = CfnManage::TagFiner.new(resource_id)
|
75
|
+
tags.get_tags(resource_type)
|
76
|
+
priority = !tags.priority.nil? ? tags.priority : priority
|
77
|
+
options = tags.options
|
78
|
+
$log.debug("setting options #{options} for #{resource_id}")
|
79
|
+
end
|
80
|
+
|
80
81
|
start_stop_handler = CfnManage::StartStopHandlerFactory.get_start_stop_handler(
|
81
82
|
resource_type,
|
82
83
|
resource_id,
|
83
|
-
|
84
|
+
options
|
84
85
|
)
|
86
|
+
|
85
87
|
@environment_resources << {
|
86
88
|
id: resource_id,
|
87
|
-
priority:
|
89
|
+
priority: priority,
|
88
90
|
handler: start_stop_handler,
|
89
91
|
type: resource_type
|
90
92
|
}
|
@@ -92,14 +94,25 @@ module CfnManage
|
|
92
94
|
end
|
93
95
|
|
94
96
|
def stop_resource(resource_id,resource_type)
|
97
|
+
priority = DEFAULT_PRIORITIES[resource_type]
|
98
|
+
options = {}
|
99
|
+
|
100
|
+
if CfnManage.find_tags?
|
101
|
+
tags = CfnManage::TagFiner.new(resource_id)
|
102
|
+
tags.get_tags(resource_type)
|
103
|
+
priority = !tags.priority.nil? ? tags.priority : priority
|
104
|
+
options = tags.options
|
105
|
+
end
|
106
|
+
|
95
107
|
start_stop_handler = CfnManage::StartStopHandlerFactory.get_start_stop_handler(
|
96
108
|
resource_type,
|
97
109
|
resource_id,
|
98
|
-
|
110
|
+
options
|
99
111
|
)
|
112
|
+
|
100
113
|
@environment_resources << {
|
101
114
|
id: resource_id,
|
102
|
-
priority:
|
115
|
+
priority: priority,
|
103
116
|
handler: start_stop_handler,
|
104
117
|
type: resource_type
|
105
118
|
}
|
@@ -116,7 +129,7 @@ module CfnManage
|
|
116
129
|
begin
|
117
130
|
$log.info("Stopping resource #{resource[:id]}")
|
118
131
|
# just print out information if running a dry run, otherwise start assets
|
119
|
-
if
|
132
|
+
if !CfnManage.dry_run?
|
120
133
|
configuration = resource[:handler].stop()
|
121
134
|
if configuration.class == Hash
|
122
135
|
s3_prefix = "environment_data/resource/#{resource[:id]}"
|
@@ -130,13 +143,13 @@ module CfnManage
|
|
130
143
|
$log.error("An exception occurred during stop operation against resource #{resource[:id]}")
|
131
144
|
$log.error("#{e.to_s}")
|
132
145
|
$log.error(e.backtrace.join("\n\t"))
|
133
|
-
if not
|
146
|
+
if not CfnManage.continue_on_error?
|
134
147
|
raise e
|
135
148
|
end
|
136
149
|
end
|
137
150
|
end
|
138
151
|
|
139
|
-
if not
|
152
|
+
if not CfnManage.dry_run? and CfnManage.wait_async?
|
140
153
|
priority.each do |resource|
|
141
154
|
begin
|
142
155
|
resource[:handler].wait('stopped')
|
@@ -144,7 +157,7 @@ module CfnManage
|
|
144
157
|
$log.error("An exception occurred during wait operation against resource #{resource[:id]}")
|
145
158
|
$log.error("#{e.to_s}")
|
146
159
|
$log.error(e.backtrace.join("\n\t"))
|
147
|
-
if not
|
160
|
+
if not CfnManage.continue_on_error?
|
148
161
|
raise e
|
149
162
|
end
|
150
163
|
end
|
@@ -164,11 +177,11 @@ module CfnManage
|
|
164
177
|
begin
|
165
178
|
$log.info("Starting resource #{resource[:id]}")
|
166
179
|
# just print out information if running a dry run, otherwise start assets
|
167
|
-
if
|
180
|
+
if !CfnManage.dry_run?
|
168
181
|
# read configuration
|
169
182
|
s3_prefix = "environment_data/resource/#{resource[:id]}"
|
170
183
|
configuration = get_object_configuration(s3_prefix)
|
171
|
-
|
184
|
+
|
172
185
|
# start
|
173
186
|
resource[:handler].start(configuration)
|
174
187
|
else
|
@@ -179,13 +192,13 @@ module CfnManage
|
|
179
192
|
$log.error("An exception occurred during start operation against resource #{resource[:id]}")
|
180
193
|
$log.error("#{e.to_s}")
|
181
194
|
$log.error(e.backtrace.join("\n\t"))
|
182
|
-
if not
|
195
|
+
if not CfnManage.continue_on_error?
|
183
196
|
raise e
|
184
197
|
end
|
185
198
|
end
|
186
199
|
end
|
187
200
|
|
188
|
-
if not
|
201
|
+
if not CfnManage.dry_run? and CfnManage.wait_async?
|
189
202
|
priority.each do |resource|
|
190
203
|
begin
|
191
204
|
resource[:handler].wait('available')
|
@@ -193,7 +206,7 @@ module CfnManage
|
|
193
206
|
$log.error("An exception occurred during wait operation against resource #{resource[:id]}")
|
194
207
|
$log.error("#{e.to_s}")
|
195
208
|
$log.error(e.backtrace.join("\n\t"))
|
196
|
-
if not
|
209
|
+
if not CfnManage.continue_on_error?
|
197
210
|
raise e
|
198
211
|
end
|
199
212
|
end
|
@@ -208,30 +221,45 @@ module CfnManage
|
|
208
221
|
resrouces = @cf_client.describe_stack_resources(stack_name: stack_name)
|
209
222
|
resrouces['stack_resources'].each do |resource|
|
210
223
|
start_stop_handler = nil
|
211
|
-
|
224
|
+
|
225
|
+
resource_id = resource['physical_resource_id']
|
226
|
+
resource_type = resource['resource_type']
|
227
|
+
priority = DEFAULT_PRIORITIES[resource_type]
|
228
|
+
options = {}
|
229
|
+
|
230
|
+
if CfnManage.find_tags? && TAGGED_RESOURCES.include?(resource_type)
|
231
|
+
tags = CfnManage::TagFinder.new(resource_id)
|
232
|
+
tags.get_tags(resource_type)
|
233
|
+
options = tags.options
|
234
|
+
priority = options[:priority] if options.has_key?(:priority)
|
235
|
+
$log.debug("setting options #{options} for #{resource_id}")
|
236
|
+
end
|
237
|
+
|
238
|
+
begin
|
212
239
|
start_stop_handler = CfnManage::StartStopHandlerFactory.get_start_stop_handler(
|
213
|
-
|
214
|
-
|
215
|
-
|
240
|
+
resource_type,
|
241
|
+
resource_id,
|
242
|
+
options
|
216
243
|
)
|
217
244
|
rescue Exception => e
|
218
|
-
$log.error("Error creating start-stop handler for resource of type #{resource['resource_type']}" +
|
245
|
+
$log.error("Error creating start-stop handler for resource of type #{resource['resource_type']} " +
|
219
246
|
"and with id #{resource['physical_resource_id']}:#{e}")
|
220
247
|
end
|
221
|
-
|
222
|
-
|
248
|
+
|
249
|
+
if !start_stop_handler.nil?
|
250
|
+
$log.debug("priority set to #{priority} for resource id: #{resource_id}, type: #{resource_type}")
|
223
251
|
@environment_resources << {
|
224
252
|
id: resource_id,
|
225
|
-
priority:
|
253
|
+
priority: priority,
|
226
254
|
handler: start_stop_handler,
|
227
|
-
type:
|
255
|
+
type: resource_type
|
228
256
|
}
|
229
257
|
end
|
230
258
|
end
|
231
259
|
end
|
232
260
|
|
233
261
|
def get_object_configuration(s3_prefix)
|
234
|
-
configuration =
|
262
|
+
configuration = {}
|
235
263
|
begin
|
236
264
|
key = "#{s3_prefix}/latest/config.json"
|
237
265
|
$log.info("Reading object configuration from s3://#{@s3_bucket}/#{key}")
|
@@ -267,4 +295,4 @@ module CfnManage
|
|
267
295
|
|
268
296
|
end
|
269
297
|
end
|
270
|
-
end
|
298
|
+
end
|