Ejemplo n.º 1
0
    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()}
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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()
        ]
Ejemplo n.º 4
0
    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))
Ejemplo n.º 5
0
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 []
Ejemplo n.º 6
0
    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()]
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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())