def get_all(cls, account=None, location=None, include_disabled=False): """Returns a list of all resources for a given account, location and resource type. Attributes: account (:obj:`Account`): Account owning the resources location (`str`): Location of the resources to return (region) include_disabled (`bool`): Include resources from disabled accounts (default: False) Returns: list of resource objects """ qry = db.Resource.filter(Resource.resource_type_id == ResourceType.get( cls.resource_type).resource_type_id) if account: qry = qry.filter(Resource.account_id == account.account_id) if not include_disabled: qry = qry.join(Account, Resource.account_id == Account.account_id).filter( Account.enabled == 1) if location: qry = qry.filter(Resource.location == location) return {res.resource_id: cls(res) for res in qry.all()}
def create(cls, resource_id, *, account_id, properties=None, tags=None, location=None, auto_add=True, auto_commit=False): """Creates a new Resource object with the properties and tags provided Args: resource_id (str): Unique identifier for the resource object account_id (int): Account ID which owns the resource properties (dict): Dictionary of properties for the resource object. tags (dict): Key / value dictionary of tags. Values must be `str` types location (str): Location of the resource, if applicable auto_add (bool): Automatically add the new resource to the DB session. Default: True auto_commit (bool): Automatically commit the change to the database. Default: False """ if cls.get(resource_id): raise ResourceException('Resource {} already exists'.format(resource_id)) res = Resource() res.resource_id = resource_id res.account_id = account_id res.location = location res.resource_type_id = ResourceType.get(cls.resource_type).resource_type_id if properties: for name, value in properties.items(): prop = ResourceProperty() prop.resource_id = res.resource_id prop.name = name prop.value = value.isoformat() if type(value) == datetime else value res.properties.append(prop) db.session.add(prop) if tags: for key, value in tags.items(): if type(value) != str: raise ValueError('Invalid object type for tag value: {}'.format(key)) tag = Tag() tag.resource_id = resource_id tag.key = key tag.value = value res.tags.append(tag) db.session.add(tag) if auto_add: db.session.add(res) if auto_commit: db.session.commit() return cls.get(res.resource_id) else: return cls(res)
def volumes(self): """Returns a list of the volumes attached to the instance Returns: `list` of `EBSVolume` """ return [ EBSVolume(res) for res in db.Resource.join( ResourceProperty, Resource.resource_id == ResourceProperty.resource_id ).filter( Resource.resource_type_id == ResourceType.get('aws_ebs_volume').resource_type_id, ResourceProperty.name == 'attachments', func.JSON_CONTAINS(ResourceProperty.value, func.JSON_QUOTE(self.id)) ).all() ]
def __register_types(self): """Iterates all entry points for resource types and registers a `resource_type_id` to class mapping Returns: `None` """ try: for ep in CINQ_PLUGINS['cloud_inquisitor.plugins.types'][ 'plugins']: cls = ep.load() self.types[ResourceType.get( cls.resource_type).resource_type_id] = cls logger.debug('Registered resource type {}'.format( cls.__name__)) except SQLAlchemyError as ex: logger.warning('Failed loading type information: {}'.format(ex))
def register_types(): """Iterates all entry points for resource types and registers a `resource_type_id` to class mapping Returns: `dict` """ # FIXME: Local import to avoid app startup failures try: from cloud_inquisitor.schema import ResourceType types = {} for ep in iter_entry_points('cloud_inquisitor.plugins.types'): cls = ep.load() types[ResourceType.get(cls.resource_type).resource_type_id] = cls logger.debug('Registered resource type {}'.format(cls.__name__)) return types except SQLAlchemyError: return []
def search(cls, *, limit=100, page=1, accounts=None, locations=None, resources=None, properties=None, include_disabled=False, return_query=False): """Search for resources based on the provided filters. If `return_query` a sub-class of `sqlalchemy.orm.Query` is returned instead of the resource list. Args: limit (`int`): Number of results to return. Default: 100 page (`int`): Pagination offset for results. Default: 1 accounts (`list` of `int`): A list of account id's to limit the returned resources to locations (`list` of `str`): A list of locations as strings to limit the search for resources ('list' of `str`): A list of resource_ids properties (`dict`): A `dict` containing property name and value pairs. Values can be either a str or a list of strings, in which case a boolean OR search is performed on the values include_disabled (`bool`): Include resources from disabled accounts. Default: False return_query (`bool`): Returns the query object prior to adding the limit and offset functions. Allows for sub-classes to amend the search feature with extra conditions. The calling function must handle pagination on its own Returns: `list` of `Resource`, `sqlalchemy.orm.Query` """ qry = db.Resource.order_by(Resource.resource_id).filter( Resource.resource_type_id == ResourceType.get( cls.resource_type).resource_type_id) if not include_disabled: qry = qry.join(Account, Resource.account_id == Account.account_id).filter( Account.enabled == 1) if session: qry = qry.filter(Resource.account_id.in_(session['accounts'])) if accounts: qry = qry.filter( Resource.account_id.in_( [Account.get(acct).account_id for acct in accounts])) if locations: qry = qry.filter(Resource.location.in_(locations)) if resources: qry = qry.filter(Resource.resource_id.in_(resources)) if properties: for prop_name, value in properties.items(): alias = aliased(ResourceProperty) qry = qry.join(alias, Resource.resource_id == alias.resource_id) if type(value) == list: where_clause = [] for item in value: where_clause.append(alias.value == item) qry = qry.filter( and_(alias.name == prop_name, or_(*where_clause)).self_group()) else: qry = qry.filter( and_(alias.name == prop_name, alias.value == value).self_group()) if return_query: return qry total = qry.count() qry = qry.limit(limit) qry = qry.offset((page - 1) * limit if page > 1 else 0) return total, [cls(x) for x in qry.all()]
from sqlalchemy.sql import func, and_ from cloud_inquisitor.constants import ROLE_USER, AccountTypes from cloud_inquisitor.database import db from cloud_inquisitor.plugins import BaseView from cloud_inquisitor.plugins.types.accounts import AWSAccount from cloud_inquisitor.plugins.types.issues import RequiredTagsIssue from cloud_inquisitor.plugins.types.resources import EC2Instance from cloud_inquisitor.schema import (Account, Resource, ResourceType, ResourceProperty, IssueProperty, Issue, IssueType, AccountType) from cloud_inquisitor.utils import MenuItem from cloud_inquisitor.wrappers import check_auth, rollback reqtag_type_id = IssueType.get(RequiredTagsIssue.issue_type).issue_type_id ec2_type_id = ResourceType.get(EC2Instance.resource_type).resource_type_id aws_account_type_id = AccountType.get(AWSAccount.account_type).account_type_id class StatsGet(BaseView): URLS = ['/api/v1/stats'] MENU_ITEMS = [ MenuItem('default', 'Dashboard', 'dashboard', 'dashboard', order=1) ] @rollback @check_auth(ROLE_USER) def get(self): rfc26 = [] accounts = list(AWSAccount.get_all(include_disabled=False).values()) instances_by_account = self._get_instances_by_account()
from sqlalchemy.sql import func, and_ from cloud_inquisitor.constants import ROLE_USER, AccountTypes from cloud_inquisitor.database import db from cloud_inquisitor.plugins import BaseView from cloud_inquisitor.plugins.types.accounts import AWSAccount from cloud_inquisitor.plugins.types.issues import RequiredTagsIssue from cloud_inquisitor.plugins.types.resources import EC2Instance, S3Bucket from cloud_inquisitor.schema import (Account, Resource, ResourceType, ResourceProperty, IssueProperty, Issue, IssueType, AccountType) from cloud_inquisitor.utils import MenuItem from cloud_inquisitor.wrappers import check_auth, rollback reqtag_type_id = IssueType.get(RequiredTagsIssue.issue_type).issue_type_id ec2_type_id = ResourceType.get(EC2Instance.resource_type).resource_type_id aws_account_type_id = AccountType.get(AWSAccount.account_type).account_type_id s3_type_id = ResourceType.get(S3Bucket.resource_type).resource_type_id class StatsGet(BaseView): URLS = ['/api/v1/stats'] MENU_ITEMS = [ MenuItem('default', 'Dashboard', 'dashboard', 'dashboard', order=1) ] @rollback @check_auth(ROLE_USER) def get(self): rfc26 = [] accounts = list(AWSAccount.get_all(include_disabled=False).values())