def test_csphost_new_init(): """Tests Host.__new__ and Host.__init__""" from apyfal.configuration import Configuration from apyfal.host import Host from apyfal.host._csp import CSPHost from apyfal.host.aws import AWSHost from apyfal.exceptions import HostConfigurationException # Mock arguments and configuration # Note that host_type is not specified here config = Configuration() try: for section in list(config._sections): if section.startswith('host'): del config._sections[section] except KeyError: pass kwargs = { 'region': 'region', 'project_id': 'project_id', 'client_id': 'client_id', 'auth_url': 'auth_url', 'interface': 'interface', 'config': config } # Test: Existing CSP class and module assert isinstance(Host(host_type="AWS", **kwargs), AWSHost) # Test: Not existing CSP module with pytest.raises(HostConfigurationException): Host(host_type="no_existing_csp") # Test: Existing CSP module, with no valid class with pytest.raises(HostConfigurationException): Host(host_type="_csp") # Test: direct instantiation of subclass without specify host_type host = AWSHost(**kwargs) # Test: repr assert repr(host) == str(host) # Test: Instantiation with missing mandatory arguments with pytest.raises(HostConfigurationException): Host(host_type="AWS", config=config) kwargs_no_client_id = kwargs.copy() del kwargs_no_client_id['client_id'] with pytest.raises(HostConfigurationException): Host(host_type="AWS", **kwargs_no_client_id) # Test: Abstract class class UncompletedCSP(CSPHost): """Uncompleted CSP class""" with pytest.raises(TypeError): UncompletedCSP()
def accelize_credentials_available(): """ Checks in Accelize credentials are available. Skips test if not, else, returns configuration. Returns: apyfal.configuration.Configuration """ from apyfal.configuration import Configuration config = Configuration() if not has_accelize_credential(config): pytest.skip('Accelize Credentials required') return config
def test_configuration_access_token_real_no_cred(): """Tests AcceleratorClient.access_token with Accelize server Test parts that don't needs credentials""" from apyfal.exceptions import ClientAuthenticationException from apyfal.configuration import Configuration config = Configuration() try: del config._sections['accelize'] except KeyError: pass config['accelize']['client_id'] = 'bad_client_id' config['accelize']['secret_id'] = 'bad_secret_id' # Test: Bad client_id with pytest.raises(ClientAuthenticationException): assert config.access_token
def test_host_init(): """Tests Host.__new__ and Host.__init__""" from apyfal.configuration import Configuration from apyfal.host import Host from apyfal.exceptions import HostConfigurationException # Mock arguments and configuration # Note that host_type is not specified here config = Configuration() try: del config._sections['host'] except KeyError: pass # Test: Not existing host module with pytest.raises(HostConfigurationException): Host(host_type="no_existing_csp") # Test: Instantiation of without specify host_type host = Host(config=config) assert host.__class__ is Host # Test: repr assert repr(host) == str(host) # Test: Passing host_ip url = 'http://127.0.0.1' host = Host(config=config, host_ip=url) host.start() assert host.url == url # Test: Passing nothing host = Host(config=config) with pytest.raises(HostConfigurationException): host.start() # Test: iter_hosts empty default assert list(host._iter_hosts()) == [] # Test: iter_hosts with proper _iter_host def _iter_hosts(): """dummy iter_host""" for index in range(2): yield dict(public_ip='127.0.0.1', host_name='prefix_accelize_pytest%d_000000000000' % index) host._iter_hosts = _iter_hosts assert list(host.iter_hosts()) == [{ 'public_ip': '127.0.0.1', 'host_name': 'prefix_accelize_pytest%d_000000000000' % index, 'accelerator': 'pytest%d' % index, 'url': 'http://127.0.0.1', 'host_type': host.host_type, '_repr': ("<apyfal.host.Host name='prefix_accelize_" "pytest%d_000000000000'>") % index } for index in range(2)] # Test: iter_hosts without public ip def _iter_hosts(): """dummy iter_host""" for index in range(2): yield dict(host_name='prefix_accelize_pytest%d_000000000000' % index) host._iter_hosts = _iter_hosts assert list(host.iter_hosts()) == [{ 'host_name': 'prefix_accelize_pytest%d_000000000000' % index, 'accelerator': 'pytest%d' % index, 'host_type': host.host_type, '_repr': ("<apyfal.host.Host name='prefix_accelize_" "pytest%d_000000000000'>") % index } for index in range(2)] # Test: iter_hosts host_name_prefix prefix = 'prefix' host = Host(config=config, host_name_prefix=prefix) assert host._host_name_prefix == prefix assert host._host_name_match is None list(host.iter_hosts(host_name_prefix=True)) assert host._host_name_match is not None assert not host._is_accelerator_host('accelize_pytest_000000000000') assert not host._is_accelerator_host('other_accelize_pytest_000000000000') assert host._is_accelerator_host('prefix_accelize_pytest_000000000000') list(host.iter_hosts(host_name_prefix=False)) assert host._is_accelerator_host('accelize_pytest_000000000000') assert host._is_accelerator_host('other_accelize_pytest_000000000000') assert host._is_accelerator_host('prefix_accelize_pytest_000000000000') list(host.iter_hosts(host_name_prefix='other')) assert not host._is_accelerator_host('accelize_pytest_000000000000') assert host._is_accelerator_host('other_accelize_pytest_000000000000') assert not host._is_accelerator_host('prefix_accelize_pytest_000000000000') # Test: not instance names list(host.iter_hosts(host_name_prefix=False)) assert not host._is_accelerator_host('pytest_000000000000') assert not host._is_accelerator_host('accelize_000000000000') assert not host._is_accelerator_host('accelize_prefix') assert not host._is_accelerator_host('accelize_prefix_000')
def test_configuration_access_token(): """Tests Configuration.access_token without Accelize server""" from apyfal.configuration import Configuration, METERING_SERVER import apyfal.exceptions as exc # Mocks some variables access_token = 'dummy_token' client_id = 'dummy_client_id', secret_id = 'dummy_secret_id' # Mocks requests in utilities class Response: """Fake requests.Response""" status_code = 200 text = json.dumps({'access_token': access_token}) @staticmethod def raise_for_status(): """Do nothing""" class DummySession(requests.Session): """Fake requests.Session""" @staticmethod def post(url, data, auth, **_): """Checks input arguments and returns fake response""" # Checks input arguments assert METERING_SERVER in url assert client_id in auth assert secret_id in auth # Returns fake response return Response() # Monkey patch requests in utilities requests_session = requests.Session requests.Session = DummySession # Tests try: # Test: No credential provided config = Configuration() try: del config._sections['accelize'] except KeyError: pass with pytest.raises(exc.ClientAuthenticationException): assert config.access_token # Test: Everything OK config = Configuration() assert config['accelize'] is not None # Creates section if not exists config._sections['accelize']['client_id'] = client_id config._sections['accelize']['secret_id'] = secret_id assert config.access_token == access_token # Test: Check dict features assert len(config) == len(config._sections) for section in config: assert section in config._sections assert section in config config._sections['accelize']['test_value'] = '1,2,3' assert config['accelize'].get_literal('test_value') == (1, 2, 3) config._sections['accelize']['test_value'] = '1\n2\n3' assert config['accelize'].get_list('test_value') == ["1", "2", "3"] assert config['accelize'].get_literal('no_value') is None assert config['accelize'].get_list('no_value') == [] # Test cached value del config._sections['accelize'] assert config.access_token == access_token # Test: Authentication failed config = Configuration() try: del config._sections['accelize'] except KeyError: pass Response.status_code = 400 with pytest.raises(exc.ClientAuthenticationException): assert config.access_token # Restore requests finally: requests.Session = requests_session
def test_csphost_user_data(tmpdir): """Tests Host._user_data""" from apyfal.configuration import Configuration from apyfal.exceptions import HostConfigurationException import apyfal.configuration as _cfg # Mock CSP class class DummyCSP(get_dummy_csp_class()): """Dummy CSP""" @property def host_name(self): """Return fake result""" return 'host_name' def _get_instance(self): """Do nothing""" def _status(self): """Do nothing""" config_content = ("[dummy]\n" "dummy1 = dummy1\n" "dummy2 = dummy2\n") config_file = tmpdir.join('dummy.conf') config_file.write(config_content) config = Configuration(str(config_file)) script_content = ("#!/usr/bin/env bash\n" "script line 1\n" "script line 2") script_file = tmpdir.join('dummy.sh') script_file.write(script_content) ssl_crt_content = "public_key" ssl_crt_file = tmpdir.join('dummy.crt') ssl_crt_file.write(ssl_crt_content) ssl_key_content = "private_key" ssl_key_file = tmpdir.join('dummy.key') ssl_key_file.write(ssl_key_content) # Test: No user data assert DummyCSP._SH_FLAG in DummyCSP(client_id='client_id', secret_id='secret_id', region='region')._user_data.decode() # Test: Get user data user_data = DummyCSP(client_id='client_id', secret_id='secret_id', region='region', init_config=config, init_script=str(script_file))._user_data.decode() # Test: Check shebang assert user_data.count('#!') == 1 assert DummyCSP._SH_FLAG in user_data # Test: Check configuration file presence for line in config_content.splitlines(): assert line in user_data # Test: Check script file presence for line in script_content.splitlines()[1:]: assert line in user_data # Test: Check path assert DummyCSP._HOME in user_data # Test: Certificate user_data = DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_crt=str(ssl_crt_file), ssl_cert_key=str(ssl_key_file))._user_data.decode() assert ssl_key_content in user_data assert ssl_crt_content in user_data assert DummyCSP._SSL_CERT_CRT in user_data assert DummyCSP._SSL_CERT_KEY in user_data # Test: Generated certificate user_data = DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_crt=str(ssl_crt_file), ssl_cert_key=str(ssl_key_file), ssl_cert_generate=True)._user_data.decode() assert ssl_crt_file.read_text('utf-8') in user_data assert ssl_key_file.read_text('utf-8') in user_data # Test: Generated temporary certificate cfg_apyfal_cert_crt = _cfg.APYFAL_CERT_CRT cfg_apyfal_cert_key = _cfg.APYFAL_CERT_KEY _cfg.APYFAL_CERT_KEY = str(tmpdir.join('dummy_generated.key')) _cfg.APYFAL_CERT_CRT = str(tmpdir.join('dummy_generated.crt')) try: csp = DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_generate=True) user_data = csp._user_data.decode() with open(csp._ssl_cert_crt, 'rt') as file: tmp_crt_content = file.read() with open(csp._ssl_cert_key, 'rt') as file: tmp_key_content = file.read() assert tmp_key_content in user_data assert tmp_crt_content in user_data # Test: Already generated, should not recreate certificates csp = DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_generate=True) user_data = csp._user_data.decode() assert tmp_key_content in user_data assert tmp_crt_content in user_data finally: _cfg.APYFAL_CERT_KEY = cfg_apyfal_cert_key _cfg.APYFAL_CERT_CRT = cfg_apyfal_cert_crt # Test: Missing key with pytest.raises(HostConfigurationException): assert DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_key=str(ssl_key_file))._user_data # Test: Missing crt with pytest.raises(HostConfigurationException): assert DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_crt=str(ssl_crt_file))._user_data # Test: Disabled certificate csp = DummyCSP(client_id='client_id', secret_id='secret_id', region='region', ssl_cert_crt=False) assert csp._ssl_cert_crt is False
def run_full_real_test_sequence(host_type, environment): """Run common real tests for all CSP. Args: host_type (str): CSP host_type. environment (dict): Environment to use """ from apyfal.configuration import Configuration from apyfal.exceptions import AcceleratorException from apyfal import iter_accelerators # Skip if no correct configuration with this host_type config = Configuration() if config['host']['host_type'] != host_type: config['host']['host_type'] = host_type try: del config['host']['client_id'] except KeyError: pass try: del config['host']['secret_id'] except KeyError: pass section = config['host.%s' % host_type] if not section['client_id'] or not section['secret_id']: pytest.skip('No configuration for %s.' % host_type) elif section['region'] not in environment: pytest.skip("No configuration for '%s' region on %s." % (section['region'], host_type)) # Enable logger from apyfal import get_logger get_logger(stdout=True) # Defines testing prefix. Used to easily found CSP object linked to a # particular test. testing_prefix = datetime.now().strftime('ApyfalTesting%H%M%S') # Add accelerator to environment environment['accelerator'] = 'apyfal_testing' config['host']['host_name_prefix'] = testing_prefix # Changes Host parameter prefix for default names # TODO: replace 'apyfal_testing' by testing_prefix variable once full # clean up of CSP objects is implemented. from apyfal.host import Host host_parameter_prefix = Host._PARAMETER_PREFIX Host._PARAMETER_PREFIX = 'ApyfalTesting' # Tests: instance_id_term = None instance_id_stop = None instance_id_keep = None try: # Start and terminate print('Test: Start and terminate') with Host(config=config, stop_mode='term') as csp_term: csp_term.start(accel_parameters=environment) instance_id_term = csp_term.instance_id # Start and stop, then terminate # Also check getting instance handle with ID print('Test: Start and stop') with Host(config=config, stop_mode='stop') as csp_stop: csp_stop.start(accel_parameters=environment) instance_id_stop = csp_stop.instance_id print('Test: Start from stopped and terminate') with Host(config=config, instance_id=instance_id_stop, stop_mode='term') as csp: csp.start(accel_parameters=environment) assert csp.instance_id == instance_id_stop # Start and keep, then # Also check getting instance handle with URL print('Test: Start and keep') with Host(config=config, stop_mode='keep') as csp_keep: csp_keep.start(accel_parameters=environment) instance_id_keep = csp_keep.instance_id instance_url_keep = csp_keep.url print('Test: Reuse with instance IP/URL') with Host(config=config, host_ip=instance_url_keep) as csp: csp.start(accel_parameters=environment) assert csp.url == instance_url_keep print('Test: Reuse with instance ID and terminate') with Host(config=config, instance_id=instance_id_keep, stop_mode='term') as csp: csp.start(accel_parameters=environment) assert csp.instance_id == instance_id_keep # Clean up testing environment finally: # Restore prefix value Host._PARAMETER_PREFIX = host_parameter_prefix # Stops all instances time.sleep(5) for accelerator in iter_accelerators(config=config): instance_id = None try: instance_id = accelerator.host.instance_id accelerator.stop('term') except AcceleratorException: pass assert instance_id not in (instance_id_term, instance_id_stop, instance_id_keep)