L G
L G

Reputation: 507

!ImportValue in Serverless Framework not working

I'm attempting to export a DynamoDb StreamArn from a stack created in CloudFormation, then reference the export using !ImportValue in the serverless.yml.

But I'm getting this error message:

unknown tag !<!ImportValue> in "/codebuild/output/src/serverless.yml"

The cloudformation and serverless.yml are defined as below. Any help appreciated.

StackA.yml

AWSTemplateFormatVersion: 2010-09-09
Description: Resources for the registration site

Resources:
  ClientTable:
    Type: AWS::DynamoDB::Table
    DeletionPolicy: Retain
    Properties:
      TableName: client
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 2
        WriteCapacityUnits: 2
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES

Outputs:  
  ClientTableStreamArn:
      Description: The ARN for My ClientTable Stream
      Value: !GetAtt ClientTable.StreamArn
      Export:
        Name: my-client-table-stream-arn

serverless.yml

service: my-service

frameworkVersion: ">=1.1.0 <2.0.0"

provider:
  name: aws
  runtime: nodejs6.10
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:DescribeStream
        - dynamodb:GetRecords
        - dynamodb:GetShardIterator
        - dynamodb:ListStreams
        - dynamodb:GetItem
        - dynamodb:PutItem
      Resource: arn:aws:dynamodb:*:*:table/client

functions:

  foo:
    handler: foo.main
    events:
      - stream:
          type: dynamodb
          arn: !ImportValue my-client-table-stream-arn
          batchSize: 1

Upvotes: 7

Views: 12082

Answers (4)

lpp
lpp

Reputation: 1

I couldn't find it clearly documented anywhere but what seemed to resolve the issue for me is:

For the Variables which need to be exposed/exported in outputs, they must have an "Export" property with a "Name" sub-property:

In serverless.ts

resources: {
    Resources: resources["Resources"],
    Outputs: {
     // For eventbus
      EventBusName: {
        Export: {
          Name: "${self:service}-${self:provider.stage}-UNIQUE_EVENTBUS_NAME",
        },
        Value: {
          Ref: "UNIQUE_EVENTBUS_NAME",
        },
      },
     // For something like sqs, or anything else, would be the same
      IDVerifyQueueARN: {
        Export: {
          Name: "${self:service}-${self:provider.stage}-UNIQUE_SQS_NAME",
        },
        Value: { "Fn::GetAtt": ["UNIQUE_SQS_NAME", "Arn"] },
      }
    },
 }

Once this is deployed you can check if the exports are present by running in the terminal (using your associated aws credentials):

aws cloudformation list-exports

Then there should be a Name property in a list:

{
  "ExportingStackId": "***",
  "Name": "${self:service}-${self:provider.stage}-UNIQUE_EVENTBUS_NAME", <-- same as given above (but will be populated with your service and stage)
  "Value": "***"
}

And then if the above is successful, you can reference it with "Fn::ImportValue" like so, e.g.:

"Resource": {
  "Fn::ImportValue": "${self:service}-${self:provider.stage}-UNIQUE_EVENTBUS_NAME",  <-- same as given above (but will be populated with your service and stage)
}

Upvotes: 0

Jenya Y.
Jenya Y.

Reputation: 3230

I struggled with this as well, and what did trick for me was:

functions:
  foo:
    handler: foo.main
    events:
      - stream:
         type: dynamodb
         arn: 
          !ImportValue my-client-table-stream-arn
         batchSize: 1

Note, that intrinsic functions ImportValue is on a new line and indented, otherwise the whole event is ignored when cloudformation-template-update-stack.json is generated.

Upvotes: 3

L G
L G

Reputation: 507

Solved by using ${cf:stackName.outputKey}

Upvotes: 20

Jamie Starke
Jamie Starke

Reputation: 9234

It appears that you're using the !ImportValue shorthand for CloudFormation YAML. My understanding is that when CloudFormation parses the YAML, and !ImportValue actually aliases Fn::ImportValue. According to the Serverless Function documentation, it appears that they should support the Fn::ImportValue form of imports.

Based on the documentation for Fn::ImportValue, you should be able to reference the your export like

  - stream:
      type: dynamodb
      arn: {"Fn::ImportValue": "my-client-table-stream-arn"}
      batchSize: 1

Hope that helps solve your issue.

Upvotes: 3

Related Questions