def setUp(self): metadata_manager = MetadataManager(["qualifier"], ) self.metadata_container = metadata_manager.read_metadata_from_strings("Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource(ApiResource("/redfish/v1/Managers/RMC", 'netloc', RESOURCE, "#Manager.1.0.0.Manager"))
def _load_metadata(self): qualifiers, services = self.get_services_and_qualifiers() metadata_manager = MetadataManager(qualifiers, ignore_types=self.ignore_types, map_types=self.map_types) if self.configuration.MetadataDirectory: cts_warning("CTS is configured to use custom metadata from: {dir}", dir=self.configuration.MetadataDirectory) metadata_container = self._load_custom_metadata( metadata_manager, self.configuration.MetadataDirectory) elif self.configuration.RedfishMetadata: cts_warning( "CTS is configured to use Redfish metadata: {metadata_version}", metadata_version=self.configuration.RedfishMetadata) metadata_container = \ self._load_custom_metadata(metadata_manager, '/'.join((Constants.METADATA_REDFISH_DIR, str(self.configuration.RedfishMetadata)))) else: metadata_container = self._load_built_in_metadata( metadata_manager, services) if metadata_container is not None: metadata_container.print_types() return metadata_container
def setUp(self): self.discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", AdditionalPropertiesPatchTest.METADATA) self.discovery_container = DiscoveryContainer()
def test_entity_sees_inherited_properties(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="A"> <EntityType Name="Resource" Abstract="false"> <Property Name="GrandpaProperty" Type="Resource.Description"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/> </Property> </EntityType> </Schema> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="B"> <EntityType Name="Resource" BaseType="A.Resource" Abstract="false"> <Property Name="DaddyProperty" Type="Resource.Id" Nullable="false"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/> </Property> </EntityType> </Schema> <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="C"> <EntityType Name="Resource" BaseType="B.Resource" Abstract="false"> <Property Name="KidProperty" Type="Resource.Id" Nullable="false"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/> </Property> </EntityType> </Schema> """ metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings(metadata) resource_definition = metadata_container.entities['C.Resource'] properties = resource_definition.properties self.assertIn('KidProperty', properties) self.assertIn('DaddyProperty', properties) self.assertIn('GrandpaProperty', properties)
def test_discovery_from_nested_additional_properties(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> <Property Name="Oem" Type="N.Oem"> </Property> </EntityType> <ComplexType Name="Oem" Abstract="false"> <Annotation Term="OData.AdditionalProperties" Bool="true"/> </ComplexType> <ComplexType Name="Inner" Abstract="false"> <NavigationProperty Name="Link" Type="N.Referenced" ContainsTarget="true"> </NavigationProperty> </ComplexType> <EntityType Name="Referenced" Abstract="false"> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "#N.Outer", "Oem": { "additional_property": { "@odata.type": "#N.Inner", "Link": { "@odata.id": "/this/is/the/link/to/be/discovered" }, } } } referenced = \ { "@odata.id": "referenced.id", "@odata.type": "#N.Referenced", } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings("Unknown", metadata) discovery_container = DiscoveryContainer() configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch( 'cts_core.discovery.api_explorer.ApiExplorer._get_resource') as get_resource: get_resource.side_effect = [(Link('link', 'netloc'), RequestStatus.SUCCESS, resource, None), (Link('link', 'netloc'), RequestStatus.SUCCESS, referenced, None)] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(2, get_resource.call_count) self.assertNotIn("ERROR::", '\n'.join(output))
def load(self): MetadataManager.SERVICE_TO_DIR = { "dummy": "example_metadata" } metadata_manager = MetadataManager([]) metadata_manager._metadata_home = Mock(return_value=os.path.dirname(os.path.realpath(__file__))) metadata_manager.read_metadata_for_services("dummy") return metadata_manager.metadata_container
def setUp(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/v1/Fabrics/1/Endpoints/8", 'netloc', RESOURCE, "#Endpoint.v1_0_0.Endpoint"))
def test_handle_collection_with_typeless_elements_referenced_by_json_pointer( self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <NavigationProperty Name="MyCollection" Type="Collection(ReferencedEntity)" ContainsTarget="true"> <Annotation Term="OData.Permissions" EnumMember="OData.Permission/Read"/> </NavigationProperty> </EntityType> <EntityType Name="ReferencedEntity" Abstract="false"> <Property Name="name" Type="Edm.String"/> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "N.Outer", "MyCollection": [ { # implicit odata.type = ReferencedEntity "@odata.id": "/outer#MyCollection/0", "name": "MyName 0" }, { # implicit odata_type = ReferencedEntity "@odata.id": "/outer#MyCollection/1", "name": "MyName 1" } ] } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings( metadata) discovery_container = DiscoveryContainer() configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch('cts_core.commons.api_caller.ApiCaller.get_resource' ) as get_resource: get_resource.side_effect = [(Link('link', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, None), (Link('link', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, None), (Link('link', 'netloc'), RequestStatus.SUCCESS, ReturnCodes.OK, resource, None)] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(3, get_resource.call_count) self.assertEqual(0, len(re.findall('ERROR::', ';'.join(output))))
def run(self): metadata_manager = MetadataManager(self.configuration) metadata_manager.load_files() metadata_container = metadata_manager.load_metadata_properties() api_explorer = ApiExplorer("/redfish/v1/", "ServiceRoot.ServiceRoot", metadata_container, self.configuration) discovery_container = api_explorer.process_with_resource(DiscoveryContainer()) discovery_container.keys() status = MetadataPatchValidator(metadata_container, self.configuration).validate(discovery_container) self.set_status(status)
def load(self, metadata_ref, qualifiers): if os.path.isfile(metadata_ref): metadata_manager = MetadataManager(qualifiers) configuration = get_configuration_from_file(metadata_ref) if configuration is None: return None if metadata_manager.download_metadata( Configuration(**configuration)): return metadata_manager.metadata_container return None
def load(self, metadata_ref, qualifiers): try: metadata_ref = self._autocomplete_name(metadata_ref) except KeyError: pass metadata_manager = MetadataManager(qualifiers) if metadata_manager.read_metadata_for_services(metadata_ref): return metadata_manager.metadata_container return None
def setUp(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( METADATA) self.discovery_container = DiscoveryContainer( metadata_container=self.metadata_container) self.validator = HierarchyValidator(self.discovery_container, self.metadata_container, MetadataConstants2_1) self.builder = ResourceBuilder(self.discovery_container)
def test_iter_all(self): metadata_manager = MetadataManager(["qualifier"]) discovery_container = DiscoveryContainer( metadata_container=metadata_manager.read_metadata_from_strings( "Unknown", self.TEST_METADATA)) chassis1_2 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Rack1", "@odata.type": "#Chassis.v1_2_0.Chassis", "ChassisType": "Rack", } discovery_container.add_resource( ApiResource("/redfish/v1/Chassis/Rack1", 'netloc', chassis1_2, "Chassis.v1_2_0.Chassis")) self.assertEqual( 1, len(list(discovery_container.iter_all("Chassis.v1_2_0.Chassis")))) self.assertEqual( 1, len(list(discovery_container.iter_all("Chassis.v1_0_0.Chassis")))) self.assertEqual( 1, len(list(discovery_container.iter_all("Chassis.Chassis")))) self.assertEqual( 1, len(list( discovery_container.iter_all("Resource.v1_0_0.Resource")))) self.assertEqual( 1, len(list(discovery_container.iter_all("Resource.Resource")))) chassis1_0 = { "@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity", "@odata.id": "/redfish/v1/Chassis/Module1", "@odata.type": "#Chassis.v1_0_0.Chassis", "ChassisType": "Module", } discovery_container.add_resource( ApiResource("/redfish/v1/Chassis/Module1", 'netloc', chassis1_0, "Chassis.v1_0_0.Chassis")) self.assertEqual( 1, len(list(discovery_container.iter_all("Chassis.v1_2_0.Chassis")))) self.assertEqual( 2, len(list(discovery_container.iter_all("Chassis.v1_0_0.Chassis")))) self.assertEqual( 2, len(list(discovery_container.iter_all("Chassis.Chassis")))) self.assertEqual( 2, len(list( discovery_container.iter_all("Resource.v1_0_0.Resource")))) self.assertEqual( 2, len(list(discovery_container.iter_all("Resource.Resource"))))
def setUp(self): self.discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings(METADATA) HardwareCheckList.MetadataConstants = MetadataConstants2_2 self.checklist = HardwareCheckList(dict()) #monkey patch self.checklist._load_metadata = lambda : self.metadata_container
def test_should_pass_if_entity_type_declared_on_ignore_list(self): metadata_manager = MetadataManager(["qualifier"], ignore_types=["N.R"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_pass_with_correct_resource(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_CORRECT, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_not_patch_if_property_annotation_is_non_trivial_and_alternative_implementation_not_known( self): """ when additional property of type 'ComplexType' does have annotation Term Nontriavial should not be patched """ metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings( AdditionalPropertiesPatchTest.METADATA) entity_json = { "@odata.type": "MyNamespace.v1_0_0.MyEntity", "Outer": { "@odata.type": "MyNamespace.v1_0_0.OuterComplexType", "Name": "OuterName", "InnerToValidate": { "@odata.type": "MyNamespace.v1_0_0.InnerComplexType", "Name": "This name property is required" } } } self.discovery_container.add_resource( ApiResource("/redfish/v1/Managers/RMC", "netloc", entity_json, "#MyNamespace.v1_0_0.MyEntity")) with mock.patch('cts_core.commons.api_caller.ApiCaller.__init__' ) as api_caller_init_mock: api_caller_init_mock.return_value = None validator = MetadataPatchValidator(metadata_container, None, PatchingStrategy2_2()) # this ValidationStatus.BLOCKED should be not affect final ValidationStatus validator._verify_property = MagicMock( return_value=(ValidationStatus.BLOCKED, None)) validator._restore_property = MagicMock( return_value=ValidationStatus.BLOCKED) validator._patch_property = MagicMock( return_value=(True, True, ValidationStatus.BLOCKED)) with StdoutCapture() as out: self.assertEqual(ValidationStatus.PASSED_WITH_WARNINGS, validator.validate(self.discovery_container)) self.assertIn('WARNING::Skipping non-trivial property Name;', out.raw)
def test_discovery_error_if_unexpected_additional_properties(self): """ Entity type used in this test does not accept additional properties. As a result, ApiExplorer is expected to raise an error about unexpected 'additional_property' property. ApiExplorer validate """ metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <Property Name="@odata.id" Type="Edm.String"/> <Property Name="@odata.type" Type="Edm.String"/> <Property Name="expected" Type="Edm.Int64"/> <Annotation Term="OData.AdditionalProperties" Bool="false"/> </EntityType> </Schema> """ resource = \ { "@odata.id": "id", "@odata.type": "N.Outer", "expected": 10, "additional_property": 1 } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", metadata) discovery_container = DiscoveryContainer() configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch( 'cts_core.discovery.api_explorer.ApiExplorer._get_resource' ) as get_resource: get_resource.side_effect = [ (Link('link', 'netloc'), RequestStatus.SUCCESS, resource, None) ] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(1, get_resource.call_count) self.assertIn("unexpected properties: [additional_property]", '\n'.join(output))
def _load_metadata(self): qualifiers, services = self.get_services_and_qualifiers() metadata_manager = MetadataManager(qualifiers, ignore_types=self.ignore_types, map_types=self.map_types) if self.configuration.MetadataDirectory: cts_warning("CTS is configured to use custom metadata from: {dir}", dir=self.configuration.MetadataDirectory) metadata_container = self._load_custom_metadata( metadata_manager, self.configuration.MetadataDirectory) else: metadata_container = self._load_built_in_metadata( metadata_manager, services) if metadata_container is not None: metadata_container.print_types() return metadata_container
def run(self): metadata_manager = MetadataManager(self.configuration) metadata_manager.load_files() metadata_container = metadata_manager.load_metadata_properties() api_explorer = ApiExplorer("/redfish/v1/", "ServiceRoot.ServiceRoot", metadata_container, self.configuration) discovery_container = api_explorer.process_with_resource( DiscoveryContainer()) status = MetadataGetValidator(metadata_container).validate( discovery_container) if status: self.set_status_passed() else: self.set_status_failed()
def test_follow_references_when_loading_remote_matadata(self): configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) manager = MetadataManager([]) with StdoutCapture() as output: with patch("cts_core.commons.api_caller.ApiCaller.get_xml" ) as get_xml: get_xml.side_effect = [ (None, RequestStatus.SUCCESS, 200, METADATA_ROOT, None), (None, RequestStatus.SUCCESS, 200, METADATA_ROOT, None) ] manager.download_metadata(configuration) arguments = [arg[0][0] for arg in get_xml.call_args_list] self.assertGreater( len([a for a in arguments if "Org.OData.Core.V1.xml" in a]), 0) self.assertEqual(-1, output.raw.find("ERROR::"))
def test_should_fail_bacause_of_unknown_complex_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn('Reference to unknown type unknown.complex.type', '\n'.join(output))
def test_should_pass_when_unknown_entity_type_mapped_to_known_one(self): metadata_manager = MetadataManager(["qualifier"], map_types={ "A": "B", "unknown.entity.type": "N.R" }) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))
def test_should_fail_bacause_of_unknown_entity_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_ENTITY_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn("ERROR::Unknown entity type 'unknown.entity.type'", output.raw)
def test_property_invalid_collection(self): METADATA = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="MyNamespace.v1_0_0"> <EntityType Name="MyEntity"> <Property name="property_name" type="Collection(MyComplexType)"> </Property> </EntityType> <ComplexType Name="MyComplexType"> <Property Name="Name" Nullable="false" Type="Edm.String"/> </ComplexType> </Schema> """ discovery_container = DiscoveryContainer() metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) EntityJson = { "@odata.type": "MyNamespace.v1_0_0.MyEntity", "property_name": { 'a': { 'x': 1 }, 'b': { 'y': 2 } } } entity_type = EntityJson["@odata.type"] with StdoutCapture() as output: self.assertEqual( ValidationStatus.FAILED, metadata_container.entities[entity_type].validate( EntityJson, '')) self.assertIn( 'ERROR::Property ->property_name is expected to be collection, but it is not' '', output.raw)
def test_should_validate_dynamic_properties_at_entity_level(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INCOMPLETE_DYNAMIC_PROPERTY, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn( 'ERROR::Required property resource.id->aaaaaaaa->Obligatory not present in the resource', '\n'.join(output))
def test_should_fail_if_property_of_incorrect_type(self): metadata_manager = MetadataManager(["qualifier"]) self.metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_INVALID_PROPERTY_VALUE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) with StdoutCapture() as output: self.assertEqual(ValidationStatus.FAILED, validator.validate(self.discovery_container)) self.assertIn( 'Property resource.id->ObjectWithNumber is expected to be json object', '\n'.join(output))
def test_discovery_can_handle_null_navigation_property(self): metadata = """ <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="N"> <EntityType Name="Outer" Abstract="false"> <NavigationProperty Name="Link" Type="N.Referenced" ContainsTarget="true"> </NavigationProperty> </EntityType> <EntityType Name="Referenced" Abstract="false"> </EntityType> </Schema> """ resource = \ { "@odata.id": "resource.id", "@odata.type": "#N.Outer", "Link": { "@odata.id": None }, } metadata_manager = MetadataManager(["qualifier"]) metadata_container = metadata_manager.read_metadata_from_strings( "Unknown", metadata) discovery_container = DiscoveryContainer() configuration = Configuration( **dict(UseSSL='True', ApiEndpoint=API_ENDPOINT)) api_explorer = ApiExplorer(metadata_container, configuration) with mock.patch( 'cts_core.discovery.api_explorer.ApiExplorer._get_resource' ) as get_resource: get_resource.side_effect = [ (Link('link', 'netloc'), RequestStatus.SUCCESS, resource, None) ] with StdoutCapture() as output: api_explorer.discover("/outer", "N.Outer", discovery_container) self.assertEqual(1, get_resource.call_count) self.assertNotIn("ERROR::", '\n'.join(output))
def test_follow_references_when_loading_local_matadata(self): MetadataManager.SERVICE_TO_DIR = {"SERVICE_A": "a"} os.path.isdir = MagicMock(return_value=True) manager = MetadataManager([]) with StdoutCapture() as output: with patch("__builtin__.open", mock_open(read_data=METADATA_ROOT)) as mock_file: with patch("cts_framework.commons.digest.DirDigest.__init__" ) as init: init.return_value = None with patch( "cts_framework.commons.digest.DirDigest.is_valid" ) as is_valid: is_valid.return_value = True manager.read_metadata_for_services("SERVICE_A") arguments = [arg[0][0] for arg in mock_file.call_args_list] self.assertGreater( len([a for a in arguments if "Org.OData.Core.V1.xml" in a]), 0)
def test_should_pass_when_unknown_complex_type_mapped_on_known_type(self): metadata_manager = MetadataManager(["qualifier"], map_types={ "A": "B", "unknown.complex.type": "N.ObjectWithNumericProperty" }) self.metadata_container = metadata_manager.read_metadata_from_strings( METADATA) self.discovery_container = DiscoveryContainer() self.discovery_container.add_resource( ApiResource("/redfish/resource1", 'netloc', RESOURCE_WITH_UNKNOWN_COMPLEX_TYPE, "#N.R")) requirements = [] validator = MetadataGetValidator(self.metadata_container, requirements) self.assertEqual(ValidationStatus.PASSED, validator.validate(self.discovery_container))