def test_multiregion_nested(region_name, statemachine_definition):
    client1 = aws_stack.create_external_boto_client("stepfunctions",
                                                    region_name=region_name)
    # create state machine
    child_machine_name = f"sf-child-{short_uid()}"
    role = aws_stack.role_arn("sfn_role")
    child_machine_result = client1.create_state_machine(
        name=child_machine_name,
        definition=json.dumps(TEST_STATE_MACHINE),
        roleArn=role)
    child_machine_arn = child_machine_result["stateMachineArn"]

    # create parent state machine
    name = f"sf-parent-{short_uid()}"
    role = aws_stack.role_arn("sfn_role")
    result = client1.create_state_machine(
        name=name,
        definition=json.dumps(statemachine_definition).replace(
            "__machine_arn__", child_machine_arn),
        roleArn=role,
    )
    machine_arn = result["stateMachineArn"]
    try:
        # list state machine
        result = client1.list_state_machines()["stateMachines"]
        assert len(result) > 0
        assert len([sm for sm in result if sm["name"] == name]) == 1
        assert len([sm for sm in result
                    if sm["name"] == child_machine_name]) == 1

        # start state machine execution
        result = client1.start_execution(stateMachineArn=machine_arn)

        execution = client1.describe_execution(
            executionArn=result["executionArn"])
        assert execution["stateMachineArn"] == machine_arn
        assert execution["status"] in ["RUNNING", "SUCCEEDED"]

        def assert_success():
            return (client1.describe_execution(
                executionArn=result["executionArn"])["status"] == "SUCCEEDED")

        wait_until(assert_success)

        result = client1.describe_state_machine_for_execution(
            executionArn=result["executionArn"])
        assert result["stateMachineArn"] == machine_arn

    finally:
        client1.delete_state_machine(stateMachineArn=machine_arn)
        client1.delete_state_machine(stateMachineArn=child_machine_arn)
Exemple #2
0
 def get_physical_resource_id(self, attribute=None, **kwargs):
     role_name = self.properties.get("RoleName")
     if not role_name:
         return role_name
     if attribute == "Arn":
         return aws_stack.role_arn(role_name)
     return role_name
    def test_try_catch_state_machine(self):
        state_machines_before = self.sfn_client.list_state_machines()["stateMachines"]

        # create state machine
        role_arn = aws_stack.role_arn("sfn_role")
        definition = clone(STATE_MACHINE_CATCH)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_1)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_2)
        definition["States"]["Start"]["Parameters"]["FunctionName"] = lambda_arn_1
        definition["States"]["ErrorHandler"]["Resource"] = lambda_arn_2
        definition["States"]["Final"]["Resource"] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = "catch-%s" % short_uid()
        result = self.sfn_client.create_state_machine(
            name=sm_name, definition=definition, roleArn=role_arn
        )

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn)
        self.assertTrue(result.get("executionArn"))

        def check_invocations():
            self.assertIn(lambda_arn_1, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            self.assertIn(lambda_arn_2, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            result = self._get_execution_results(sm_arn)
            self.assertEqual({"Hello": TEST_RESULT_VALUE}, result.get("handled"))

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
Exemple #4
0
 def __init__(self):
     # maps (API id) -> [authorizers]
     self.authorizers = {}
     # maps (API id) -> [validators]
     self.validators = {}
     # maps (API id) -> [documentation_parts]
     self.documentation_parts = {}
     # maps (API id) -> [gateway_responses]
     self.gateway_responses = {}
     # account details
     self.account = {
         "cloudwatchRoleArn": aws_stack.role_arn("api-gw-cw-role"),
         "throttleSettings": {
             "burstLimit": 1000,
             "rateLimit": 500
         },
         "features": ["UsagePlans"],
         "apiKeyVersion": "1",
     }
     # maps (domain_name) -> [path_mappings]
     self.base_path_mappings = {}
     # maps ID to VPC link details
     self.vpc_links = {}
     # maps cert ID to client certificate details
     self.client_certificates = {}
Exemple #5
0
 def __init__(self):
     # TODO: introduce a RestAPI class to encapsulate the variables below
     # maps (API id) -> [authorizers]
     self.authorizers: Dict[str, List[Dict]] = {}
     # maps (API id) -> [validators]
     self.validators: Dict[str, List[Dict]] = {}
     # maps (API id) -> [documentation_parts]
     self.documentation_parts: Dict[str, List[Dict]] = {}
     # maps (API id) -> [gateway_responses]
     self.gateway_responses: Dict[str, List[Dict]] = {}
     # account details
     self.account: Dict[str, Any] = {
         "cloudwatchRoleArn": aws_stack.role_arn("api-gw-cw-role"),
         "throttleSettings": {
             "burstLimit": 1000,
             "rateLimit": 500
         },
         "features": ["UsagePlans"],
         "apiKeyVersion": "1",
     }
     # maps (domain_name) -> [path_mappings]
     self.base_path_mappings: Dict[str, List[Dict]] = {}
     # maps ID to VPC link details
     self.vpc_links: Dict[str, Dict] = {}
     # maps cert ID to client certificate details
     self.client_certificates: Dict[str, Dict] = {}
def test_multiregion(region_name):
    other_region = "us-east-1" if region_name != "us-east-1" else "us-east-2"
    # TODO: create client factory fixture
    client1 = aws_stack.connect_to_service("stepfunctions",
                                           region_name=region_name)
    client2 = aws_stack.connect_to_service("stepfunctions",
                                           region_name=other_region)

    # create state machine
    name = "sf-%s" % short_uid()
    role = aws_stack.role_arn("sfn_role")
    result = client1.create_state_machine(
        name=name, definition=json.dumps(TEST_STATE_MACHINE), roleArn=role)
    machine_arn = result["stateMachineArn"]

    # list state machine
    result = client1.list_state_machines()["stateMachines"]
    result = [sm for sm in result if sm["name"] == name]
    assert len(result) > 0

    # start state machine execution
    result = client1.start_execution(stateMachineArn=machine_arn)
    assert f":{region_name}:" in result["executionArn"]
    assert f":{region_name}_" not in result["executionArn"]

    # assert state machine does not exist in other region
    result = client2.list_state_machines()["stateMachines"]
    result = [sm for sm in result if sm["name"] == name]
    assert len(result) == 0

    with pytest.raises(Exception):
        client1.start_execution(
            stateMachineArn=machine_arn.replace(region_name, other_region))
    def test_cfn_handle_events_rule_without_name(self):
        events = aws_stack.connect_to_service('events')

        rs = events.list_rules()
        rule_names = [rule['Name'] for rule in rs['Rules']]

        stack_name = 'stack-%s' % short_uid()
        _deploy_stack(stack_name=stack_name,
                      template_body=TEST_TEMPLATE_18 %
                      aws_stack.role_arn('sfn_role'))

        rs = events.list_rules()
        new_rules = [
            rule for rule in rs['Rules'] if rule['Name'] not in rule_names
        ]
        self.assertEqual(len(new_rules), 1)
        rule = new_rules[0]

        self.assertEqual(rule['ScheduleExpression'], 'cron(0/1 * * * ? *)')

        cfn = aws_stack.connect_to_service('cloudformation')
        cfn.delete_stack(StackName=stack_name)
        time.sleep(1)

        rs = events.list_rules()
        self.assertNotIn(rule['Name'], [r['Name'] for r in rs['Rules']])
Exemple #8
0
    def test_create_run_state_machine(self):
        state_machines_before = self.sfn_client.list_state_machines()['stateMachines']

        # create state machine
        role_arn = aws_stack.role_arn('sfn_role')
        definition = clone(STATE_MACHINE_BASIC)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_1)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_2)
        definition['States']['step1']['Resource'] = lambda_arn_1
        definition['States']['step2']['Resource'] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = 'basic-%s' % short_uid()
        result = self.sfn_client.create_state_machine(name=sm_name, definition=definition, roleArn=role_arn)

        # assert that the SM has been created
        self.assert_machine_created(state_machines_before)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn)
        self.assertTrue(result.get('executionArn'))

        def check_invocations():
            self.assertIn(lambda_arn_1, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            self.assertIn(lambda_arn_2, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            result = self._get_execution_results(sm_arn)
            self.assertEqual(result['result_value'], {'Hello': TEST_RESULT_VALUE})

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=0.7, retries=25)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
Exemple #9
0
    def test_intrinsic_functions(self):
        state_machines_before = self.sfn_client.list_state_machines()['stateMachines']

        # create state machine
        role_arn = aws_stack.role_arn('sfn_role')
        definition = clone(STATE_MACHINE_INTRINSIC_FUNCS)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_5)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_5)
        if isinstance(definition['States']['state1'].get('Parameters'), dict):
            definition['States']['state1']['Parameters']['lambda_params']['FunctionName'] = lambda_arn_1
            definition['States']['state3']['Resource'] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = 'intrinsic-%s' % short_uid()
        result = self.sfn_client.create_state_machine(name=sm_name, definition=definition, roleArn=role_arn)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        input = {}
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn, input=json.dumps(input))
        self.assertTrue(result.get('executionArn'))

        def check_invocations():
            self.assertIn(lambda_arn_1, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            self.assertIn(lambda_arn_2, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            result = self._get_execution_results(sm_arn)
            self.assertEqual(result.get('result_value'), {'payload': {'values': [1, 'v2']}})

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
Exemple #10
0
    def test_create_choice_state_machine(self):
        state_machines_before = self.sfn_client.list_state_machines()['stateMachines']
        role_arn = aws_stack.role_arn('sfn_role')

        definition = clone(STATE_MACHINE_CHOICE)
        lambda_arn_4 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_4)
        definition['States']['Add']['Resource'] = lambda_arn_4
        definition = json.dumps(definition)
        sm_name = 'choice-%s' % short_uid()
        result = self.sfn_client.create_state_machine(name=sm_name, definition=definition, roleArn=role_arn)

        # assert that the SM has been created
        self.assert_machine_created(state_machines_before)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        input = {'x': '1', 'y': '2'}
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn, input=json.dumps(input))
        self.assertTrue(result.get('executionArn'))

        # define expected output
        test_output = {**input, 'added': {'Hello': TEST_RESULT_VALUE}}

        def check_result():
            result = self._get_execution_results(sm_arn)
            self.assertEqual(result, test_output)

        # assert that the result is correct
        retry(check_result, sleep=2, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
Exemple #11
0
    def test_create_run_map_state_machine(self):
        names = ['Bob', 'Meg', 'Joe']
        test_input = [{'map': name} for name in names]
        test_output = [{'Hello': name} for name in names]
        state_machines_before = self.sfn_client.list_state_machines()['stateMachines']

        role_arn = aws_stack.role_arn('sfn_role')
        definition = clone(STATE_MACHINE_MAP)
        lambda_arn_3 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_3)
        definition['States']['ExampleMapState']['Iterator']['States']['CallLambda']['Resource'] = lambda_arn_3
        definition = json.dumps(definition)
        sm_name = 'map-%s' % short_uid()
        result = self.sfn_client.create_state_machine(name=sm_name, definition=definition, roleArn=role_arn)

        # assert that the SM has been created
        self.assert_machine_created(state_machines_before)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn, input=json.dumps(test_input))
        self.assertTrue(result.get('executionArn'))

        def check_invocations():
            self.assertIn(lambda_arn_3, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            result = self._get_execution_results(sm_arn)
            self.assertEqual(result, test_output)

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
Exemple #12
0
    def test_create_choice_state_machine(self):
        state_machines_before = self.sfn_client.list_state_machines()["stateMachines"]
        role_arn = aws_stack.role_arn("sfn_role")

        definition = clone(STATE_MACHINE_CHOICE)
        lambda_arn_4 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_4)
        definition["States"]["Add"]["Resource"] = lambda_arn_4
        definition = json.dumps(definition)
        sm_name = "choice-%s" % short_uid()
        result = self.sfn_client.create_state_machine(
            name=sm_name, definition=definition, roleArn=role_arn
        )

        # assert that the SM has been created
        self.assert_machine_created(state_machines_before)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        input = {"x": "1", "y": "2"}
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn, input=json.dumps(input))
        self.assertTrue(result.get("executionArn"))

        # define expected output
        test_output = {**input, "added": {"Hello": TEST_RESULT_VALUE}}

        def check_result():
            result = self._get_execution_results(sm_arn)
            self.assertEqual(test_output, result)

        # assert that the result is correct
        retry(check_result, sleep=2, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
 def IAM_Role_get_cfn_attribute(self, attribute_name):
     try:
         return IAM_Role_get_cfn_attribute_orig(self, attribute_name)
     except Exception:
         if attribute_name == 'Arn':
             return aws_stack.role_arn(self.name)
         raise
    def test_create_run_state_machine(self):
        state_machines_before = self.sfn_client.list_state_machines()['stateMachines']

        # create state machine
        role_arn = aws_stack.role_arn('sfn_role')
        definition = clone(STATE_MACHINE_DEF)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_1)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_2)
        definition['States']['step1']['Resource'] = lambda_arn_1
        definition['States']['step2']['Resource'] = lambda_arn_2
        definition = json.dumps(definition)
        result = self.sfn_client.create_state_machine(
            name=STATE_MACHINE_NAME, definition=definition, roleArn=role_arn)

        # assert that the SM has been created
        state_machines_after = self.sfn_client.list_state_machines()['stateMachines']
        self.assertEqual(len(state_machines_after), len(state_machines_before) + 1)

        # run state machine
        state_machines = self.sfn_client.list_state_machines()['stateMachines']
        sm_arn = [m['stateMachineArn'] for m in state_machines if m['name'] == STATE_MACHINE_NAME][0]
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn)
        self.assertTrue(result.get('executionArn'))

        def check_invocations():
            assert lambda_api.LAMBDA_EXECUTOR.function_invoke_times[lambda_arn_1]
            assert lambda_api.LAMBDA_EXECUTOR.function_invoke_times[lambda_arn_2]

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=0.7, retries=20)

        # clean up
        self.sfn_client.delete_state_machine(stateMachineArn=sm_arn)
    def test_lambda_start_stepfunctions_execution(self):
        function_name = '{}-{}'.format(TEST_LAMBDA_FUNCTION_PREFIX,
                                       short_uid())
        resource_lambda_name = '{}-{}'.format(TEST_LAMBDA_FUNCTION_PREFIX,
                                              short_uid())
        state_machine_name = 'state-machine-{}'.format(short_uid())

        testutil.create_lambda_function(
            handler_file=TEST_LAMBDA_START_EXECUTION_FILE,
            func_name=function_name,
            runtime=LAMBDA_RUNTIME_PYTHON36)

        testutil.create_lambda_function(handler_file=TEST_LAMBDA_ECHO_FILE,
                                        func_name=resource_lambda_name,
                                        runtime=LAMBDA_RUNTIME_PYTHON36)

        state_machine_def = {
            'StartAt': 'step1',
            'States': {
                'step1': {
                    'Type': 'Task',
                    'Resource':
                    aws_stack.lambda_function_arn(resource_lambda_name),
                    'ResultPath': '$.result_value',
                    'End': True
                }
            }
        }

        sfn_client = aws_stack.connect_to_service('stepfunctions')
        rs = sfn_client.create_state_machine(
            name=state_machine_name,
            definition=json.dumps(state_machine_def),
            roleArn=aws_stack.role_arn('sfn_role'))
        sm_arn = rs['stateMachineArn']

        self.lambda_client.invoke(FunctionName=function_name,
                                  Payload=json.dumps({
                                      'state_machine_arn': sm_arn,
                                      'region_name': config.DEFAULT_REGION,
                                      'input': {}
                                  }))
        time.sleep(1)

        rs = sfn_client.list_executions(stateMachineArn=sm_arn)

        # assert that state machine get executed 1 time
        self.assertEqual(
            len([
                ex for ex in rs['executions']
                if ex['stateMachineArn'] == sm_arn
            ]), 1)

        # clean up
        testutil.delete_lambda_function(function_name)
        testutil.delete_lambda_function(resource_lambda_name)

        # clean up
        sfn_client.delete_state_machine(stateMachineArn=sm_arn)
    def test_create_run_map_state_machine(self):
        test_input = [
            {
                'map': 'Bob'
            },
            {
                'map': 'Meg'
            },
            {
                'map': 'Joe'
            }
        ]
        test_output = [
            {
                'Hello': 'Bob'
            },
            {
                'Hello': 'Meg'
            },
            {
                'Hello': 'Joe'
            }
        ]
        state_machines_before = self.sfn_client.list_state_machines()['stateMachines']

        role_arn = aws_stack.role_arn('sfn_role')
        definition = clone(MAP_STATE_MACHINE_DEF)
        lambda_arn_3 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_3)
        definition['States']['ExampleMapState']['Iterator']['States']['CallLambda']['Resource'] = lambda_arn_3
        definition = json.dumps(definition)
        result = self.sfn_client.create_state_machine(
            name=MAP_STATE_MACHINE_NAME, definition=definition, roleArn=role_arn)

        # assert that the SM has been created
        state_machines_after = self.sfn_client.list_state_machines()['stateMachines']
        self.assertEqual(len(state_machines_after), len(state_machines_before) + 1)

        # run state machine
        state_machines = self.sfn_client.list_state_machines()['stateMachines']
        sm_arn = [m['stateMachineArn'] for m in state_machines if m['name'] == MAP_STATE_MACHINE_NAME][0]
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn, input=json.dumps(test_input))
        self.assertTrue(result.get('executionArn'))

        def check_invocations():
            self.assertIn(lambda_arn_3, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            response = self.sfn_client.list_executions(stateMachineArn=sm_arn)
            execution = response['executions'][0]
            result = self.sfn_client.get_execution_history(executionArn=execution['executionArn'])
            events = sorted(result['events'], key=lambda event: event['id'])
            result = json.loads(events[-1]['executionSucceededEventDetails']['output'])
            self.assertEqual(result, test_output)

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=0.7, retries=2)

        # clean up
        self.sfn_client.delete_state_machine(stateMachineArn=sm_arn)
Exemple #17
0
    def test_create_run_state_machine(self):
        state_machines_before = self.sfn_client.list_state_machines(
        )['stateMachines']

        # create state machine
        role_arn = aws_stack.role_arn('sfn_role')
        definition = clone(STATE_MACHINE_DEF)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_1)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_2)
        definition['States']['step1']['Resource'] = lambda_arn_1
        definition['States']['step2']['Resource'] = lambda_arn_2
        definition = json.dumps(definition)
        result = self.sfn_client.create_state_machine(name=STATE_MACHINE_NAME,
                                                      definition=definition,
                                                      roleArn=role_arn)

        # assert that the SM has been created
        state_machines_after = self.sfn_client.list_state_machines(
        )['stateMachines']
        self.assertEqual(len(state_machines_after),
                         len(state_machines_before) + 1)

        # run state machine
        state_machines = self.sfn_client.list_state_machines()['stateMachines']
        sm_arn = [
            m['stateMachineArn'] for m in state_machines
            if m['name'] == STATE_MACHINE_NAME
        ][0]
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn)
        self.assertTrue(result.get('executionArn'))

        def check_invocations():
            self.assertIn(lambda_arn_1,
                          lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            self.assertIn(lambda_arn_2,
                          lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            response = self.sfn_client.list_executions(stateMachineArn=sm_arn)
            execution = response['executions'][0]
            result = self.sfn_client.get_execution_history(
                executionArn=execution['executionArn'])
            events = sorted(result['events'], key=lambda event: event['id'])
            result = json.loads(
                events[-1]['executionSucceededEventDetails']['output'])
            self.assertEqual(result['result_value'],
                             {'Hello': TEST_RESULT_VALUE})

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=0.7, retries=25)

        # clean up
        self.sfn_client.delete_state_machine(stateMachineArn=sm_arn)
Exemple #18
0
 def __init__(self):
     self.authorizers = {}
     self.validators = {}
     self.documentation_parts = {}
     self.gateway_responses = {}
     self.account = {
         "cloudwatchRoleArn": aws_stack.role_arn("api-gw-cw-role"),
         "throttleSettings": {"burstLimit": 1000, "rateLimit": 500},
         "features": ["UsagePlans"],
         "apiKeyVersion": "1",
     }
     self.base_path_mappings = {}
     self.vpc_links = {}
     self.client_certificates = {}
Exemple #19
0
 def __init__(self):
     # maps (API id) -> [authorizers]
     self.authorizers = {}
     # maps (API id) -> [validators]
     self.validators = {}
     # account details
     self.account = {
         'cloudwatchRoleArn': aws_stack.role_arn('api-gw-cw-role'),
         'throttleSettings': {
             'burstLimit': 1000,
             'rateLimit': 500
         },
         'features': ['UsagePlans'],
         'apiKeyVersion': '1'
     }
    def test_intrinsic_functions(self, stepfunctions_client):
        if os.environ.get("AWS_DEFAULT_REGION") != "us-east-1":
            pytest.skip("skipping non us-east-1 temporarily")

        state_machines_before = stepfunctions_client.list_state_machines(
        )["stateMachines"]

        # create state machine
        role_arn = aws_stack.role_arn("sfn_role")
        definition = clone(STATE_MACHINE_INTRINSIC_FUNCS)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_5)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_5)
        if isinstance(definition["States"]["state1"].get("Parameters"), dict):
            definition["States"]["state1"]["Parameters"]["lambda_params"][
                "FunctionName"] = lambda_arn_1
            definition["States"]["state3"]["Resource"] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = f"intrinsic-{short_uid()}"
        stepfunctions_client.create_state_machine(name=sm_name,
                                                  definition=definition,
                                                  roleArn=role_arn)

        # run state machine
        sm_arn = get_machine_arn(sm_name, stepfunctions_client)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        input = {}
        result = stepfunctions_client.start_execution(stateMachineArn=sm_arn,
                                                      input=json.dumps(input))
        assert result.get("executionArn")

        def check_invocations():
            assert lambda_arn_1 in lambda_api.LAMBDA_EXECUTOR.function_invoke_times
            assert lambda_arn_2 in lambda_api.LAMBDA_EXECUTOR.function_invoke_times
            # assert that the result is correct
            result = _get_execution_results(sm_arn, stepfunctions_client)
            assert {
                "payload": {
                    "values": [1, "v2"]
                }
            } == result.get("result_value")

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        cleanup(sm_arn, state_machines_before, stepfunctions_client)
    def test_intrinsic_functions(self):
        state_machines_before = self.sfn_client.list_state_machines(
        )["stateMachines"]

        # create state machine
        role_arn = aws_stack.role_arn("sfn_role")
        definition = clone(STATE_MACHINE_INTRINSIC_FUNCS)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_5)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_5)
        if isinstance(definition["States"]["state1"].get("Parameters"), dict):
            definition["States"]["state1"]["Parameters"]["lambda_params"][
                "FunctionName"] = lambda_arn_1
            definition["States"]["state3"]["Resource"] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = "intrinsic-%s" % short_uid()
        self.sfn_client.create_state_machine(name=sm_name,
                                             definition=definition,
                                             roleArn=role_arn)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        input = {}
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn,
                                                 input=json.dumps(input))
        self.assertTrue(result.get("executionArn"))

        def check_invocations():
            self.assertIn(lambda_arn_1,
                          lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            self.assertIn(lambda_arn_2,
                          lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            result = self._get_execution_results(sm_arn)
            self.assertEqual({"payload": {
                "values": [1, "v2"]
            }}, result.get("result_value"))

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
    def test_events_state_machine(self, stepfunctions_client):
        events = aws_stack.create_external_boto_client("events")
        state_machines_before = stepfunctions_client.list_state_machines(
        )["stateMachines"]

        # create event bus
        bus_name = f"bus-{short_uid()}"
        events.create_event_bus(Name=bus_name)

        # create state machine
        definition = clone(STATE_MACHINE_EVENTS)
        definition["States"]["step1"]["Parameters"]["Entries"][0][
            "EventBusName"] = bus_name
        definition = json.dumps(definition)
        sm_name = f"events-{short_uid()}"
        role_arn = aws_stack.role_arn("sfn_role")
        stepfunctions_client.create_state_machine(name=sm_name,
                                                  definition=definition,
                                                  roleArn=role_arn)

        # run state machine
        events_before = len(TEST_EVENTS_CACHE)
        sm_arn = get_machine_arn(sm_name, stepfunctions_client)
        result = stepfunctions_client.start_execution(stateMachineArn=sm_arn)
        assert result.get("executionArn")

        def check_invocations():
            # assert that the event is received
            assert events_before + 1 == len(TEST_EVENTS_CACHE)
            last_event = TEST_EVENTS_CACHE[-1]
            assert bus_name == last_event["EventBusName"]
            assert "TestSource" == last_event["Source"]
            assert "TestMessage" == last_event["DetailType"]
            assert {
                "Message": "Hello from Step Functions!"
            } == json.loads(last_event["Detail"])

        # assert that the event bus has received an event from the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        cleanup(sm_arn, state_machines_before, stepfunctions_client)
        events.delete_event_bus(Name=bus_name)
    def test_events_state_machine(self):
        events = aws_stack.connect_to_service("events")
        state_machines_before = self.sfn_client.list_state_machines(
        )["stateMachines"]

        # create event bus
        bus_name = f"bus-{short_uid()}"
        events.create_event_bus(Name=bus_name)

        # create state machine
        definition = clone(STATE_MACHINE_EVENTS)
        definition["States"]["step1"]["Parameters"]["Entries"][0][
            "EventBusName"] = bus_name
        definition = json.dumps(definition)
        sm_name = "events-%s" % short_uid()
        role_arn = aws_stack.role_arn("sfn_role")
        self.sfn_client.create_state_machine(name=sm_name,
                                             definition=definition,
                                             roleArn=role_arn)

        # run state machine
        events_before = len(TEST_EVENTS_CACHE)
        sm_arn = self.get_machine_arn(sm_name)
        result = self.sfn_client.start_execution(stateMachineArn=sm_arn)
        self.assertTrue(result.get("executionArn"))

        def check_invocations():
            # assert that the event is received
            self.assertEqual(events_before + 1, len(TEST_EVENTS_CACHE))
            last_event = TEST_EVENTS_CACHE[-1]
            self.assertEqual(bus_name, last_event["EventBusName"])
            self.assertEqual("TestSource", last_event["Source"])
            self.assertEqual("TestMessage", last_event["DetailType"])
            self.assertEqual({"Message": "Hello from Step Functions!"},
                             json.loads(last_event["Detail"]))

        # assert that the event bus has received an event from the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
        events.delete_event_bus(Name=bus_name)
Exemple #24
0
 def __init__(self):
     # maps (API id) -> [authorizers]
     self.authorizers = {}
     # maps (API id) -> [validators]
     self.validators = {}
     # account details
     self.account = {
         'cloudwatchRoleArn': aws_stack.role_arn('api-gw-cw-role'),
         'throttleSettings': {
             'burstLimit': 1000,
             'rateLimit': 500
         },
         'features': ['UsagePlans'],
         'apiKeyVersion': '1'
     }
     # maps (domain_name) -> [path_mappings]
     self.base_path_mappings = {}
     # maps ID to VPC link details
     self.vpc_links = {}
     # maps cert ID to client certificate details
     self.client_certificates = {}
Exemple #25
0
    def test_create_run_map_state_machine(self):
        names = ["Bob", "Meg", "Joe"]
        test_input = [{"map": name} for name in names]
        test_output = [{"Hello": name} for name in names]
        state_machines_before = self.sfn_client.list_state_machines()["stateMachines"]

        role_arn = aws_stack.role_arn("sfn_role")
        definition = clone(STATE_MACHINE_MAP)
        lambda_arn_3 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_3)
        definition["States"]["ExampleMapState"]["Iterator"]["States"]["CallLambda"][
            "Resource"
        ] = lambda_arn_3
        definition = json.dumps(definition)
        sm_name = "map-%s" % short_uid()
        _ = self.sfn_client.create_state_machine(
            name=sm_name, definition=definition, roleArn=role_arn
        )

        # assert that the SM has been created
        self.assert_machine_created(state_machines_before)

        # run state machine
        sm_arn = self.get_machine_arn(sm_name)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        result = self.sfn_client.start_execution(
            stateMachineArn=sm_arn, input=json.dumps(test_input)
        )
        self.assertTrue(result.get("executionArn"))

        def check_invocations():
            self.assertIn(lambda_arn_3, lambda_api.LAMBDA_EXECUTOR.function_invoke_times)
            # assert that the result is correct
            result = self._get_execution_results(sm_arn)
            self.assertEqual(test_output, result)

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        self.cleanup(sm_arn, state_machines_before)
    def test_try_catch_state_machine(self, stepfunctions_client):
        if os.environ.get("AWS_DEFAULT_REGION") != "us-east-1":
            pytest.skip("skipping non us-east-1 temporarily")

        state_machines_before = stepfunctions_client.list_state_machines(
        )["stateMachines"]

        # create state machine
        role_arn = aws_stack.role_arn("sfn_role")
        definition = clone(STATE_MACHINE_CATCH)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_1)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_2)
        definition["States"]["Start"]["Parameters"][
            "FunctionName"] = lambda_arn_1
        definition["States"]["ErrorHandler"]["Resource"] = lambda_arn_2
        definition["States"]["Final"]["Resource"] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = f"catch-{short_uid()}"
        stepfunctions_client.create_state_machine(name=sm_name,
                                                  definition=definition,
                                                  roleArn=role_arn)

        # run state machine
        sm_arn = get_machine_arn(sm_name, stepfunctions_client)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        result = stepfunctions_client.start_execution(stateMachineArn=sm_arn)
        assert result.get("executionArn")

        def check_invocations():
            assert lambda_arn_1 in lambda_api.LAMBDA_EXECUTOR.function_invoke_times
            assert lambda_arn_2 in lambda_api.LAMBDA_EXECUTOR.function_invoke_times
            # assert that the result is correct
            result = _get_execution_results(sm_arn, stepfunctions_client)
            assert {"Hello": TEST_RESULT_VALUE} == result.get("handled")

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=1, retries=10)

        # clean up
        cleanup(sm_arn, state_machines_before, stepfunctions_client)
    def test_create_run_state_machine(self, stepfunctions_client):
        state_machines_before = stepfunctions_client.list_state_machines(
        )["stateMachines"]

        # create state machine
        role_arn = aws_stack.role_arn("sfn_role")
        definition = clone(STATE_MACHINE_BASIC)
        lambda_arn_1 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_1)
        lambda_arn_2 = aws_stack.lambda_function_arn(TEST_LAMBDA_NAME_2)
        definition["States"]["step1"]["Resource"] = lambda_arn_1
        definition["States"]["step2"]["Resource"] = lambda_arn_2
        definition = json.dumps(definition)
        sm_name = f"basic-{short_uid()}"
        stepfunctions_client.create_state_machine(name=sm_name,
                                                  definition=definition,
                                                  roleArn=role_arn)

        # assert that the SM has been created
        assert_machine_created(state_machines_before, stepfunctions_client)

        # run state machine
        sm_arn = get_machine_arn(sm_name, stepfunctions_client)
        lambda_api.LAMBDA_EXECUTOR.function_invoke_times.clear()
        result = stepfunctions_client.start_execution(stateMachineArn=sm_arn)
        assert result.get("executionArn")

        def check_invocations():
            assert lambda_arn_1 in lambda_api.LAMBDA_EXECUTOR.function_invoke_times
            assert lambda_arn_2 in lambda_api.LAMBDA_EXECUTOR.function_invoke_times
            # assert that the result is correct
            result = _get_execution_results(sm_arn, stepfunctions_client)
            assert {"Hello": TEST_RESULT_VALUE} == result["result_value"]

        # assert that the lambda has been invoked by the SM execution
        retry(check_invocations, sleep=0.7, retries=25)

        # clean up
        cleanup(sm_arn, state_machines_before, stepfunctions_client)
    def connect_api_gateway_to_s3(self, bucket_name, file_name, api_id, method):
        """Connects the root resource of an api gateway to the given object of an s3 bucket.

        """
        apigw_client = aws_stack.connect_to_service('apigateway')
        s3_uri = 'arn:aws:apigateway:{}:s3:path/{}/{}'.format(aws_stack.get_region(), bucket_name, file_name)

        test_role = 'test-s3-role'
        role_arn = aws_stack.role_arn(role_name=test_role)
        resources = apigw_client.get_resources(restApiId=api_id)
        # using the root resource '/' directly for this test
        root_resource_id = resources['items'][0]['id']
        apigw_client.put_method(
            restApiId=api_id, resourceId=root_resource_id, httpMethod=method, authorizationType='NONE',
            apiKeyRequired=False, requestParameters={})
        apigw_client.put_integration(
            restApiId=api_id,
            resourceId=root_resource_id,
            httpMethod=method,
            type='AWS',
            integrationHttpMethod=method,
            uri=s3_uri,
            credentials=role_arn)
Exemple #29
0
    def test_scheduled_expression_events(self):
        class HttpEndpointListener(ProxyListener):
            def forward_request(self, method, path, data, headers):
                event = json.loads(to_str(data))
                events.append(event)
                return 200

        local_port = get_free_tcp_port()
        proxy = start_proxy(local_port,
                            backend_url=None,
                            update_listener=HttpEndpointListener())
        wait_for_port_open(local_port)

        topic_name = 'topic-{}'.format(short_uid())
        queue_name = 'queue-{}'.format(short_uid())
        rule_name = 'rule-{}'.format(short_uid())
        endpoint = '{}://{}:{}'.format(get_service_protocol(),
                                       config.LOCALSTACK_HOSTNAME, local_port)
        sm_role_arn = aws_stack.role_arn('sfn_role')
        sm_name = 'state-machine-{}'.format(short_uid())
        topic_target_id = 'target-{}'.format(short_uid())
        sm_target_id = 'target-{}'.format(short_uid())
        queue_target_id = 'target-{}'.format(short_uid())

        events = []
        state_machine_definition = """
        {
            "StartAt": "Hello",
            "States": {
                "Hello": {
                    "Type": "Pass",
                    "Result": "World",
                    "End": true
                }
            }
        }
        """

        state_machine_arn = self.sfn_client.create_state_machine(
            name=sm_name,
            definition=state_machine_definition,
            roleArn=sm_role_arn)['stateMachineArn']

        topic_arn = self.sns_client.create_topic(Name=topic_name)['TopicArn']
        self.sns_client.subscribe(TopicArn=topic_arn,
                                  Protocol='http',
                                  Endpoint=endpoint)

        queue_url = self.sqs_client.create_queue(
            QueueName=queue_name)['QueueUrl']
        queue_arn = aws_stack.sqs_queue_arn(queue_name)

        event = {'env': 'testing'}

        self.events_client.put_rule(Name=rule_name,
                                    ScheduleExpression='rate(1 minutes)')

        self.events_client.put_targets(Rule=rule_name,
                                       Targets=[{
                                           'Id': topic_target_id,
                                           'Arn': topic_arn,
                                           'Input': json.dumps(event)
                                       }, {
                                           'Id': sm_target_id,
                                           'Arn': state_machine_arn,
                                           'Input': json.dumps(event)
                                       }, {
                                           'Id': queue_target_id,
                                           'Arn': queue_arn,
                                           'Input': json.dumps(event)
                                       }])

        def received(q_url):
            # state machine got executed
            executions = self.sfn_client.list_executions(
                stateMachineArn=state_machine_arn)['executions']
            self.assertGreaterEqual(len(executions), 1)

            # http endpoint got events
            self.assertGreaterEqual(len(events), 2)
            notifications = [
                event['Message'] for event in events
                if event['Type'] == 'Notification'
            ]
            self.assertGreaterEqual(len(notifications), 1)

            # get state machine execution detail
            execution_arn = executions[0]['executionArn']
            execution_input = self.sfn_client.describe_execution(
                executionArn=execution_arn)['input']

            # get message from queue
            msgs = self.sqs_client.receive_message(QueueUrl=q_url).get(
                'Messages', [])
            self.assertGreaterEqual(len(msgs), 1)

            return execution_input, notifications[0], msgs[0]

        execution_input, notification, msg_received = retry(received,
                                                            retries=5,
                                                            sleep=15,
                                                            q_url=queue_url)
        self.assertEqual(json.loads(notification), event)
        self.assertEqual(json.loads(execution_input), event)
        self.assertEqual(json.loads(msg_received['Body']), event)

        proxy.stop()

        self.events_client.remove_targets(Rule=rule_name,
                                          Ids=[topic_target_id, sm_target_id],
                                          Force=True)
        self.events_client.delete_rule(Name=rule_name, Force=True)

        self.sns_client.delete_topic(TopicArn=topic_arn)
        self.sfn_client.delete_state_machine(stateMachineArn=state_machine_arn)

        self.sqs_client.delete_queue(QueueUrl=queue_url)
Exemple #30
0
    def test_scheduled_expression_events(
        self, stepfunctions_client, sns_client, sqs_client, events_client
    ):
        class HttpEndpointListener(ProxyListener):
            def forward_request(self, method, path, data, headers):
                event = json.loads(to_str(data))
                events.append(event)
                return 200

        local_port = get_free_tcp_port()
        proxy = start_proxy(local_port, update_listener=HttpEndpointListener())
        wait_for_port_open(local_port)

        topic_name = "topic-{}".format(short_uid())
        queue_name = "queue-{}".format(short_uid())
        fifo_queue_name = "queue-{}.fifo".format(short_uid())
        rule_name = "rule-{}".format(short_uid())
        endpoint = "{}://{}:{}".format(
            get_service_protocol(), config.LOCALSTACK_HOSTNAME, local_port
        )
        sm_role_arn = aws_stack.role_arn("sfn_role")
        sm_name = "state-machine-{}".format(short_uid())
        topic_target_id = "target-{}".format(short_uid())
        sm_target_id = "target-{}".format(short_uid())
        queue_target_id = "target-{}".format(short_uid())
        fifo_queue_target_id = "target-{}".format(short_uid())

        events = []
        state_machine_definition = """
        {
            "StartAt": "Hello",
            "States": {
                "Hello": {
                    "Type": "Pass",
                    "Result": "World",
                    "End": true
                }
            }
        }
        """

        state_machine_arn = stepfunctions_client.create_state_machine(
            name=sm_name, definition=state_machine_definition, roleArn=sm_role_arn
        )["stateMachineArn"]

        topic_arn = sns_client.create_topic(Name=topic_name)["TopicArn"]
        sns_client.subscribe(TopicArn=topic_arn, Protocol="http", Endpoint=endpoint)

        queue_url = sqs_client.create_queue(QueueName=queue_name)["QueueUrl"]
        fifo_queue_url = sqs_client.create_queue(
            QueueName=fifo_queue_name,
            Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
        )["QueueUrl"]
        queue_arn = aws_stack.sqs_queue_arn(queue_name)
        fifo_queue_arn = aws_stack.sqs_queue_arn(fifo_queue_name)

        event = {"env": "testing"}

        events_client.put_rule(Name=rule_name, ScheduleExpression="rate(1 minutes)")

        events_client.put_targets(
            Rule=rule_name,
            Targets=[
                {"Id": topic_target_id, "Arn": topic_arn, "Input": json.dumps(event)},
                {
                    "Id": sm_target_id,
                    "Arn": state_machine_arn,
                    "Input": json.dumps(event),
                },
                {"Id": queue_target_id, "Arn": queue_arn, "Input": json.dumps(event)},
                {
                    "Id": fifo_queue_target_id,
                    "Arn": fifo_queue_arn,
                    "Input": json.dumps(event),
                    "SqsParameters": {"MessageGroupId": "123"},
                },
            ],
        )

        def received(q_urls):
            # state machine got executed
            executions = stepfunctions_client.list_executions(stateMachineArn=state_machine_arn)[
                "executions"
            ]
            assert len(executions) >= 1

            # http endpoint got events
            assert len(events) >= 2
            notifications = [
                event["Message"] for event in events if event["Type"] == "Notification"
            ]
            assert len(notifications) >= 1

            # get state machine execution detail
            execution_arn = executions[0]["executionArn"]
            execution_input = stepfunctions_client.describe_execution(executionArn=execution_arn)[
                "input"
            ]

            all_msgs = []
            # get message from queue
            for url in q_urls:
                msgs = sqs_client.receive_message(QueueUrl=url).get("Messages", [])
                assert len(msgs) >= 1
                all_msgs.append(msgs[0])

            return execution_input, notifications[0], all_msgs

        execution_input, notification, msgs_received = retry(
            received, retries=5, sleep=15, q_urls=[queue_url, fifo_queue_url]
        )
        assert json.loads(notification) == event
        assert json.loads(execution_input) == event
        for msg_received in msgs_received:
            assert json.loads(msg_received["Body"]) == event

        # clean up
        proxy.stop()
        self.cleanup(
            None, rule_name, target_ids=[topic_target_id, sm_target_id], queue_url=queue_url
        )
        sns_client.delete_topic(TopicArn=topic_arn)
        stepfunctions_client.delete_state_machine(stateMachineArn=state_machine_arn)