Skip to content

Commit

Permalink
Merge pull request #236 from cloudify-cosmo/1.5-build
Browse files Browse the repository at this point in the history
Changes for 1.5 version
  • Loading branch information
Jessiebr authored Aug 10, 2017
2 parents ca37ea4 + 6ebae5f commit 5256014
Show file tree
Hide file tree
Showing 14 changed files with 157 additions and 41 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@
- Fixed error message when unlinking route table from gateway
- Support passing runtime properties to create operation
1.4.13
- Fixed bug that instance get resource returns something when no id was provided
- Fixed bug that instance get resource returns something when no id was provided
1.5
- Associate ElasticIP to resources base on ip property instead of base on resource type
- Fix the need for an operations name to be in the format <something>.<create/start/stop/delete> (Aria Tosca)
- Add connect Security Groups to Instance via InstanceConnectedToSecurityGroup relationship
- Support adding VPC Peering Connection + Use external routes.
55 changes: 33 additions & 22 deletions cloudify_aws/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,47 +411,39 @@ def delete_external_resource_naively(self):

return True

def cloudify_resource_state_change_handler(self, args=None):
def cloudify_resource_state_change_handler(self, state, args=None):
"""
Take steps to create a desired resource state.
If the operation is a retry do not try to call the state change again.
:return:
"""

full_operation_name = ctx.operation.name
short_operation_name = full_operation_name.split('.').pop()
internal_resource_function = getattr(self,
short_operation_name)
post_operation_funtion = getattr(self,
'post_{0}'.format(
short_operation_name))

if 'delete' in short_operation_name:
if 'delete' in state['short_operation_name']:
external_resource_function = self.delete_external_resource_naively
else:
external_resource_function = self.use_external_resource_naively

if ctx.operation.retry_number == 0:
ctx.logger.info(
'Initializing AWS {0}-{1} sequence.'
.format(self.aws_resource_type, short_operation_name))
.format(self.aws_resource_type, state['short_operation_name']))

ret = \
external_resource_function() \
or internal_resource_function(args)
or state['internal_resource_function'](args)

if ret is False:
raise NonRecoverableError(
'Neither external resource, nor Cloudify resource, '
'unable to {0} this resource.'
.format(short_operation_name))
post_operation_funtion()
.format(state['short_operation_name']))
state['post_operation_funtion']()
ctx.logger.info(
'AWS {0}-{1}: primary stage complete.'
.format(self.aws_resource_type, short_operation_name))
.format(self.aws_resource_type, state['short_operation_name']))
resource = self.get_resource()
if not resource and 'delete' in short_operation_name:
if not resource and 'delete' in state['short_operation_name']:
ctx.logger.info('AWS {0} ID# {1} no longer extant.'
.format(self.aws_resource_type,
self.resource_id))
Expand All @@ -462,21 +454,40 @@ def cloudify_resource_state_change_handler(self, args=None):
ctx.logger.info(
'Unable to verify AWS {0} ID# {1} state.'
.format(self.aws_resource_type, self.resource_id))
return self.cloudify_operation_exit_handler(resource_state,
short_operation_name)
return \
self.cloudify_operation_exit_handler(resource_state,
state['short_operation_name'])

def resource_state_helper(self, operation):

internal_resource_function = getattr(self,
operation)
post_operation_funtion = getattr(self,
'post_{0}'.format(
operation))
state = dict(
short_operation_name=operation,
internal_resource_function=internal_resource_function,
post_operation_funtion=post_operation_funtion
)
return state

# Cloudify workflow operation helpers
def create_helper(self, args=None):
return self.cloudify_resource_state_change_handler(args)
state = self.resource_state_helper('create')
return self.cloudify_resource_state_change_handler(state, args)

def start_helper(self, args=None):
return self.cloudify_resource_state_change_handler(args)
state = self.resource_state_helper('start')
return self.cloudify_resource_state_change_handler(state, args)

def stop_helper(self, args=None):
return self.cloudify_resource_state_change_handler(args)
state = self.resource_state_helper('stop')
return self.cloudify_resource_state_change_handler(state, args)

def delete_helper(self, args=None):
return self.cloudify_resource_state_change_handler(args)
state = self.resource_state_helper('delete')
return self.cloudify_resource_state_change_handler(state, args)

def modify_helper(self, new_attributes):
ctx.logger.info(
Expand Down
19 changes: 14 additions & 5 deletions cloudify_aws/ec2/elasticip.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ def __init__(self, client=None):
'{0}_ids'.format(constants.INSTANCE['AWS_RESOURCE_TYPE'])
}

def _is_ip_prop(self):
for prop in ctx.source.instance.runtime_properties.iteritems():
if 'ip' in prop[0].split('_'):
return True
return False

def associate(self, args=None, **_):
""" Associates an Elastic IP created by Cloudify with an EC2 Instance
that was also created by Cloudify.
Expand All @@ -70,11 +76,14 @@ def associate(self, args=None, **_):
source_id = self.source_resource_id
elasticip = self.target_resource_id

if 'cloudify.aws.nodes.Instance' in ctx.source.node.type_hierarchy:
associate_args = dict(instance_id=source_id, public_ip=elasticip)
elif 'cloudify.aws.nodes.Interface' in ctx.source.node.type_hierarchy:
associate_args = dict(network_interface_id=source_id,
public_ip=elasticip)
if self._is_ip_prop():
for type in ctx.source.node.type_hierarchy:
if 'Instance' in type.split('.'):
associate_args = dict(instance_id=source_id,
public_ip=elasticip)
elif 'Interface' in type.split('.'):
associate_args = dict(network_interface_id=source_id,
public_ip=elasticip)

if constants.ELASTICIP['ALLOCATION_ID'] in \
ctx.target.instance.runtime_properties:
Expand Down
9 changes: 9 additions & 0 deletions cloudify_aws/ec2/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,17 @@ def _get_instance_parameters(self, args=None):
attached_group_ids = \
utils.get_target_external_resource_ids(
constants.INSTANCE_SECURITY_GROUP_RELATIONSHIP,
ctx.instance) or utils.get_target_external_resource_ids(
'InstanceConnectedToSecurityGroup',
ctx.instance)

groups = ctx.node.properties['parameters'].get('security_group_ids',
None)
if groups:
ctx.node.properties['parameters'].pop('security_group_ids')
for group in groups:
attached_group_ids.append(group)

if provider_variables.get(constants.AGENTS_SECURITY_GROUP):
attached_group_ids.append(
provider_variables[constants.AGENTS_SECURITY_GROUP])
Expand Down
3 changes: 2 additions & 1 deletion cloudify_aws/ec2/keypair.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ def _save_key_pair(self, key_pair_object):

try:
directory = os.path.dirname(file_path)
os.makedirs(directory)
if not os.path.isdir(directory):
os.makedirs(directory)
except OSError as e:
ctx.logger.error(
'Cannot create parent dirs to {0}: {1}'
Expand Down
4 changes: 2 additions & 2 deletions cloudify_aws/vpc/tests/blueprint/plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
plugins:
aws:
executor: central_deployment_agent
source: https://github.com/cloudify-cosmo/cloudify-aws-plugin/archive/1.4.13.zip
source: https://github.com/cloudify-cosmo/cloudify-aws-plugin/archive/1.5.zip
package_name: cloudify-aws-plugin
package_version: '1.4.13'
package_version: '1.5'

data_types:

Expand Down
85 changes: 83 additions & 2 deletions cloudify_aws/vpc/vpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,40 @@ def __init__(self, target_account_id=None, routes=None, client=None):
self.target_vpc_peering_connection_id = \
self.get_vpc_peering_connection_id(
ctx.target.instance,
self.target_vpc_id,
self.source_vpc_id,
'vpc_peer_id')
self.source_get_all_handler = {
'function': self.client.get_all_route_tables,
'argument':
'{0}_ids'.format(constants.ROUTE_TABLE['AWS_RESOURCE_TYPE'])
}

def disassociate_helper(self, args=None):

if not (self.source_resource_id and self.target_resource_id):
ctx.logger.error(
'Source or target resources, '
'does not exists, unable to disassociate.')
return False

ctx.logger.info(
'Attempting to disassociate {0} from {1}.'
.format(self.source_resource_id, self.target_resource_id))

if self.use_source_external_resource_naively():
ctx.logger.info(
'executing vpc peering connection disassociation '
'despite the fact that this is an external relationship'
)

if self.disassociate(args):
return self.post_disassociate()

raise NonRecoverableError(
'Source is neither external resource, '
'nor Cloudify resource, unable to disassociate {0} from {1}.'
.format(self.source_resource_id, self.target_resource_id))

def associate_helper(self, args):
if self.use_source_external_resource_naively():
ctx.logger.info(
Expand Down Expand Up @@ -144,6 +170,7 @@ def _generate_association_args(self):

def disassociate(self, args):
self.delete_routes()
self.delete_target_routes()
disassociate_args = dict(
vpc_peering_connection_id=self.source_vpc_peering_connection_id
)
Expand All @@ -161,6 +188,12 @@ def post_associate(self):
vpc_peer_id=self.target_vpc_id,
routes=self.routes
)
target_peering_connection = dict(
vpc_peering_connection_id=self.resource_id,
vpc_id=self.target_vpc_id,
vpc_peer_id=self.source_vpc_id,
routes=[]
)
if 'vpc_peering_connections' \
not in ctx.source.instance.runtime_properties:
ctx.source.instance.runtime_properties[
Expand All @@ -172,7 +205,7 @@ def post_associate(self):
ctx.target.instance.runtime_properties[
'vpc_peering_connections'] = []
ctx.target.instance.runtime_properties[
'vpc_peering_connections'].append(cx)
'vpc_peering_connections'].append(target_peering_connection)
return True

def delete_routes(self):
Expand Down Expand Up @@ -228,6 +261,7 @@ def add_route_to_target_vpc(self):
"""

source_vpc_cidr_block = ''
target_vpc_peering_connections = []

vpcs = self.execute(self.client.get_all_vpcs)
for vpc in vpcs:
Expand All @@ -246,11 +280,58 @@ def add_route_to_target_vpc(self):
route_table_id=route_table.id,
route=new_route
)
created_route = new_route
created_route.update({'route_table_id': route_table.id})
ctx.logger.debug('created target vpc route: {0}'.format(
created_route))
for vpc_peering_connection in \
ctx.target.instance.runtime_properties[
'vpc_peering_connections']:
if vpc_peering_connection['vpc_peering_connection_id'] \
== self.source_vpc_peering_connection_id:
vpc_peering_connection['routes'].append(created_route)
target_vpc_peering_connections.append(
vpc_peering_connection)
if not route_created:
return False

ctx.target.instance.runtime_properties['vpc_peering_connections'] = \
target_vpc_peering_connections

return True

def delete_target_routes(self):
target_aws_config = ctx.target.node.properties['aws_config']
client = connection.VPCConnectionClient().client(
aws_config=target_aws_config)
target_vpc_peering_connections = \
ctx.target.instance.runtime_properties \
.get('vpc_peering_connections')
for vpc_peering_connection in target_vpc_peering_connections:
ctx.logger.debug('VPC peering connection: {0}'.format(
vpc_peering_connection))
for route in vpc_peering_connection['routes']:
args = dict(
route_table_id=route['route_table_id'],
destination_cidr_block=route['destination_cidr_block']
)
try:
output = client.delete_route(**args)
except exception.EC2ResponseError as e:
if constants.ROUTE_NOT_FOUND_ERROR in str(e):
ctx.logger.info(
'Could not delete route: {0} route not '
'found on route_table.'
.format(route, route['route_table_id']))
return True
raise NonRecoverableError('{0}'.format(str(e)))

if output:
if route in vpc_peering_connection['routes']:
vpc_peering_connection['routes'].remove(route)
return True
return False


class Vpc(AwsBaseNode):

Expand Down
4 changes: 2 additions & 2 deletions plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
plugins:
aws:
executor: central_deployment_agent
source: https://github.com/cloudify-cosmo/cloudify-aws-plugin/archive/1.4.13.zip
source: https://github.com/cloudify-cosmo/cloudify-aws-plugin/archive/1.5.zip
package_name: cloudify-aws-plugin
package_version: '1.4.13'
package_version: '1.5'

data_types:

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
author='Gigaspaces',
author_email='[email protected]',

version='1.4.13',
version='1.5',
description='Cloudify plugin for AWS infrastructure.',

# This must correspond to the actual packages in the plugin.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tosca_definitions_version: cloudify_dsl_1_3

imports:
- http://www.getcloudify.org/spec/cloudify/4.0.1/types.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.4.13/plugin.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.5/plugin.yaml

inputs:

Expand Down
2 changes: 1 addition & 1 deletion system_tests/manager/resources/sg-blueprint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tosca_definitions_version: cloudify_dsl_1_3

imports:
- http://www.getcloudify.org/spec/cloudify/4.0.1/types.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.4.13/plugin.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.5/plugin.yaml

inputs:

Expand Down
2 changes: 1 addition & 1 deletion system_tests/manager/resources/simple-blueprint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tosca_definitions_version: cloudify_dsl_1_3

imports:
- http://www.getcloudify.org/spec/cloudify/4.0.1/types.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.4.13/plugin.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.5/plugin.yaml

inputs:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tosca_definitions_version: cloudify_dsl_1_3

imports:
- http://www.getcloudify.org/spec/cloudify/4.0.1/types.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.4.13/plugin.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.5/plugin.yaml

inputs:

Expand Down
2 changes: 1 addition & 1 deletion system_tests/manager/resources/vpc_test_blueprint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tosca_definitions_version: cloudify_dsl_1_3

imports:
- http://www.getcloudify.org/spec/cloudify/4.0.1/types.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.4.13/plugin.yaml
- https://raw.githubusercontent.com/cloudify-cosmo/cloudify-aws-plugin/1.5/plugin.yaml

inputs:

Expand Down

0 comments on commit 5256014

Please sign in to comment.