Add describe_spot_price_history (#4261)
This commit is contained in:
parent
6d9abe1111
commit
69cc92f780
@ -5562,6 +5562,30 @@ class SpotFleetBackend(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class SpotPriceBackend(object):
|
||||||
|
def describe_spot_price_history(self, instance_types=None, filters=None):
|
||||||
|
matches = INSTANCE_TYPE_OFFERINGS["availability-zone"]
|
||||||
|
matches = matches[self.region_name]
|
||||||
|
|
||||||
|
def matches_filters(offering, filters):
|
||||||
|
def matches_filter(key, values):
|
||||||
|
if key == "availability-zone":
|
||||||
|
return offering.get("Location") in values
|
||||||
|
elif key == "instance-type":
|
||||||
|
return offering.get("InstanceType") in values
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return all([matches_filter(key, values) for key, values in filters.items()])
|
||||||
|
|
||||||
|
matches = [o for o in matches if matches_filters(o, filters)]
|
||||||
|
|
||||||
|
if instance_types:
|
||||||
|
matches = [t for t in matches if t.get("InstanceType") in instance_types]
|
||||||
|
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
class ElasticAddress(TaggedEC2Resource, CloudFormationModel):
|
class ElasticAddress(TaggedEC2Resource, CloudFormationModel):
|
||||||
def __init__(self, ec2_backend, domain, address=None, tags=None):
|
def __init__(self, ec2_backend, domain, address=None, tags=None):
|
||||||
self.ec2_backend = ec2_backend
|
self.ec2_backend = ec2_backend
|
||||||
@ -7568,6 +7592,7 @@ class EC2Backend(
|
|||||||
VPCGatewayAttachmentBackend,
|
VPCGatewayAttachmentBackend,
|
||||||
SpotFleetBackend,
|
SpotFleetBackend,
|
||||||
SpotRequestBackend,
|
SpotRequestBackend,
|
||||||
|
SpotPriceBackend,
|
||||||
ElasticAddressBackend,
|
ElasticAddressBackend,
|
||||||
KeyPairBackend,
|
KeyPairBackend,
|
||||||
DHCPOptionsSetBackend,
|
DHCPOptionsSetBackend,
|
||||||
|
@ -35,9 +35,13 @@ class SpotInstances(BaseResponse):
|
|||||||
return template.render(requests=requests)
|
return template.render(requests=requests)
|
||||||
|
|
||||||
def describe_spot_price_history(self):
|
def describe_spot_price_history(self):
|
||||||
raise NotImplementedError(
|
instance_types_filters = self._get_multi_param("InstanceType")
|
||||||
"SpotInstances.describe_spot_price_history is not yet implemented"
|
filter_dict = filters_from_querystring(self.querystring)
|
||||||
|
prices = self.ec2_backend.describe_spot_price_history(
|
||||||
|
instance_types_filters, filter_dict
|
||||||
)
|
)
|
||||||
|
template = self.response_template(DESCRIBE_SPOT_PRICE_HISTORY_TEMPLATE)
|
||||||
|
return template.render(prices=prices)
|
||||||
|
|
||||||
def request_spot_instances(self):
|
def request_spot_instances(self):
|
||||||
price = self._get_param("SpotPrice")
|
price = self._get_param("SpotPrice")
|
||||||
@ -228,3 +232,18 @@ CANCEL_SPOT_INSTANCES_TEMPLATE = """<CancelSpotInstanceRequestsResponse xmlns="h
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</spotInstanceRequestSet>
|
</spotInstanceRequestSet>
|
||||||
</CancelSpotInstanceRequestsResponse>"""
|
</CancelSpotInstanceRequestsResponse>"""
|
||||||
|
|
||||||
|
DESCRIBE_SPOT_PRICE_HISTORY_TEMPLATE = """<DescribeSpotPriceHistoryResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||||
|
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
|
||||||
|
<spotPriceHistorySet>
|
||||||
|
{% for price in prices %}
|
||||||
|
<item>
|
||||||
|
<instanceType>{{ price.InstanceType }}</instanceType>
|
||||||
|
<productDescription>Linux/UNIX (Amazon VPC)</productDescription>
|
||||||
|
<spotPrice>0.00001</spotPrice>
|
||||||
|
<availabilityZone>{{ price.Location }}</availabilityZone>
|
||||||
|
<timestamp>2006-01-02T15:04:05.999999999Z</timestamp>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</spotPriceHistorySet>
|
||||||
|
</DescribeSpotPriceHistoryResponse>"""
|
||||||
|
@ -313,3 +313,24 @@ def test_launch_instance_instance_lifecycle():
|
|||||||
response = client.describe_instances()
|
response = client.describe_instances()
|
||||||
instance = response["Reservations"][0]["Instances"][0]
|
instance = response["Reservations"][0]["Instances"][0]
|
||||||
instance["InstanceLifecycle"].should.equal("")
|
instance["InstanceLifecycle"].should.equal("")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_spot_price_history():
|
||||||
|
client = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
# test filter
|
||||||
|
response = client.describe_spot_price_history(
|
||||||
|
Filters=[
|
||||||
|
{"Name": "availability-zone", "Values": ["us-east-1a"]},
|
||||||
|
{"Name": "instance-type", "Values": ["t3a.micro"]},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
price = response["SpotPriceHistory"][0]
|
||||||
|
price["InstanceType"].should.equal("t3a.micro")
|
||||||
|
price["AvailabilityZone"].should.equal("us-east-1a")
|
||||||
|
|
||||||
|
# test instance types
|
||||||
|
i_types = ["t3a.micro", "t3.micro"]
|
||||||
|
response = client.describe_spot_price_history(InstanceTypes=i_types)
|
||||||
|
price = response["SpotPriceHistory"][0]
|
||||||
|
assert price["InstanceType"] in i_types
|
||||||
|
Loading…
x
Reference in New Issue
Block a user