Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue defining onSuccess for Destination with Fn::Join function #7492

Closed
jliburd-nsi opened this issue Mar 20, 2020 · 7 comments
Closed

Issue defining onSuccess for Destination with Fn::Join function #7492

jliburd-nsi opened this issue Mar 20, 2020 · 7 comments
Assignees

Comments

@jliburd-nsi
Copy link

jliburd-nsi commented Mar 20, 2020

Bug Report

Description

  1. What did you do?
    I added a destination to my serverless framework template and defined the onSuccess attribute as a lambda function using the Fn::Join function.

  2. What happened?

When deploying the template I received an error "functionAddress.startsWith is not a function" (See below)

  1. What should've happened?

The serverless template should have deployed successfully. Please note that when I hardcode the Lambda ARN the deployment works fine

  1. What's the content of your serverless.yml file?

service: dev-test
#app and org for use with dashboard.serverless.com
#app: your-app-name
#org: your-org-name

frameworkVersion: "=1.67.0"

provider:
name: aws
runtime: nodejs12.x
stage: ${opt:stage, "dev"}
region: ${opt:region, "us-east-1"}
environment:
NODE_PATH: "./:/opt/nodejs/node_modules"

functions:
myTest:
handler: handler.main
description: Testing destinations
layers:
- Fn::Join:
- ''
- - 'arn:aws:lambda:'
- Ref: AWS::Region
- ':'
- Ref: AWS::AccountId
- ':layer:dev-libs:1'
events:
- http:
path: register
method: post
cors: true
destinations:
onSuccess: { 'Fn::Join': [':', ['arn:aws:lambda', { Ref: 'AWS::Region' }, { Ref: 'AWS::AccountId' }, 'function:hello-world-hello-test1']] }

  1. What's the output you get when you use the SLS_DEBUG=* environment variable (e.g. SLS_DEBUG=* serverless deploy)

Serverless: Load command interactiveCli
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command config:tabcompletion
Serverless: Load command config:tabcompletion:install
Serverless: Load command config:tabcompletion:uninstall
Serverless: Load command create
Serverless: Load command install
Serverless: Load command package
Serverless: Load command deploy
Serverless: Load command deploy:function
Serverless: Load command deploy:list
Serverless: Load command deploy:list:functions
Serverless: Load command invoke
Serverless: Load command invoke:local
Serverless: Load command info
Serverless: Load command logs
Serverless: Load command metrics
Serverless: Load command print
Serverless: Load command remove
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command slstats
Serverless: Load command plugin
Serverless: Load command plugin
Serverless: Load command plugin:install
Serverless: Load command plugin
Serverless: Load command plugin:uninstall
Serverless: Load command plugin
Serverless: Load command plugin:list
Serverless: Load command plugin
Serverless: Load command plugin:search
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command upgrade
Serverless: Load command uninstall
Serverless: Load command login
Serverless: Load command logout
Serverless: Load command generate-event
Serverless: Load command test
Serverless: Load command dashboard
Serverless: Load command output
Serverless: Load command output:get
Serverless: Load command output:list
Serverless: Load command param
Serverless: Load command param:get
Serverless: Load command param:list
Serverless: Invoke deploy
Serverless: Invoke package
Serverless: Invoke aws:common:validate
Serverless: Invoke aws:common:cleanupTempDir
Serverless: Packaging service...
Serverless: Excluding development dependencies...

Type Error ---------------------------------------------

TypeError: functionAddress.startsWith is not a function
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:611:28
at AwsCompileFunctions.ensureTargetExecutionPermission (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:618:7)
at AwsCompileFunctions.memoized [as ensureTargetExecutionPermission] (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/node_modules/lodash/lodash.js:10552:27)
at AwsCompileFunctions.compileFunctionDestinations (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:583:14)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:555:56
at ReadStream. (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:465:15)
at ReadStream.emit (events.js:223:5)
at ReadStream.EventEmitter.emit (domain.js:475:20)
at internal/fs/streams.js:218:14
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:57:14
at FSReqCallback.oncomplete (fs.js:146:23)
From previous event:
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:555:40
From previous event:
at AwsCompileFunctions.compileFunction (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:121:25)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:642:62
From previous event:
at AwsCompileFunctions.compileFunctions (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:642:22)
From previous event:
at Object.package:compileFunctions [as hook] (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/aws/package/compile/functions/index.js:32:12)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:490:55
From previous event:
at PluginManager.invoke (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:490:22)
at PluginManager.spawn (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:510:17)
at Deploy. (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:115:50)
From previous event:
at Object.before:deploy:deploy [as hook] (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:100:30)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:490:55
From previous event:
at PluginManager.invoke (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:490:22)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:525:24
From previous event:
at PluginManager.run (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/classes/PluginManager.js:525:8)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/Serverless.js:133:33
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
From previous event:
at Serverless.run (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/lib/Serverless.js:120:74)
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/bin/serverless.js:82:30
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:136:16
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:57:14
at FSReqCallback.oncomplete (fs.js:146:23)
From previous event:
at /home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/bin/serverless.js:82:8
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
From previous event:
at Object. (/home/tester/.nvm/versions/node/v12.14.1/lib/node_modules/serverless/bin/serverless.js:71:4)
at Module._compile (internal/modules/cjs/loader.js:955:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
at Module.load (internal/modules/cjs/loader.js:811:32)
at Function.Module._load (internal/modules/cjs/loader.js:723:14)
at Function.Module.runMain (internal/modules/cjs/loader.js:1043:10)
at internal/main/run_main_module.js:17:11

Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com

Your Environment Information ---------------------------
Operating System: linux
Node Version: 12.14.1
Framework Version: 1.67.0
Plugin Version: 3.5.0
SDK Version: 2.3.0
Components Version: 2.22.3

Possible similar issues:

@medikoo
Copy link
Contributor

medikoo commented Apr 8, 2020

@jliburd-nsi thanks for report.

Yes, currently the only supported values are function name or resource ARN

Therefore in your case you should input ARN as a string (you may use Serverless variables) and not as a CloudFormation instruction.

There's of course issue of error reporting in such case, that's a clear bug, that will be addressed once we have #7335 in

@jthomerson
Copy link
Contributor

@medikoo this is more than just an error reporting issue - it's a serious deficiency in the Destinations support. For example, I can't do this:

functions:
   sendToSlack:
      name: '${self:custom.objectPrefix}-sendToSlack'
      handler: src/SendAlertToSlack.handler
      environment:
         WEBHOOK_URL: '${self:custom.rootSettings.slackWebhookURL}'
      memorySize: 128
      timeout: 2
      events:
         -
            sns:
               arn: { Ref: 'AlertsTopic' }
               topicName: '${self:custom.objectPrefix}-Alerts'
      destinations:
         onFailure: { Ref: 'AlertsEmailFallbackTopic' }

In this example, I create two topics in the service - one that the alerts come into, which invokes a Lambda function. But if the Lambda fails, I want the message to go to a fallback topic that's created in the same service.

Because it's created in the same service, I can't just make an ARN string or else the dependency won't be recognized. Of course, just making ARN strings is a horrible hack anyway - you should use Ref or Fn::ImportValue.

This is an age-old problem that happens in many new integrations in the Serverless framework - support for strings and using framework-specific references (like the way to reference a function), but not supporting the (much more important) CloudFront-native Ref/import/export features.

@jthomerson
Copy link
Contributor

@jliburd-nsi if it helps, you can work around this defect by just making your own destination in the resources section of the template. Given my example in my last comment, you could add this to configure it:

resources:
   Resources:
      # Must manually configure the destinations until serverless#7492 is resolved
      # See https://github.com/serverless/serverless/issues/7492
      SendToSlackFallbackDestination:
         Type: 'AWS::Lambda::EventInvokeConfig'
         Properties:
            FunctionName: { Ref: 'SendToSlackLambdaFunction' }
            Qualifier: '$LATEST'
            MaximumRetryAttempts: 2
            MaximumEventAgeInSeconds: 120
            DestinationConfig:
               OnFailure: { Destination: { Ref: 'AlertsEmailFallbackTopic' } }

Note that this is not quite as good as if the framework did it for you, because we just have to use $LATEST for the qualifier. If the framework did it, it could point to the exact version that is being deployed. Unfortunately, the resource ID for the version resource is not something that can easily be referenced in a template because the framework generates an ID like SendToSlackLambdaVersiongB3IkjmYg6Wgpye0STcrCMsEoe1a8cvsTohzybdNgHo.

Also note that you'll have to give the function permission to publish to the topic - something that the framework would also presumably do for you. Here's an example, building on my earlier example, where you can add the sns:Publish permission to your function using iamRoleStatements. Note that I'm using the serverless-iam-roles-per-function plugin, as I highly recommend you do as well, but you could put this permission in your provider block, as is typical with Serverless stacks, if you want.

functions:
   sendToSlack:
      name: '${self:custom.objectPrefix}-sendToSlack'
      handler: src/SendAlertToSlack.handler
      environment:
         WEBHOOK_URL: '${self:custom.rootSettings.slackWebhookURL}'
      memorySize: 128
      timeout: 2
      events:
         -
            sns:
               arn: { Ref: 'AlertsTopic' }
               topicName: '${self:custom.objectPrefix}-Alerts'
      iamRoleStatements:
         -
            Effect: 'Allow'
            Action: 'sns:Publish'
            Resource: { Ref: 'AlertsEmailFallbackTopic' }

@medikoo
Copy link
Contributor

medikoo commented Aug 25, 2020

@jthomerson for configured destinations we need to also ensure proper execution permissions This is the reason why we limit supported ARN format variants

Still we're definitely open for improvement that adds support for other formats ensuring access rights are not affected.
Please open dedicated issue for it (outlining possible solution proposal)

I'm going to close this one, as it's a configuration validation issue, which will be addressed with #8017

@whisller
Copy link

whisller commented Dec 9, 2020

@jthomerson @medikoo In 2.15.0 I am still experiencing this issue for:

  destinations:
   onFailure: { "Fn::Join": [":", ["arn:aws:sqs", Ref: "AWS::Region", Ref: "AWS::AccountId", "${self:service}-synchronise-dlq"]] }

@medikoo
Copy link
Contributor

medikoo commented Dec 9, 2020

@whisller please create a bug report (respecting all it's remarks)

@metaory
Copy link

metaory commented Apr 11, 2022

simply forming the arn works fine:
onFailure: arn:aws:sqs:${aws:region}:${aws:accountId}:my-queue-dlq

instead of
onFailure: !Ref MyQueueDLQ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants