File: __init__.py

package info (click to toggle)
python-moto 5.1.18-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 116,520 kB
  • sloc: python: 636,725; javascript: 181; makefile: 39; sh: 3
file content (125 lines) | stat: -rw-r--r-- 4,137 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import json
import os
from functools import wraps
from time import sleep
from uuid import uuid4

import boto3
from botocore.exceptions import ClientError

from moto import mock_aws


def lambda_aws_verified(func):
    """
    Function that is verified to work against AWS.
    Can be run against AWS at any time by setting:
      MOTO_TEST_ALLOW_AWS_REQUEST=true

    If this environment variable is not set, the function runs in a `mock_aws` context.

    This decorator will:
      - Create an IAM-role that can be used by AWSLambda functions table
      - Run the test
      - Delete the role
    """

    @wraps(func)
    def pagination_wrapper(**kwargs):
        role_name = "moto_test_role_" + str(uuid4())[0:6]

        allow_aws_request = (
            os.environ.get("MOTO_TEST_ALLOW_AWS_REQUEST", "false").lower() == "true"
        )

        if allow_aws_request:
            return create_role_and_test(kwargs, role_name)
        else:
            with mock_aws():
                return create_role_and_test(kwargs, role_name)

    def create_role_and_test(kwargs, role_name):
        from .test_lambda import _lambda_region

        policy_doc = {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "LambdaAssumeRole",
                    "Effect": "Allow",
                    "Principal": {"Service": "lambda.amazonaws.com"},
                    "Action": "sts:AssumeRole",
                }
            ],
        }
        iam = boto3.client("iam", region_name=_lambda_region)
        iam_role_arn = iam.create_role(
            RoleName=role_name,
            AssumeRolePolicyDocument=json.dumps(policy_doc),
            Path="/",
        )["Role"]["Arn"]

        try:
            # Role is not immediately available
            check_iam_role_is_ready_to_use(iam_role_arn, role_name, _lambda_region)

            kwargs["iam_role_arn"] = iam_role_arn
            resp = func(**kwargs)
        finally:
            for policy in iam.list_attached_role_policies(RoleName=role_name)[
                "AttachedPolicies"
            ]:
                iam.detach_role_policy(
                    RoleName=role_name,
                    PolicyArn=policy["PolicyArn"],
                )
            iam.delete_role(RoleName=role_name)

        return resp

    def check_iam_role_is_ready_to_use(role_arn: str, role_name: str, region: str):
        from .utilities import get_test_zip_file1

        iam = boto3.client("iam", region_name=region)

        # The waiter is normally used to wait until a resource is ready
        wait_for_role = iam.get_waiter("role_exists")
        wait_for_role.wait(RoleName=role_name)

        # HOWEVER:
        # Just because the role exists, doesn't mean it can be used by Lambda
        # The only reliable way to check if our role is ready:
        #   - try to create a function and see if it succeeds
        #
        # The alternive is to wait between 5 and 10 seconds, which is not a great solution either
        _lambda = boto3.client("lambda", region)
        for _ in range(15):
            try:
                fn_name = f"fn_for_{role_name}"
                _lambda.create_function(
                    FunctionName=fn_name,
                    Runtime="python3.11",
                    Role=role_arn,
                    Handler="lambda_function.lambda_handler",
                    Code={"ZipFile": get_test_zip_file1()},
                )
                # If it succeeded, our role is ready
                _lambda.delete_function(FunctionName=fn_name)

                return
            except ClientError:
                sleep(1)
        raise Exception(
            f"Couldn't create test Lambda FN using IAM role {role_name}, probably because it wasn't ready in time"
        )

    return pagination_wrapper


def delete_all_layer_versions(client, layer_name: str):
    versions = client.list_layer_versions(LayerName=layer_name)["LayerVersions"]
    for version in versions:
        client.delete_layer_version(
            LayerName=layer_name,
            VersionNumber=version["Version"],
        )