Serverless-application-model: AWS::Serverless::Api .Stage and .Deployment attributes not supported despite documentation saying otherwise

Created on 21 Nov 2018  路  2Comments  路  Source: aws/serverless-application-model

Description:

The 2016-10-31 docs state

SAM will generate an API Gateway Stage and API Gateway Deployment for every AWS::Serverless::Api resource. If you want to refer to these properties in an intrinsic function such as Ref or Fn::GetAtt, you can append .Stage and .Deployment suffix to the API's Logical ID. SAM will convert it to the correct Logical ID of the auto-generated Stage or Deployment resource respectively.

When I try to use !GetAtt Api.Stage I get the errors:

Template error: resource Api does not support attribute type Stage in Fn::GetAtt

or

Template error: resource Api does not support attribute type Deployment in Fn::GetAtt

Steps to reproduce the issue:

  1. Submit the below template through the CloudFormation console
  2. View the Change Set

Template:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Bug demo

Resources:
  Api:
    Type: AWS::Serverless::Api
    Properties:
      StageName: "1"
      DefinitionBody:
        swagger: '2.0'
        info:
          description: Your first API with Amazon API Gateway. This is a sample API that integrates
            via HTTP with our demo Pet Store endpoints
          title: PetStore
        schemes:
        - https
        paths:
          "/":
            get:
              tags:
              - pets
              description: PetStore HTML web page containing API usage information
              consumes:
              - application/json
              produces:
              - text/html
              responses:
                '200':
                  description: Successful operation
                  headers:
                    Content-Type:
                      type: string
                      description: Media type of request
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: '200'
                    responseParameters:
                      method.response.header.Content-Type: "'text/html'"
                    responseTemplates:
                      text/html: |-
                        <html>
                            <head>
                                <style>
                                body {
                                    color: #333;
                                    font-family: Sans-serif;
                                    max-width: 800px;
                                    margin: auto;
                                }
                                </style>
                            </head>
                            <body>
                                <h1>Welcome to your Pet Store API</h1>
                                <p>
                                    You have succesfully deployed your first API. You are seeing this HTML page because the <code>GET</code> method to the root resource of your API returns this content as a Mock integration.
                                </p>
                                <p>
                                    The Pet Store API contains the <code>/pets</code> and <code>/pets/{petId}</code> resources. By making a <a href="/$context.stage/pets/" target="_blank"><code>GET</code> request</a> to <code>/pets</code> you can retrieve a list of Pets in your API. If you are looking for a specific pet, for example the pet with ID 1, you can make a <a href="/$context.stage/pets/1" target="_blank"><code>GET</code> request</a> to <code>/pets/1</code>.
                                </p>
                                <p>
                                    You can use a REST client such as <a href="https://www.getpostman.com/" target="_blank">Postman</a> to test the <code>POST</code> methods in your API to create a new pet. Use the sample body below to send the <code>POST</code> request:
                                </p>
                                <pre>
                        {
                            "type" : "cat",
                            "price" : 123.11
                        }
                                </pre>
                            </body>
                        </html>
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock

Outputs:
  api:
    Description: xxx
    Value: !Ref Api
  stage:
    Description: xxx
    Value: !GetAtt Api.Stage
  deploy:
    Description: xxx
    Value: !GetAtt Api.Deployment

!Ref Api works fine. The other 2 outputs should work but do not.

Observed result:
Error(s) in Change sets:

Template error: resource Api does not support attribute type Stage in Fn::GetAtt
Template error: resource Api does not support attribute type Deployment in Fn::GetAtt

Expected result:
No errors and the Outputs show the Stage and Deployment physical ids.

Most helpful comment

For anyone in google-land looking to use these with !Sub, you can use the long form:

Outputs:
  allthings:
    Description: all the things
    Value:
      Fn::Sub:
        - "api: ${api} - deploy: ${deploy} - stage: ${stage}"
        - api: !Ref Api
          deploy: !Ref Api.Deployment
          stage: !Ref Api.Stage

All 2 comments

You should use !Ref to access the .Stage and .Deployment physical ids.

For anyone in google-land looking to use these with !Sub, you can use the long form:

Outputs:
  allthings:
    Description: all the things
    Value:
      Fn::Sub:
        - "api: ${api} - deploy: ${deploy} - stage: ${stage}"
        - api: !Ref Api
          deploy: !Ref Api.Deployment
          stage: !Ref Api.Stage
Was this page helpful?
0 / 5 - 0 ratings

Related issues

yan12125 picture yan12125  路  3Comments

angustohrallegrinski picture angustohrallegrinski  路  3Comments

willdady picture willdady  路  3Comments

axpence picture axpence  路  3Comments

restfulhead picture restfulhead  路  4Comments