serverless-heaven / serverless-aws-alias

Alias support for Serverless 1.x
MIT License
189 stars 66 forks source link

Two functions with two different stream event sources default to same event source #139

Open austin43 opened 5 years ago

austin43 commented 5 years ago

When two functions are created, The alias stack creates two different eventSourceMappings. Each are bound to the first lambda function's stream.

handler: lambdaOne/index.index
role: LambdaOneRole
events:
  - stream: 
        Fn::ImportValue:
            KinesisStreamArn-${self:provider.stage}
handler: lambdaTwo/index.index
role: LambdaTwoRole
events:
  - stream:
        Fn::ImportValue:
            DynamodbStreamArn-${self:provider.stage}
//cloudformation-template-update-alias-stack.json
...
    "LambdaOneEventSourceMappingDynamodbMyTableStream": {
      "Type": "AWS::Lambda::EventSourceMapping",
      "DependsOn": [
        "LambdaOneAlias"
      ],
      "Properties": {
        "BatchSize": 10,
        "EventSourceArn": "arn:aws:kinesis:us-east-1:ACCOUNT_ID:stream/myKinesisStream",
        "FunctionName": {
          "Ref": "LambdaOneAlias"
        },
        "StartingPosition": "TRIM_HORIZON",
        "Enabled": "True"
      }
    },
    "LambdaTwoEventSourceMappingKinesisMyKinesisStream": {
      "Type": "AWS::Lambda::EventSourceMapping",
      "DependsOn": [
        "LambdaTwoAlias"
      ],
      "Properties": {
        "BatchSize": 10,
        "EventSourceArn": "arn:aws:kinesis:us-east-1:ACCOUNT_ID:stream/myKinesisStream",
        "FunctionName": {
          "Ref": "LambdaTwoAlias"
        },
        "StartingPosition": "TRIM_HORIZON",
        "Enabled": "True"
      }
    }

This binding is correct in cloudformation-template-update-stack.json, but for some reason the first function stream binding is always bound in the alias. If I reverse the order of LambdaOne and LambdaTwo in serverless.yml, the dynamo stream is bound to both rather than kinesis.

serverless 1.32.0 serverless-aws-alias 1.7.1 plugins:

austin43 commented 5 years ago

This appears to happen when you have defined roles for each lambda function separately. If the same permissions are placed in the default role, and I do not define explicit roles for my lambdas, it does not occur.

Tangentially, this also raises the question of why a default role is always expected by this plugin. If you do not use one, but have roles defined for each of your lambdas individually, serverless-aws-alias will fail with a message of: Cannot read property 'Properties' of undefined

https://github.com/HyperBrain/serverless-aws-alias/blob/master/lib/stackops/lambdaRole.js#L38

Should we be able to define the service with no default role?

austin43 commented 5 years ago

This seems to be related to an undefined stack output showing up. The stack output for the first stream binding gets stored in the stack as undefined, so it binds each subsequent eventSourceMapping to the same undefined name, thus causing LambdaTwo to bind to the kinesis stream instead of dynamo. Looking into why this happens and if it's a bug that only shows up with the way we're using the plugin, but would appreciate some insight if anyone has any.

mwillfox commented 5 years ago

I am also seeing this behavior. If I reference the kinesis stream ARN using Fn::GetAtt then those functions will have the correct event source mapping. However, if I reference the kinesis stream ARN directly or using some kind of custom variable, all functions will default to the same kinesis stream from the first.