Repository: Netflix/consoleme
File: consoleme/lib/aws.py (Python)

Code before:
    for instance_profile in role.instance_profiles.all():
        instance_profile.load()
        log.info(
            {
                **log_data,
                "message": "Removing and deleting instance profile from role",
                "instance_profile": instance_profile.name,
            }
        )
        await sync_to_async(instance_profile.remove_role)(RoleName=role.name,)
        await sync_to_async(instance_profile.delete)()

    # Detach managed policies
    for policy in role.attached_policies.all():
        policy.load()
        log.info(
            {
                **log_data,
                "message": "Detaching managed policy from role",
                "policy_arn": policy.arn,
            }
        )
        await sync_to_async(policy.detach_role)(RoleName=role_name)

    # Delete Inline policies
    for policy in role.policies.all():
        policy.load()
        log.info(
            {
                **log_data,
                "message": "Deleting inline policy on role",
                "policy_name": policy.name,
            }
        )
        await sync_to_async(policy.delete)()

    log.info({**log_data, "message": "Performing role deletion"})
    await sync_to_async(role.delete)()
    stats.count(f"{log_data['function']}.success", tags={"role_name": role_name})


async def fetch_role_details(account_id, role_name):
    log_data = {
        "function": f"{__name__}.{sys._getframe().f_code.co_name}",
        "message": "Attempting to fetch role details",
        "account": account_id,
        "role": role_name,
    }
    log.info(log_data)
    iam_resource = await sync_to_async(boto3_cached_conn)(
        "iam",

Review comment (suggestion):
Are these making calls to AWS? Tornado is single-threaded so anything that blocks the thread will prevent the web server from handling other requests. If this call takes a significant amount of time, consider running it in its own thread and awaiting it:

`for policy in await sync_to_async(role.policies.all)():`

Code after:
    for instance_profile in await sync_to_async(role.instance_profiles.all)():
        await sync_to_async(instance_profile.load)()
        log.info(
            {
                **log_data,
                "message": "Removing and deleting instance profile from role",
                "instance_profile": instance_profile.name,
            }
        )
        await sync_to_async(instance_profile.remove_role)(RoleName=role.name,)
        await sync_to_async(instance_profile.delete)()

    # Detach managed policies
    for policy in await sync_to_async(role.attached_policies.all)():
        await sync_to_async(policy.load)()
        log.info(
            {
                **log_data,
                "message": "Detaching managed policy from role",
                "policy_arn": policy.arn,
            }
        )
        await sync_to_async(policy.detach_role)(RoleName=role_name)

    # Delete Inline policies
    for policy in await sync_to_async(role.policies.all)():
        await sync_to_async(policy.load)()
        log.info(
            {
                **log_data,
                "message": "Deleting inline policy on role",
                "policy_name": policy.name,
            }
        )
        await sync_to_async(policy.delete)()

    log.info({**log_data, "message": "Performing role deletion"})
    await sync_to_async(role.delete)()
    stats.count(f"{log_data['function']}.success", tags={"role_name": role_name})


async def fetch_role_details(account_id, role_name):
    log_data = {
        "function": f"{__name__}.{sys._getframe().f_code.co_name}",
        "message": "Attempting to fetch role details",
        "account": account_id,
        "role": role_name,
    }
    log.info(log_data)
    iam_resource = await sync_to_async(boto3_cached_conn)(
        "iam",