Banning
Banning

Reputation: 58

Lambda invoke Lambda via API Gateway

I can't seem to get this to work. I create 2 lambdas via C9. I'm using boto3 to invoke one lambda from another. Everything seems to work just fine via C9 but when I publish and try to access via API Gateway I keep getting "Endpoint request timed out" errors.

I know it can't be a timeout issue because I've set up my yaml files to have enough time to execute and the lambda right now are really simple (only returning a string)

here are my current yaml file. I'm wondering if maybe there are some sort of permissions I need to include for API Gateway in the second yaml

Lambda1

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Resources:
    api:
        Type: 'AWS::Serverless::Function'
        Properties:
        Description: ''
        Handler: api/lambda_function.lambda_handler
        MemorySize: 256
        Role: 'arn:aws:iam::820788395625:role/service-role/api_int-role'
        Runtime: python3.6
        Timeout: 30
        VpcConfig:
            SecurityGroupIds:
                - ...
            SubnetIds:
                - ...
        Policies: AWSLambdaFullAccess

Lambda2

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Resources:
    api:
        Type: 'AWS::Serverless::Function'
        Properties:
            Description: ''
            Handler: api/lambda_function.lambda_handler
            MemorySize: 512
            Role: 'arn:aws:iam::820788395625:role/service-role/api_int-role'
            Runtime: python3.6
            Timeout: 15
            VpcConfig:
                SecurityGroupIds:
                    - ...
                SubnetIds:
                    - ...

I just set up an API Gateway endpoint directly to Lambda2 and it returned no problem. So...

API Gateway -> Lambda 2 (works) API Gateway -> Lambda 1 -> Lambda 2 (does not work)

So for some reason when I want to call Lambda 2 via Lambda 1 over API Gateway it doesn't work.

Here is the code that is calling the 2nd Lambda

import json
import boto3

def lambda_handler(event, context):
    print('call boto3 client')
    lambda_client = boto3.client('lambda', region_name='us-east-1')
    print('boto3 client called')

    print('invoke lambda')
    env_response = lambda_client.invoke(
        FunctionName='cloud9-apiAlpha-api-TBSOYXLVBCLX',
        InvocationType='RequestResponse',
        Payload=json.dumps(event)
    )
    print('lambda invoked')

    print('env_response')
    print(env_response)
    print(env_response['Payload'])
    print(env_response['Payload'].read())

    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/json', 
            'Access-Control-Allow-Methods': 'POST,GET,OPTIONS,PUT,DELETE',
            'Access-Control-Allow-Origin': '*'
        },
        'body': 'HELLO WORLD!',
        'isBase64Encoded': False
    }

Now when I look at the logs it gets to print('invoke lambda') but then stops and timesout

Upvotes: 0

Views: 1109

Answers (2)

Banning
Banning

Reputation: 58

Finally found the solution. The answer to my particular problem was Lambda 1 & Lambda 2 were operating over VPC thus no internet connection. Once I removed VPC from Lambda 1 the invocation of Lambda 2 worked without any problems.

Just wanted to share in case I can save anyone else a weeks worth of debugging LOL

Upvotes: 1

amittn
amittn

Reputation: 2355

1.Invoking a Lambda from another Lambda can't be done without some configuration. In your .yml file, permission must be specified in order to invoke another Lambda. This can be accomplished by adding an iamRoleStatements section under the provider property or by add the simple policy AWSLambdaRole to the existing role attached to the lambda function_1.

provider:  
    name: aws
    runtime: <runtime goes here> # e.g. python3.6 or nodejs6.10
    iamRoleStatements:
      - Effect: Allow
        Action:
          - lambda:InvokeFunction
        Resource: "*" 

or do this add/attach this policy to your existing role attached to your lambda function_1 AWSLambdaRole

2.Invoking lambda function_1 code attached.

global LAMBDA_CLIENT
if not LAMBDA_CLIENT:
    LAMBDA_CLIENT = boto3.client('lambda')
try:
    encoded_payload = json.dumps({'message': 'this is an invokcation call form lambda_1'}).encode(UTF_8)

    invoke_resp = lambda_client.invoke(
        FunctionName='function_2',
        InvocationType='RequestResponse',
        Payload=encoded_payload)

    status_code = invoke_resp['StatusCode']
    if status_code != 200:
        LOGGER.error('error ')
    paylaod = invoke_resp['Payload'].read()
    resp = json.loads(payload)
    print(resp)
except Exception:

IF you are using InvocationType=RequestResponse then you can return some response form function_2.

Upvotes: 1

Related Questions