Skip to content

Commit

Permalink
Merge pull request #437 from cloudify-cosmo/RD-3452-aws-spot-fleet-do…
Browse files Browse the repository at this point in the history
…esnt-create-in-install-stage

Rd 3452 aws spot fleet doesnt create in install stage
  • Loading branch information
EarthmanT authored Mar 8, 2022
2 parents acb8ba3 + f05d4e0 commit d8a506f
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
5 changes: 5 additions & 0 deletions cloudify_aws/ec2/resources/securitygroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ def check_status(self):
return 'OK'
return 'NOT OK'

@property
def status(self):
'''Gets the status of an external resource'''
return self.properties

def create(self, params):
"""
Create a new AWS EC2 NetworkInterface.
Expand Down
48 changes: 39 additions & 9 deletions cloudify_aws/ec2/resources/spot_fleet_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
AWS EC2 VPC interface
'''
# Third Party imports
from botocore.exceptions import ClientError, ParamValidationError
from botocore.exceptions import ClientError

from cloudify.exceptions import OperationRetry
from cloudify.exceptions import OperationRetry, NonRecoverableError

# Local imports
from cloudify_aws.ec2 import EC2Base
from cloudify_aws.common import decorators, utils
from cloudify_aws.ec2.resources.instances import INSTANCE_ID
from cloudify_aws.common.constants import (
EXTERNAL_RESOURCE_ID_MULTIPLE as MULTI_ID)

RESOURCE_TYPE = 'EC2 Spot Fleet Request'
SpotFleetRequest = 'SpotFleetRequest'
Expand All @@ -41,7 +44,7 @@ class EC2SpotFleetRequest(EC2Base):
def __init__(self, ctx_node, resource_id=None, client=None, logger=None):
EC2Base.__init__(self, ctx_node, resource_id, client, logger)
self.type_name = RESOURCE_TYPE
self._properties = None
self._properties = {}

def get(self, spot_fleet_request_ids=None):
self.logger.debug(
Expand All @@ -53,24 +56,30 @@ def get(self, spot_fleet_request_ids=None):
try:
return self.make_client_call(
'describe_spot_fleet_requests', params)
except (ParamValidationError, ClientError):
except (NonRecoverableError):
return

@property
def properties(self):
'''Gets the properties of an external resource'''
if not self._properties:
resources = self.get()
if len(resources):
if resources and 'SpotFleetRequestConfigs' in resources:
self._properties = resources[SpotFleetRequestConfigs][0]
return self._properties

@property
def status(self):
'''Gets the status of an external resource'''
if self.properties:
config = self.properties[SpotFleetRequestConfig]
return config['SpotFleetRequestState']
props = self.properties
if SpotFleetRequestConfig in props:
return props[SpotFleetRequestConfig].get('SpotFleetRequestState')

@property
def check_status(self):
if self.status in ['active']:
return 'OK'
return 'NOT OK'

@property
def active_instances(self):
Expand All @@ -92,10 +101,11 @@ def delete(self, params=None):
'''
return self.make_client_call('cancel_spot_fleet_requests', params)

def list_spot_fleet_instances(self, params):
def list_spot_fleet_instances(self, params=None):
'''
Checks current instances of AWS EC2 Spot Fleet Request.
'''
params = params or {SpotFleetRequestIds: [self.resource_id]}
return self.make_client_call('describe_spot_fleet_instances', params)


Expand Down Expand Up @@ -127,6 +137,26 @@ def create(ctx, iface, resource_config, **_):
utils.update_resource_id(ctx.instance, spot_fleed_request_id)


@decorators.aws_resource(EC2SpotFleetRequest,
RESOURCE_TYPE,
ignore_properties=True,
waits_for_status=False)
def poststart(ctx, iface, resource_config, wait_for_target_capacity=True, **_):
if not wait_for_target_capacity:
return
target_capacity = resource_config.get('TargetCapacity')
spot_fleet_instances = iface.list_spot_fleet_instances()
active = spot_fleet_instances.get('ActiveInstances')
if not len(active) == target_capacity:
raise OperationRetry(
'Waiting for active instance number to match target capacity.')
if MULTI_ID not in ctx.instance.runtime_properties:
ctx.instance.runtime_properties[MULTI_ID] = []
for instance in active:
instance_id = instance.get(INSTANCE_ID, '')
ctx.instance.runtime_properties[MULTI_ID].append(instance_id)


@decorators.aws_resource(EC2SpotFleetRequest,
RESOURCE_TYPE,
ignore_properties=True,
Expand Down
34 changes: 32 additions & 2 deletions cloudify_aws/ec2/tests/test_spot_fleet_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_class_properties(self):
self.spot_fleet_request.client = self.make_client_function(
'describe_spot_fleet_requests', return_value=value)
res = self.spot_fleet_request.properties
self.assertIsNone(res)
self.assertEqual({}, res)

value = {
'SpotFleetRequestConfigs': [
Expand All @@ -72,13 +72,14 @@ def test_class_properties(self):
res['SpotFleetRequestConfig'][SpotFleetRequestId],
'foo')

def test_class_status(self):
def test_class_status_none(self):
value = {}
self.spot_fleet_request.client = self.make_client_function(
'describe_spot_fleet_requests', return_value=value)
res = self.spot_fleet_request.status
self.assertIsNone(res)

def test_class_status_active(self):
value = {
'SpotFleetRequestConfigs': [
{
Expand All @@ -89,6 +90,7 @@ def test_class_status(self):
}
]
}
self.spot_fleet_request.resource_id = 'foo'
self.spot_fleet_request.client = self.make_client_function(
'describe_spot_fleet_requests', return_value=value)
res = self.spot_fleet_request.status
Expand Down Expand Up @@ -135,6 +137,34 @@ def test_delete(self):
spot_fleet_request.delete(
ctx=ctx, iface=iface, resource_config={})

def test_poststart(self):
ctx = self.get_mock_ctx(SpotFleetRequest)
config = {'SpotFleetRequestConfig': {SpotFleetRequestId: 'foo'}}
self.spot_fleet_request.resource_id = \
config['SpotFleetRequestConfig'][SpotFleetRequestId]
iface = MagicMock()
iface.list_spot_fleet_instances = self.mock_return(
{
'ActiveInstances': [
{
'InstanceId': 'foo',
'InstanceType': 'bar',
'SpotInstanceRequestId': 'foo',
'InstanceHealth': 'baz'
},
],
'NextToken': 'string',
'SpotFleetRequestId': 'foo'
}
)

spot_fleet_request.poststart(ctx=ctx, iface=iface, resource_config={
'TargetCapacity': 1
})
self.assertTrue(
'foo' in ctx.instance.runtime_properties['aws_resource_ids']
)


if __name__ == '__main__':
unittest.main()
5 changes: 3 additions & 2 deletions cloudify_aws/eks/resources/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,9 @@ def get_zones(ctx, subnets):
zones = []
for subnet in subnets:
subnet_iface = EC2Subnet(ctx.node, subnet, logger=ctx.logger)
availability_zone = subnet_iface.properties['AvailabilityZone']
zones.append(availability_zone)
availability_zone = subnet_iface.properties.get('AvailabilityZone')
if availability_zone:
zones.append(availability_zone)
return zones


Expand Down

0 comments on commit d8a506f

Please sign in to comment.