Hi,
I’m trying to build an app with serverless which has two services. One service defines a SNS topic which it publishes notifications about items becoming available. The other service (or job, really) picks up those notifications and does some processing.
Here’s the severless.yml for the bit that exports the SNS topic:
service: myspecialapp-feeds
app: myspecialapp
org: naxxfish
tenant: naxxfish
package:
individually: true
provider:
name: aws
runtime: nodejs12.x
region: eu-west-1
stage: ${opt:stage, 'dev'}
iamRoleStatements:
- Effect: "Allow"
Resource:
- "arn:aws:sns:eu-west-1:${self:custom.accountId}:${opt:stage, 'dev'}-feedUpdateRequested"
- !Ref ItemUpdatedNotificationTopic
Action:
- "sns:Publish"
- "sns:CreateTopic"
- Effect: "Allow"
Resource:
- { "Fn::GetAtt": [ "itemsTable", "Arn" ]}
- { "Fn::GetAtt": [ "feedsTable", "Arn" ]}
Action:
- "dynamodb:Scan"
- "dynamodb:GetItem"
- "dynamodb:UpdateItem"
- "dynamodb:PutItem"
functions:
getFeed:
handler: src/getFeed.get
events:
- http:
path: feed/{id}
method: get
updateFeed:
handler: src/updateFeed.update
environment:
itemUpdatedTopic: { "Ref": "ItemUpdatedNotificationTopic" } #"arn:aws:sns:eu-west-1:${self:custom.accountId}:${opt:stage, 'dev'}-itemUpdated"
events:
- sns:
topicName: "${opt:stage, 'dev'}-feedUpdateRequested"
displayName: "Update Feed Request"
scheduleFeedUpdates:
handler: src/scheduleFeedUpdates.scheduler
environment:
topicArn: "arn:aws:sns:eu-west-1:${self:custom.accountId}:${opt:stage, 'dev'}-feedUpdateRequested"
events:
- schedule: cron(0 * * * ? *)
plugins:
- serverless-offline
- serverless-dynamodb-local
- serverless-offline-sns
- serverless-pseudo-parameters
resources:
Outputs:
ItemUpdatedNotificationTopicArn:
Description: SNS topic which holds notifications of a new item becoming available
Value:
Ref: ItemUpdatedNotificationTopic
Export:
Name: ${self:custom.stage}-ItemUpdatedNotificationTopicArn
Resources:
ItemUpdatedNotificationTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: New Item notification
TopicName: ${self:custom.stage, 'dev'}-ItemUpdatedNotification
itemsTable:
Type: AWS::DynamoDB::Table
DeletionPolicy: Retain
Properties:
TableName: items
AttributeDefinitions:
- AttributeName: itemHash
AttributeType: S
KeySchema:
- AttributeName: itemHash
KeyType: HASH
BillingMode: PAY_PER_REQUEST
feedsTable:
Type: AWS::DynamoDB::Table
DeletionPolicy: Retain
Properties:
TableName: feeds
AttributeDefinitions:
- AttributeName: feedId
AttributeType: S
KeySchema:
- AttributeName: feedId
KeyType: HASH
BillingMode: PAY_PER_REQUEST
custom:
accountId: 123456789012
stage: ${opt:stage, self:provider.stage, 'dev'}
resourceStages:
prod: prod
dev: dev
resourceStage: ${self:custom.resourceStages.${self:custom.stage}, self:custom.resourceStages.dev}
And then here’s the other end that uses that SNS topic
service: myspecialapp-analyser
app: myspecialapp
org: naxxfish
tenant: naxxfish
package:
individually: true
provider:
name: aws
runtime: nodejs12.x
region: eu-west-1
stage: ${opt:stage, 'dev'}
iamRoleStatements:
- Effect: "Allow"
Action:
- "states:StartExecution"
Resource:
- ${self:resources.Outputs.ProcessItemStateMachine.Value}
functions:
analyseItem:
handler: src/analyseItem.analyse
environment:
stateMachineArn: ${self:resources.Outputs.ProcessItemStateMachine.Value}
mediaS3Bucket: ${self:resources.Outputs.MediaBucketName.Value}
events:
- sns:
arn: ${self:custom.itemUpdatedTopicArn}
topicName: ${self:custom.stage}-ItemUpdatedNotificationTopicArn
downloadItem:
handler: src/downloadItem.download
timeout: 60
stepFunctions:
stateMachines:
ProcessItemStateMachine: ${file(./src/state-machines.yml):ProcessItemStateMachine}
plugins:
- serverless-offline
- serverless-dynamodb-local
- serverless-offline-sns
- serverless-step-functions
- serverless-pseudo-parameters
resources:
Outputs:
ProcessItemStateMachine:
Description: The ARN of the process item state machine
Value: !GetAtt ProcessItemStateMachineStepFunctionsStateMachine.Arn
MediaBucketName:
Value:
Ref: MediaBucket
Resources:
MediaBucket:
Type: AWS::S3::Bucket
custom:
itemUpdatedTopicArn: !ImportValue "${self:custom.stage}-ItemUpdatedNotificationTopicArn"
accountId: 123456789012
stage: ${opt:stage, self:provider.stage}
resourceStages:
prod: prod
dev: dev
resourceStage: ${self:custom.resourceStages.${self:custom.stage}, self:custom.resourceStages.dev}
The first deploys fine, but the second gives me
An error occurred: IamRoleLambdaExecution - Unsupported attribute Arn.
I’m pretty perplexed as I can’t figure out which bit is using the unsupported attribute in that IamRoleLambdaExecution resource.
Any ideas as to what might be wrong here?
Thanks!