def test_when_stack_name_is_not_supplied(monkeypatch, datafiles):

    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    i = {'nostackname': 'one-rds-db-stack'}
    f = {'fragment': 'test data', 'requestId': 'my_request_id', 'params': i}

    with pytest.raises(Exception) as e:
        handler(f, test_context)
    assert str(e.value) == "stackname parameter was not defined in the macro"
def test_point_in_time_restore_latest_restorable_time(rds_stub, lambda_stub,
                                                      cloudformation_stub,
                                                      monkeypatch, datafiles,
                                                      mocker):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "false")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "shared")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "true")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    test_snapshot_id = uuid.uuid4()
    target_db_instance_id = "tdi{0}".format(str(test_snapshot_id))
    """
        Monkey patch gives the following error: TypeError: 'UUID' object is not callable
        monkeypatch.setattr(uuid, "uuid4", test_snapshot_id)
    """
    mocker.patch.object(uuid, 'uuid4', return_value=test_snapshot_id)
    _mock_get_function_name(lambda_stub, datafiles, test_context.function_name,
                            test_context.invoked_function_arn)
    _mock_list_tags(lambda_stub)
    _mock_describe_db_instances(rds_stub, datafiles, None, None)
    _mock_add_tag(lambda_stub,
                  lambdas.ugc_rds_macro.point_in_time_db_instance_tag,
                  target_db_instance_id)

    response = {
        "DBInstance": {
            "AllocatedStorage": 20,
            "DBInstanceArn":
            "arn:aws:rds:us-east-1:123456789012:db:restored-test-instance",
            "DBInstanceStatus": "creating",
            "DBInstanceIdentifier": "restored-test-instance"
        }
    }
    rds_stub.add_response('restore_db_instance_to_point_in_time',
                          expected_params={
                              'SourceDBInstanceIdentifier': 'dv-ugc-postgres',
                              'TargetDBInstanceIdentifier':
                              target_db_instance_id,
                              'UseLatestRestorableTime': True
                          },
                          service_response=response)

    (expected,
     db_instance_template) = _read_test_data(datafiles,
                                             "db_instance_template.json",
                                             "db_instance_template.json")
    i = {'stackname': 'dv-rds-database-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_point_in_time_restore_using_invalid_time(rds_stub, lambda_stub,
                                                  monkeypatch, datafiles,
                                                  mocker):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "false")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "shared")
    monkeypatch.setenv("restore_time", "INVALID_DATE")
    monkeypatch.setenv("restore_point_in_time", "true")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    test_snapshot_id = uuid.uuid4()
    mocker.patch.object(uuid, 'uuid4', return_value=test_snapshot_id)
    _mock_get_function_name(lambda_stub, datafiles, test_context.function_name,
                            test_context.invoked_function_arn)
    _mock_list_tags(lambda_stub)
    _mock_describe_db_instances(rds_stub, datafiles, None, None)

    (expected,
     db_instance_template) = _read_test_data(datafiles,
                                             "db_instance_template.json",
                                             "db_instance_template.json")

    i = {'stackname': 'dv-rds-database-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_snapshot_identifer_with_invalid_snapshot_type(rds_stub, monkeypatch,
                                                       datafiles):

    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "true")
    monkeypatch.setenv("snapshot_id", "")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "invalid_snapshot_type")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "")

    _mock_describe_db_instances(rds_stub, datafiles, None, None)

    (expected,
     db_instance_template) = _read_test_data(datafiles,
                                             "db_instance_template.json",
                                             "db_instance_template.json")

    i = {'stackname': 'one-rds-db-stack'}
    f = {'fragment': expected, 'requestId': 'my_request_id', 'params': i}

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_handler_add_multiple_properties(monkeypatch, datafiles):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "false")
    monkeypatch.setenv("snapshot_id", "")
    monkeypatch.setenv(
        "properties_to_add",
        '{"BackupRetentionPeriod": {"Ref": "BackupRetentionDays"}},{"DBName": { "Ref": "DatabaseName"}}'
    )
    monkeypatch.setenv("rds_snapshot_stack_name", "arn")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    (expected, db_instance_template) = _read_test_data(
        datafiles, "db_instance_template_with_multiple_props_added.json",
        "db_instance_template_props_removed.json")

    i = {'stackname': 'one-rds-db-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_handler_add_property(monkeypatch, datafiles):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "False")
    monkeypatch.setenv("snapshot_id", "")
    monkeypatch.setenv(
        "properties_to_add",
        '{"BackupRetentionPeriod": {"Ref": "BackupRetentionDays"}}')
    monkeypatch.setenv("rds_snapshot_stack_name", "")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "")

    (expected, db_instance_template) = _read_test_data(
        datafiles, "db_instance_template_with_property_added.json",
        "db_instance_template.json")

    i = {'stackname': 'one-rds-db-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_handler_remove_multiple_properties(monkeypatch, datafiles):

    monkeypatch.setenv("replace_with_snapshot", "False")
    monkeypatch.setenv("snapshot_id", "")
    monkeypatch.setenv("properties_to_remove", "DBInstanceIdentifier, DBName")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "")

    (expected, db_instance_template) = _read_test_data(
        datafiles, "db_instance_template_with_multiple_props_removed.json",
        "db_instance_template.json")

    i = {'stackname': 'one-rds-db-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)

    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_invalid_log_level(monkeypatch, datafiles):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "false")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "shared")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "true")
    monkeypatch.setenv("log_level", "not_valid")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    (expected,
     db_instance_template) = _read_test_data(datafiles,
                                             "db_instance_template.json",
                                             "db_instance_template.json")

    i = {'stackname': 'dv-rds-database-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    print("exepect={0}".format(expected))
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_point_in_time_restore_when_instance_is_being_modified(
        rds_stub, lambda_stub, cloudformation_stub, monkeypatch, datafiles,
        mocker):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "false")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "shared")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "true")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    test_snapshot_id = uuid.uuid4()
    target_db_instance_id = "tdi{0}".format(str(test_snapshot_id))
    mocker.patch.object(uuid, 'uuid4', return_value=test_snapshot_id)
    _mock_get_function_name(lambda_stub, datafiles, test_context.function_name,
                            test_context.invoked_function_arn)
    _mock_describe_db_instances(rds_stub, datafiles, target_db_instance_id,
                                "Modifying")

    list_tag_response = {
        "Tags": {
            "aws:cloudformation:logical-id":
            "RdsSnapShotLambdaFunction",
            "aws:cloudformation:stack-id":
            "arn:aws:cloudformation:eu-west-2:546933502184:stack/ugc-rds-db-macro/ef020480-19c5-11ea-9f4f-0617023ccf6e",
            lambdas.ugc_rds_macro.point_in_time_db_instance_tag:
            target_db_instance_id
        }
    }
    lambda_stub.add_response(
        "list_tags",
        expected_params={'Resource': test_context.invoked_function_arn},
        service_response=list_tag_response)

    (expected,
     db_instance_template) = _read_test_data(datafiles,
                                             "db_instance_template.json",
                                             "db_instance_template.json")

    i = {'stackname': 'dv-rds-database-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    print("exepect={0}".format(expected))
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_point_in_time_create_snap_shot(mocker, monkeypatch, lambda_stub,
                                        rds_stub, datafiles):
    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "false")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "shared")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "true")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)
    monkeypatch.setenv("log_level", "info")

    test_snapshot_id = uuid.uuid4()
    target_db_instance_id = "tdi{0}".format(str(test_snapshot_id))
    mocker.patch.object(uuid, 'uuid4', return_value=test_snapshot_id)
    _mock_describe_db_instances(rds_stub, datafiles, target_db_instance_id,
                                "Available")
    _mock_get_function_name(lambda_stub, datafiles, test_context.function_name,
                            test_context.invoked_function_arn)
    create_db_response = {
        "DBSnapshot": {
            "DBSnapshotIdentifier": target_db_instance_id,
            "DBInstanceIdentifier": "five-ugc-postgres",
            "Engine": "postgres",
            "AllocatedStorage": 20,
            "Status": "creating",
            "Port": 5432,
            "AvailabilityZone": "eu-west-2a",
            "VpcId": "vpc-19483f70",
            "InstanceCreateTime": "2019-12-09T14:31:25.541Z",
            "MasterUsername": "******",
            "EngineVersion": "9.6.15",
            "LicenseModel": "postgresql-license",
            "SnapshotType": "manual",
            "OptionGroupName": "default:postgres-9-6",
            "PercentProgress": 0,
            "StorageType": "standard",
            "Encrypted": True,
            "KmsKeyId":
            "arn:aws:kms:eu-west-2:546933502184:key/729df303-6521-4f52-8e09-b8156fc1265b",
            "DBSnapshotArn":
            "arn:aws:rds:eu-west-2:546933502184:snapshot:my-snapshot-1",
            "IAMDatabaseAuthenticationEnabled": False,
            "ProcessorFeatures": [],
            "DbiResourceId": "db-PSC7UU72SDEX7TDNFIKJNUCOVA"
        }
    }

    snapshot_id = "rsi{0}".format(str(test_snapshot_id))

    rds_stub.add_response('create_db_snapshot',
                          expected_params={
                              'DBSnapshotIdentifier': snapshot_id,
                              'DBInstanceIdentifier': target_db_instance_id
                          },
                          service_response=create_db_response)

    list_tag_response = {
        "Tags": {
            "aws:cloudformation:logical-id":
            "RdsSnapShotLambdaFunction",
            "aws:cloudformation:stack-id":
            "arn:aws:cloudformation:eu-west-2:546933502184:stack/ugc-rds-db-macro/ef020480-19c5-11ea-9f4f-0617023ccf6e",
            lambdas.ugc_rds_macro.point_in_time_db_instance_tag:
            '{0}:{1}:{2}'.format(target_db_instance_id, "creating",
                                 target_db_instance_id)
        }
    }
    lambda_stub.add_response(
        "list_tags",
        expected_params={'Resource': test_context.invoked_function_arn},
        service_response=list_tag_response)

    lambda_stub.add_response(
        "tag_resource",
        expected_params={
            'Resource': test_context.invoked_function_arn,
            'Tags': {
                lambdas.ugc_rds_macro.point_in_time_snapshot_db_instance_tag:
                "{0}:{1}:{2}".format(snapshot_id, "creating",
                                     target_db_instance_id)
            }
        },
        service_response={})

    lambda_stub.add_response("untag_resource",
                             expected_params={
                                 'Resource': test_context.invoked_function_arn,
                                 'TagKeys': ['ugc:point-in-time:dbinstance']
                             },
                             service_response={})

    (expected,
     db_instance_template) = _read_test_data(datafiles,
                                             "db_instance_template.json",
                                             "db_instance_template.json")

    #_mock_delete_db_instance(rds_stub, datafiles, target_db_instance_id)

    i = {'stackname': 'dv-rds-database-stack'}
    f = {
        'fragment': db_instance_template,
        'requestId': 'my_request_id',
        'params': i
    }

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected
def test_snapshot_identifer_with_snapshot_type(rds_stub, monkeypatch,
                                               datafiles):

    monkeypatch.setenv("properties_to_remove", "")
    monkeypatch.setenv("replace_with_snapshot", "true")
    monkeypatch.setenv("snapshot_id", "")
    monkeypatch.setenv("properties_to_add", "")
    monkeypatch.setenv("rds_snapshot_stack_name", "mv-rds-db-stack")
    monkeypatch.setenv("snapshot_type", "shared")
    monkeypatch.setenv("restore_time", "")
    monkeypatch.setenv("restore_point_in_time", "")
    monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", test_context.function_name)

    _mock_describe_db_instances(rds_stub, datafiles, None, None)

    response = {
        'DBSnapshots': [{
            'DBSnapshotIdentifier':
            'rds:mv-ugc-postgres-2019-12-06-11-10',
            'DBInstanceIdentifier':
            'mv-ugc-postgres',
            'SnapshotCreateTime':
            datetime(2019, 12, 6, 11, 10, 33, 790000),
            'Engine':
            'postgres',
            'AllocatedStorage':
            20,
            'Status':
            'available',
            'Port':
            5432,
            'AvailabilityZone':
            'eu-west-2b',
            'VpcId':
            'vpc-19483f70',
            'InstanceCreateTime':
            datetime(2019, 12, 6, 11, 9, 28, 424000),
            'MasterUsername':
            '******',
            'EngineVersion':
            '9.6.15',
            'LicenseModel':
            'postgresql-license',
            'SnapshotType':
            'automated',
            'OptionGroupName':
            'default:postgres-9-6',
            'PercentProgress':
            100,
            'StorageType':
            'standard',
            'Encrypted':
            True,
            'KmsKeyId':
            'arn:aws:kms:eu-west-2:546933502184:key/83f283d1-7b58-4827-854c-db776149795f',
            'DBSnapshotArn':
            'arn:aws:rds:eu-west-2:546933502184:snapshot:rds:mv-ugc-postgres-2019-12-06-11-10',
            'IAMDatabaseAuthenticationEnabled':
            False,
            'ProcessorFeatures': [],
            'DbiResourceId':
            'db-CQ76MXOJJIFBOQ7WT63Y6AXUKA'
        }],
        'ResponseMetadata': {
            'RequestId': '8290e734-5717-4c94-9ed5-1eaf0aa20ec6',
            'HTTPStatusCode': 200,
            'HTTPHeaders': {
                'x-amzn-requestid': '8290e734-5717-4c94-9ed5-1eaf0aa20ec6',
                'content-type': 'text/xml',
                'content-length': '1687',
                'date': 'Fri, 06 Dec 2019 15:02:09 GMT'
            },
            'RetryAttempts': 0
        }
    }
    rds_stub.add_response('describe_db_snapshots',
                          expected_params={
                              'DBInstanceIdentifier': 'mr1qf4ez7ls7xfn',
                              'SnapshotType': 'shared'
                          },
                          service_response=response)

    (expected, db_instance_template) = _read_test_data(
        datafiles, "db_instance_template_with_snapshot_specified.json",
        "db_instance_template.json")

    i = {'stackname': 'one-rds-db-stack'}
    f = {'fragment': expected, 'requestId': 'my_request_id', 'params': i}

    res = handler(f, test_context)
    assert res['requestId'] == "my_request_id"
    assert res['fragment'] == expected