<reponame>szpotona/cloudify-aws-plugin
# Copyright (c) 2018 Cloudify Platform Ltd. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''
    RDS.Instance
    ~~~~~~~~~~~~
    AWS RDS instance interface
'''
# Standard Imports
from datetime import datetime

# Third party imports
from botocore.exceptions import ClientError

# Local imports
from cloudify_aws.common._compat import text_type
from cloudify.exceptions import NonRecoverableError
from cloudify_aws.common import decorators, utils
from cloudify_aws.rds import RDSBase

RESOURCE_TYPE = 'RDS DB Instance'


class DBInstance(RDSBase):
    '''
        AWS RDS DB Instance interface
    '''

    def __init__(self, ctx_node, resource_id=None, client=None, logger=None):
        RDSBase.__init__(self, ctx_node, resource_id, client, logger)
        self.type_name = RESOURCE_TYPE

    @property
    def properties(self):
        '''Gets the properties of an external resource'''
        if not self.resource_id:
            return
        resources = None
        try:
            resources = self.client.describe_db_instances(
                DBInstanceIdentifier=self.resource_id)
        except ClientError:
            pass
        if not resources or not resources.get('DBInstances', list()):
            return None
        return resources['DBInstances'][0]

    @property
    def status(self):
        '''Gets the status of an external resource'''
        props = self.properties
        if not props:
            return None
        return props['DBInstanceStatus']

    def create(self, params):
        '''
            Create a new AWS RDS DB instance.
        .. note:
            See http://bit.ly/2p4c3Bx for config details.
        '''
        return self.make_client_call('create_db_instance', params)

    def delete(self, params=None):
        '''
            Deletes an existing AWS RDS DB instance.
        .. note:
            See http://bit.ly/2pkNk91 for config details.
        '''
        params = params or dict(SkipFinalSnapshot=True)
        params.update(dict(
            DBInstanceIdentifier=self.resource_id))
        self.logger.debug('Deleting %s with parameters: %s'
                          % (self.type_name, params))
        self.client.delete_db_instance(**params)


@decorators.aws_resource(DBInstance, RESOURCE_TYPE,
                         waits_for_status=False)
def prepare(ctx, resource_config, **_):
    '''Prepares an AWS RDS Instance'''
    # Save the parameters
    ctx.instance.runtime_properties['resource_config'] = resource_config


@decorators.aws_resource(DBInstance, RESOURCE_TYPE)
@decorators.wait_for_status(
    status_good=['available'],
    status_pending=['creating', 'modifying', 'backing-up'])
def create(ctx, iface, resource_config, **_):
    '''Creates an AWS RDS Instance'''
    # Build API params
    params = \
        dict() if not resource_config else resource_config.copy()
    params.update(dict(DBInstanceIdentifier=iface.resource_id))
    # Actually create the resource
    res = iface.create(params)
    db_instance = res['DBInstance']
    for key, value in db_instance.items():
        if key == 'DBInstanceIdentifier':
            iface.update_resource_id(value)
            utils.update_resource_id(ctx.instance, value)
            continue
        elif key == 'DBInstanceArn':
            utils.update_resource_arn(ctx.instance, value)
            continue
        elif isinstance(value, datetime):
            value = text_type(value)
        ctx.instance.runtime_properties[key] = value


@decorators.aws_resource(DBInstance, RESOURCE_TYPE,
                         ignore_properties=True,
                         waits_for_status=False)
def start(ctx, iface, resource_config, **_):
    '''Updates an AWS RDS Instance Runtime Properties'''

    db_instance = iface.properties
    for key, value in db_instance.items():
        if key == 'DBInstanceIdentifier':
            iface.update_resource_id(value)
            utils.update_resource_id(ctx.instance, value)
            continue
        elif key == 'DBInstanceArn':
            utils.update_resource_arn(ctx.instance, value)
            continue
        elif isinstance(value, datetime):
            value = text_type(value)
        ctx.instance.runtime_properties[key] = value


@decorators.aws_resource(DBInstance, RESOURCE_TYPE,
                         ignore_properties=True)
@decorators.wait_for_delete(status_pending=['deleting'])
def delete(iface, resource_config, **_):
    '''Deletes an AWS RDS Instance'''
    iface.delete(resource_config)


@decorators.aws_relationship(DBInstance, RESOURCE_TYPE)
def prepare_assoc(ctx, iface, resource_config, **inputs):
    '''Prepares to associate an RDS Instance to something else'''
    if utils.is_node_type(ctx.target.node,
                          'cloudify.nodes.aws.rds.SubnetGroup'):
        ctx.source.instance.runtime_properties[
            'resource_config']['DBSubnetGroupName'] = utils.get_resource_id(
            node=ctx.target.node,
            instance=ctx.target.instance,
            raise_on_missing=True)
    elif utils.is_node_type(ctx.target.node,
                            'cloudify.nodes.aws.rds.OptionGroup'):
        ctx.source.instance.runtime_properties[
            'resource_config']['OptionGroupName'] = utils.get_resource_id(
            node=ctx.target.node,
            instance=ctx.target.instance,
            raise_on_missing=True)
    elif utils.is_node_type(ctx.target.node,
                            'cloudify.nodes.aws.rds.ParameterGroup'):
        ctx.source.instance.runtime_properties[
            'resource_config']['DBParameterGroupName'] = utils.get_resource_id(
            node=ctx.target.node,
            instance=ctx.target.instance,
            raise_on_missing=True)
    elif (utils.is_node_type(
            ctx.target.node, 'cloudify.aws.ec2.SecurityGroup') or
          utils.is_node_type(
            ctx.target.node, 'cloudify.nodes.aws.ec2.SecurityGroup')):
        security_groups = \
            ctx.source.instance.runtime_properties['resource_config'].get(
                'VpcSecurityGroupIds', list())
        security_groups.append(
            utils.get_resource_id(
                node=ctx.target.node,
                instance=ctx.target.instance,
                raise_on_missing=True))
        ctx.source.instance.runtime_properties[
            'resource_config']['VpcSecurityGroupIds'] = security_groups
    elif utils.is_node_type(ctx.target.node,
                            'cloudify.nodes.aws.iam.Role'):
        if not inputs.get('iam_role_type_key') or \
                not inputs.get('iam_role_id_key'):
            raise NonRecoverableError(
                'Missing required relationship inputs "iam_role_type_key" '
                'and/or "iam_role_id_key".')
        ctx.source.instance.runtime_properties[
            'resource_config'][inputs['iam_role_type_key']] = \
            utils.get_resource_string(
                node=ctx.target.node,
                instance=ctx.target.instance,
                attribute_key=inputs['iam_role_id_key'])


@decorators.aws_relationship(DBInstance, RESOURCE_TYPE)
def detach_from(ctx, iface, resource_config, **_):
    '''Detaches an RDS Instance from something else'''
    pass

# Copyright (c) 2018 Cloudify Platform Ltd. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''
    RDS.Instance
    ~~~~~~~~~~~~
    AWS RDS instance interface
'''
# Standard Imports
from datetime import datetime

# Third party imports
from botocore.exceptions import ClientError

# Local imports
from cloudify_aws.common._compat import text_type
from cloudify.exceptions import NonRecoverableError
from cloudify_aws.common import decorators, utils
from cloudify_aws.rds import RDSBase

RESOURCE_TYPE = 'RDS DB Instance'


class DBInstance(RDSBase):
    '''
        AWS RDS DB Instance interface
    '''

    def __init__(self, ctx_node, resource_id=None, client=None, logger=None):
        RDSBase.__init__(self, ctx_node, resource_id, client, logger)
        self.type_name = RESOURCE_TYPE

    @property
    def properties(self):
        '''Gets the properties of an external resource'''
        if not self.resource_id:
            return
        resources = None
        try:
            resources = self.client.describe_db_instances(
                DBInstanceIdentifier=self.resource_id)
        except ClientError:
            pass
        if not resources or not resources.get('DBInstances', list()):
            return None
        return resources['DBInstances'][0]

    @property
    def status(self):
        '''Gets the status of an external resource'''
        props = self.properties
        if not props:
            return None
        return props['DBInstanceStatus']

    def create(self, params):
        '''
            Create a new AWS RDS DB instance.
        .. note:
            See http://bit.ly/2p4c3Bx for config details.
        '''
        return self.make_client_call('create_db_instance', params)

    def delete(self, params=None):
        '''
            Deletes an existing AWS RDS DB instance.
        .. note:
            See http://bit.ly/2pkNk91 for config details.
        '''
        params = params or dict(SkipFinalSnapshot=True)
        params.update(dict(
            DBInstanceIdentifier=self.resource_id))
        self.logger.debug('Deleting %s with parameters: %s'
                          % (self.type_name, params))
        self.client.delete_db_instance(**params)


@decorators.aws_resource(DBInstance, RESOURCE_TYPE,
                         waits_for_status=False)
def prepare(ctx, resource_config, **_):
    '''Prepares an AWS RDS Instance'''
    # Save the parameters
    ctx.instance.runtime_properties['resource_config'] = resource_config


@decorators.aws_resource(DBInstance, RESOURCE_TYPE)
@decorators.wait_for_status(
    status_good=['available'],
    status_pending=['creating', 'modifying', 'backing-up'])
def create(ctx, iface, resource_config, **_):
    '''Creates an AWS RDS Instance'''
    # Build API params
    params = \
        dict() if not resource_config else resource_config.copy()
    params.update(dict(DBInstanceIdentifier=iface.resource_id))
    # Actually create the resource
    res = iface.create(params)
    db_instance = res['DBInstance']
    for key, value in db_instance.items():
        if key == 'DBInstanceIdentifier':
            iface.update_resource_id(value)
            utils.update_resource_id(ctx.instance, value)
            continue
        elif key == 'DBInstanceArn':
            utils.update_resource_arn(ctx.instance, value)
            continue
        elif isinstance(value, datetime):
            value = text_type(value)
        ctx.instance.runtime_properties[key] = value


@decorators.aws_resource(DBInstance, RESOURCE_TYPE,
                         ignore_properties=True,
                         waits_for_status=False)
def start(ctx, iface, resource_config, **_):
    '''Updates an AWS RDS Instance Runtime Properties'''

    db_instance = iface.properties
    for key, value in db_instance.items():
        if key == 'DBInstanceIdentifier':
            iface.update_resource_id(value)
            utils.update_resource_id(ctx.instance, value)
            continue
        elif key == 'DBInstanceArn':
            utils.update_resource_arn(ctx.instance, value)
            continue
        elif isinstance(value, datetime):
            value = text_type(value)
        ctx.instance.runtime_properties[key] = value


@decorators.aws_resource(DBInstance, RESOURCE_TYPE,
                         ignore_properties=True)
@decorators.wait_for_delete(status_pending=['deleting'])
def delete(iface, resource_config, **_):
    '''Deletes an AWS RDS Instance'''
    iface.delete(resource_config)


@decorators.aws_relationship(DBInstance, RESOURCE_TYPE)
def prepare_assoc(ctx, iface, resource_config, **inputs):
    '''Prepares to associate an RDS Instance to something else'''
    if utils.is_node_type(ctx.target.node,
                          'cloudify.nodes.aws.rds.SubnetGroup'):
        ctx.source.instance.runtime_properties[
            'resource_config']['DBSubnetGroupName'] = utils.get_resource_id(
            node=ctx.target.node,
            instance=ctx.target.instance,
            raise_on_missing=True)
    elif utils.is_node_type(ctx.target.node,
                            'cloudify.nodes.aws.rds.OptionGroup'):
        ctx.source.instance.runtime_properties[
            'resource_config']['OptionGroupName'] = utils.get_resource_id(
            node=ctx.target.node,
            instance=ctx.target.instance,
            raise_on_missing=True)
    elif utils.is_node_type(ctx.target.node,
                            'cloudify.nodes.aws.rds.ParameterGroup'):
        ctx.source.instance.runtime_properties[
            'resource_config']['DBParameterGroupName'] = utils.get_resource_id(
            node=ctx.target.node,
            instance=ctx.target.instance,
            raise_on_missing=True)
    elif (utils.is_node_type(
            ctx.target.node, 'cloudify.aws.ec2.SecurityGroup') or
          utils.is_node_type(
            ctx.target.node, 'cloudify.nodes.aws.ec2.SecurityGroup')):
        security_groups = \
            ctx.source.instance.runtime_properties['resource_config'].get(
                'VpcSecurityGroupIds', list())
        security_groups.append(
            utils.get_resource_id(
                node=ctx.target.node,
                instance=ctx.target.instance,
                raise_on_missing=True))
        ctx.source.instance.runtime_properties[
            'resource_config']['VpcSecurityGroupIds'] = security_groups
    elif utils.is_node_type(ctx.target.node,
                            'cloudify.nodes.aws.iam.Role'):
        if not inputs.get('iam_role_type_key') or \
                not inputs.get('iam_role_id_key'):
            raise NonRecoverableError(
                'Missing required relationship inputs "iam_role_type_key" '
                'and/or "iam_role_id_key".')
        ctx.source.instance.runtime_properties[
            'resource_config'][inputs['iam_role_type_key']] = \
            utils.get_resource_string(
                node=ctx.target.node,
                instance=ctx.target.instance,
                attribute_key=inputs['iam_role_id_key'])


@decorators.aws_relationship(DBInstance, RESOURCE_TYPE)
def detach_from(ctx, iface, resource_config, **_):
    '''Detaches an RDS Instance from something else'''
    pass
# Copyright (c) 2018 Cloudify Platform Ltd. All rights reserved # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # #        http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. RDS.Instance     ~~~~~~~~~~~~     AWS RDS instance interface # Standard Imports # Third party imports # Local imports AWS RDS DB Instance interface Gets the properties of an external resource Gets the status of an external resource Create a new AWS RDS DB instance.         .. note:             See http://bit.ly/2p4c3Bx for config details. Deletes an existing AWS RDS DB instance.         .. note:             See http://bit.ly/2pkNk91 for config details. Prepares an AWS RDS Instance # Save the parameters Creates an AWS RDS Instance # Build API params # Actually create the resource Updates an AWS RDS Instance Runtime Properties Deletes an AWS RDS Instance Prepares to associate an RDS Instance to something else Detaches an RDS Instance from something else