from __future__ import absolute_import, print_function
+import json
import time
import unittest
self.assertTrue(self.driver_mock.called)
self.assertEqual(kwargs, self.driver_mock.call_args[1])
- def test_create_location_loaded_at_initialization(self):
- kwargs = {'location': 'testregion'}
- driver = self.new_driver(create_kwargs=kwargs)
- self.assertTrue(self.driver_mock().list_locations)
-
- def test_create_image_loaded_at_initialization(self):
- kwargs = {'image': 'testimage'}
- driver = self.new_driver(create_kwargs=kwargs)
- self.assertTrue(self.driver_mock().list_images)
+ def test_create_image_loaded_at_initialization_by_name(self):
+ image_mocks = [testutil.cloud_object_mock(c) for c in 'abc']
+ list_method = self.driver_mock().list_images
+ list_method.return_value = image_mocks
+ driver = self.new_driver(create_kwargs={'image': 'B'})
+ self.assertEqual(1, list_method.call_count)
+
+ def test_list_sizes_requires_location_match(self):
+ locations = [testutil.cloud_object_mock(name)
+ for name in ['there', 'here', 'other']]
+ self.driver_mock().list_locations.return_value = locations
+ driver = self.new_driver(create_kwargs={'location': 'HERE'})
+ driver.list_sizes()
+ self.assertIs(locations[1],
+ self.driver_mock().list_sizes.call_args[0][0])
def test_create_includes_ping_secret(self):
arv_node = testutil.arvados_node_mock(info={'ping_secret': 'ssshh'})
driver = self.new_driver()
driver.create_node(testutil.MockSize(1), arv_node)
- create_method = self.driver_mock().create_node
- self.assertTrue(create_method.called)
- create_metadata = create_method.call_args[1].get('ex_metadata')
- self.assertIsInstance(create_metadata, dict)
- self.assertIn('ping_secret=ssshh',
- create_metadata.get('pingUrl', 'arg missing'))
-
- def test_generate_metadata_for_new_arvados_node(self):
- arv_node = testutil.arvados_node_mock(8)
- driver = self.new_driver(list_kwargs={'list': 'test'})
- self.assertEqual({'ex_metadata': {'list': 'test'}},
- driver.arvados_create_kwargs(arv_node))
+ metadata = self.driver_mock().create_node.call_args[1]['ex_metadata']
+ self.assertIn('ping_secret=ssshh', metadata.get('user-data'))
- def test_tags_set_default_hostname_from_new_arvados_node(self):
- arv_node = testutil.arvados_node_mock(hostname=None)
- cloud_node = testutil.cloud_node_mock(1)
+ def test_create_sets_default_hostname(self):
driver = self.new_driver()
- driver.sync_node(cloud_node, arv_node)
- tag_mock = self.driver_mock().ex_set_node_tags
- self.assertTrue(tag_mock.called)
- self.assertEqual(['hostname-dynamic.compute.zzzzz.arvadosapi.com'],
- tag_mock.call_args[0][1])
-
- def test_sync_node_sets_static_hostname(self):
+ driver.create_node(testutil.MockSize(1),
+ testutil.arvados_node_mock(254, hostname=None))
+ create_kwargs = self.driver_mock().create_node.call_args[1]
+ self.assertEqual('compute-0000000000000fe-zzzzz',
+ create_kwargs.get('name'))
+ self.assertEqual('dynamic.compute.zzzzz.arvadosapi.com',
+ create_kwargs.get('ex_metadata', {}).get('hostname'))
+
+ def test_create_tags_from_list_tags(self):
+ driver = self.new_driver(list_kwargs={'tags': 'testA, testB'})
+ driver.create_node(testutil.MockSize(1), testutil.arvados_node_mock())
+ self.assertEqual(['testA', 'testB'],
+ self.driver_mock().create_node.call_args[1]['ex_tags'])
+
+ def test_list_nodes_requires_tags_match(self):
+ # A node matches if our list tags are a subset of the node's tags.
+ # Test behavior with no tags, no match, partial matches, different
+ # order, and strict supersets.
+ cloud_mocks = [
+ testutil.cloud_node_mock(node_num, tags=tag_set)
+ for node_num, tag_set in enumerate(
+ [[], ['bad'], ['good'], ['great'], ['great', 'ok'],
+ ['great', 'good'], ['good', 'fantastic', 'great']])]
+ cloud_mocks.append(testutil.cloud_node_mock())
+ self.driver_mock().list_nodes.return_value = cloud_mocks
+ driver = self.new_driver(list_kwargs={'tags': 'good, great'})
+ self.assertItemsEqual(['5', '6'], [n.id for n in driver.list_nodes()])
+
+ def build_gce_metadata(self, metadata_dict):
+ # Convert a plain metadata dictionary to the GCE data structure.
+ return {
+ 'kind': 'compute#metadata',
+ 'fingerprint': 'testprint',
+ 'items': [{'key': key, 'value': metadata_dict[key]}
+ for key in metadata_dict],
+ }
+
+ def check_sync_node_updates_hostname_tag(self, plain_metadata):
+ start_metadata = self.build_gce_metadata(plain_metadata)
arv_node = testutil.arvados_node_mock(1)
- cloud_node = testutil.cloud_node_mock(2)
+ cloud_node = testutil.cloud_node_mock(
+ 2, metadata=start_metadata.copy(),
+ zone=testutil.cloud_object_mock('testzone'))
driver = self.new_driver()
driver.sync_node(cloud_node, arv_node)
- tag_mock = self.driver_mock().ex_set_node_tags
- self.assertTrue(tag_mock.called)
- self.assertEqual(['hostname-compute1.zzzzz.arvadosapi.com'],
- tag_mock.call_args[0][1])
-
- def test_node_create_time(self):
- refsecs = int(time.time())
- reftuple = time.gmtime(refsecs)
+ args, kwargs = self.driver_mock().connection.async_request.call_args
+ self.assertEqual('/zones/TESTZONE/instances/2/setMetadata', args[0])
+ for key in ['kind', 'fingerprint']:
+ self.assertEqual(start_metadata[key], kwargs['data'][key])
+ plain_metadata['hostname'] = 'compute1.zzzzz.arvadosapi.com'
+ self.assertEqual(
+ plain_metadata,
+ {item['key']: item['value'] for item in kwargs['data']['items']})
+
+ def test_sync_node_updates_hostname_tag(self):
+ self.check_sync_node_updates_hostname_tag(
+ {'testkey': 'testvalue', 'hostname': 'startvalue'})
+
+ def test_sync_node_adds_hostname_tag(self):
+ self.check_sync_node_updates_hostname_tag({'testkey': 'testval'})
+
+ def test_sync_node_raises_exception_on_failure(self):
+ arv_node = testutil.arvados_node_mock(8)
+ cloud_node = testutil.cloud_node_mock(
+ 9, metadata={}, zone=testutil.cloud_object_mock('failzone'))
+ mock_response = self.driver_mock().connection.async_request()
+ mock_response.success.return_value = False
+ mock_response.error = 'sync error test'
+ driver = self.new_driver()
+ with self.assertRaises(Exception) as err_check:
+ driver.sync_node(cloud_node, arv_node)
+ self.assertIs(err_check.exception.__class__, Exception)
+ self.assertIn('sync error test', str(err_check.exception))
+
+ def test_node_create_time_zero_for_unknown_nodes(self):
node = testutil.cloud_node_mock()
- node.extra = {'launch_time': time.strftime('%Y-%m-%dT%H:%M:%S.000Z',
- reftuple)}
- self.assertEqual(refsecs, gce.ComputeNodeDriver.node_start_time(node))
+ self.assertEqual(0, gce.ComputeNodeDriver.node_start_time(node))
- def test_generate_metadata_for_new_arvados_node(self):
- arv_node = testutil.arvados_node_mock(8)
- driver = self.new_driver(list_kwargs={'list': 'test'})
- self.assertEqual({'ex_metadata': {'list': 'test'}},
- driver.arvados_create_kwargs(arv_node))
+ def test_node_create_time_for_known_node(self):
+ node = testutil.cloud_node_mock(metadata=self.build_gce_metadata(
+ {'booted_at': '1970-01-01T00:01:05Z'}))
+ self.assertEqual(65, gce.ComputeNodeDriver.node_start_time(node))
+
+ def test_node_create_time_recorded_when_node_boots(self):
+ start_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
+ arv_node = testutil.arvados_node_mock()
+ driver = self.new_driver()
+ driver.create_node(testutil.MockSize(1), arv_node)
+ metadata = self.driver_mock().create_node.call_args[1]['ex_metadata']
+ self.assertLessEqual(start_time, metadata.get('booted_at'))
def test_deliver_ssh_key_in_metadata(self):
test_ssh_key = 'ssh-rsa-foo'
arv_node = testutil.arvados_node_mock(1)
- with mock.patch('__builtin__.open', mock.mock_open(read_data=test_ssh_key)) as mock_file:
+ with mock.patch('__builtin__.open',
+ mock.mock_open(read_data=test_ssh_key)) as mock_file:
driver = self.new_driver(create_kwargs={'ssh_key': 'ssh-key-file'})
mock_file.assert_called_once_with('ssh-key-file')
- self.assertEqual({'ex_metadata': {'sshKeys': 'root:ssh-rsa-foo'}},
- driver.arvados_create_kwargs(arv_node))
+ driver.create_node(testutil.MockSize(1), arv_node)
+ metadata = self.driver_mock().create_node.call_args[1]['ex_metadata']
+ self.assertEqual('root:ssh-rsa-foo', metadata.get('sshKeys'))
def test_create_driver_with_service_accounts(self):
- srv_acct_config = { 'service_accounts': '{ "email": "foo@bar", "scopes":["storage-full"]}' }
+ service_accounts = {'email': 'foo@bar', 'scopes': ['storage-full']}
+ srv_acct_config = {'service_accounts': json.dumps(service_accounts)}
arv_node = testutil.arvados_node_mock(1)
driver = self.new_driver(create_kwargs=srv_acct_config)
- create_kwargs = driver.arvados_create_kwargs(arv_node)
- self.assertEqual({u'email': u'foo@bar', u'scopes': [u'storage-full']},
- create_kwargs['ex_service_accounts'])
+ driver.create_node(testutil.MockSize(1), arv_node)
+ self.assertEqual(
+ service_accounts,
+ self.driver_mock().create_node.call_args[1]['ex_service_accounts'])