vm_shepherd 1.5.1 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vm_shepherd/aws_manager.rb +48 -15
- data/lib/vm_shepherd/version.rb +1 -1
- data/spec/vm_shepherd/aws_manager_spec.rb +4 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1db947ff086cec29ff5a2565d8e54041203a97b1
|
4
|
+
data.tar.gz: 6caa24f8e4508aa51a0c73a72c54e738a05afb93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df565e43afea2322d0f018b4a38485ec9edea318bfa90020b605ea584771a94da433c5239db5b077e4fd9aed6d0ccf26fcf728f69c968fcaf33d2edeb4932e53
|
7
|
+
data.tar.gz: 0ac5752d872b82b6fcfbd5c3b1bbc3d55ce00d34baa77d35ebc0b0ad3496d6ef9343b7aa94b2d8e730818d1f69d259c5530e1d4b446dda79a2caaabb9cfc095b
|
@@ -9,6 +9,15 @@ module VmShepherd
|
|
9
9
|
DO_NOT_TERMINATE_TAG_KEY = 'do_not_terminate'
|
10
10
|
ELB_SECURITY_GROUP_NAME = 'ELB Security Group'
|
11
11
|
|
12
|
+
CREATE_IN_PROGRESS = 'CREATE_IN_PROGRESS'
|
13
|
+
CREATE_COMPLETE = 'CREATE_COMPLETE'
|
14
|
+
ROLLBACK_IN_PROGRESS = 'ROLLBACK_IN_PROGRESS'
|
15
|
+
ROLLBACK_COMPLETE = 'ROLLBACK_COMPLETE'
|
16
|
+
DELETE_IN_PROGRESS = 'DELETE_IN_PROGRESS'
|
17
|
+
DELETE_COMPLETE = 'DELETE_COMPLETE'
|
18
|
+
|
19
|
+
attr_writer :logger
|
20
|
+
|
12
21
|
def initialize(env_config)
|
13
22
|
AWS.config(
|
14
23
|
access_key_id: env_config.fetch(:aws_access_key),
|
@@ -16,25 +25,29 @@ module VmShepherd
|
|
16
25
|
region: env_config.fetch(:region),
|
17
26
|
)
|
18
27
|
@env_config = env_config
|
28
|
+
@logger = logger
|
19
29
|
end
|
20
30
|
|
21
31
|
def prepare_environment(cloudformation_template_file)
|
22
32
|
template = File.read(cloudformation_template_file)
|
23
33
|
|
24
34
|
cfm = AWS::CloudFormation.new
|
35
|
+
logger.info('Starting CloudFormation Stack Creation')
|
25
36
|
stack = cfm.stacks.create(env_config.fetch(:stack_name), template, parameters: env_config.fetch(:parameters), capabilities: ['CAPABILITY_IAM'])
|
26
37
|
|
38
|
+
logger.info("Waiting for status: #{CREATE_COMPLETE}")
|
27
39
|
retry_until(retry_limit: 360) do
|
28
40
|
status = stack.status
|
41
|
+
logger.info("current stack status: #{status}")
|
29
42
|
case status
|
30
|
-
when
|
43
|
+
when CREATE_COMPLETE
|
31
44
|
true
|
32
|
-
when
|
45
|
+
when CREATE_IN_PROGRESS
|
33
46
|
false
|
34
|
-
when
|
47
|
+
when ROLLBACK_IN_PROGRESS
|
35
48
|
false
|
36
49
|
else
|
37
|
-
stack.delete if status ==
|
50
|
+
stack.delete if status == ROLLBACK_COMPLETE
|
38
51
|
raise "Unexpected status for stack #{env_config.fetch(:stack_name)} : #{status}"
|
39
52
|
end
|
40
53
|
end
|
@@ -47,6 +60,7 @@ module VmShepherd
|
|
47
60
|
def deploy(ami_file_path:, vm_config:)
|
48
61
|
image_id = read_ami_id(ami_file_path)
|
49
62
|
|
63
|
+
logger.info('Starting AMI Instance creation')
|
50
64
|
instance =
|
51
65
|
retry_until do
|
52
66
|
begin
|
@@ -62,27 +76,27 @@ module VmShepherd
|
|
62
76
|
end
|
63
77
|
end
|
64
78
|
|
79
|
+
logger.info('waiting until the instance status is running')
|
65
80
|
retry_until do
|
66
81
|
begin
|
67
|
-
instance.status
|
82
|
+
status = instance.status
|
83
|
+
logger.info("current status: #{status}")
|
84
|
+
status == :running
|
68
85
|
rescue AWS::EC2::Errors::InvalidInstanceID::NotFound
|
69
86
|
false
|
70
87
|
end
|
71
88
|
end
|
72
89
|
|
90
|
+
logger.info('Creating an Elastic IP and assigning it to the instance')
|
73
91
|
elastic_ip = AWS.ec2.elastic_ips.create(vpc: true)
|
74
92
|
instance.associate_elastic_ip(elastic_ip.allocation_id)
|
75
93
|
instance.add_tag('Name', value: vm_config.fetch(:vm_name))
|
76
94
|
end
|
77
95
|
|
78
|
-
def read_ami_id(ami_file_path)
|
79
|
-
YAML.load_file(ami_file_path)[env_config.fetch(:region)]
|
80
|
-
end
|
81
|
-
|
82
96
|
def clean_environment
|
83
97
|
[:public_subnet_id, :private_subnet_id].each do |subnet_id|
|
84
|
-
|
85
|
-
clear_subnet(
|
98
|
+
aws_subnet_id = env_config.fetch(:outputs).fetch(subnet_id)
|
99
|
+
clear_subnet(aws_subnet_id) if aws_subnet_id
|
86
100
|
end
|
87
101
|
|
88
102
|
if (elb_config = env_config[:elb])
|
@@ -91,7 +105,10 @@ module VmShepherd
|
|
91
105
|
|
92
106
|
if (bucket_name = env_config.fetch(:outputs, {}).fetch(:s3_bucket_name, nil))
|
93
107
|
bucket = AWS::S3.new.buckets[bucket_name]
|
94
|
-
|
108
|
+
if bucket && bucket.exists?
|
109
|
+
logger.info("clearing bucket: #{bucket_name}")
|
110
|
+
bucket.clear!
|
111
|
+
end
|
95
112
|
end
|
96
113
|
|
97
114
|
delete_stack(env_config.fetch(:stack_name))
|
@@ -111,7 +128,7 @@ module VmShepherd
|
|
111
128
|
end
|
112
129
|
|
113
130
|
private
|
114
|
-
attr_reader :env_config
|
131
|
+
attr_reader :env_config, :logger
|
115
132
|
|
116
133
|
def subnet_id(stack, elb_config)
|
117
134
|
stack.outputs.detect { |o| o.key == elb_config[:stack_output_keys][:subnet_id] }.value
|
@@ -122,12 +139,14 @@ module VmShepherd
|
|
122
139
|
end
|
123
140
|
|
124
141
|
def clear_subnet(subnet_id)
|
142
|
+
logger.info("Clearing contents of subnet: #{subnet_id}")
|
125
143
|
subnet = AWS.ec2.subnets[subnet_id]
|
126
144
|
volumes = []
|
127
145
|
subnet.instances.each do |instance|
|
128
146
|
instance.attachments.each do |_, attachment|
|
129
147
|
volumes.push(attachment.volume) unless attachment.delete_on_termination
|
130
148
|
end
|
149
|
+
logger.info("terminating instance #{instance.id}")
|
131
150
|
instance.terminate
|
132
151
|
end
|
133
152
|
destroy_volumes(volumes)
|
@@ -136,6 +155,7 @@ module VmShepherd
|
|
136
155
|
def destroy_volumes(volumes)
|
137
156
|
volumes.each do |volume|
|
138
157
|
begin
|
158
|
+
logger.info("trying to delete volume: #{volume.id}")
|
139
159
|
volume.delete
|
140
160
|
rescue AWS::EC2::Errors::VolumeInUse
|
141
161
|
sleep 5
|
@@ -148,10 +168,13 @@ module VmShepherd
|
|
148
168
|
if (elb = AWS::ELB.new.load_balancers.find { |lb| lb.name == elb_name })
|
149
169
|
sg = elb.security_groups.first
|
150
170
|
net_interfaces = AWS.ec2.network_interfaces.select { |ni| ni.security_groups.map(&:id).include? sg.id }
|
171
|
+
logger.info("deleting elb: #{elb.name}")
|
151
172
|
elb.delete
|
173
|
+
logger.info('waiting until elb is deleted')
|
152
174
|
retry_until do
|
153
175
|
!elb.exists? && !net_interfaces.map(&:exists?).any?
|
154
176
|
end
|
177
|
+
logger.info("deleting elb security group: #{sg.id}")
|
155
178
|
sg.delete
|
156
179
|
end
|
157
180
|
end
|
@@ -172,6 +195,7 @@ module VmShepherd
|
|
172
195
|
}
|
173
196
|
end
|
174
197
|
|
198
|
+
logger.info('Creating an ELB')
|
175
199
|
elb.client.create_load_balancer(elb_params)
|
176
200
|
end
|
177
201
|
|
@@ -183,6 +207,7 @@ module VmShepherd
|
|
183
207
|
vpc_id: vpc_id,
|
184
208
|
}
|
185
209
|
|
210
|
+
logger.info('Creating a Security Group for the ELB')
|
186
211
|
security_group_response = AWS.ec2.client.create_security_group(sg_params)
|
187
212
|
|
188
213
|
AWS.ec2.security_groups[security_group_response[:group_id]].tap do |security_group|
|
@@ -195,23 +220,31 @@ module VmShepherd
|
|
195
220
|
def delete_stack(stack_name)
|
196
221
|
cfm = AWS::CloudFormation.new
|
197
222
|
stack = cfm.stacks[stack_name]
|
223
|
+
logger.info('deleting CloudFormation stack')
|
198
224
|
stack.delete
|
225
|
+
logger.info("waiting until status: #{DELETE_COMPLETE}")
|
199
226
|
retry_until(retry_limit: 360) do
|
200
227
|
begin
|
201
228
|
status = stack.status
|
229
|
+
logger.info("current stack status: #{status}")
|
202
230
|
case status
|
203
|
-
when
|
231
|
+
when DELETE_COMPLETE
|
204
232
|
true
|
205
|
-
when
|
233
|
+
when DELETE_IN_PROGRESS
|
206
234
|
false
|
207
235
|
else
|
208
236
|
raise "Unexpected status for stack #{stack_name} : #{status}"
|
209
237
|
end
|
210
238
|
rescue AWS::CloudFormation::Errors::ValidationError
|
211
239
|
raise if stack.exists?
|
240
|
+
logger.info('stack deleted successfully')
|
212
241
|
true
|
213
242
|
end
|
214
243
|
end if stack
|
215
244
|
end
|
245
|
+
|
246
|
+
def read_ami_id(ami_file_path)
|
247
|
+
YAML.load_file(ami_file_path)[env_config.fetch(:region)]
|
248
|
+
end
|
216
249
|
end
|
217
250
|
end
|
data/lib/vm_shepherd/version.rb
CHANGED
@@ -42,7 +42,7 @@ module VmShepherd
|
|
42
42
|
}
|
43
43
|
end
|
44
44
|
|
45
|
-
subject(:ami_manager) { AwsManager.new(env_config) }
|
45
|
+
subject(:ami_manager) { AwsManager.new(env_config). tap { |manager| manager.logger = Logger.new(StringIO.new) } }
|
46
46
|
|
47
47
|
before do
|
48
48
|
expect(AWS).to receive(:config).with(
|
@@ -257,15 +257,15 @@ module VmShepherd
|
|
257
257
|
let(:subnets) { instance_double(AWS::EC2::SubnetCollection) }
|
258
258
|
let(:subnet1) { instance_double(AWS::EC2::Subnet, instances: subnet1_instances) }
|
259
259
|
let(:subnet2) { instance_double(AWS::EC2::Subnet, instances: subnet2_instances) }
|
260
|
-
let(:instance1) { instance_double(AWS::EC2::Instance, tags: {}) }
|
261
|
-
let(:instance2) { instance_double(AWS::EC2::Instance, tags: {}) }
|
260
|
+
let(:instance1) { instance_double(AWS::EC2::Instance, tags: {}, id: 'instance1') }
|
261
|
+
let(:instance2) { instance_double(AWS::EC2::Instance, tags: {}, id: 'instance2') }
|
262
262
|
let(:subnet1_instances) { [instance1] }
|
263
263
|
let(:subnet2_instances) { [instance2] }
|
264
264
|
let(:cfm) { instance_double(AWS::CloudFormation, stacks: stack_collection) }
|
265
265
|
let(:stack) { instance_double(AWS::CloudFormation::Stack, status: 'DELETE_COMPLETE', delete: nil) }
|
266
266
|
let(:stack_collection) { instance_double(AWS::CloudFormation::StackCollection) }
|
267
267
|
|
268
|
-
let(:instance1_volume) { instance_double(AWS::EC2::Volume) }
|
268
|
+
let(:instance1_volume) { instance_double(AWS::EC2::Volume, id: 'volume-id') }
|
269
269
|
let(:instance1_attachment) do
|
270
270
|
instance_double(AWS::EC2::Attachment, volume: instance1_volume, delete_on_termination: true)
|
271
271
|
end
|