def test_deploy_to_s3(self): cfn_pipeline = CFNPipeline(logger, clients) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket", "SNSTopic": "SNSTopic:SNSTopic:SNSTopic:SNSTopic:SNSTopic", "ReportKey": "ReportKey", "ReportBucket": "ReportBucket", "StackCreationRoleArn": "arn::::StackCreationRoleArn", "KeyBucket": "KeyBucket", "DeployBucket": "DeployBucket", "DeployKey": "DeployKey" }) cfn_pipeline.consume_event(event, MockContext(), 'critical') self.assertEqual(None, cfn_pipeline.deploy_to_s3())
def test_build_execution_report(self): cfn_pipeline = CFNPipeline(logger, clients) cfn_pipeline.consume_event(event, MockContext(), 'critical') self.assertEqual( True, cfn_pipeline.build_execution_report( sns_topic=':::TestTopic', s3_bucket='TestBucket').startswith( 'Report for pipelineName execution pipelineExecutionId'))
def test_anon_reporting(self): cfn_pipeline = CFNPipeline(logger, clients) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket" }) cfn_pipeline.consume_event(event, MockContext(), 'critical') self.assertEqual(None, cfn_pipeline.anon_reporting('message', 'status'))
def test_delete_provisioned_product(self): cfn_pipeline = CFNPipeline(logger, clients) expected = { 'status': 'success', 'stackid': 'StackId', 'region': 'us-east-1', 'detail': None } self.assertEqual( expected, cfn_pipeline.delete_provisioned_product('pp-ProvisionedProductId', 'StackId', 'us-east-1'))
def test_delete_stacks(self): cfn_pipeline = CFNPipeline(logger, clients) stacks = [{ 'region': 'us-east-1', 'stackid': 'StackId1' }, { 'region': 'us-west-1', 'stackid': 'StackId2' }, { 'region': 'us-east-1', 'stackid': 'StackId3' }] expected = { 'inprogress': [{ 'status': 'inprogress', 'stackid': 'StackId3', 'region': 'us-east-1', 'detail': 'CREATE_IN_PROGRESS', 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }], 'success': [{ 'status': 'success', 'stackid': 'StackId2', 'region': 'us-west-1', 'detail': 'CREATE_COMPLETE', 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }], 'error': [{ 'status': 'error', 'stackid': 'StackId1', 'region': 'us-east-1', 'detail': [ 'CREATE_FAILED', [[ 'CREATE_FAILED', 'LogicalResourceId', 'ResourceStatusReason' ]] ], 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }] } self.assertEqual(expected, cfn_pipeline.delete_stacks(stacks))
def test_consume_event(self): cfn_pipeline = CFNPipeline(logger, clients) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket", "SNSTopic": "SNSTopic:SNSTopic:SNSTopic:SNSTopic:SNSTopic", "ReportKey": "ReportKey", "ReportBucket": "ReportBucket" }) self.assertEqual( None, cfn_pipeline.consume_event(event, MockContext(), 'critical')) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket", "CleanupPrevious": "Yes", "CleanupFailed": "Yes", "CleanupNonFailed": "Yes" }) self.assertEqual( None, cfn_pipeline.consume_event(event, MockContext(), 'critical')) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket", "CleanupPrevious": "No", "CleanupFailed": "No", "CleanupNonFailed": "No" }) self.assertEqual( None, cfn_pipeline.consume_event(event, MockContext(), 'critical')) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = "this isn't json" with self.assertRaises(ValueError): self.assertRaises( ValueError, cfn_pipeline.consume_event(event, MockContext(), 'critical')) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps( {"ScratchBucket": "ScratchBucket"}) with self.assertRaises(ValueError): cfn_pipeline.consume_event(event, MockContext(), 'critical')
def test_provision_product(self): cfn_pipeline = CFNPipeline(logger, clients) cfn_pipeline.consume_event(event, MockContext(), 'error') expected = { 'inprogress': [{ 'status': 'inprogress', 'stackid': 'StackId3', 'region': 'us-east-1', 'detail': 'CREATE_IN_PROGRESS', 'artifact': 'TemplateArtifact', 'testname': 'defaults' }, { 'status': 'inprogress', 'stackid': 'StackId3', 'region': 'eu-west-1', 'detail': 'CREATE_IN_PROGRESS', 'artifact': 'TemplateArtifact', 'testname': 'defaults' }], 'success': [], 'error': [] } self.assertEqual(expected, cfn_pipeline.provision_product())
def test_find_in_obj(self): cfn_pipeline = CFNPipeline(logger, clients) obj = { "Resources": { "TestResource": { "Type": "AWS::TestResource", "Properties": { "TestList": [{ "TestKey": "TestVal" }] } } } } matches = [] def matching_func(obj, val): return True self.assertEqual( None, cfn_pipeline.find_in_obj(obj, 'testVal', matching_func, matches, case_sensitive=False)) expected = [{ 'regions': [], 'path': '[Resources][TestResource][Type]', 'value': u'aws::testresource' }, { 'regions': [], 'path': '[Resources][TestResource][Properties][TestList][0][TestKey]', 'value': u'testval' }] self.assertEqual(expected, matches)
def test_continue_job_later(self): cfn_pipeline = CFNPipeline(logger, clients) self.assertEqual( None, cfn_pipeline.continue_job_later('continuation message')) long_message = '' while len(long_message) < 2049: long_message += 'a' event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket" }) cfn_pipeline.consume_event(event, MockContext(), 'critical') self.assertEqual(None, cfn_pipeline.continue_job_later(long_message))
def test_cleanup_previous_stacks(self): cfn_pipeline = CFNPipeline(logger, clients) cfn_pipeline.consume_event(event, MockContext(), 'critical') expected = { 'inprogress': [{ 'status': 'inprogress', 'stackid': 'StackId3', 'region': 'us-east-1', 'detail': 'CREATE_IN_PROGRESS', 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }, { 'status': 'inprogress', 'stackid': 'StackId3', 'region': 'eu-west-1', 'detail': 'CREATE_IN_PROGRESS', 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }], 'success': [{ 'status': 'success', 'stackid': 'StackId2', 'region': 'us-east-1', 'detail': 'CREATE_COMPLETE', 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }, { 'status': 'success', 'stackid': 'StackId2', 'region': 'eu-west-1', 'detail': 'CREATE_COMPLETE', 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }], 'error': [{ 'status': 'error', 'stackid': 'StackId1', 'region': 'us-east-1', 'detail': [ 'CREATE_FAILED', [[ 'CREATE_FAILED', 'LogicalResourceId', 'ResourceStatusReason' ]] ], 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }, { 'status': 'error', 'stackid': 'StackId1', 'region': 'eu-west-1', 'detail': [ 'CREATE_FAILED', [[ 'CREATE_FAILED', 'LogicalResourceId', 'ResourceStatusReason' ]] ], 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }] } self.assertEqual(expected, cfn_pipeline.cleanup_previous_stacks())
def test_get_templates(self): cfn_pipeline = CFNPipeline(logger, clients) cfn_pipeline.consume_event(event, MockContext(), 'critical') self.assertIn('aws-vpc.template', cfn_pipeline.get_templates().keys())
def test_test_stacks(self): cfn_pipeline = CFNPipeline(logger, clients) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket", "SNSTopic": "SNSTopic:SNSTopic:SNSTopic:SNSTopic:SNSTopic", "ReportKey": "ReportKey", "ReportBucket": "ReportBucket", "StackCreationRoleArn": "arn::::StackCreationRoleArn", "KeyBucket": "KeyBucket" }) cfn_pipeline.consume_event(event, MockContext(), 'critical') def test_func(**kwargs): return { "stackid": "stackid", "region": "region", "logical_resource_id": "logical_resource_id", "physical_resource_id": "physical_resource_id", "success": True } expected = { 'success': [{ 'stackid': 'stackid', 'region': 'region', 'logical_resource_id': 'logical_resource_id', 'testname': 'defaults', 'artifact': 'TemplateArtifact', 'physical_resource_id': 'physical_resource_id' }, { 'stackid': 'stackid', 'region': 'region', 'logical_resource_id': 'logical_resource_id', 'testname': 'defaults', 'artifact': 'TemplateArtifact', 'physical_resource_id': 'physical_resource_id' }], 'error': [] } self.assertEqual(expected, cfn_pipeline.test_stacks(test_func)) logical_resource_ids = ['testResource'] self.assertEqual( expected, cfn_pipeline.test_stacks(test_func, logical_resource_ids)) resource_types = ["AWS::ResourceType"] expected = { 'error': [], 'success': [{ 'artifact': 'TemplateArtifact', 'logical_resource_id': 'logical_resource_id', 'physical_resource_id': 'physical_resource_id', 'region': 'region', 'stackid': 'stackid', 'testname': 'defaults' }, { 'artifact': 'TemplateArtifact', 'logical_resource_id': 'logical_resource_id', 'physical_resource_id': 'physical_resource_id', 'region': 'region', 'stackid': 'stackid', 'testname': 'defaults' }] } self.assertEqual( expected, cfn_pipeline.test_stacks(test_func, resource_types=resource_types)) logical_resource_id_prefix = "Logical" self.assertEqual( expected, cfn_pipeline.test_stacks( test_func, resource_types=resource_types, logical_resource_id_prefix=logical_resource_id_prefix)) resource_types = ["AWS::NonExistant"] expected = {'error': [], 'success': []} self.assertEqual( expected, cfn_pipeline.test_stacks(test_func, resource_types=resource_types))
def test___init__(self): cfn_pipeline = CFNPipeline(logger, clients) self.assertIsNotNone(cfn_pipeline.anon_usage_reporting_url)
def test__get_regions(self): cfn_pipeline = CFNPipeline(logger, clients) self.assertEqual(['us-east-1', 'us-west-1'], cfn_pipeline._get_regions())
def test_create_stacks(self): cfn_pipeline = CFNPipeline(logger, clients) event['CodePipeline.job']['data']['actionConfiguration'][ 'configuration']['UserParameters'] = json.dumps({ "CITestPath": "ci", "ScratchBucket": "ScratchBucket", "SNSTopic": "SNSTopic:SNSTopic:SNSTopic:SNSTopic:SNSTopic", "ReportKey": "ReportKey", "ReportBucket": "ReportBucket", "StackCreationRoleArn": "arn::::StackCreationRoleArn", "KeyBucket": "KeyBucket" }) cfn_pipeline.consume_event(event, MockContext(), 'critical') expected = { 'inprogress': [], 'success': [], 'error': [{ 'status': 'error', 'stackid': 'StackId1', 'region': 'us-east-1', 'detail': [ 'CREATE_FAILED', [[ 'CREATE_FAILED', 'LogicalResourceId', 'ResourceStatusReason' ]] ], 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }, { 'status': 'error', 'stackid': 'StackId1', 'region': 'eu-west-1', 'detail': [ 'CREATE_FAILED', [[ 'CREATE_FAILED', 'LogicalResourceId', 'ResourceStatusReason' ]] ], 'artifact': 'cfn_cicd_artifact', 'testname': 'cfn_cicd_testname' }] } self.assertEqual(expected, cfn_pipeline.create_stacks())
def test_upload_output_artifact(self): cfn_pipeline = CFNPipeline(logger, clients) cfn_pipeline.consume_event(event, MockContext(), 'critical') self.assertEqual(None, cfn_pipeline.upload_output_artifact({}))
def test_put_job_failure(self): cfn_pipeline = CFNPipeline(logger, clients) self.assertEqual(None, cfn_pipeline.put_job_failure('failure message'))
from awsclients import AwsClients from cfnpipeline import CFNPipeline from logger import Logger loglevel = 'debug' logger = Logger(loglevel=loglevel) logger.info('New Lambda container initialised, logging configured.') clients = AwsClients(logger) pipeline_run = CFNPipeline(logger, clients) def lambda_handler(event, context): try: logger.config(context.aws_request_id, loglevel=loglevel) logger.debug("Handler starting...") logger.debug(event) pipeline_run.consume_event(event, context, loglevel=loglevel) logger.info({'event': 'new_invoke'}) pipeline_run.deploy_to_s3() pipeline_run.put_job_success("S3 bucket updated successfully") return except Exception as e: logger.error("Unhandled exception!", exc_info=1) pipeline_run.put_job_failure(str(e))
def test_put_job_success(self): cfn_pipeline = CFNPipeline(logger, clients) self.assertEqual(None, cfn_pipeline.put_job_success('success message'))