def test_global_implicit_global_config(): """ Global config is instantiated from config.json if not explicitly set """ assert Config.get_instance().api_key == conf_dict.get('apiKey') assert Config.get_instance().api_url == conf_dict.get('apiEndpoint') assert isinstance(Config.get_instance().products, list) assert len(Config.get_instance().products) == 1 assert Config.get_instance().products[0] == conf_dict.get('products')
def __init__(self, config=None): self._config = config or Config.get_instance() self._tier_account_requests = TierAccountRequestResource( config=self._config) self._tier_config_requests = TierConfigRequestResource( config=self._config) self._asset_requests = AssetRequestResource(config=self._config)
def collect_usage_records(self, items, project, start_time, end_time): """Create UsageRecord object for each type of resources""" consumptions = { 'CPU_consumption': CPU(), 'Storage_consumption': Storage(), 'RAM_consumption': RAM(), 'Floating_IP_consumption': FloatingIP(), 'LB_consumption': LoadBalancer(), 'K8S_consumption': K8saas(), 'Win_VM_consumption': WinVM(), 'Outgoing_Traffic_consumption': OutgoingTraffic() } conf = Config.get_instance() consumptions.update( {mpn: Zero() for mpn in conf.misc.get('report_zero_usage', [])}) def known_resources(item): return item in consumptions def collect_item_consumption(item): return self.create_record( project, start_time, end_time, item, consumptions.get(item).collect_consumption( project, start_time, end_time)) return map(collect_item_consumption, filter(known_resources, items))
def get_templates(self, config=None): """ :param Config config: Configuration to use, or None for environment config. :return: List of all templates associated with the product. :rtype: List[Template] """ text, _ = ApiClient(config or Config.get_instance(), 'products/' + self.id + '/templates').get() return Template.deserialize(text)
def keystone_client(self): """Create KeystoneClient object using KeystoneSession""" c = Config.get_instance() return KeystoneClient( session=self.keystone_session, endpoint_override=c.infra_keystone_endpoint, connect_retries=2, )
def get_answer(self, product, answer): """Get template object specified in the Config""" c = Config.get_instance() line = c.templates.get(product, {}).get(answer) if line is None: return line if line.startswith('TL'): return ActivationTemplateResponse(line) return ActivationTileResponse(line)
def __init__(self, config, base_path): # type: (Config, str) -> None # Set base URL self._base_path = base_path # Set passed config or globally configured instance self._config = config or Config.get_instance() if not isinstance(self._config, Config): raise ValueError('A valid Config object must be passed or globally configured.')
def get_requests(self, config=None): """ Get the requests for this asset. :param Config config: Config object or ``None`` to use environment config (default). :return: The requests for this asset. :rtype: List[Fulfillment] """ from connect.config import Config from connect.resources.base import ApiClient from .fulfillment import Fulfillment text, _ = ApiClient(config or Config.get_instance(), 'assets/' + self.id + '/requests').get() return Fulfillment.deserialize(text)
def get_function_rv(): if PasswordFilter.is_enabled is None: PasswordFilter.is_enabled = Config.get_instance( ).misc['hidePasswordsInLog'] if PasswordFilter.is_enabled and re.search( PasswordFilter.type_pattern, record.msg): msg = record.msg.replace("\n", "\\n").replace("\\'", "'") for pattern in PasswordFilter.password_patterns: match = re.search(pattern, msg) if match: return match.group(1) logger.warning( "Message does not match against password patterns") return None
def keystone_session(self): """Create KeystoneSession object using params in the Config""" c = Config.get_instance() auth = identity.v3.Password( auth_url=c.infra_keystone_endpoint, username=c.infra_user, project_name=c.infra_project, password=c.infra_password, user_domain_name=c.infra_domain, project_domain_name=c.infra_domain, reauthenticate=True, ) return KeystoneSession(auth=auth, verify=False)
def get_product_configurations(self, filters=None, config=None): """ :param Dict[str, Any] filters: Filters for the requests. Supported filters are: - ``parameter.id`` - ``parameter.title`` - ``parameter.scope`` - ``marketplace.id`` - ``marketplace.name`` - ``item.id`` - ``item.name`` - ``value`` :param Config config: Configuration to use, or None for environment config. :return: A list with the product configuration parameter data. :rtype: List[ProductConfigurationParameter] """ text, _ = ApiClient(config or Config.get_instance(), 'products/' + self.id + '/configurations').get(params=filters) return ProductConfigurationParameter.deserialize(text)
def get_product_configurations(self, filters=None, config=None): """ :param dict|Query filters: Filters for the requests. Supported filters are: - ``parameter.id`` - ``parameter.title`` - ``parameter.scope`` - ``marketplace.id`` - ``marketplace.name`` - ``item.id`` - ``item.name`` - ``value`` :param Config config: Configuration to use, or None for environment config. :return: A list with the product configuration parameter data. :rtype: List[ProductConfigurationParameter] """ query = copy(filters) if isinstance(filters, Query) else Query(filters) text, _ = ApiClient( config or Config.get_instance(), 'products/' + self.id + '/configurations' + query.compile()).get() return ProductConfigurationParameter.deserialize(text)
def __init__(self, config=None): self._config = config or Config.get_instance() self._tier_accounts = TierAccountResource(config=self._config)
def process_request(self, request): """Each new Fulfillment is processed by this function""" conf = Config.get_instance() # store all processed request for debug self.fulfillments.append(request) if request.needs_migration(): # Skip request if it needs migration # (migration is performed by an external service) self.logger.info('Skipping request %s because it needs migration.', request.id) raise SkipRequest() param_partner_id = None if not conf.misc['domainCreation']: self.logger.info('Request "%s" needs domain that created manually. ' 'Lookup for domain name in tier1 configuration data...', request.id) partner_data = self.get_tier_partner_data(request.asset.tiers.tier1.id) if partner_data is None: raise SkipRequest('Misconfiguration: there is no "partner_id" parameter in tier1 "%s" config' % request.asset.tiers.tier1.id) elif partner_data.value is None: raise SkipRequest(message='Please specify "partner_id" parameter value in tier1 "%s" config' % request.asset.tiers.tier1.id) param_partner_id = partner_data.value self.logger.info('Got the following domain data from tier1 config: "%s"' % param_partner_id) project = None params = {p.id: p for p in request.asset.params} # get account parameters from Asset param_domain_name = params.get('domain_name') param_domain_id = params.get('domain_id') param_project_id = params.get('project_id') param_user_id = params.get('user_id') self.logger.info("param_partner_id: %s, param_domain_name: %s, param_domain_id: %s, " "param_project_id: %s, param_user_id: %s", param_partner_id, param_domain_name and param_domain_name.value, param_domain_id and param_domain_id.value, param_project_id and param_project_id.value, param_user_id and param_user_id.value) if request.type in ('purchase', 'resume', 'change'): if not conf.misc['domainCreation']: # if domain creation is set to manual, needs to check: # - if domain with such description exists in the cloud, go to next steps # - if not - return nice message and set request status domain = self.get_existing_domain(partner_id=param_partner_id) if domain is None: raise SkipRequest('Request "%s" needs domain that created manually. ' 'Cannot find any domain with description "%s"' % (request.id, param_partner_id)) else: # create domain customer_id = request.asset.tiers.customer.id customer_name = request.asset.tiers.customer.name domain = self.create_or_update_domain( name=customer_id, description=customer_name, domain_id=param_domain_id and param_domain_id.value) # create project project_description = request.asset.id project_name = params.get('project') and params['project'].value or project_description project = self.create_project( project_id=param_project_id and param_project_id.value, name=project_name, domain=domain, description=project_description, enabled=False) # create user user_description = request.asset.id user_name = params.get('user') and params['user'].value or user_description user_password = params.get('password') and params['password'].value or pwgen() user = self.create_user( user_id=param_user_id and param_user_id.value, name=user_name, domain=domain, description=user_description, password=user_password) # check conflicts conflicts = [] if project is None: if params.get('project'): params['project'].value_error = 'This project name is already taken, please choose a different name' params['project'].constraints = None conflicts.append(params['project']) if user is None: if params.get('user'): params['user'].value_error = 'This user name is already taken, please choose a different name' params['user'].constraints = None conflicts.append(params['user']) if conflicts: if user: user.delete() if project: project.delete() raise InquireRequest(params=conflicts) if user is None: raise Exception('Unable to create a user') if project is None: raise Exception('Unable to create a project') # update params (project_id, user_id) params_update = [] if param_domain_name and param_domain_name.value != domain.name: param_domain_name.value = domain.name param_domain_name.constraints = None params_update.append(param_domain_name) if param_domain_id and param_domain_id.value != domain.id: param_domain_id.value = domain.id param_domain_id.constraints = None params_update.append(param_domain_id) if param_project_id and param_project_id.value != project.id: param_project_id.value = project.id param_project_id.constraints = None params_update.append(param_project_id) if param_user_id and param_user_id.value != user.id: param_user_id.value = user.id param_user_id.constraints = None params_update.append(param_user_id) self.update_parameters(request.id, params_update) # assign roles user_roles = ['project_admin'] if conf.misc['imageUpload']: user_roles.append('image_upload') self.assign_user_roles(user, project, roles=user_roles) # configure quotas def get_item_limit(item): limit_param = next((p for p in item.params if p.id == 'item_limit'), None) try: return int(limit_param.value) except Exception: return -1 def get_quota(item, error=FailRequest("ERROR: REQUESTED LIMITS ARE HIGHER THEN HARD LIMITS")): if item is None: return 0 quantity = item.quantity item_limit = get_item_limit(item) if item_limit >= 0: if quantity > item_limit: raise error if quantity < 0: quantity = item_limit return quantity items = {item.mpn.lower(): item for item in request.asset.items} self.logger.info('VIP requested items %r', items) try: # get quota limits from Asset parameters cpu_quota = get_quota(items.get('cpu_limit', items.get("cpu_consumption", None))) ram_quota = get_quota(items.get('ram_limit', items.get("ram_consumption", None))) vol_quota = get_quota(items.get('storage_limit', items.get("storage_consumption", None))) # fail request if basic limits are missing if 0 in (cpu_quota, ram_quota, vol_quota): raise FailRequest("CPU, RAM, and Storage limits cannot be 0") fip_quota = get_quota(items.get('floating_ip_limit', items.get("floating_ip_consumption", None))) lb_quota = get_quota(items.get('lbaas_limit', items.get("lb_consumption", None))) k8s_quota = get_quota(items.get('k8saas_limit', items.get("k8s_consumption", None))) errors = [] updaters = [] def apply_quota(updater, client, quotas): try: u = updater(client, project.id) u.update(quotas) updaters.append(u) except BadQuota as e: errors.append(e.message) try: # update project quotas apply_quota(CinderQuotaUpdater, self.cinder_client, { 'gigabytes_default': vol_quota}) apply_quota(NovaQuotaUpdater, self.nova_client, { 'cores': cpu_quota, 'ram': (ram_quota * 1024 if ram_quota > 0 else ram_quota)}) apply_quota(NeutronQuotaUpdater, self.neutron_client, { 'floatingip': fip_quota}) apply_quota(OctaviaQuotaUpdater, self.octavia_client, { 'load_balancer': lb_quota}) apply_quota(MagnumQuotaUpdater, self.magnum_client, { 'hard_limit': k8s_quota}) if errors: rollback_error = False for u in updaters: try: u.rollback() except Exception: rollback_error = True self.logger.exception("Unable to rollback quotas") if rollback_error: raise Exception('Unable to setup quotas') raise FailRequest('\n'.join(errors)) except Exception as e: self.logger.exception("Unable to setup quotas") for u in updaters: try: u.rollback() except Exception: self.logger.exception("Unable to rollback quotas") raise e except FailRequest: if request.type == 'purchase': # remove project if we fail to process 'purchase' request if project: project.delete() project = None raise except SkipRequest: raise except Exception: self.logger.exception("Unable to setup quotas") raise rv = self.get_answer(request.asset.product.id, 'grant') if not project.enabled: # if project was suspended a long time ago we open new usage # reporting interval setting start_usage_report_time. But if # stop_report_time is not equal last_report_time then there # was no report closing previous usage reporting interval. # So the gap between stop and start will be ignored. stop_report_time = self.get_stop_report_time(request, project) last_report_time, _ = self.get_last_report_time(request, project) if stop_report_time != last_report_time: stop_report_time = '' report_time = datetime.utcnow().replace(microsecond=0) self.keystone_client.projects.update( project, enabled=True, start_usage_report_time=report_time.isoformat() if stop_report_time else '', stop_usage_report_time=stop_report_time) project.update(enabled=True) if rv: return rv elif request.type in ('suspend', 'cancel'): self.suspend_project( request, param_domain_id and param_domain_id.value or None, param_project_id and param_project_id.value or None, param_user_id and param_user_id.value or None, ) # TODO implement automatic cleanup after Asset cancellation try: pid = param_project_id and param_project_id.value or None if request.type == 'cancel' and pid: self.keystone_client.projects.update( pid, description='SCHEDULED FOR DELETE') except Exception: pass return self.get_answer(request.asset.product.id, 'revoke') or '' self.logger.warning("Do not know what to do with such request") raise SkipRequest()
def __init__(self, config=None): self._config = config or Config.get_instance() self._billing_request = BillingRequestResource(config=self._config) self._recurring_asset = RecurringAssetResource(config=self._config)
def __init__(self, config=None): self._config = config or Config.get_instance()
def test_global_config_immutable_properties(): with pytest.raises(AttributeError): Config.get_instance().api_key = conf_dict.get('apiKey') Config.get_instance().api_url = conf_dict.get('apiEndpoint') Config.get_instance().products = [conf_dict.get('products')]