Source code for satellite_populate.api

# coding: utf-8
"""Implements API populator using Nailgun"""
from nailgun import entities
from nailgun.entity_mixins import EntitySearchMixin
from requests.exceptions import HTTPError

from satellite_populate.base import BasePopulator


[docs]class APIPopulator(BasePopulator): """Populates system using API/Nailgun"""
[docs] def add_and_log_error(self, action_data, rendered_action_data, search, e=None): """Add to validation errors and outputs error""" error_message = "%s: %s %s" % ( self.mode, str(e) if e else '', action_data) if e and hasattr(e, 'response') and e.response is not None: error_message += str(e.response.content) self.logger.error(error_message) self.validation_errors.append({ 'search': search, 'message': error_message, 'rendered_action_data': rendered_action_data, 'action_data': action_data })
[docs] def populate(self, rendered_action_data, action_data, search, action): """Populates the System using Nailgun based on value provided in `action` argument gets the proper CRUD method to execute dynamically """ model = getattr(entities, action_data['model']) silent_errors = action_data.get('silent_errors', False) try: # self.action_create|action_update|action_delete result = getattr(self, "action_{0}".format(action))( rendered_action_data, action_data, search, model, silent_errors ) except HTTPError as e: self.add_and_log_error(action_data, rendered_action_data, search, e) except Exception as e: self.add_and_log_error(action_data, rendered_action_data, search, e) if silent_errors: return raise else: self.add_to_registry(action_data, result)
[docs] def action_create(self, rendered_action_data, action_data, search, model, silent_errors): """Creates new entity if does not exists or get existing entity and return Entity object""" result = self.get_search_result( model, search, unique=True, silent_errors=silent_errors ) if result: self.logger.info( "create: Entity already exists: %s %s", model.__name__, result.id ) self.found.append(result) else: result = model(**rendered_action_data).create() self.logger.info( "create: Entity created: %s %s", model.__name__, result.id ) self.created.append(result) return result
[docs] def action_update(self, rendered_action_data, action_data, search, model, silent_errors): """Updates an existing entity""" search_data = action_data.get('search_query') entity_id = action_data.get('id') if not entity_id and not search_data: raise RuntimeError("update: missing id or search_query") if not entity_id: search_result = self.get_search_result( model, search, unique=True, silent_errors=silent_errors ) if not search_result: raise RuntimeError("update: Cannot find entity") entity_id = search_result.id entity = model(id=entity_id, **rendered_action_data) entity.update(list(rendered_action_data.keys())) self.logger.info("update: %s %s", model, entity_id) return entity
[docs] def action_delete(self, rendered_action_data, action_data, search, model, silent_errors): """Deletes an existing entity""" search_data = action_data.get('search_query') entity_id = action_data.get('id') if not entity_id and not search_data: raise RuntimeError("delete: missing id or search_query") if not entity_id: search_result = self.get_search_result( model, search, unique=True, silent_errors=silent_errors ) if not search_result: raise RuntimeError("delete: Cannot find entity") entity_id = search_result.id # currently only works based on a single id # should iterate all results and delete one by one? model(id=entity_id).delete() self.logger.info("delete: %s %s", model, entity_id)
[docs] def validate(self, rendered_action_data, action_data, search, action): """Based on action fields or using action_data['search_query'] searches the system and validates the existence of all entities """ silent_errors = action_data.get('silent_errors', False) if action not in ['create', 'assertion'] or action_data.get( 'skip_validation' ): # validate only create and assertion crud actions return model = getattr(entities, action_data['model']) if not issubclass(model, EntitySearchMixin): raise TypeError("{0} not searchable".format(model.__name__)) try: # 1) check if entity exists result = self.get_search_result( model, search, unique=True, silent_errors=silent_errors ) except HTTPError as e: self.add_and_log_error(action_data, rendered_action_data, search, e) else: if result: self.logger.info( "validate: Entity found: %s %s", model.__name__, result.id ) self.found.append(result) self.add_to_registry(action_data, result) else: # should add None to registry, else references fail self.logger.info( "validate: result not found for query %s %s", model.__name__, action_data ) self.add_to_registry(action_data, None) self.add_and_log_error( action_data, rendered_action_data, search, 'entity does not exist in the system' )