serverless: EventBridge event setting arn with ImportValue causes TypeError
Bug Report
Description
- What did you do?
- Trying to import a Custom event bus arn from another stack caused a type error.
- What happened?
- Failed with error
- Retried using inline
!ImportValuesyntax also failed - Tried with a hardcoded arn and successfully deployed
- What should’ve happened?
- Stack deploy with event from imported bus
- What’s the content of your
serverless.ymlfile?
Framework Core: 1.59.1
Plugin: 3.2.5
SDK: 2.2.1
Components Core: 1.1.2
Components CLI: 1.4.0
service: Example
custom:
env: ${file(.env.yml)}
provider:
name: aws
profile: ${opt:aws-profile, self:custom.env.defaults.profile}
stage: ${opt:stage, self:custom.env.defaults.stage}
region: ${opt:region, self:custom.env.defaults.region}
runtime: nodejs12.x
functions:
testFunc:
handler: src/this/is/a/test.handler
events:
- eventBridge:
eventBus:
Fn::ImportValue: OtherStackBusArn
# also tried -
# eventBus: !ImportValue OtherStackBusArn
pattern:
source:
- event.test
- What’s the output you get when you use the
SLS_DEBUG=*environment variable (e.g.SLS_DEBUG=* serverless deploy)
TypeError: EventBus.startsWith is not a function
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/eventBridge/index.js:121:30
at Array.forEach (<anonymous>)
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/eventBridge/index.js:29:28
at Array.forEach (<anonymous>)
at AwsCompileEventBridgeEvents.compileEventBridgeEvents (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/eventBridge/index.js:23:31)
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:489:55
From previous event:
at PluginManager.invoke (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:489:22)
at PluginManager.spawn (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:509:17)
at Deploy.<anonymous> (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:115:50)
From previous event:
at Object.before:deploy:deploy [as hook] (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:100:30)
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:489:55
From previous event:
at PluginManager.invoke (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:489:22)
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:524:24
From previous event:
at PluginManager.run (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/classes/PluginManager.js:524:8)
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/Serverless.js:115:33
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
From previous event:
at Serverless.run (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/lib/Serverless.js:102:74)
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/bin/serverless.js:72:30
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:111:16
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:45:10
at FSReqCallback.oncomplete (fs.js:146:23)
From previous event:
at /######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/bin/serverless.js:72:8
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
From previous event:
at Object.<anonymous> (/######/.nvm/versions/node/v12.13.1/lib/node_modules/serverless/bin/serverless.js:61:4)
at Module._compile (internal/modules/cjs/loader.js:959:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
at Module.load (internal/modules/cjs/loader.js:815:32)
at Function.Module._load (internal/modules/cjs/loader.js:727:14)
at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
at internal/main/run_main_module.js:17:11
Similar or dependent issues:
- This issue from the forum about partner events seems at least tangentially related
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 10
- Comments: 41 (31 by maintainers)
@medikoo I have completed work on the branch linked to above to deploy EventBridge resources using CloudFormation. I have no doubt there will be changes needed as it is not a trivial change and I’ve had to do a lot learning about how the framework is operation to complete it. Are you happy for me to create a PR off of it and we can go from there?
Glad to help!
Just to recap, the workaround is not to use an imported value but passing the eventbus’ name instead of the ARN.
This virtually removes the ability of using eventbus’ ARN (it will only work when it’s hardcoded). I believe that’s fine as we can still use eventbus’ name. But, yes, it should be clarified in the documentation.
Summing up:
@DaveLo I’ve looked into that more deeply, and to me it appears that there’s inconsistency in our config design.
e.g. for S3 buckets or cognito user pools, resources are referenced by name, and via additional
existing: truesetting we eventually mark that given resource already exists, so there should not be creation attempt.While in case of event bridge, we resolve the intention from the name format (if it’s an ARN, we imply
existing: true, and if not, then we create).I believe right way to approach it, is to bring same
existing: truesetting support to event bridge configuration (and ensure that that CF instructions are supported for name), that way it’ll work for you as expected. (Unfortunately to not break things in v1, we still need to support ARN resolution).@pmuens What do you think about that?
Thank you both @cjuega and @capgadsx - I believe I know what the issue is here. In order to generate proper
AWS:SourceArnwe need to have the ability to extractnameof the event bus. It was possible to do when using explicitarnpassed as a string, however, when passing arn with CF intrinsic command, it’s impossible to reason aboutname, which results in invalidSourceArnbeing generated. The proper approach in that situation would be to pass imported name as suggested in workaround by @cjuega. I believe we should clarify that in the documentation.What is the current situation regarding this case? Is a bug fix planned?
Thanks @DaveLo for looking into that.
Firstly, this issue comes from fact, that CloudFormation instructions are not normally supported on serverless configuration level. Technically they can be supported only if given setting value is propagated as is to CloudFormation template property (where given instruction is supported), but it requires further effort to implement such support.
Ideally Framework should fail with a meaningful error on such attempts, but it doesn’t (hence ugly errors as
EventBus.startsWith is not a function). We plan to address that at #6562Now, concerning your proposal (on bringing support for CF instruction format to
eventBusproperty):Currently the framework assumes event bus exists, only if value passed to
eventBusresolves to string that starts witharn. See, this setting is propagated as is to custom resource:https://github.com/serverless/serverless/blob/2938a95b8711d3bfab1e665318f46f66db91d6a4/lib/plugins/aws/package/compile/events/eventBridge/index.js#L94
and then read here:
https://github.com/serverless/serverless/blob/2938a95b8711d3bfab1e665318f46f66db91d6a4/lib/plugins/aws/customResources/resources/eventBridge/lib/eventBridge.js#L10
Hey, I thought I might take a crack at this. I looked at how it’s handled in SQS events, but I don’t think it tracks exactly.
From looking at the code it looks like we always want the event bus name not the arn so that it can be used in constructing the rule arn. maybe it’s easier to import the name by exporting the external Ref (name for EventBridge)? Then you could look for Fn::ImportValue (
(typeof EventBus !== 'string' && 'Fn::ImportValue' in EventBus)from sqs event) and workflow from there?@pgrzesik, do you mean before using the new
useCloudFormation: truefeature? I used to pass it explicitly in an envvar. Using!ImportValuethrown anEventBus.startsWith is not a functionerror as described in the bug report.According to serverless’ doc, this should be supported:
After the changes implemented at https://github.com/serverless/serverless/pull/8437, I would expect the following to also be supported:
am I missing something?
I’m experiencing issues with this implementation in serverless@v2.28.0. Here is my setup:
I have the following resource defined:
Then, in my lambda definitions, I use
!GetAtt DomainEventBus.Arnor!ImportValue DomainEventBusArnto indicate which eventbus triggers a lambda:Deployment works fine. It seems everything is correct. However, my lambdas are not triggered when events are sent to the bus. After some troubleshooting I have found lambdas’ Resource-based policy is wrong. In particular,
AWS:SourceArncondition has a wrong ARN. It seems eventbus’ name is not extracted from the ARN in order to build rule’s ARN.The quick workaround is to use
!Ref DomainEventBusto use eventbus’ name instead of its ARN.@stuartforrest-infinity, do you think your change may have broken this? Using ARN used to work when using custom resources to create the event bus.
@stuartforrest-infinity if it’s the case, then definitely we can include that, and all the instructions can be put into documentation of deprecation (we document each one here: https://www.serverless.com/framework/docs/deprecations/)
If you mean that this crash happens in custom resource lambda (during deployment), then it means that setup of access rules which this lambda needs, needs to be updated here:
https://github.com/serverless/serverless/blob/fbf99fa2abf9ce3bc13fc4a6c8439a650d3eaa4e/lib/plugins/aws/package/compile/events/eventBridge/index.js#L152-L168