207 lines
7.6 KiB
Python
207 lines
7.6 KiB
Python
import pytest
|
|
|
|
from moto.rds.utils import (
|
|
ORDERABLE_DB_INSTANCE_ENCODING,
|
|
FilterDef,
|
|
apply_filter,
|
|
decode_orderable_db_instance,
|
|
encode_orderable_db_instance,
|
|
merge_filters,
|
|
validate_filters,
|
|
)
|
|
|
|
|
|
class TestFilterValidation:
|
|
@classmethod
|
|
def setup_class(cls):
|
|
cls.filter_defs = {
|
|
"not-implemented": FilterDef(None, ""),
|
|
"identifier": FilterDef(["identifier"], "Object Identifiers"),
|
|
}
|
|
|
|
def test_unrecognized_filter_raises_exception(self):
|
|
filters = {"invalid-filter-name": ["test-value"]}
|
|
with pytest.raises(KeyError) as ex:
|
|
validate_filters(filters, self.filter_defs)
|
|
assert "Unrecognized filter name: invalid-filter-name" in str(ex)
|
|
|
|
def test_empty_filter_values_raises_exception(self):
|
|
filters = {"identifier": []}
|
|
with pytest.raises(ValueError) as ex:
|
|
validate_filters(filters, self.filter_defs)
|
|
assert "Object Identifiers must not be empty" in str(ex)
|
|
|
|
def test_unimplemented_filter_raises_exception(self):
|
|
filters = {"not-implemented": ["test-value"]}
|
|
with pytest.raises(NotImplementedError):
|
|
validate_filters(filters, self.filter_defs)
|
|
|
|
|
|
class Resource:
|
|
def __init__(self, identifier, **kwargs):
|
|
self.identifier = identifier
|
|
self.__dict__.update(kwargs)
|
|
|
|
|
|
class TestResourceFiltering:
|
|
@classmethod
|
|
def setup_class(cls):
|
|
cls.filter_defs = {
|
|
"identifier": FilterDef(["identifier"], "Object Identifiers"),
|
|
"nested-resource": FilterDef(["nested.identifier"], "Nested Identifiers"),
|
|
"common-attr": FilterDef(["common_attr"], ""),
|
|
"multiple-attrs": FilterDef(["common_attr", "uncommon_attr"], ""),
|
|
}
|
|
cls.resources = {
|
|
"identifier-0": Resource("identifier-0"),
|
|
"identifier-1": Resource("identifier-1", common_attr="common"),
|
|
"identifier-2": Resource("identifier-2"),
|
|
"identifier-3": Resource("identifier-3", nested=Resource("nested-id-1")),
|
|
"identifier-4": Resource("identifier-4", common_attr="common"),
|
|
"identifier-5": Resource("identifier-5", uncommon_attr="common"),
|
|
}
|
|
|
|
def test_filtering_on_nested_attribute(self):
|
|
filters = {"nested-resource": ["nested-id-1"]}
|
|
filtered_resources = apply_filter(self.resources, filters, self.filter_defs)
|
|
assert len(filtered_resources) == 1
|
|
assert "identifier-3" in filtered_resources
|
|
|
|
def test_filtering_on_common_attribute(self):
|
|
filters = {"common-attr": ["common"]}
|
|
filtered_resources = apply_filter(self.resources, filters, self.filter_defs)
|
|
assert len(filtered_resources) == 2
|
|
assert "identifier-1" in filtered_resources
|
|
assert "identifier-4" in filtered_resources
|
|
|
|
def test_filtering_on_multiple_attributes(self):
|
|
filters = {"multiple-attrs": ["common"]}
|
|
filtered_resources = apply_filter(self.resources, filters, self.filter_defs)
|
|
assert len(filtered_resources) == 3
|
|
assert "identifier-1" in filtered_resources
|
|
assert "identifier-4" in filtered_resources
|
|
assert "identifier-5" in filtered_resources
|
|
|
|
def test_filters_with_multiple_values(self):
|
|
filters = {"identifier": ["identifier-0", "identifier-3", "identifier-5"]}
|
|
filtered_resources = apply_filter(self.resources, filters, self.filter_defs)
|
|
assert len(filtered_resources) == 3
|
|
assert "identifier-0" in filtered_resources
|
|
assert "identifier-3" in filtered_resources
|
|
assert "identifier-5" in filtered_resources
|
|
|
|
def test_multiple_filters(self):
|
|
filters = {
|
|
"identifier": ["identifier-1", "identifier-3", "identifier-5"],
|
|
"common-attr": ["common"],
|
|
"multiple-attrs": ["common"],
|
|
}
|
|
filtered_resources = apply_filter(self.resources, filters, self.filter_defs)
|
|
assert len(filtered_resources) == 1
|
|
assert "identifier-1" in filtered_resources
|
|
|
|
|
|
class TestMergingFilters:
|
|
def test_when_filters_to_update_is_none(self):
|
|
filters_to_update = {"filter-name": ["value1"]}
|
|
merged = merge_filters(filters_to_update, None)
|
|
assert merged == filters_to_update
|
|
|
|
def test_when_filters_to_merge_is_none(self):
|
|
filters_to_merge = {"filter-name": ["value1"]}
|
|
merged = merge_filters(None, filters_to_merge)
|
|
assert merged == filters_to_merge
|
|
|
|
def test_when_both_filters_are_none(self):
|
|
merged = merge_filters(None, None)
|
|
assert merged == {}
|
|
|
|
def test_values_are_merged(self):
|
|
filters_to_update = {"filter-name": ["value1"]}
|
|
filters_to_merge = {"filter-name": ["value2"]}
|
|
merged = merge_filters(filters_to_update, filters_to_merge)
|
|
assert merged == {"filter-name": ["value1", "value2"]}
|
|
|
|
def test_complex_merge(self):
|
|
filters_to_update = {
|
|
"filter-name-1": ["value1"],
|
|
"filter-name-2": ["value1", "value2"],
|
|
"filter-name-3": ["value1"],
|
|
}
|
|
filters_to_merge = {
|
|
"filter-name-1": ["value2"],
|
|
"filter-name-3": ["value2"],
|
|
"filter-name-4": ["value1", "value2"],
|
|
}
|
|
merged = merge_filters(filters_to_update, filters_to_merge)
|
|
assert len(merged.keys()) == 4
|
|
for value in merged.values():
|
|
assert value == ["value1", "value2"]
|
|
|
|
|
|
def test_encode_orderable_db_instance():
|
|
"""Verify the data can be encoded/decoded to something more compact.
|
|
|
|
Data from AWS comes in a specific format.
|
|
"""
|
|
original = {
|
|
"Engine": "neptune",
|
|
"EngineVersion": "1.0.3.0",
|
|
"DBInstanceClass": "db.r4.2xlarge",
|
|
"LicenseModel": "amazon-license",
|
|
"AvailabilityZones": [
|
|
{"Name": "us-east-1a"},
|
|
{"Name": "us-east-1b"},
|
|
{"Name": "us-east-1c"},
|
|
{"Name": "us-east-1d"},
|
|
{"Name": "us-east-1e"},
|
|
{"Name": "us-east-1f"},
|
|
],
|
|
"MultiAZCapable": False,
|
|
"ReadReplicaCapable": False,
|
|
"Vpc": True,
|
|
"SupportsStorageEncryption": True,
|
|
"StorageType": "aurora",
|
|
"SupportsIops": False,
|
|
"SupportsEnhancedMonitoring": False,
|
|
"SupportsIAMDatabaseAuthentication": True,
|
|
"SupportsPerformanceInsights": False,
|
|
"AvailableProcessorFeatures": [],
|
|
"SupportedEngineModes": ["provisioned"],
|
|
"SupportsKerberosAuthentication": False,
|
|
"OutpostCapable": False,
|
|
"SupportedActivityStreamModes": [],
|
|
"SupportsGlobalDatabases": False,
|
|
"SupportsClusters": True,
|
|
"Support edNetworkTypes": ["IPV4"],
|
|
}
|
|
short = encode_orderable_db_instance(original)
|
|
assert decode_orderable_db_instance(short) == original
|
|
|
|
|
|
def test_encode_orderable_db_instance__short_format():
|
|
"""Verify this works in a random format.
|
|
|
|
We don't know for sure what AWS returns, so it should always work
|
|
regardless of the input.
|
|
"""
|
|
short = {
|
|
"Engine": "neptune",
|
|
"EngineVersion": "1.0.3.0",
|
|
"DBInstanceClass": "db.r4.2xlarge",
|
|
"LicenseModel": "amazon-license",
|
|
"SupportsKerberosAuthentication": False,
|
|
"OutpostCapable": False,
|
|
"SupportedActivityStreamModes": [],
|
|
"SupportsGlobalDatabases": False,
|
|
"SupportsClusters": True,
|
|
"SupportedNetworkTypes": ["IPV4"],
|
|
}
|
|
assert decode_orderable_db_instance(encode_orderable_db_instance(short)) == short
|
|
|
|
|
|
def test_verify_encoding_is_unique():
|
|
assert len(set(ORDERABLE_DB_INSTANCE_ENCODING.values())) == len(
|
|
ORDERABLE_DB_INSTANCE_ENCODING.keys()
|
|
)
|