Repository: Netflix/consoleme
File: default_plugins/consoleme_default_plugins/plugins/aws/aws.py (Python)

Code before:

            # If not in Redis or it's older than an hour, proceed to DynamoDB:
            result = await sync_to_async(self.dynamo.fetch_iam_role)(
                role_arn, account_id
            )

        # If it's NOT in dynamo, or if we're forcing a refresh, we need to reach out to AWS and fetch:
        if force_refresh or not result.get("Item"):
            if force_refresh:
                log_data["message"] = "Force refresh is enabled. Going out to AWS."
                stats.count(
                    "aws.fetch_iam_role.force_refresh",
                    tags={"account_id": account_id, "role_arn": role_arn},
                )
            else:
                log_data["message"] = "Role is missing in DDB. Going out to AWS."
                stats.count(
                    "aws.fetch_iam_role.missing_dynamo",
                    tags={"account_id": account_id, "role_arn": role_arn},
                )
            log.debug(log_data)
            try:
                tasks = []
                role_name = role_arn.split("/")[-1]
                # Instantiate a cached CloudAux client
                if run_sync:
                    client = boto3_cached_conn(
                        "iam",
                        account_number=account_id,
                        assume_role=config.get("policies.role_name"),
                        read_only=True,
                        retry_max_attempts=2,
                    )
                else:
                    client = await sync_to_async(boto3_cached_conn)(
                        "iam",
                        account_number=account_id,
                        assume_role=config.get("policies.role_name"),
                        read_only=True,
                        retry_max_attempts=2,
                    )
                conn = {
                    "account_number": account_id,
                    "assume_role": config.get("policies.role_name"),
                    "region": config.region,
                }
                if run_sync:
                    role = client.get_role(RoleName=role_name)["Role"]
                    role["ManagedPolicies"] = get_role_managed_policies(
                        {"RoleName": role_name}, **conn
                    )

Review comment (suggestion):
This would be easier to follow if you split the sync and async flows out into separate functions that are called from this one, e.g.:

```python
if run_sync:
    role = _get_role_sync(account_id, role_name, ...)
else:
    role = await _get_role_async(blah...)
```

Code after:
        ]

        for t in all_tasks:
            tasks.append(
                asyncio.ensure_future(sync_to_async(t)({"RoleName": role_name}, **conn))
            )

        responses = asyncio.gather(*tasks)
        async_task_result = await responses
        role = async_task_result[0]["Role"]
        role["ManagedPolicies"] = async_task_result[1]
        role["InlinePolicies"] = async_task_result[2]
        role["Tags"] = async_task_result[3]
        return role

    async def fetch_iam_role(
        self,
        account_id: str,
        role_arn: str,
        force_refresh: bool = False,
        run_sync=False,
    ) -> Optional[Dict[str, Any]]:
        """Fetch the IAM Role template from Redis and/or Dynamo.

        :param account_id:
        :param role_arn:
        :return:
        """
        log_data: dict = {
            "function": f"{__name__}.{self.__class__.__name__}.{sys._getframe().f_code.co_name}",
            "role_arn": role_arn,
            "account_id": account_id,
            "force_refresh": force_refresh,
        }

        result: dict = {}

        if not force_refresh:
            # First check redis:
            result: str = await sync_to_async(self._fetch_role_from_redis)(role_arn)

            if result:
                result: dict = json.loads(result)

                # If this item is less than an hour old, then return it from Redis.
                if result["ttl"] > int(
                    (datetime.utcnow() - timedelta(hours=1)).timestamp()
                ):
                    log_data["message"] = "Role not in Redis -- fetching from DDB."
                    log.debug(log_data)
                    stats.count(