# Path: repokid/datasource/plugin.py
# class DatasourcePlugin(RepokidPlugin, Generic[KT, VT]):
#     """A dict-like container that can be used to retrieve and store data"""
# 
#     _data: Dict[KT, VT]
#     _seeded: List[str]
# 
#     def __init__(self, config: Optional[RepokidConfig] = None):
#         super().__init__(config=config)
#         self._data = {}
#         self._seeded = []
# 
#     def __getitem__(self, name: KT) -> VT:
#         return self._data[name]
# 
#     def __iter__(self) -> Iterator[VT]:
#         return iter(cast(Iterable[VT], self._data))
# 
#     def keys(self) -> Iterable[KT]:
#         return self._data.keys()
# 
#     def items(self) -> ItemsView[KT, VT]:
#         return self._data.items()
# 
#     def values(self) -> ValuesView[VT]:
#         return self._data.values()
# 
#     def get(self, identifier: KT) -> VT:
#         raise NotImplementedError
# 
#     def seed(self, identifier: KT) -> Iterable[KT]:
#         raise NotImplementedError
# 
#     def reset(self) -> None:
#         logger.debug("resetting %s", type(self).__name__)
#         self._data = {}
#         self._seeded = []
# 
# Path: repokid/exceptions.py
# class NotFoundError(Exception):
#     pass
# 
# Path: repokid/plugin.py
# class Singleton(M_A):
#     _instances: Dict[str, Singleton] = {}
# 
#     def __call__(cls, *args: Any, **kwargs: Any) -> Singleton:
#         if cls.__name__ not in cls._instances:
#             cls._instances[cls.__name__] = super(Singleton, cls).__call__(
#                 *args, **kwargs
#             )
#         return cls._instances[cls.__name__]
# 
# Path: repokid/types.py
# KT = TypeVar("KT")
# VT = TypeVar("VT")
# 
# Path: repokid/types.py
# KT = TypeVar("KT")
# VT = TypeVar("VT")


import copy
import logging
from typing import Dict
from typing import Iterable
from typing import Optional
from cloudaux.aws.iam import get_account_authorization_details
from cloudaux.orchestration.aws.iam.role import FLAGS
from cloudaux.orchestration.aws.iam.role import get_role
from repokid.datasource.plugin import DatasourcePlugin
from repokid.exceptions import NotFoundError
from repokid.plugin import Singleton
from repokid.types import IAMEntry
from repokid.types import RepokidConfig
            raise NotFoundError
        self._data[arn] = role_info
        return role_info

    def get(self, arn: str) -> IAMEntry:
        result = self._data.get(arn)
        if not result:
            return self._fetch(arn)
        return result

    def get_id_for_arn(self, arn: str) -> Optional[str]:
        return self._arn_to_id.get(arn)

    def _get_ids_for_account(self, account_number: str) -> Iterable[str]:
        ids_for_account = [
            k for k, v in self.items() if v["Arn"].split(":")[4] == account_number
        ]
        return ids_for_account

    def seed(self, account_number: str) -> Iterable[str]:
        if account_number in self._seeded:
            return self._get_ids_for_account(account_number)
        fetched_data = self._fetch_account(account_number)
        new_keys = fetched_data.keys()
        self._data.update(fetched_data)
        self._seeded.append(account_number)
        return new_keys


# TODO: Implement retrieval of IAM data from AWS Config

# Path: repokid/datasource/plugin.py
# class DatasourcePlugin(RepokidPlugin, Generic[KT, VT]):
#     """A dict-like container that can be used to retrieve and store data"""
# 
#     _data: Dict[KT, VT]
#     _seeded: List[str]
# 
#     def __init__(self, config: Optional[RepokidConfig] = None):
#         super().__init__(config=config)
#         self._data = {}
#         self._seeded = []
# 
#     def __getitem__(self, name: KT) -> VT:
#         return self._data[name]
# 
#     def __iter__(self) -> Iterator[VT]:
#         return iter(cast(Iterable[VT], self._data))
# 
#     def keys(self) -> Iterable[KT]:
#         return self._data.keys()
# 
#     def items(self) -> ItemsView[KT, VT]:
#         return self._data.items()
# 
#     def values(self) -> ValuesView[VT]:
#         return self._data.values()
# 
#     def get(self, identifier: KT) -> VT:
#         raise NotImplementedError
# 
#     def seed(self, identifier: KT) -> Iterable[KT]:
#         raise NotImplementedError
# 
#     def reset(self) -> None:
#         logger.debug("resetting %s", type(self).__name__)
#         self._data = {}
#         self._seeded = []
# 
# Path: repokid/exceptions.py
# class NotFoundError(Exception):
#     pass
# 
# Path: repokid/plugin.py
# class Singleton(M_A):
#     _instances: Dict[str, Singleton] = {}
# 
#     def __call__(cls, *args: Any, **kwargs: Any) -> Singleton:
#         if cls.__name__ not in cls._instances:
#             cls._instances[cls.__name__] = super(Singleton, cls).__call__(
#                 *args, **kwargs
#             )
#         return cls._instances[cls.__name__]
# 
# Path: repokid/types.py
# KT = TypeVar("KT")
# VT = TypeVar("VT")
# 
# Path: repokid/types.py
# KT = TypeVar("KT")
# VT = TypeVar("VT")


# Path: repokid/datasource/iam.py
import copy
import logging
from typing import Dict
from typing import Iterable
from typing import Optional
from cloudaux.aws.iam import get_account_authorization_details
from cloudaux.orchestration.aws.iam.role import FLAGS
from cloudaux.orchestration.aws.iam.role import get_role
from repokid.datasource.plugin import DatasourcePlugin
from repokid.exceptions import NotFoundError
from repokid.plugin import Singleton
from repokid.types import IAMEntry
from repokid.types import RepokidConfig

            raise NotFoundError
        self._data[arn] = role_info
        return role_info

    def get(self, arn: str) -> IAMEntry:
        result = self._data.get(arn)
        if not result:
            return self._fetch(arn)
        return result

    def get_id_for_arn(self, arn: str) -> Optional[str]:
        return self._arn_to_id.get(arn)

    def _get_ids_for_account(self, account_number: str) -> Iterable[str]:
        ids_for_account = [
            k for k, v in self.items() if v["Arn"].split(":")[4] == account_number
        ]
        return ids_for_account

    def seed(self, account_number: str) -> Iterable[str]:
        if account_number in self._seeded:
            return self._get_ids_for_account(account_number)
        fetched_data = self._fetch_account(account_number)
        new_keys = fetched_data.keys()
        self._data.update(fetched_data)
        self._seeded.append(account_number)
        return new_keys


# TODO: Implement retrieval of IAM data from AWS Config

class ConfigDatasource(DatasourcePlugin[str, IAMEntry], metaclass=Singleton):