def setup_once(self): super(SandBoxTestCase, self).setup_once() log.info("\n\n\n--------------- Preparing sandbox... ---------------") self.service_instances = [] self.regular_instances = [] #todo: refactor, reading `_ or _ or _` is unclear final result if os.getenv("QUBELL_IT_LOCAL"): self.parameters['organization'] = None org = self.parameters.get('organization') or getattr(self, 'source_name', False) or self.__class__.__name__ self.sandbox = SandBox(self.platform, self.environment(org)) if hasattr(self, '_wait_for_prev'): # in case of simultaneous run spreads preparation on timeline # todo: it seems sometimes later test is executed earlier and still race may occur SPREAD_IN_TIME_MULTIPLIER = 5 time.sleep(self._wait_for_prev * SPREAD_IN_TIME_MULTIPLIER) self.organization = self.sandbox.make() if self.__dict__.get('platform_version'): ver = self.organization.get_default_environment().get_backend_version() try: current_version = float(ver) except ValueError: # dev version: '41.0.148.g5ef3b00 2015-05-14 14:49:36' # universe version: 'v. v41.0.171.g8230c89' current_version = float(re.findall(r'\d+', ver)[0]+'.'+re.findall(r'\d+', ver)[1]) required_version = float(self.platform_version) if current_version < required_version: self.setup_skip = 'Platform version %s required, got %s' % (required_version, current_version) ### Start ### if self.setup_skip: pass # go to exit else: # If 'meta' in sandbox, restore applications that comes in meta before. if hasattr(self, 'meta'): apps_under_test = [app['name'] for app in self.sandbox.sandbox['applications']] self.organization.set_applications_from_meta(self.meta, exclude=apps_under_test) services_to_start = [x for x in self.sandbox['applications'] if x.get('add_as_service', False)] instances_to_start = [x for x in self.sandbox['applications'] if x.get('launch', True) and not x.get('add_as_service', False)] for appdata in services_to_start: ins = self.launch_instance(appdata) self.service_instances.append(ins) self.organization.environments[self.current_environment].add_service(ins, force=True) self.check_instances(self.service_instances) for appdata in instances_to_start: self.regular_instances.append(self.launch_instance(appdata)) self.check_instances(self.regular_instances) log.info("\n--------------- Sandbox prepared ---------------\n\n")
class SandBoxTestCase(SetupOnce, unittest.TestCase): platform = None parameters = None sandbox = None environments = None applications = [] apps = [] # fixme: moved up for backward compatibility instances = [] current_environment = DEFAULT_ENV_NAME() setup_skip = None @classmethod def environment(cls, organization): provider_config = PROVIDER_CONFIG # Old style components tests declared name as 'test-provider'. Now we cannot add this provider to env where another provider set. if (cls.parameters['provider_name']=='test-provider') or (not(cls.parameters['provider_name'])): prov = PROVIDER['provider_name'] else: prov = cls.parameters['provider_name'] # Default add-on for every env addon = {"services": [{"name": DEFAULT_CREDENTIAL_SERVICE()}, {"name": DEFAULT_WORKFLOW_SERVICE()}, {"name": prov} ]} servs = [{"type": COBALT_SECURE_STORE_TYPE, "name": DEFAULT_CREDENTIAL_SERVICE()}, {"type": WORKFLOW_SERVICE_TYPE, "name": DEFAULT_WORKFLOW_SERVICE()}, {"type": CLOUD_ACCOUNT_TYPE, "name": prov, "parameters": provider_config}] insts = [] # Add provider, keystore, workflow to every env. envs = cls.environments or [{"name": DEFAULT_ENV_NAME()},] for env in envs: env.update(addon) return { "organization": {"name": organization}, "services": servs, "instances": insts, "environments": envs, "applications": cls.apps or cls.applications} @classmethod def timeout(cls): return 15 def setup_once(self): super(SandBoxTestCase, self).setup_once() log.info("\n\n\n--------------- Preparing sandbox... ---------------") self.service_instances = [] self.regular_instances = [] #todo: refactor, reading `_ or _ or _` is unclear final result if os.getenv("QUBELL_IT_LOCAL"): self.parameters['organization'] = None org = self.parameters.get('organization') or getattr(self, 'source_name', False) or self.__class__.__name__ self.sandbox = SandBox(self.platform, self.environment(org)) if hasattr(self, '_wait_for_prev'): # in case of simultaneous run spreads preparation on timeline # todo: it seems sometimes later test is executed earlier and still race may occur SPREAD_IN_TIME_MULTIPLIER = 5 time.sleep(self._wait_for_prev * SPREAD_IN_TIME_MULTIPLIER) self.organization = self.sandbox.make() if self.__dict__.get('platform_version'): ver = self.organization.get_default_environment().get_backend_version() try: current_version = float(ver) except ValueError: # dev version: '41.0.148.g5ef3b00 2015-05-14 14:49:36' # universe version: 'v. v41.0.171.g8230c89' current_version = float(re.findall(r'\d+', ver)[0]+'.'+re.findall(r'\d+', ver)[1]) required_version = float(self.platform_version) if current_version < required_version: self.setup_skip = 'Platform version %s required, got %s' % (required_version, current_version) ### Start ### if self.setup_skip: pass # go to exit else: # If 'meta' in sandbox, restore applications that comes in meta before. if hasattr(self, 'meta'): apps_under_test = [app['name'] for app in self.sandbox.sandbox['applications']] self.organization.set_applications_from_meta(self.meta, exclude=apps_under_test) services_to_start = [x for x in self.sandbox['applications'] if x.get('add_as_service', False)] instances_to_start = [x for x in self.sandbox['applications'] if x.get('launch', True) and not x.get('add_as_service', False)] for appdata in services_to_start: ins = self.launch_instance(appdata) self.service_instances.append(ins) self.organization.environments[self.current_environment].add_service(ins, force=True) self.check_instances(self.service_instances) for appdata in instances_to_start: self.regular_instances.append(self.launch_instance(appdata)) self.check_instances(self.regular_instances) log.info("\n--------------- Sandbox prepared ---------------\n\n") def teardown_once(self): log.info("\n--------------- Cleaning sandbox ---------------") self.destroy_instances(self.regular_instances) self.destroy_instances(reversed(self.service_instances)) self.regular_instances = [] self.service_instances = [] log.info("\n--------------- Sandbox cleaned ---------------\n") super(SandBoxTestCase, self).teardown_once() def setUp(self): super(SandBoxTestCase, self).setUp() if self.setup_skip: self.skipTest(self.setup_skip) def launch_instance(cls, appdata): application = cls.organization.applications[appdata['name']] environment = cls.organization.environments[cls.current_environment] instance = cls.organization.create_instance(application=application, environment=environment, parameters=appdata.get('parameters', {}), **appdata.get('settings',{})) return instance @classmethod def check_instances(cls, instances): for instance in instances: if not instance.running(timeout=cls.timeout()): if instance.error: # If error message exists - status should be error, else instance faced timeout error = instance.error.strip() else: error = 'Instance status: %s after timeout %s' % (instance.status, cls.timeout()) # TODO: if instance fails to start during tests, add proper unittest log if os.getenv("QUBELL_DEBUG", None) and not('false' in os.getenv("QUBELL_DEBUG", None)): pass assert False, "Instance %s (%s): %s" % (instance.name, instance.instanceId, error) @classmethod def destroy_instances(cls, instances): if os.getenv("QUBELL_DEBUG", None) and not('false' in os.getenv("QUBELL_DEBUG", None)): log.info("QUBELL_DEBUG is ON\n DO NOT clean sandbox") else: for instance in instances: instance.destroy() if not instance.destroyed(cls.timeout()): log.error("Instance {0} ({1}) was not destroyed properly. Org: {2}, App: {3} ".format(instance.id, instance.name, instance.organizationId, instance.applicationId)) # todo: method is used in decarator only, would be nice to refactor def find_by_application_name(self, name): instances = self.regular_instances+self.service_instances for inst in instances: if inst.application.name == name: return inst raise NotFoundError("Instance of '{}' application is not found among: {}.". format(name, ", ".join([i.name for i in instances]))) def shortDescription(self): """ http://www.saltycrane.com/blog/2012/07/how-prevent-nose-unittest-using-docstring-when-verbosity-2/ """ return None