def handler(event, context): stack_arn = event['StackId'] stack = stack_info.StackInfoManager().get_stack_info(stack_arn) props = properties.load(event, {'ReferenceName': properties.String()}) request_type = event['RequestType'] if request_type not in ['Create', 'Update', 'Delete']: raise RuntimeError('Unexpected request type: {}'.format(request_type)) data = {} if request_type != 'Delete': data = { 'PhysicalId': _get_reference_physical_id(stack, props.ReferenceName) } physical_resource_id = aws_utils.construct_custom_physical_resource_id_with_data( stack_arn, event['LogicalResourceId'], {'ReferenceName': props.ReferenceName}) return custom_resource_response.success_response(data, physical_resource_id)
def handler(event, context): props = properties.load(event, PROPERTIES_SCHEMA) request_type = event['RequestType'] stack_arn = event['StackId'] logical_role_name = props.FunctionName stack_manager = stack_info.StackInfoManager() id_data = aws_utils.get_data_from_custom_physical_resource_id( event.get('PhysicalResourceId', None)) if request_type == 'Delete': role_utils.delete_access_control_role(id_data, logical_role_name) response_data = {} else: stack = stack_manager.get_stack_info(stack_arn) if request_type == 'Create': project_service_lambda_arn = _get_project_service_lambda_arn(stack) assume_role_service = 'lambda.amazonaws.com' role_arn = role_utils.create_access_control_role( stack_manager, id_data, stack_arn, logical_role_name, assume_role_service, default_policy=get_default_policy(project_service_lambda_arn)) elif request_type == 'Update': role_arn = role_utils.get_access_control_role_arn( id_data, logical_role_name) else: raise RuntimeError( 'Unexpected request type: {}'.format(request_type)) _add_built_in_settings(props.Settings.__dict__, stack) # Check if we have a folder just for this function, if not use the default output_key = input_key = _get_input_key(props) if not props.IgnoreAppendingSettingsToZip: output_key = _inject_settings(props.Settings.__dict__, props.Runtime, props.ConfigurationBucket, input_key, props.FunctionName) cc_settings = copy.deepcopy(props.Settings.__dict__) # Remove "Services" from settings because they get injected into the python code package during _inject_settings # TODO: move handling of project-level service interfaces to the same code as cross-gem interfaces if "Services" in cc_settings: del cc_settings["Services"] response_data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': output_key, 'Runtime': props.Runtime, 'Role': role_arn, 'RoleName': role_utils.get_access_control_role_name(stack_arn, logical_role_name), 'ComposedLambdaConfiguration': { 'Code': { 'S3Bucket': props.ConfigurationBucket, 'S3Key': output_key }, "Environment": { "Variables": cc_settings }, 'Role': role_arn, 'Runtime': props.Runtime }, "CCSettings": cc_settings } physical_resource_id = aws_utils.construct_custom_physical_resource_id_with_data( stack_arn, event['LogicalResourceId'], id_data) custom_resource_response.succeed(event, context, response_data, physical_resource_id)
def handler(event, context): """Entry point for the Custom::ServiceApi resource handler.""" stack_id = event['StackId'] request_type = event['RequestType'] logical_resource_id = event['LogicalResourceId'] logical_role_name = logical_resource_id stack_manager = stack_info.StackInfoManager() stack = stack_manager.get_stack_info(stack_id) rest_api_resource_name = stack.stack_name + '-' + logical_resource_id id_data = aws_utils.get_data_from_custom_physical_resource_id( event.get('PhysicalResourceId', None)) response_data = {} project_tags = { constant.PROJECT_NAME_TAG: stack.project_stack.project_name, constant.STACK_ID_TAG: stack_id } if request_type == 'Create': props = properties.load(event, PROPERTY_SCHEMA) role_arn = role_utils.create_access_control_role( stack_manager, id_data, stack.stack_arn, logical_role_name, API_GATEWAY_SERVICE_NAME) swagger_content = get_configured_swagger_content( stack, props, role_arn, rest_api_resource_name) rest_api_id = create_api_gateway(rest_api_resource_name, props, swagger_content) service_url = get_service_url(rest_api_id, stack.region) register_service_interfaces(stack, service_url, swagger_content) update_api_gateway_tags(rest_api_id, event, project_tags) response_data['Url'] = service_url id_data['RestApiId'] = rest_api_id elif request_type == 'Update': rest_api_id = id_data.get('RestApiId', None) if not rest_api_id: raise RuntimeError( 'No RestApiId found in id_data: {}'.format(id_data)) props = properties.load(event, PROPERTY_SCHEMA) role_arn = role_utils.get_access_control_role_arn( id_data, logical_role_name) swagger_content = get_configured_swagger_content( stack, props, role_arn, rest_api_resource_name) update_api_gateway(rest_api_id, props, swagger_content) service_url = get_service_url(rest_api_id, stack.region) register_service_interfaces(stack, service_url, swagger_content) update_api_gateway_tags(rest_api_id, event, project_tags) response_data['Url'] = service_url elif request_type == 'Delete': if not id_data: # The will be no data in the id if Cloud Formation cancels a resource creation # (due to a failure in another resource) before it processes the resource create # response. Apparently Cloud Formation has an internal temporary id for the # resource and uses it for the delete request. # # Unfortunately there isn't a good way to deal with this case. We don't have the # id data, so we can't clean up the things it identifies. At best we can allow the # stack cleanup to continue, leaving the rest API behind and role behind. print('WARNING: No id_data provided on delete.') else: rest_api_id = id_data.get('RestApiId', None) if not rest_api_id: raise RuntimeError( 'No RestApiId found in id_data: {}'.format(id_data)) delete_api_gateway(rest_api_id) service_url = get_service_url(rest_api_id, stack.region) unregister_service_interfaces(stack, service_url) del id_data['RestApiId'] role_utils.delete_access_control_role(id_data, logical_role_name) else: raise RuntimeError('Invalid RequestType: {}'.format(request_type)) physical_resource_id = aws_utils.construct_custom_physical_resource_id_with_data( event['StackId'], logical_resource_id, id_data) return custom_resource_response.success_response(response_data, physical_resource_id)
def handler(event, context): props = properties.load(event, PROPERTIES_SCHEMA) request_type = event['RequestType'] stack_arn = event['StackId'] logical_role_name = props.FunctionName stack_manager = stack_info.StackInfoManager() id_data = aws_utils.get_data_from_custom_physical_resource_id(event.get('PhysicalResourceId', None)) if request_type == 'Delete': role_utils.delete_access_control_role( id_data, logical_role_name) response_data = {} else: stack = stack_manager.get_stack_info(stack_arn) if request_type == 'Create': project_service_lambda_arn = _get_project_service_lambda_arn(stack) assume_role_service = 'lambda.amazonaws.com' role_arn = role_utils.create_access_control_role( stack_manager, id_data, stack_arn, logical_role_name, assume_role_service, default_policy = get_default_policy(project_service_lambda_arn)) elif request_type == 'Update': role_arn = role_utils.get_access_control_role_arn( id_data, logical_role_name) else: raise RuntimeError('Unexpected request type: {}'.format(request_type)) _add_built_in_settings(props.Settings.__dict__, stack) # give access to project level ServiceDirectory APIs # Other deployment-level APIs are handled in InterfaceDependeny resolver custom resource type permitted_arns = _add_services_settings(stack, props.Settings.__dict__, props.Services) _add_service_access_policy_to_role(role_arn, permitted_arns) # Check if we have a folder just for this function, if not use the default output_key = input_key = _get_input_key(props) if not props.IgnoreAppendingSettingsToZip: output_key = _inject_settings(props.Settings.__dict__, props.Runtime, props.ConfigurationBucket, input_key, props.FunctionName) response_data = { 'ConfigurationBucket': props.ConfigurationBucket, 'ConfigurationKey': output_key, 'Runtime': props.Runtime, 'Role': role_arn, 'RoleName': role_utils.get_access_control_role_name(stack_arn, logical_role_name), 'ComposedLambdaConfiguration': { 'Code': { 'S3Bucket': props.ConfigurationBucket, 'S3Key': output_key }, 'Role': role_arn, 'Runtime': props.Runtime } } physical_resource_id = aws_utils.construct_custom_physical_resource_id_with_data(stack_arn, event['LogicalResourceId'], id_data) custom_resource_response.succeed(event, context, response_data, physical_resource_id)