def setup( self, mock_discovery, mock_validate_region, mock_service_account ): """Set up kwargs dict.""" self.kwargs = { 'config': 'tests/data/config', 'distro_name': 'SLES', 'image_id': 'fakeimage', 'no_default_test_dirs': True, 'service_account_file': 'tests/gce/service-account.json', 'ssh_private_key_file': 'tests/data/ida_test', 'test_files': ['test_image'] } driver = MagicMock() mock_discovery.build.return_value = driver service_account = MagicMock() mock_service_account.Credentials.\ from_service_account_file.return_value = service_account self.cloud = GCECloud(**self.kwargs)
def test_gce_exception_required_args(self): """Test an exception is raised if required args missing.""" self.kwargs['service_account_file'] = None self.kwargs['ssh_private_key_file'] = None # Test service account file required with pytest.raises(GCECloudException) as error: GCECloud(**self.kwargs) assert str(error.value) == \ 'Service account file is required to connect to GCE.' self.kwargs['service_account_file'] = 'tests/gce/service-account.json' # Test ssh private key file required with pytest.raises(GCECloudException) as error: GCECloud(**self.kwargs) assert str(error.value) == \ 'SSH private key file is required to connect to instance.' self.kwargs['ssh_private_key_file'] = 'tests/data/ida_test'
class TestGCECloud(object): """Test GCE cloud class.""" @patch('img_proof.ipa_gce.service_account') @patch.object(GCECloud, '_validate_region') @patch('img_proof.ipa_gce.discovery') def setup(self, mock_discovery, mock_validate_region, mock_service_account): """Set up kwargs dict.""" self.kwargs = { 'config': 'tests/data/config', 'distro_name': 'SLES', 'image_id': 'fakeimage', 'no_default_test_dirs': True, 'service_account_file': 'tests/gce/service-account.json', 'ssh_private_key_file': 'tests/data/ida_test', 'test_files': ['test_image'] } driver = MagicMock() mock_discovery.build.return_value = driver service_account = MagicMock() mock_service_account.Credentials.\ from_service_account_file.return_value = service_account self.cloud = GCECloud(**self.kwargs) def test_gce_exception_required_args(self): """Test an exception is raised if required args missing.""" self.kwargs['service_account_file'] = None self.kwargs['ssh_private_key_file'] = None # Test service account file required with pytest.raises(GCECloudException) as error: GCECloud(**self.kwargs) assert str(error.value) == \ 'Service account file is required to connect to GCE.' self.kwargs['service_account_file'] = 'tests/gce/service-account.json' # Test ssh private key file required with pytest.raises(GCECloudException) as error: GCECloud(**self.kwargs) assert str(error.value) == \ 'SSH private key file is required to connect to instance.' self.kwargs['ssh_private_key_file'] = 'tests/data/ida_test' @patch('img_proof.ipa_gce.service_account') def test_gce_get_service_account_info_invalid(self, mock_service_account): """Test get credentials method with invalid service account.""" self.cloud.service_account_file = \ 'tests/gce/invalid-service-account.json' with pytest.raises(GCECloudException) as error: self.cloud._get_credentials() msg = 'Service account JSON file is invalid for GCE. ' \ 'client_email key is expected. See getting started ' \ 'docs for information on GCE configuration.' assert str(error.value) == msg def test_gce_get_instance(self): """Test gce get instance method.""" instance = MagicMock() instances_obj = MagicMock() operation = MagicMock() operation.execute.return_value = instance instances_obj.get.return_value = operation self.cloud.compute_driver.instances.return_value = instances_obj val = self.cloud._get_instance() assert val == instance self.cloud.running_instance_id = 'test-instance' instances_obj.get.side_effect = get_http_error( 'test-instance cannot be found.') with pytest.raises(GCECloudException) as error: self.cloud._get_instance() exc = "Unable to retrieve instance: test-instance cannot be found." assert str(error.value) == exc def test_gce_get_network(self): """Test GCE get network method.""" network = MagicMock() networks_obj = MagicMock() operation = MagicMock() operation.execute.return_value = network networks_obj.get.return_value = operation self.cloud.compute_driver.networks.return_value = networks_obj result = self.cloud._get_network('test-network') assert result == network networks_obj.get.side_effect = get_http_error( 'Resource test-network not found.') msg = 'Unable to retrieve network: Resource test-network not found.' with pytest.raises(GCECloudException) as error: self.cloud._get_network('test-network') assert msg == str(error.value) def test_gce_get_subnet(self): """Test GCE get subnetwork method.""" subnetwork = MagicMock() subnet_obj = MagicMock() operation = MagicMock() operation.execute.return_value = subnetwork subnet_obj.get.return_value = operation self.cloud.compute_driver.subnetworks.return_value = subnet_obj self.cloud.region = 'us-west-1a' result = self.cloud._get_subnet('test-subnet') assert result == subnetwork subnet_obj.get.side_effect = get_http_error( 'Resource test-subnet not found.') msg = 'Unable to retrieve subnet: Resource test-subnet not found.' with pytest.raises(GCECloudException) as error: self.cloud._get_subnet('test-subnet') assert msg == str(error.value) def test_gce_get_instance_type(self): """Test GCE get instance type method.""" machine_type = MagicMock() machine_type_obj = MagicMock() operation = MagicMock() operation.execute.return_value = machine_type machine_type_obj.get.return_value = operation self.cloud.compute_driver.machineTypes.return_value = machine_type_obj result = self.cloud._get_instance_type('n1-standard-1') assert result == machine_type machine_type_obj.get.side_effect = get_http_error( 'Resource n1-standard-1 not found.') msg = 'Unable to retrieve instance type: ' \ 'Resource n1-standard-1 not found.' with pytest.raises(GCECloudException) as error: self.cloud._get_instance_type('n1-standard-1') assert msg == str(error.value) def test_gce_get_image(self): """Test GCE get image method.""" image = MagicMock() image_obj = MagicMock() operation = MagicMock() operation.execute.return_value = image image_obj.get.return_value = operation self.cloud.compute_driver.images.return_value = image_obj result = self.cloud._get_image('fake-image-20200202') assert result == image image_obj.get.side_effect = get_http_error( 'Resource fake-image-20200202 not found.') msg = 'Unable to retrieve image: ' \ 'Resource fake-image-20200202 not found.' with pytest.raises(GCECloudException) as error: self.cloud._get_image('fake-image-20200202') assert msg == str(error.value) def test_gce_get_disk(self): """Test GCE get image method.""" disk = MagicMock() disk_obj = MagicMock() operation = MagicMock() operation.execute.return_value = disk disk_obj.get.return_value = operation self.cloud.compute_driver.disks.return_value = disk_obj result = self.cloud._get_disk('disk12') assert result == disk disk_obj.get.side_effect = get_http_error('Resource disk12 not found.') msg = 'Unable to retrieve disk: ' \ 'Resource disk12 not found.' with pytest.raises(GCECloudException) as error: self.cloud._get_disk('disk12') assert msg == str(error.value) @patch.object(GCECloud, '_get_subnet') def test_get_network_config(self, mock_get_subnet): subnet = 'projects/test/regions/us-west1/subnetworks/sub-123' net = 'projects/test/global/networks/network' mock_get_subnet.return_value = {'selfLink': subnet, 'network': net} subnet_config = self.cloud._get_network_config('sub-123') assert subnet_config['network'] == net assert subnet_config['subnetwork'] == subnet def test_get_shielded_instance_config(self): si_config = self.cloud.get_shielded_instance_config() assert si_config['enableSecureBoot'] is False assert si_config['enableVtpm'] assert si_config['enableIntegrityMonitoring'] def test_get_instance_config(self): config = self.cloud.get_instance_config( 'instance123', 'n1-standard-1', [{}], '*****@*****.**', 'image123', 'secretkey', shielded_instance_config={'shielded': 'config'}) assert 'metadata' in config assert 'serviceAccounts' in config assert 'machineType' in config assert 'disks' in config assert 'networkInterfaces' in config assert 'name' in config assert 'shieldedInstanceConfig' in config @patch.object(GCECloud, '_wait_on_instance') @patch.object(GCECloud, '_wait_on_operation') @patch.object(GCECloud, '_get_network') @patch.object(GCECloud, '_get_image') @patch.object(GCECloud, '_get_instance_type') @patch('img_proof.ipa_utils.generate_instance_name') def test_gce_launch_instance(self, mock_generate_instance_name, mock_get_instance_type, mock_get_image, mock_get_network, mock_wait_on_operation, mock_wait_on_instance): """Test GCE launch instance method.""" mock_generate_instance_name.return_value = 'test-instance' mock_get_network.return_value = { 'selfLink': 'projects/test/global/networks/net1' } mock_get_image.return_value = { 'selfLink': 'projects/test/global/images/img-123' } mock_get_instance_type.return_value = { 'selfLink': 'zones/us-west1-a/machineTypes/n1-standard-1' } mock_wait_on_operation.return_value = {} instances_obj = MagicMock() operation = MagicMock() operation.execute.return_value = {'name': 'operation123'} instances_obj.insert.return_value = operation self.cloud.compute_driver.instances.return_value = instances_obj self.cloud.region = 'us-west1-a' self.cloud._launch_instance() assert self.cloud.running_instance_id == 'test-instance' assert mock_wait_on_instance.call_count == 1 # Exception on operation mock_wait_on_operation.return_value = { 'error': { 'errors': [{ 'code': 'QUOTA_EXCEEDED', 'message': 'Too many cpus.' }] } } with pytest.raises(IpaRetryableError) as error: self.cloud._launch_instance() assert 'Failed to launch instance: Too many cpus.' == str(error.value) # Exception on API call mock_wait_on_operation.return_value = {} instances_obj.insert.side_effect = get_http_error( 'Invalid instance type.', '412') with pytest.raises(IpaRetryableError) as error: self.cloud._launch_instance() msg = 'Failed to launch instance: Invalid instance type.' assert msg == str(error.value) @patch.object(GCECloud, '_get_disk') @patch.object(GCECloud, '_get_instance') def test_gce_set_image_id(self, mock_get_instance, mock_get_disk): """Test gce cloud set image id method.""" instance = { 'disks': [{ 'deviceName': 'disk123', 'boot': True, 'source': 'https://www.googleapis.com/compute/v1/projects/' 'test/zones/us-west1-a/disks/disk123' }] } disk = { 'sourceImage': 'projects/suse/global/images/opensuse-leap-15.0' } mock_get_instance.return_value = instance mock_get_disk.return_value = disk self.cloud._set_image_id() assert self.cloud.image_id == 'opensuse-leap-15.0' assert mock_get_instance.call_count == 1 assert mock_get_disk.call_count == 1 def test_gce_validate_region(self): """Test gce cloud set image id method.""" zones_obj = MagicMock() operation = MagicMock() operation.execute.return_value = None zones_obj.get.return_value = operation self.cloud.compute_driver.zones.return_value = zones_obj with pytest.raises(GCECloudException) as error: self.cloud._validate_region() assert str(error.value) == \ 'Zone is required for GCE cloud framework: Example: us-west1-a' self.cloud.region = 'fake' with pytest.raises(GCECloudException) as error: self.cloud._validate_region() assert str(error.value) == \ 'fake is not a valid GCE zone. Example: us-west1-a' @patch.object(GCECloud, '_get_instance') def test_gce_is_instance_running(self, mock_get_instance): """Test gce cloud is instance runnning method.""" mock_get_instance.return_value = {'status': 'RUNNING'} assert self.cloud._is_instance_running() assert mock_get_instance.call_count == 1 mock_get_instance.return_value = {'status': 'TERMINATED'} assert not self.cloud._is_instance_running() @patch.object(GCECloud, '_get_instance') def test_gce_set_instance_ip(self, mock_get_instance): """Test gce cloud set instance ip method.""" mock_get_instance.return_value = { 'networkInterfaces': [{ 'some': 'data' }] } self.cloud.running_instance_id = 'test' with pytest.raises(GCECloudException) as error: self.cloud._set_instance_ip() assert str(error.value) == \ 'IP address for instance: test cannot be found.' assert mock_get_instance.call_count == 1 mock_get_instance.return_value = { 'networkInterfaces': [{ 'networkIP': '10.0.0.0' }] } self.cloud._set_instance_ip() assert self.cloud.instance_ip == '10.0.0.0' @patch.object(GCECloud, '_wait_on_instance') def test_gce_start_instance(self, mock_wait_on_instance): """Test gce start instance method.""" mock_wait_on_instance.return_value = None instances_obj = MagicMock() operation = MagicMock() operation.execute.return_value = None instances_obj.start.return_value = operation self.cloud.compute_driver.instances.return_value = instances_obj self.cloud._start_instance() assert instances_obj.start.call_count == 1 @patch.object(GCECloud, '_wait_on_instance') def test_gce_stop_instance(self, mock_wait_on_instance): """Test gce stop instance method.""" mock_wait_on_instance.return_value = None instances_obj = MagicMock() operation = MagicMock() operation.execute.return_value = None instances_obj.stop.return_value = operation self.cloud.compute_driver.instances.return_value = instances_obj self.cloud._stop_instance() assert instances_obj.stop.call_count == 1 def test_gce_terminate_instance(self): """Test gce terminate instance method.""" instances_obj = MagicMock() operation = MagicMock() operation.execute.return_value = None instances_obj.delete.return_value = operation self.cloud.compute_driver.instances.return_value = instances_obj self.cloud._terminate_instance() assert instances_obj.delete.call_count == 1 def test_gce_get_console_log(self): """Test gce get console log method.""" instances_obj = MagicMock() operation = MagicMock() operation.execute.return_value = {'content': 'some output'} instances_obj.getSerialPortOutput.return_value = operation self.cloud.compute_driver.instances.return_value = instances_obj self.cloud.get_console_log() assert instances_obj.getSerialPortOutput.call_count == 1 @patch('img_proof.ipa_gce.time') def test_wait_on_operation(self, mock_time): self.cloud.service_account_project = 'test_project' self.cloud.region = 'us-west1-a' mock_time.sleep.return_value = None mock_time.time.return_value = 10 zone_ops_obj = MagicMock() operation = MagicMock() operation.execute.return_value = {'status': 'DONE'} zone_ops_obj.get.return_value = operation self.cloud.compute_driver.zoneOperations.return_value = zone_ops_obj result = self.cloud._wait_on_operation('operation213') assert result['status'] == 'DONE' assert zone_ops_obj.get.call_count == 1
def test_image( cloud_name, accelerated_networking=None, access_key_id=None, account=None, cleanup=None, config=None, description=None, distro=None, early_exit=None, history_log=None, image_id=None, image_project=None, inject=None, instance_type=None, ip_address=None, log_level=None, no_default_test_dirs=None, cloud_config=None, region=None, results_dir=None, running_instance_id=None, secret_access_key=None, security_group_id=None, service_account_file=None, ssh_key_name=None, ssh_private_key_file=None, ssh_user=None, subnet_id=None, test_dirs=None, tests=None, timeout=None, vnet_name=None, vnet_resource_group=None, collect_vm_info=None, compartment_id=None, availability_domain=None, signing_key_fingerprint=None, signing_key_file=None, tenancy=None, oci_user_id=None, enable_secure_boot=None, enable_uefi=None, log_callback=None, prefix_name=None, retry_count=None ): """Creates a cloud framework instance and initiates testing.""" kwargs = { 'cleanup': cleanup, 'config': config, 'description': description, 'distro_name': distro, 'early_exit': early_exit, 'history_log': history_log, 'image_id': image_id, 'inject': inject, 'instance_type': instance_type, 'log_level': log_level, 'no_default_test_dirs': no_default_test_dirs, 'cloud_config': cloud_config, 'region': region, 'results_dir': results_dir, 'running_instance_id': running_instance_id, 'ssh_private_key_file': ssh_private_key_file, 'ssh_user': ssh_user, 'subnet_id': subnet_id, 'test_dirs': test_dirs, 'test_files': tests, 'timeout': timeout, 'collect_vm_info': collect_vm_info, 'enable_secure_boot': enable_secure_boot, 'enable_uefi': enable_uefi, 'log_callback': log_callback, 'prefix_name': prefix_name, 'retry_count': retry_count } cloud_name = cloud_name.lower() if cloud_name == 'azure': cloud = AzureCloud( accelerated_networking=accelerated_networking, service_account_file=service_account_file, vnet_name=vnet_name, vnet_resource_group=vnet_resource_group, **kwargs ) elif cloud_name == 'ec2': cloud = EC2Cloud( access_key_id=access_key_id, account_name=account, secret_access_key=secret_access_key, security_group_id=security_group_id, ssh_key_name=ssh_key_name, **kwargs ) elif cloud_name == 'gce': cloud = GCECloud( service_account_file=service_account_file, image_project=image_project, **kwargs ) elif cloud_name == 'ssh': cloud = SSHCloud( ip_address=ip_address, **kwargs ) elif cloud_name == 'oci': cloud = OCICloud( compartment_id=compartment_id, availability_domain=availability_domain, signing_key_fingerprint=signing_key_fingerprint, signing_key_file=signing_key_file, tenancy=tenancy, oci_user_id=oci_user_id, **kwargs ) else: raise IpaControllerException( 'Cloud framework: %s unavailable.' % cloud_name ) return cloud.test_image()