252
210
'secret-key': 'hoover',
254
212
self.assertEqual(aws.euca_environ, {
255
'AWS_ACCESS_KEY': 'skeleton',
256
'AWS_SECRET_KEY': 'hoover',
257
213
'EC2_ACCESS_KEY': 'skeleton',
258
214
'EC2_SECRET_KEY': 'hoover',
259
215
'EC2_URL': 'https://france.ec2.amazonaws.com',
261
217
self.assertEqual(aws.region, 'france')
219
def test_get_environ(self):
220
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
221
environ = dict(os.environ)
223
'EC2_ACCESS_KEY': 'skeleton-key',
224
'EC2_SECRET_KEY': 'secret-skeleton-key',
225
'EC2_URL': 'https://ca-west.ec2.amazonaws.com',
227
self.assertEqual(aws.get_environ(), environ)
230
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
231
with patch('subprocess.check_call',
232
return_value='quxx') as co_mock:
233
result = aws.euca('foo-bar', ['baz', 'qux'])
234
co_mock.assert_called_once_with(['euca-foo-bar', 'baz', 'qux'],
235
env=aws.get_environ())
236
self.assertEqual(result, 'quxx')
238
def test_get_euca_output(self):
239
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
240
with patch('subprocess.check_output',
241
return_value='quxx') as co_mock:
242
result = aws.get_euca_output('foo-bar', ['baz', 'qux'])
243
co_mock.assert_called_once_with(['euca-foo-bar', 'baz', 'qux'],
244
env=aws.get_environ())
245
self.assertEqual(result, 'quxx')
263
247
def test_iter_security_groups(self):
267
def __init__(self, name):
268
self.name, self.id = name, name + "-id"
270
for name in ['foo', 'foobar', 'baz']:
271
group = FakeGroup(name)
274
client = MagicMock(spec=['get_all_security_groups'])
275
client.get_all_security_groups.return_value = list(make_group())
276
with patch('substrate.ec2.connect_to_region',
277
return_value=client) as ctr_mock:
278
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
248
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
250
def make_group(name):
252
'GROUP', name + '-id', '689913858002',
253
name, 'juju group', 'vpc-1f40b47a'])
255
return_value = ''.join(
256
make_group(g) + '\n' for g in ['foo', 'foobar', 'baz'])
257
return_value += 'RANDOM\n'
259
with patch('subprocess.check_output',
260
return_value=return_value) as co_mock:
279
261
groups = list(aws.iter_security_groups())
280
self.assertEqual(groups, [
281
('foo-id', 'foo'), ('foobar-id', 'foobar'), ('baz-id', 'baz')])
282
self.assert_ec2_connection_call(ctr_mock)
284
def assert_ec2_connection_call(self, ctr_mock):
285
ctr_mock.assert_called_once_with(
286
'ca-west', aws_access_key_id='skeleton-key',
287
aws_secret_access_key='secret-skeleton-key')
262
co_mock.assert_called_once_with(
263
['euca-describe-groups', '--filter', 'description=juju group'],
264
env=aws.get_environ())
265
self.assertEqual(groups, [
266
('foo-id', 'foo'), ('foobar-id', 'foobar'), ('baz-id', 'baz')])
289
268
def test_iter_instance_security_groups(self):
291
MagicMock(instances=[MagicMock(groups=[
292
SecurityGroup(id='foo', name='bar'), ])]),
293
MagicMock(instances=[MagicMock(groups=[
294
SecurityGroup(id='baz', name='qux'),
295
SecurityGroup(id='quxx-id', name='quxx'), ])]),
297
client = MagicMock(spec=['get_all_instances'])
298
client.get_all_instances.return_value = instances
299
with patch('substrate.ec2.connect_to_region',
300
return_value=client) as ctr_mock:
301
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
269
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
270
with patch.object(aws, 'get_ec2_connection') as gec_mock:
272
MagicMock(instances=[MagicMock(groups=[
273
SecurityGroup(id='foo', name='bar'),
275
MagicMock(instances=[MagicMock(groups=[
276
SecurityGroup(id='baz', name='qux'),
277
SecurityGroup(id='quxx-id', name='quxx'),
280
gai_mock = gec_mock.return_value.get_all_instances
281
gai_mock.return_value = instances
302
282
groups = list(aws.iter_instance_security_groups())
304
groups, [('foo', 'bar'), ('baz', 'qux'), ('quxx-id', 'quxx')])
305
client.get_all_instances.assert_called_once_with(instance_ids=None)
306
self.assert_ec2_connection_call(ctr_mock)
283
gec_mock.assert_called_once_with()
284
self.assertEqual(groups, [
285
('foo', 'bar'), ('baz', 'qux'), ('quxx-id', 'quxx')])
286
gai_mock.assert_called_once_with(instance_ids=None)
308
288
def test_iter_instance_security_groups_instances(self):
310
MagicMock(instances=[MagicMock(groups=[
311
SecurityGroup(id='foo', name='bar'),
313
MagicMock(instances=[MagicMock(groups=[
314
SecurityGroup(id='baz', name='qux'),
315
SecurityGroup(id='quxx-id', name='quxx'),
318
client = MagicMock(spec=['get_all_instances'])
319
client.get_all_instances.return_value = instances
320
with patch('substrate.ec2.connect_to_region',
321
return_value=client) as ctr_mock:
322
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
323
list(aws.iter_instance_security_groups(['abc', 'def']))
324
client.get_all_instances.assert_called_once_with(
325
instance_ids=['abc', 'def'])
326
self.assert_ec2_connection_call(ctr_mock)
289
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
290
with patch.object(aws, 'get_ec2_connection') as gec_mock:
292
MagicMock(instances=[MagicMock(groups=[
293
SecurityGroup(id='foo', name='bar'),
295
MagicMock(instances=[MagicMock(groups=[
296
SecurityGroup(id='baz', name='qux'),
297
SecurityGroup(id='quxx-id', name='quxx'),
300
gai_mock = gec_mock.return_value.get_all_instances
301
gai_mock.return_value = instances
302
list(aws.iter_instance_security_groups(['abc', 'def']))
303
gai_mock.assert_called_once_with(instance_ids=['abc', 'def'])
328
305
def test_destroy_security_groups(self):
329
client = MagicMock(spec=['delete_security_group'])
330
client.delete_security_group.return_value = True
331
with patch('substrate.ec2.connect_to_region',
332
return_value=client) as ctr_mock:
333
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
306
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
307
with patch('subprocess.check_call') as cc_mock:
334
308
failures = aws.destroy_security_groups(
335
309
['foo', 'foobar', 'baz'])
336
calls = [call(name='foo'), call(name='foobar'), call(name='baz')]
337
self.assertEqual(client.delete_security_group.mock_calls, calls)
338
self.assertEqual(failures, [])
339
self.assert_ec2_connection_call(ctr_mock)
310
self.assertEqual(cc_mock.mock_calls[0], call(
311
['euca-delete-group', 'foo'], env=aws.get_environ()))
312
self.assertEqual(cc_mock.mock_calls[1], call(
313
['euca-delete-group', 'foobar'], env=aws.get_environ()))
314
self.assertEqual(cc_mock.mock_calls[2], call(
315
['euca-delete-group', 'baz'], env=aws.get_environ()))
316
self.assertEqual(3, cc_mock.call_count)
317
self.assertEqual(failures, [])
341
319
def test_destroy_security_failures(self):
342
client = MagicMock(spec=['delete_security_group'])
343
client.delete_security_group.return_value = False
344
with patch('substrate.ec2.connect_to_region',
345
return_value=client) as ctr_mock:
346
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
347
failures = aws.destroy_security_groups(
348
['foo', 'foobar', 'baz'])
349
self.assertEqual(failures, ['foo', 'foobar', 'baz'])
350
self.assert_ec2_connection_call(ctr_mock)
353
def make_aws_connection(self, return_value):
354
client = MagicMock(spec=['get_all_network_interfaces'])
355
client.get_all_network_interfaces.return_value = return_value
356
with patch('substrate.ec2.connect_to_region',
357
return_value=client) as ctr_mock:
358
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
360
self.assert_ec2_connection_call(ctr_mock)
320
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
321
with patch('subprocess.check_call',
322
side_effect=CalledProcessError(1, 'foo')):
323
failures = aws.destroy_security_groups(['foo', 'foobar',
325
self.assertEqual(failures, ['foo', 'foobar', 'baz'])
327
def test_get_ec2_connection(self):
328
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
329
return_value = object()
330
with patch('boto.ec2.connect_to_region',
331
return_value=return_value) as ctr_mock:
332
connection = aws.get_ec2_connection()
333
ctr_mock.assert_called_once_with(
334
'ca-west', aws_access_key_id='skeleton-key',
335
aws_secret_access_key='secret-skeleton-key')
336
self.assertIs(connection, return_value)
338
def make_aws_connection(self):
339
with AWSAccount.manager_from_config(get_aws_env().config) as aws:
340
aws.get_ec2_connection = MagicMock()
341
connection = aws.get_ec2_connection.return_value
342
return aws, connection
362
344
def make_interface(self, group_ids):
363
interface = MagicMock(spec=['groups', 'delete', 'id'])
345
interface = MagicMock()
364
346
interface.groups = [SecurityGroup(id=g) for g in group_ids]
367
349
def test_delete_detached_interfaces_with_id(self):
350
aws, connection = self.make_aws_connection()
368
351
foo_interface = self.make_interface(['bar-id'])
369
352
baz_interface = self.make_interface(['baz-id', 'bar-id'])
370
with self.make_aws_connection([foo_interface, baz_interface]) as aws:
371
unclean = aws.delete_detached_interfaces(['bar-id'])
372
foo_interface.delete.assert_called_once_with()
373
baz_interface.delete.assert_called_once_with()
353
gani_mock = connection.get_all_network_interfaces
354
gani_mock.return_value = [foo_interface, baz_interface]
355
unclean = aws.delete_detached_interfaces(['bar-id'])
356
gani_mock.assert_called_once_with(
357
filters={'status': 'available'})
358
foo_interface.delete.assert_called_once_with()
359
baz_interface.delete.assert_called_once_with()
374
360
self.assertEqual(unclean, set())
376
362
def test_delete_detached_interfaces_without_id(self):
363
aws, connection = self.make_aws_connection()
377
364
baz_interface = self.make_interface(['baz-id'])
378
with self.make_aws_connection([baz_interface]) as aws:
379
unclean = aws.delete_detached_interfaces(['bar-id'])
365
connection.get_all_network_interfaces.return_value = [baz_interface]
366
unclean = aws.delete_detached_interfaces(['bar-id'])
380
367
self.assertEqual(baz_interface.delete.call_count, 0)
381
368
self.assertEqual(unclean, set())
383
370
def prepare_delete_exception(self, error_code):
371
aws, connection = self.make_aws_connection()
384
372
baz_interface = self.make_interface(['bar-id'])
385
373
e = EC2ResponseError('status', 'reason')
386
374
e.error_code = error_code
387
375
baz_interface.delete.side_effect = e
376
connection.get_all_network_interfaces.return_value = [baz_interface]
377
return aws, baz_interface
390
379
def test_delete_detached_interfaces_in_use(self):
391
baz_interface = self.prepare_delete_exception(
380
aws, baz_interface = self.prepare_delete_exception(
392
381
'InvalidNetworkInterface.InUse')
393
with self.make_aws_connection([baz_interface]) as aws:
394
unclean = aws.delete_detached_interfaces(['bar-id', 'foo-id'])
382
unclean = aws.delete_detached_interfaces(['bar-id', 'foo-id'])
395
383
baz_interface.delete.assert_called_once_with()
396
384
self.assertEqual(unclean, set(['bar-id']))
398
386
def test_delete_detached_interfaces_not_found(self):
399
baz_interface = self.prepare_delete_exception(
387
aws, baz_interface = self.prepare_delete_exception(
400
388
'InvalidNetworkInterfaceID.NotFound')
401
with self.make_aws_connection([baz_interface]) as aws:
402
unclean = aws.delete_detached_interfaces(['bar-id', 'foo-id'])
389
unclean = aws.delete_detached_interfaces(['bar-id', 'foo-id'])
403
390
baz_interface.delete.assert_called_once_with()
404
391
self.assertEqual(unclean, set(['bar-id']))
406
393
def test_delete_detached_interfaces_other(self):
407
baz_interface = self.prepare_delete_exception(
394
aws, baz_interface = self.prepare_delete_exception(
408
395
'InvalidNetworkInterfaceID')
409
with self.make_aws_connection([baz_interface]) as aws:
410
with self.assertRaises(EC2ResponseError):
411
aws.delete_detached_interfaces(['bar-id', 'foo-id'])
396
with self.assertRaises(EC2ResponseError):
397
aws.delete_detached_interfaces(['bar-id', 'foo-id'])
414
400
def get_os_config():