def test_stack_exists() -> None:
    """
    Tests that stack actually was created.

    :return: No return.
    """
    client = Credentials().boto_session.client('cloudformation')

    stacks = client.list_stacks(
        StackStatusFilter=['CREATE_COMPLETE'])['StackSummaries']
    stacks = [stack['StackName'] for stack in stacks]

    assert TestingStack.name() in stacks
def test_stack_exists() -> None:
    """
    Tests that stack actually was created.

    :return: No return.
    """
    # The stack name is provided by the cf testing manager.
    stack_name = f'{TestingManager.get_global_prefix()}TestStack'

    client = Credentials().boto_session.client('cloudformation')

    stacks = client.list_stacks(StackStatusFilter=['CREATE_COMPLETE'])['StackSummaries']
    stacks = [stack['StackName'] for stack in stacks]

    assert stack_name in stacks
示例#3
0
def test_invoke_function() -> None:
    """
    Invokes a backend lambda function and tests its response.

    :return: No return.
    """
    function_name = Infrastructure.get_output(
        Infrastructure.LAMBDA_FUNCTION_NAME_KEY)

    logger.info(f'Invoking function: {function_name}.')

    session = Credentials().boto_session
    response = session.client('lambda').invoke(
        FunctionName=function_name, InvocationType='RequestResponse')

    logger.info(f'Response from lambda function: {response}.')
def test_RESOURCE_lambda_layer_WITH_deployed_lambda_function_4_EXPECT_execution_successful():
    """
    Test whether a layer provides necessary functionality.

    :return: No return.
    """
    # Create client for Lambda service.
    lambda_client = Credentials().boto_session.client('lambda')

    # Invoke a specific lambda function.
    response = lambda_client.invoke(
        FunctionName=MainStack.get_output(MainStack.LAMBDA_FUNCTION_4_NAME_KEY),
        InvocationType='RequestResponse',
        Payload=json.dumps({'heartbeat': True})
    )

    # If Lambda function was not executed, it returns a string 'null'.
    data = response['Payload'].read().decode()
    assert data == 'null'
def test_RESOURCE_lambda_layer_WITH_deployed_lambda_function_2_EXPECT_execution_successful():
    """
    Test whether the layer provides necessary functionality.

    :return: No return.
    """
    # Create client for lambda service.
    lambda_client = Credentials().boto_session.client('lambda')

    # Invoke specific lambda function.
    response = lambda_client.invoke(
        FunctionName=MainStack.get_output(MainStack.LAMBDA_FUNCTION_2_NAME_KEY),
        InvocationType='RequestResponse'
    )

    # Parse the result.
    payload: StreamingBody = response['Payload']
    data = [item.decode() for item in payload.iter_lines()]

    print(data)
    def load_outputs(
            credentials: Optional[Credentials] = None) -> Dict[str, str]:
        """
        Loads this stack's outputs.

        :param credentials: Optional credentials for AWS API commands.

        :return: All outputs in a form of a dictionary.
        """
        credentials = credentials or Credentials()
        return CfOutputs(credentials.boto_session).get_outputs(
            TestingStack.name())[TestingStack.name()]
示例#7
0
def test_RESOURCE_lambda_layer_WITH_with_unit_tests_EXPECT_execution_successful_tests_pass(
):
    """
    Test whether the layer provides necessary functionality and unit tests pass.

    :return: No return.
    """
    # Create client for lambda service.
    lambda_client = Credentials().boto_session.client('lambda')

    # Invoke specific lambda function.
    response = lambda_client.invoke(FunctionName=MainStack.get_output(
        MainStack.LAMBDA_FUNCTION_UNIT_TESTS_NAME_KEY),
                                    InvocationType='RequestResponse')

    # Parse the result.
    payload: StreamingBody = response['Payload']
    data = [item.decode() for item in payload.iter_lines()]
    data = json.loads(''.join(data))

    # Assert that the result is as expected i.e. all unit tests inside lambda function have passed.
    assert data.get('ExitCode') == 0, data
def test_RESOURCE_lambda_layer_WITH_deployed_lambda_function_1_EXPECT_execution_successful():
    """
    Test whether the layer provides necessary functionality.

    :return: No return.
    """
    # Create client for lambda service.
    lambda_client = Credentials().boto_session.client('lambda')

    # Invoke specific lambda function.
    response = lambda_client.invoke(
        FunctionName=MainStack.get_output(MainStack.LAMBDA_FUNCTION_1_NAME_KEY),
        InvocationType='RequestResponse'
    )

    # Parse the result.
    payload: StreamingBody = response['Payload']
    data = [item.decode() for item in payload.iter_lines()]
    data = json.loads(''.join(data))

    # Assert that the result is as expected.
    assert data['Boto3Version'] == '1.16.35', data
    assert data['BotocoreVersion'] == '1.19.35', data
示例#9
0
class StackWaiter:
    """
    Waiter class that waits for a cloud formation stack to stabilize.
    """

    def __init__(self, stack_name: str):
        self.__stack_name = stack_name
        self.__client = Credentials().boto_session.client('cloudformation')

    def wait(self, current_iteration: int = 0, max_iterations: int = 100, sleep_time: int = 5) -> None:
        """
        Waits for a given stack to stabilize. E.g. waits when CREATE_IN_PROGRESS turns into CREATE_COMPLETE.

        :param current_iteration: This is a recursive function. This parameter indicates current iteration.
        :param max_iterations: Specifies maximum amount of iterations allowed.
        :param sleep_time: Specifies how long to sleep between iterations.

        :return: No return.
        """
        if current_iteration == max_iterations:
            raise RecursionError()

        stack_status = self.__get_stack_status() or ''
        logger.info(f'Stack status: {stack_status}.')

        if '_IN_PROGRESS' in stack_status:
            time.sleep(sleep_time)
            self.wait(current_iteration + 1, max_iterations, sleep_time)

    def __get_stack_status(self) -> Optional[str]:
        """
        Gets given stack status e.g. CREATE_IN_PROGRESS.

        :return: Stack status.
        """
        try:
            stack = self.__client.describe_stacks(StackName=self.__stack_name)['Stacks'][0]
            return stack['StackStatus']
        except ClientError as ex:
            # Retrieve code and message from an error.
            code = ex.response['Error']['Code']
            message = ex.response['Error']['Message']

            # If stack does not exist, its fine, just return None.
            if code == 'ValidationError' and 'does not exist' in message.lower():
                return

            # Otherwise throw an exception.
            raise
def test_deployed() -> None:
    """
    Tests that deployments were created and stage was deployed.

    :return: No return.
    """
    response = Credentials().boto_session.client(
        'apigatewayv2').get_deployments(
            ApiId=TestingInfrastructure.get_output('ApiId'), MaxResults='25')

    items = response['Items']

    print(len(items))
    print(items)

    assert len(list(items)) >= 5

    for deployment in items:
        assert deployment['AutoDeployed'] is False
        assert deployment['DeploymentStatus'] == 'DEPLOYED'
示例#11
0
import os

from b_aws_testing_framework.credentials import Credentials
from b_aws_testing_framework.tools.cdk_testing.cdk_tool_config import CdkToolConfig
from b_aws_testing_framework.tools.cdk_testing.testing_manager import TestingManager

CDK_PATH = f'{os.path.dirname(os.path.abspath(__file__))}'
MANAGER = TestingManager(
    Credentials(), CdkToolConfig(CDK_PATH, destroy_before_preparing=False))


def pytest_sessionstart(session):
    MANAGER.set_global_prefix()
    MANAGER.prepare_infrastructure()


def pytest_sessionfinish(session, exitstatus):
    MANAGER.destroy_infrastructure()
示例#12
0
def pytest_sessionstart(session):
    """
    Called after the Session object has been created and
    before performing collection and entering the run test loop.
    """
    TestingManager(Credentials(), CdkToolConfig(CDK_PATH)).prepare_infrastructure()
示例#13
0
 def __init__(self, stack_name: str):
     self.__stack_name = stack_name
     self.__client = Credentials().boto_session.client('cloudformation')
示例#14
0
def pytest_configure(*args, **kwargs):
    """
    Called after command line options have been parsed and all plugins and initial conftest files been loaded.
    """
    TestingManager(Credentials(), CdkToolConfig(CDK_PATH)).prepare_infrastructure()
示例#15
0
from os.path import abspath as apat
from os.path import dirname as dirn

from b_aws_testing_framework.credentials import Credentials
from b_aws_testing_framework.tools.cdk_testing.cdk_tool_config import CdkToolConfig
from b_aws_testing_framework.tools.cdk_testing.testing_manager import TestingManager

CDK_PATH = dirn(apat(__file__))
MANAGER = TestingManager(Credentials(), CdkToolConfig(CDK_PATH))


def pytest_configure(*args, **kwargs):
    """
    Called after command line options have been parsed and
    all plugins and initial conftest files been loaded.
    """
    MANAGER.set_global_prefix()
    MANAGER.prepare_infrastructure()


def pytest_unconfigure(*args, **kwargs):
    """
    Called before test process is exited.
    """
    MANAGER.destroy_infrastructure()
示例#16
0
def pytest_unconfigure(*args, **kwargs):
    """
    Called before test process is exited.
    """
    TestingManager(Credentials(), CdkToolConfig(CDK_PATH)).destroy_infrastructure()
示例#17
0
def pytest_sessionfinish(session, exitstatus):
    """
    Called after whole test run finished, right before
    returning the exit status to the system.
    """
    TestingManager(Credentials(), CdkToolConfig(CDK_PATH)).destroy_infrastructure()