def test_no_filters_relation(self):
        digest = ResourceDigest(id="1", type="type")
        edge = ResourceEdge(from_node=digest, to_node=digest)
        relations = filter_relations(
            [
                Resource(
                    digest=digest,
                    name="name",
                    tags=[ResourceTag(key="key", value="value")],
                )
            ],
            [edge],
        )

        assert_that(relations).is_length(1).contains(edge)
    def run(
        self,
        provider: str,
        options: BaseAwsOptions,
        diagram_builder: BaseDiagram,
        title: str,
        filename: str,
    ):
        """
        Executes a command.

        The project's development pattern is a file with the respective name of the parent
        resource (e.g. compute, network), classes of child resources inside this file and run() method to execute
        respective check. So it makes sense to load dynamically.
        """
        # Iterate to get all modules
        message_handler("\nInspecting resources", "HEADER")
        providers = []
        for name in os.listdir(
            dirname(__file__) + "/../provider/" + provider + "/resource"
        ):
            if name.endswith(".py"):
                # strip the extension
                module = name[:-3]

                # Load and call all run check
                for nameclass, cls in inspect.getmembers(
                    importlib.import_module(
                        "provider." + provider + ".resource." + module
                    ),
                    inspect.isclass,
                ):
                    if (
                        issubclass(cls, ResourceProvider)
                        and cls is not ResourceProvider
                    ):
                        providers.append((nameclass, cls))
        providers.sort(key=lambda x: x[0])

        all_resources: List[Resource] = []
        resource_relations: List[ResourceEdge] = []

        with ThreadPoolExecutor(15) as executor:
            provider_results = executor.map(
                lambda data: execute_provider(options, data), providers
            )

        for provider_results in provider_results:
            if provider_results[0] is not None:
                all_resources.extend(provider_results[0])
            if provider_results[1] is not None:
                resource_relations.extend(provider_results[1])

        unique_resources_dict: Dict[ResourceDigest, Resource] = dict()
        for resource in all_resources:
            unique_resources_dict[resource.digest] = resource

        unique_resources = list(unique_resources_dict.values())

        unique_resources.sort(key=lambda x: x.group + x.digest.type + x.name)
        resource_relations.sort(
            key=lambda x: x.from_node.type
            + x.from_node.id
            + x.to_node.type
            + x.to_node.id
        )

        # Resource filtering and sorting
        filtered_resources = filter_resources(unique_resources, self.filters)
        filtered_resources.sort(key=lambda x: x.group + x.digest.type + x.name)

        # Relationships filtering and sorting
        filtered_relations = filter_relations(filtered_resources, resource_relations)
        filtered_relations.sort(
            key=lambda x: x.from_node.type
            + x.from_node.id
            + x.to_node.type
            + x.to_node.id
        )

        # Diagram integration
        diagram_builder.build(
            resources=filtered_resources,
            resource_relations=filtered_relations,
            title=title,
            filename=filename,
        )

        # TODO: Generate reports in json/csv/pdf/xls
        report = Report()
        report.general_report(
            resources=filtered_resources, resource_relations=filtered_relations
        ),
        report.html_report(
            resources=filtered_resources,
            resource_relations=filtered_relations,
            title=title,
            filename=filename,
        )
    def test_no_filtered_relation(self):
        digest = ResourceDigest(id="1", type="type")
        relations = filter_relations(
            [], [ResourceEdge(from_node=digest, to_node=digest)])

        assert_that(relations).is_length(0)