Source code for boto3_helpers.arn

from boto3 import client as boto3_client


class ARN:
    __slots__ = [
        'partition',
        'service',
        'region',
        'account_id',
        'resource_type',
        'resource_id',
        'resource_separator',
    ]

    def __init__(
        self, partition, service, region, account_id, *args, resource_separator='/'
    ):
        self.partition = partition
        self.service = service
        self.region = region
        self.account_id = account_id
        if len(args) == 1:
            self.resource_type = ''
            self.resource_id = args[0]
        elif len(args) == 2:
            self.resource_type = args[0]
            self.resource_id = args[1]
        else:
            raise ValueError('Invalid resource')
        self.resource_separator = resource_separator

    def __str__(self):
        if not self.resource_type:
            return (
                f'arn:{self.partition}:{self.service}:{self.region}:{self.account_id}:'
                f'{self.resource_id}'
            )
        else:
            return (
                f'arn:{self.partition}:{self.service}:{self.region}:{self.account_id}:'
                f'{self.resource_type}{self.resource_separator}{self.resource_id}'
            )

    @classmethod
    def from_existing(cls, existing):
        parts = existing.split(':')
        resource_separator = '/'
        if len(parts) == 6:
            if '/' in parts[5]:
                parts[5:] = parts[5].split('/', 1)
        elif len(parts) == 7:
            resource_separator = ':'

        return cls(*parts[1:], resource_separator=resource_separator)


[docs]def construct_arn(existing=None, *, sts_client=None, **kwargs): """Construct an ARN from an existing one. * *existing* is used as a template. If not provided, one will be derived from your IAM user or role. * *sts_client* is a ``boto3.client('sts')`` instance. If not given, is created with ``boto3.client('sts')``. This will only be used if *existing* is not supplied. * *kwargs* can include any of the following: ``partition``, ``service``, ``region``, ``account_id``, ``resource_type``, ``resource_separator``, ``resource_id``. Some ARNs end with ``resource_id``. You can construct these by supplying ``resource_type=''`` and ``resource_id='DesiredID'``. Other ARNs end with ``resource_type:resource_id``. You can construct these by supplying ``resource_type='DesiredType'``, ``resource_separator=':'``, and ``resource_id='DesiredID'`` Still other ARNs end with ``resource_type/resource_id``. You can construct these by supplying ``resource_type='DesiredType'``, ``resource_separator='/'``, and ``resource_id='DesiredID'`` Converting one format to another: .. code-block:: python from boto3_helpers.arn import construct_arn existing = 'arn:aws:dynamodb:us-east-2:00000000:table/demo' new = construct_arn( existing, service='lambda', resource_type='function', resource_separator=':', resource_id='example' ) print(new) # arn:aws:lambda:us-east-2:00000000:function:example Starting from your IAM user or role: .. code-block:: python from boto3_helpers.arn import construct_arn new = construct_arn( service='dynamodb', resource_type='table', resource_id='demo' ) print(new) # arn:aws:dynamodb:us-east-2:00000000:table/demo """ if existing is None: sts_client = sts_client or boto3_client('sts') existing = sts_client.get_caller_identity()['Arn'] kwargs.setdefault('region', sts_client.meta.region_name) obj = ARN.from_existing(existing) for k, v in kwargs.items(): setattr(obj, k, v) return str(obj)