Source code for idem_aws.states.aws.iam.instance_profile

"""
Autogenerated using `pop-create-idem <https://gitlab.com/saltstack/pop/pop-create-idem>`__

hub.exec.boto3.client.iam.create_instance_profile
hub.exec.boto3.client.iam.delete_instance_profile
hub.exec.boto3.client.iam.get_instance_profile
hub.exec.boto3.client.iam.list_instance_profiles
hub.exec.boto3.client.iam.tag_instance_profile
hub.exec.boto3.client.iam.untag_instance_profile
resource = await hub.tool.boto3.resource.create(ctx, "iam", "InstanceProfile", name)
hub.tool.boto3.resource.exec(resource, add_role, *args, **kwargs)
hub.tool.boto3.resource.exec(resource, delete, *args, **kwargs)
hub.tool.boto3.resource.exec(resource, remove_role, *args, **kwargs)
"""
import copy
from dataclasses import field
from dataclasses import make_dataclass
from typing import Any
from typing import Dict
from typing import List

__contracts__ = ["resource"]


TREQ = {
    "absent": {
        "require": [
            "aws.iam.role.absent",
        ],
    },
}


[docs]async def present( hub, ctx, name: str, resource_id: str = None, path: str = None, roles: List = None, tags: Dict[str, Any] or List[ make_dataclass( "Tag", [("Key", str, field(default=None)), ("Value", str, field(default=None))], ) ] = None, ) -> Dict[str, Any]: """ **Autogenerated function** Creates a new instance profile. For information about instance profiles, see Using roles for applications on Amazon EC2 in the IAM User Guide, and Instance profiles in the Amazon EC2 User Guide. For information about the number of instance profiles you can create, see IAM object quotas in the IAM User Guide. Tags can be set on a newly created instance profile, or updated on an existing one. Roles are set and updated as a day-2 operation. Args: name(str): AWS Instance Profile Name. resource_id(str, Optional): AWS Instance Profile Name. path(str, Optional): The path to the instance profile. roles(str, Optional): A list with up to one role name. Instance profile can be associated with a single role. tags(Dict or List, Optional): Dict in the format of {tag-key: tag-value} or List of tags in the format of [{"Key": tag-key, "Value": tag-value}] to associate with the IAM instance profile. Each tag consists of a key name and an associated value. Defaults to None. * (Key): The key name that can be used to look up or retrieve the associated value. For example, Department or Cost Center are common choices. * (Value): The value associated with this tag. For example, tags with a key name of Department could have values such as Human Resources, Accounting, and Support. Tags with a key name of Cost Center might have values that consist of the number associated with the different cost centers in your company. Typically, many resources have tags with the same key name but with different values. Amazon Web Services always interprets the tag Value as a single string. If you need to store an array, you can store comma-separated values in the string. However, you must interpret the value in your code. Returns: Dict[str, Any] Request Syntax: [iam-instance-profile-name]: aws.iam.instance_profile.present: - name: 'string' - resource_id: 'string' - path: 'string' - roles: - RoleName: 'string' - Tags: - Key: 'string' Value: 'string' Example: .. code-block:: sls inst-profile-1: aws.iam.instance_profile.present: - name: inst-profile-1 - path: /aws-service-inst-profile/ - roles: - RoleName: role-1 - Tags: - Key: test-1 Value: test-1-val """ result = dict(comment=[], old_state=None, new_state=None, name=name, result=True) before = await hub.exec.aws.iam.instance_profile.get( ctx, name=name, resource_id=resource_id ) if not before["result"]: result["result"] = False result["comment"] = before["comment"] return result if isinstance(tags, List): tags = hub.tool.aws.tag_utils.convert_tag_list_to_dict(tags) if before["ret"]: result["old_state"] = before["ret"] result["new_state"] = copy.deepcopy(before["ret"]) result["comment"] += [f"'{name}' already exists"] # Update key tags if tags are specified if tags is not None and tags != result["old_state"].get("tags", None): hub.log.debug(f"aws.iam.instance_profile '{name}' tags update") update_ret = ( await hub.exec.aws.iam.instance_profile.update_instance_profile_tags( ctx=ctx, instance_profile_name=resource_id if resource_id else name, old_tags=result["old_state"].get("tags"), new_tags=tags, ) ) result["result"] = update_ret["result"] result["comment"] += update_ret["comment"] if not result["result"]: return result if ctx.get("test", False) and update_ret["ret"] is not None: result["new_state"]["tags"] = update_ret["ret"] else: if ctx.get("test", False): result["new_state"] = hub.tool.aws.test_state_utils.generate_test_state( enforced_state={}, desired_state={ "name": name, "path": path, "roles": roles, "tags": tags, }, ) result["comment"] = hub.tool.aws.comment_utils.would_create_comment( resource_type="aws.iam.instance_profile", name=name ) return result try: ret = await hub.exec.boto3.client.iam.create_instance_profile( ctx, InstanceProfileName=name, Path=path, Tags=hub.tool.aws.tag_utils.convert_tag_dict_to_list(tags) if tags else None, ) result["result"] = ret["result"] if not ret["result"]: result["comment"] = ret["comment"] return result result["comment"] = hub.tool.aws.comment_utils.create_comment( resource_type="aws.iam.instance_profile", name=name ) except hub.tool.boto3.exception.ClientError as e: result["comment"] += [f"{e.__class__.__name__}: {e}"] result["result"] = False update_ret = None if roles is not None: # Instance profile can be associated only with a single role # Remove existing role curr_role = None new_role = None if before["ret"] and before["ret"].get("roles", []): curr_role = before["ret"].get("roles")[0]["RoleName"] if roles: new_role = roles[0]["RoleName"] if curr_role != new_role: if curr_role is not None and not ctx.get("test", False): hub.log.debug( f"Removing role '{curr_role}' from instance profile '{name}'" ) update_ret = ( await hub.exec.boto3.client.iam.remove_role_from_instance_profile( ctx, InstanceProfileName=name, RoleName=curr_role ) ) if not update_ret["result"]: result["result"] = False result["comment"] = update_ret["comment"] return result result["comment"] += [ f"Role '{curr_role}' was removed from instance profile '{name}'" ] if new_role is not None and not ctx.get("test", False): hub.log.debug(f"Adding role '{new_role}' to instance profile '{name}'") update_ret = ( await hub.exec.boto3.client.iam.add_role_to_instance_profile( ctx, InstanceProfileName=name, RoleName=new_role ) ) if not update_ret["result"]: result["result"] = False result["comment"] = update_ret["comment"] return result result["comment"] += [ f"Role '{new_role}' was added to instance profile '{name}'" ] # Test context when updating roles if ctx.get("test", False): result["comment"] += [f"Updated role in instance profile '{name}'."] result["new_state"]["roles"] = ( [{"RoleName": new_role}] if new_role is not None else [] ) return result if ctx.get("test", False): return result if before["ret"] and update_ret is None: result["new_state"] = copy.deepcopy(result["old_state"]) else: after = await hub.exec.aws.iam.instance_profile.get( ctx, name=name, resource_id=resource_id ) if not after["result"]: result["result"] = False result["comment"] = after["comment"] return result result["new_state"] = after["ret"] return result
[docs]async def absent(hub, ctx, name: str, resource_id: str = None) -> Dict[str, Any]: """ **Autogenerated function** Deletes the specified instance profile. The instance profile must not have an associated role. Make sure that you do not have any Amazon EC2 instances running with the instance profile you are about to delete. Deleting a role or instance profile that is associated with a running instance will break any applications running on the instance. For more information about instance profiles, see About instance profiles. Args: name(str): AWS Instance Profile Name. resource_id(str, Optional): AWS Instance Profile Name. If not specified, Idem will use "name" parameter to identify the role policy on AWS. Returns: Dict[str, Any] Request Syntax: [iam-instance-profile-name]: aws.iam.instance_profile.present: - name: 'string' Examples: .. code-block:: sls instance-profile-test: aws.iam.instance_profile.absent: - name: instance-profile-test """ result = dict(comment=[], old_state=None, new_state=None, name=name, result=True) if not resource_id: result["comment"] = hub.tool.aws.comment_utils.already_absent_comment( resource_type="aws.iam.instance_profile", name=name ) return result before = await hub.exec.aws.iam.instance_profile.get( ctx, name=name, resource_id=resource_id ) if not before["result"]: result["comment"] = before["comment"] result["result"] = False return result if not before["ret"]: result["comment"] = hub.tool.aws.comment_utils.already_absent_comment( resource_type="aws.iam.instance_profile", name=name ) return result else: try: result["old_state"] = before["ret"] if ctx.get("test", False): result["comment"] = hub.tool.aws.comment_utils.would_delete_comment( resource_type="aws.iam.instance_profile", name=name ) return result ret = await hub.exec.boto3.client.iam.delete_instance_profile( ctx, InstanceProfileName=name, ) if not ret["result"]: result["comment"] = ret["comment"] result["result"] = False return result result["comment"] = hub.tool.aws.comment_utils.delete_comment( resource_type="aws.iam.instance_profile", name=name ) except hub.tool.boto3.exception.ClientError as e: result["comment"] += [f"{e.__class__.__name__}: {e}"] return result
[docs]async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]: """ **Autogenerated function** Describe the resource in a way that can be recreated/managed with the corresponding "present" function Lists the instance profiles that have the specified path prefix. If there are none, the operation returns an empty list. For more information about instance profiles, see About instance profiles. IAM resource-listing operations return a subset of the available attributes for the resource. For example, this operation does not return tags, even though they are an attribute of the returned object. To view all of the information for an instance profile, see GetInstanceProfile. You can paginate the results using the MaxItems and Marker parameters. Returns: Dict[str, Any] Examples: .. code-block:: bash $ idem describe aws.iam.instance_profile """ result = {} ret = await hub.exec.boto3.client.iam.list_instance_profiles(ctx) if not ret["result"]: hub.log.warning(f"Could not describe aws.iam.instance_profile {ret['comment']}") return {} for instance_profile in ret["ret"]["InstanceProfiles"]: # This is required to get tags for each instance profile list_instance_profile_roles is not working resource = await hub.exec.aws.iam.instance_profile.get( ctx, name=instance_profile["InstanceProfileName"], resource_id=instance_profile["InstanceProfileName"], ) if not resource["result"]: hub.log.info( f"Failed to retrieve aws.iam.instance_profile {instance_profile['InstanceProfileName']}: {resource['comment']}" ) continue resource_key = f"iam-instance-profile-{resource['ret']['name']}" result[resource_key] = { "aws.iam.instance_profile.present": [ {parameter_key: parameter_value} for parameter_key, parameter_value in resource["ret"].items() ] } return result