Пример #1
0
 def test_deployment_access_arn_discovered_with_deleted(self):
     mock_deployment_access_stack_arn = 'deployment-access-stack-arn'
     mock_describe_stacks_result = {
         'Stacks': [{
             'StackId': 'wrong-stack-id',
             'StackStatus': 'DELETE_COMPLETE'
         }, {
             'StackId': mock_deployment_access_stack_arn,
             'StackStatus': 'UPDATE_COMPLETE'
         }]
     }
     mock_deployment_access_stack_name = MOCK_STACK_NAME + '-Access'
     mock_deployment_access = 'test-deployment-access'
     with mock.patch('stack_info.DeploymentAccessInfo',
                     return_value=mock_deployment_access
                     ) as mock_DeploymentAccessInfo:
         with mock_aws.patch_client('cloudformation',
                                    'describe_stacks',
                                    return_value=mock_describe_stacks_result
                                    ) as mock_describe_stacks:
             target = stack_info.DeploymentInfo(MOCK_STACK_ARN)
             actual_deployment_access = target.deployment_access
             self.assertIs(actual_deployment_access, mock_deployment_access)
             mock_DeploymentAccessInfo.assert_called_once_with(
                 mock_deployment_access_stack_arn,
                 deployment_info=target,
                 client=target.client)
             mock_describe_stacks.assert_called_once_with(
                 StackName=mock_deployment_access_stack_name)
Пример #2
0
 def test_deployment_name(self):
     mock_deployment_name = 'test-deployment'
     mock_parameters = {'DeploymentName': mock_deployment_name}
     with mock.patch('stack_info.DeploymentInfo.parameters',
                     new=mock.PropertyMock(return_value=mock_parameters)):
         target = stack_info.DeploymentInfo(MOCK_STACK_ARN)
         self.assertEquals(target.deployment_name, mock_deployment_name)
Пример #3
0
 def test_deployment_access_provided(self):
     mock_deployment_access = 'test-deployment-access'
     target = stack_info.DeploymentInfo(
         MOCK_STACK_ARN,
         deployment_access_info=mock_deployment_access,
         client=MOCK_CLIENT)
     actual_deployment_access = target.deployment_access
     self.assertIs(actual_deployment_access, mock_deployment_access)
def handler(event, context):
    
    props = properties.load(event, {
        'ConfigurationBucket': properties.String(), # Currently not used
        'ConfigurationKey': properties.String(),    # Depend on unique upload id in key to force Cloud Formation to call handler
        'RoleLogicalId': properties.String(),
        'MetadataKey': properties.String(),
        'PhysicalResourceId': properties.String(),
        'UsePropagationDelay': properties.String(),
        'RequireRoleExists': properties.String(default='true'),
        'ResourceGroupStack': properties.String(default=''),
        'DeploymentStack': properties.String(default='')})

    if props.ResourceGroupStack is '' and props.DeploymentStack is '':
        raise ValidationError('A value for the ResourceGroupStack property or the DeploymentStack property must be provided.')

    if props.ResourceGroupStack is not '' and props.DeploymentStack is not '':
        raise ValidationError('A value for only the ResourceGroupStack property or the DeploymentStack property can be provided.')

    use_propagation_delay = props.UsePropagationDelay.lower() == 'true'
    
    data = {}
    stack_infos = []
    
    if props.ResourceGroupStack is not '':
        resource_group_info = stack_info.ResourceGroupInfo(props.ResourceGroupStack)
        
        # create a list of stack-infos, starting at the resource group level and working our way upward
        stack_infos = _build_stack_infos_list(resource_group_info) 
        
    else: # DeploymentStack
        deployment_info = stack_info.DeploymentInfo(props.DeploymentStack)
        
        # create a list of stack-infos, starting at the deployment level and working our way upward
        stack_infos = _build_stack_infos_list(deployment_info)
    
    # go through each of the stack infos, trying to find the specified role
    for stack in stack_infos:
        role = stack.resources.get_by_logical_id(props.RoleLogicalId, expected_type='AWS::IAM::Role', optional=True)
        
        if role is not None:
            break

    role_physical_id = None
    if role is not None:
        role_physical_id = role.physical_id

    if role_physical_id is None:
        if props.RequireRoleExists.lower() == 'true':
            raise ValidationError('Could not find role \'{}\'.'.format(props.RoleLogicalId))
    else:
        if type(stack_infos[0]) is stack_info.ResourceGroupInfo:
            _process_resource_group_stack(event['RequestType'], stack_infos[0], role_physical_id, props.MetadataKey, use_propagation_delay)
        else:
            for resource_group_info in stack_infos[0].resource_groups:
                _process_resource_group_stack(event['RequestType'], resource_group_info, role_physical_id, props.MetadataKey, use_propagation_delay)

    custom_resource_response.succeed(event, context, data, props.PhysicalResourceId)
Пример #5
0
 def test_constructor(self):
     target = stack_info.DeploymentInfo(
         MOCK_STACK_ARN,
         client=MOCK_CLIENT,
         stack_description=MOCK_STACK_DESCRIPTION)
     self.assertEquals(target.stack_type,
                       stack_info.StackInfo.STACK_TYPE_DEPLOYMENT)
     self.assertIs(target.client, MOCK_CLIENT)
     self.assertIs(target.stack_description, MOCK_STACK_DESCRIPTION)
Пример #6
0
 def test_deployment_access_arn_discovered_with_access_denied(self):
     mock_describe_stacks_result = ClientError(
         {'Error': {
             'Code': 'ValidationError'
         }}, 'describe-stacks')
     mock_deployment_access_stack_name = MOCK_STACK_NAME + '-Access'
     with mock_aws.patch_client('cloudformation',
                                'describe_stacks',
                                side_effect=mock_describe_stacks_result
                                ) as mock_describe_stacks:
         target = stack_info.DeploymentInfo(MOCK_STACK_ARN)
         actual_deployment_access = target.deployment_access
         self.assertIsNone(actual_deployment_access)
         mock_describe_stacks.assert_called_once_with(
             StackName=mock_deployment_access_stack_name)
Пример #7
0
 def test_resource_groups(self):
     mock_physical_resource_id_1 = 'mock_physical_resource_id_1'
     mock_physical_resource_id_2 = 'mock_physical_resource_id_2'
     mock_logical_resource_id_1 = 'mock_logical_id_1'
     mock_logical_resource_id_2 = 'mock_logical_id_2'
     mock_resource_1 = mock.MagicMock()
     mock_resource_1.physical_id = mock_physical_resource_id_1
     mock_resource_1.logical_id = mock_logical_resource_id_1
     mock_resource_1.type = 'AWS::CloudFormation::Stack'
     mock_resource_2 = mock.MagicMock()
     mock_resource_2.physical_id = mock_physical_resource_id_2
     mock_resource_2.logical_id = mock_logical_resource_id_2
     mock_resource_2.type = 'AWS::CloudFormation::Stack'
     mock_resource_3 = mock.MagicMock()
     mock_resource_3.physical_id = 'not-used'
     mock_resource_3.logical_id = 'not-used'
     mock_resource_3.type = 'not-a-stack'
     mock_resource_4 = mock.MagicMock()
     mock_resource_4.physical_id = 'not-used'
     mock_resource_4.logical_id = 'not-used'
     mock_resource_4.type = 'not-a-stack'
     mock_resources = [
         mock_resource_3, mock_resource_1, mock_resource_4, mock_resource_2
     ]
     mock_resource_group_1 = 'test-resource-group-1'
     mock_resource_group_2 = 'test-resource-group-2'
     mock_resource_groups = [mock_resource_group_1, mock_resource_group_2]
     with mock.patch(
             'stack_info.ResourceGroupInfo',
             side_effect=mock_resource_groups) as mock_ResourceGroupInfo:
         with mock.patch('stack_info.DeploymentInfo.resources',
                         new_callable=mock.PropertyMock,
                         return_value=mock_resources):
             target = stack_info.DeploymentInfo(MOCK_STACK_ARN,
                                                client=MOCK_CLIENT)
             actual_resource_groups = target.resource_groups
             self.assertItemsEqual(actual_resource_groups,
                                   mock_resource_groups)
             mock_ResourceGroupInfo.assert_any_call(
                 mock_physical_resource_id_1,
                 resource_group_name=mock_logical_resource_id_1,
                 client=target.client,
                 deployment_info=target)
             mock_ResourceGroupInfo.assert_any_call(
                 mock_physical_resource_id_2,
                 resource_group_name=mock_logical_resource_id_2,
                 client=target.client,
                 deployment_info=target)
Пример #8
0
 def test_deployment_access_arn_discovered_with_not_access_denied(self):
     mock_error_code = 'SomeErrorCode'
     mock_describe_stacks_result = ClientError(
         {'Error': {
             'Code': mock_error_code
         }}, 'describe-stacks')
     mock_deployment_access_stack_name = MOCK_STACK_NAME + '-Access'
     with mock_aws.patch_client('cloudformation',
                                'describe_stacks',
                                side_effect=mock_describe_stacks_result
                                ) as mock_describe_stacks:
         target = stack_info.DeploymentInfo(MOCK_STACK_ARN)
         with self.assertRaisesRegexp(ClientError, mock_error_code):
             actual_deployment_access = target.deployment_access
         mock_describe_stacks.assert_called_once_with(
             StackName=mock_deployment_access_stack_name)
Пример #9
0
 def test_deployment_access_arn_provided(self):
     mock_deployment_access = 'test-deployment-access'
     with mock.patch('stack_info.DeploymentAccessInfo',
                     return_value=mock_deployment_access
                     ) as mock_DeploymentAccessInfo:
         mock_deployment_access_stack_arn = 'deployment-access-stack-arn'
         target = stack_info.DeploymentInfo(
             MOCK_STACK_ARN,
             deployment_access_stack_arn=mock_deployment_access_stack_arn,
             client=MOCK_CLIENT)
         actual_deployment_access = target.deployment_access
         self.assertIs(actual_deployment_access, mock_deployment_access)
         mock_DeploymentAccessInfo.assert_called_once_with(
             mock_deployment_access_stack_arn,
             deployment_info=target,
             client=MOCK_CLIENT)
Пример #10
0
 def test_project_discovered(self):
     mock_project_stack_id = 'test-project-stack-id'
     mock_project = 'test-project-info'
     mock_parameters = {'ProjectStackId': mock_project_stack_id}
     with mock.patch('stack_info.ProjectInfo',
                     return_value=mock_project) as mock_ProjectInfo:
         with mock.patch(
                 'stack_info.DeploymentInfo.parameters',
                 new=mock.PropertyMock(return_value=mock_parameters)):
             target = stack_info.DeploymentInfo(MOCK_STACK_ARN,
                                                client=MOCK_CLIENT)
             actual_project = target.project
             actual_project_2 = target.project
             self.assertIs(actual_project, mock_project)
             self.assertIs(actual_project_2, mock_project)
             mock_ProjectInfo.assert_called_once_with(mock_project_stack_id,
                                                      client=MOCK_CLIENT)
Пример #11
0
 def test_project_provided(self):
     mock_project_info = 'test-project-info'
     target = stack_info.DeploymentInfo(MOCK_STACK_ARN,
                                        project_info=mock_project_info)
     self.assertIs(target.project, mock_project_info)