Added instance type offer filters

This commit is contained in:
Nuwan Goonasekera 2020-11-23 15:25:23 +05:30
parent 4245497a97
commit a69bad57ef
No known key found for this signature in database
GPG Key ID: 4C28B687668239D8
4 changed files with 2261 additions and 0 deletions

View File

@ -169,6 +169,10 @@ INSTANCE_TYPES = _load_resource(
resource_filename(__name__, "resources/instance_types.json")
)
INSTANCE_TYPE_OFFERINGS = _load_resource(
resource_filename(__name__, "resources/instance_type_offerings.json")
)
AMIS = _load_resource(
os.environ.get("MOTO_AMIS_PATH")
or resource_filename(__name__, "resources/amis.json"),
@ -1122,6 +1126,50 @@ class InstanceBackend(object):
return reservations
<<<<<<< HEAD
=======
class InstanceTypeBackend(object):
def __init__(self):
super(InstanceTypeBackend, self).__init__()
def describe_instance_types(self, instance_types=None):
matches = INSTANCE_TYPES.values()
if instance_types:
matches = [t for t in matches if t.get('apiname') in instance_types]
if len(instance_types) > len(matches):
unknown_ids = set(instance_types) - set(matches)
raise InvalidInstanceTypeError(unknown_ids)
return matches
class InstanceTypeOfferingBackend(object):
def __init__(self):
super(InstanceTypeOfferingBackend, self).__init__()
def describe_instance_type_offerings(self, location_type=None, filters=None):
matches = INSTANCE_TYPE_OFFERINGS
location_type = location_type or "region"
def matches_filters(offering, filters):
for key, values in filters.items():
if key == "location":
if location_type in ("availability-zone", "availability-zone-id"):
return offering.get('location') in values
elif location_type == "region":
return any(v for v in values
if offering.get('location').startswith(v))
else:
return False
elif key == "instance-type":
return offering.get('instance_type') in values
else:
return False
return True
matches = [o for o in matches if matches_filters(o, filters)]
return matches
class KeyPair(object):
def __init__(self, name, fingerprint, material):
self.name = name
@ -6010,6 +6058,8 @@ class IamInstanceProfileAssociationBackend(object):
class EC2Backend(
BaseBackend,
InstanceBackend,
InstanceTypeBackend,
InstanceTypeOfferingBackend,
TagBackend,
EBSBackend,
RegionsAndZonesBackend,

File diff suppressed because it is too large Load Diff

View File

@ -150,6 +150,14 @@ class InstanceResponse(BaseResponse):
template = self.response_template(EC2_DESCRIBE_INSTANCE_TYPES)
return template.render(instance_types=instance_types)
def describe_instance_type_offerings(self):
location_type_filters = self._get_multi_param("LocationType")
filter_dict = filters_from_querystring(self.querystring)
offerings = self.ec2_backend.describe_instance_type_offerings(
location_type_filters, filter_dict)
template = self.response_template(EC2_DESCRIBE_INSTANCE_TYPE_OFFERINGS)
return template.render(instance_type_offerings=offerings)
def describe_instance_attribute(self):
# TODO this and modify below should raise IncorrectInstanceState if
# instance not in stopped state
@ -841,3 +849,18 @@ EC2_DESCRIBE_INSTANCE_TYPES = """<?xml version="1.0" encoding="UTF-8"?>
{% endfor %}
</instanceTypeSet>
</DescribeInstanceTypesResponse>"""
EC2_DESCRIBE_INSTANCE_TYPE_OFFERINGS = """<?xml version="1.0" encoding="UTF-8"?>
<DescribeInstanceTypeOfferingsResponse xmlns="http://api.outscale.com/wsdl/fcuext/2014-04-15/">
<requestId>f8b86168-d034-4e65-b48d-3b84c78e64af</requestId>
<instanceTypeOfferingSet>
{% for offering in instance_type_offerings %}
<item>
<instanceType>{{ offering.instance_type }}</instanceType>
<location>{{ offering.location }}</location>
<locationType>{{ offering.location_type }}</locationType>
</item>
{% endfor %}
</instanceTypeOfferingSet>
</DescribeInstanceTypeOfferingsResponse>"""

View File

@ -0,0 +1,58 @@
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_describe_instance_type_offerings():
client = boto3.client("ec2", "us-east-1")
offerings = client.describe_instance_type_offerings()
offerings.should.have.key("InstanceTypeOfferings")
offerings["InstanceTypeOfferings"].should_not.be.empty
offerings["InstanceTypeOfferings"][0].should.have.key("InstanceType")
offerings["InstanceTypeOfferings"][0].should.have.key("Location")
offerings["InstanceTypeOfferings"][0].should.have.key("LocationType")
@mock_ec2
def test_describe_instance_type_offering_filter_by_type():
client = boto3.client("ec2", "us-east-1")
offerings = client.describe_instance_type_offerings(
Filters=[{"Name": "instance-type", "Values": ["t2.nano"]}])
offerings.should.have.key("InstanceTypeOfferings")
offerings["InstanceTypeOfferings"].should_not.be.empty
offerings["InstanceTypeOfferings"].should.have.length_of(2)
offerings["InstanceTypeOfferings"][0]['InstanceType'].should.equal('t2.nano')
offerings["InstanceTypeOfferings"][-1]['InstanceType'].should.equal('t2.nano')
offerings["InstanceTypeOfferings"][0]['Location'].should.equal('us-east-1a')
@mock_ec2
def test_describe_instance_type_offering_filter_by_zone():
client = boto3.client("ec2", "us-east-1")
offerings = client.describe_instance_type_offerings(
Filters=[{"Name": "location", "Values": ["us-east-1c"]}])
offerings.should.have.key("InstanceTypeOfferings")
offerings["InstanceTypeOfferings"].should_not.be.empty
offerings["InstanceTypeOfferings"].should.have.length_of(1)
offerings["InstanceTypeOfferings"][0]['InstanceType'].should.equal('a1.2xlarge')
offerings["InstanceTypeOfferings"][0]['Location'].should.equal('us-east-1c')
@mock_ec2
def test_describe_instance_type_offering_filter_by_region():
client = boto3.client("ec2", "us-east-1")
offerings = client.describe_instance_type_offerings(
LocationType="region", Filters=[{"Name": "location", "Values": ["us-west-1"]}])
offerings.should.have.key("InstanceTypeOfferings")
offerings["InstanceTypeOfferings"].should_not.be.empty
offerings["InstanceTypeOfferings"].should.have.length_of(2)
offerings["InstanceTypeOfferings"][0]['InstanceType'].should.equal('a1.4xlarge')
offerings["InstanceTypeOfferings"][0]['Location'].should.equal('us-west-1a')