Search code examples
amazon-web-servicesaws-lambdaaws-cloudformationaws-api-gatewaynested-stack

Error understanding Apigateway and nested stack on AWS cloudformation


I working into decouple a big template with lambdas that use apigateway AWS. I resolve multiple errors about nested stack process, but currently error its not clear. Could you check whats its the problem into definitions?

Main stack show general error from api substack create, but api-substack show next error:

Template error: instance of Fn::Sub references invalid resource attribute CreateCatalogFunctionDev.Arn

Next show a code of templates:

Main Template

  SubStackAPIDev:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: https://s3.awsroute.com/substack-api.yaml
      TimeoutInMinutes: 5      
      Parameters:
        CreateCatalogFunctionDev: !GetAtt CreateCatalogFunctionDev.Outputs.CreateCatalogFunctionDev
      
      
  SubStackCreateCatalogDev:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      TemplateURL: https://s3.awsroute.com/substack-create-catalog.yaml
      TimeoutInMinutes: 5
      Parameters:
        APIDev: !GetAtt SubStackAPIDev.Outputs.APIGateway

SubStackCreateCatalogDev

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Description: >
  SAM template for create catalog


Parameters:
  SecretsManagerName:
    Type: String
    Description: "Secrets Manager Name"
  SnsTopicArn:
    Type: String
    Default: arn:aws:sns:us-west-2:XXXXXX:SNS-errorNotification
    Description: "Sns topic error handler email notification"
  APIDev:
    Type: AWS::Serverless::Api
    
Resources:
  LayerDev:
    Type: 'AWS::Serverless::LayerVersion'
    Properties:
      ContentUri: ../../layer
      CompatibleRuntimes:
        - python3.6
        - python3.7
        - python3.8
      RetentionPolicy: Delete
  CreateCatalogFunctionDev:
    Type: AWS::Serverless::Function
    Properties:
      Description: Recieve api request and and process data.
      CodeUri: ../../src/catalog/create_catalog/
      Handler: create_catalog.lambda_handler
      Runtime: python3.8
      FunctionName: CreateCatalogFunctionDev
      Role: arn:aws:iam::XXXXXXXX:role/lambda-essential-role
      Timeout: 480
      Environment:
        Variables:
          CREATE_CATALOG_SECRET_NAME: !Sub '${SecretsManagerName}'
          SNS_ARN: !Sub '${SnsTopicArn}'
      Layers:
        - arn:aws:lambda:us-west-2:XXXXXXX:layer:requests:1
        - arn:aws:lambda:us-west-2:XXXXXXX:layer:requests-oauthlib:1
        - !Ref LayerDev
      Events:
        CreateCatalogApiEvent:
          Type: Api
          Properties:
            Path: /api-channel/products/catalog
            Method: POST
            RestApiId: !Ref APIDev

SubStack API

AWSTemplateFormatVersion: "2010-09-09"

Transform: AWS::Serverless-2016-10-31

Description: >
  sub_channels_appi
   SAM template for API

Parameters:
  SwaggerFile:
    Type: String
    # TODO dejar URL de S3 de gitla-cicd
    Default: "s3://cf-templates-1hurrmgzyzoz3-ap-northeast-1/swagger_dev.yaml"
    Description: "This swagger file Amazon S3 path"
  SecretsManagerName:
    Type: String
    Default: "/channels/Dev"
    Description: "Secrets Manager Name"
  StageName:
    Type: String
    Default: "${stageVariables.alias}"
    Description: "This is the alias to the swagger file"
  UsaSupplyApiUrlDev:
    Type: String
    Default: "https://thecornercloud.com/developers/index.php/"
    Description: "Corner Cloud Staging"
  SnsTopicArn:
    Type: String
    Default: arn:aws:sns:us-west-2:000365055762:channels-errorNotification
    Description: "Sns topic error handler email notification"
  CreateCatalogFunctionDev:
    Type: String

Resources:
  #######################################
  # Serverless LayerVersion
  #######################################
  LayerDev:
    Type: 'AWS::Serverless::LayerVersion'
    Properties:
      ContentUri: ../../layer
      CompatibleRuntimes:
        - python3.6
        - python3.7
        - python3.8
      RetentionPolicy: Delete

  #######################################
  # Serverless API
  #######################################
  APIDev:
    Type: AWS::Serverless::Api
    Properties:
      Auth:
        ApiKeyRequired: true
      StageName: dev
      EndpointConfiguration: REGIONAL
      DefinitionBody:
        Fn::Transform:
          Name: AWS::Include
          Parameters:
            Location: !Ref SwaggerFile
      Variables:
        alias: dev

  #######################################
  # ApiGateway ApiKey
  #######################################
  APIKeyDev:
    Type: AWS::ApiGateway::ApiKey
    Properties:
      Name: "APIKeyDev"
      Description: "API Key Dev"
      Enabled: true
      GenerateDistinctId: false
      StageKeys:
        - RestApiId: !Ref APIDev
          StageName: !Ref APIDev.Stage

  #######################################
  # ApiGateway UsagePlan
  #######################################
  APIUsagePlanDev:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn: APIDev
    Properties:
      ApiStages:
        - ApiId: !Ref APIDev
          Stage: !Ref APIDev.Stage
      Quota:
        Limit: 5000
        Period: MONTH
      Throttle:
        BurstLimit: 200
        RateLimit: 100
      UsagePlanName: APIUsagePlanDev
  #######################################
  # ApiGateway UsagePlanKey
  #######################################
  APIUsagePlanKeyDev:
    Type: AWS::ApiGateway::UsagePlanKey
    Properties:
      KeyId: !Ref APIKeyDev
      KeyType: API_KEY
      UsagePlanId: !Ref APIUsagePlanDev

  #######################################
  # ApiGateway Deployment
  #######################################
  DeploymentApiIdDev:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref APIDev 
Outputs:

  APIGateway:
    Description: "API Gateway Reference"
    Value: !Ref APIDev
    Export:
      Name: !Join [":", [!Ref "AWS::StackName", "APIDev"]]

And finally the swagger file (honestly, I didn't define the api with this method and think that I want remove swagger if is possible). swagger-dev

swagger: "2.0"
info:
  version: "1.0.0"
  title: "APIDev"
tags:
  - name: "Channels"
    description: "Manage Channels process."
schemes:
  - "https"
x-amazon-apigateway-api-key-source: "HEADER"
securityDefinitions:
  APIKey:
    type: apiKey
    name: X-Api-Key
    in: header 
paths:
  /channels/products/catalog:
    post:
      tags:
        - "Channels"
      summary: " products catalog post."
      operationId: "ProductsCatalogPostDev"
      produces:
        - "application/json"
      responses:
        201:
          description: "Successful Operation"
        400:
          description: "Invalid parameters"
        401:
          description: "Unauthorized"
        405:
          description: "Validation exception"
      security:
        - APIKey: []
      x-amazon-apigateway-integration:
        uri:
          Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CreateCatalogFunctionDev.Arn}/invocations
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"

Solution

  • Your CreateCatalogFunctionDev is in a different sub-stack then APIDev. You can't reference resources directly across stacks. You either have to export/import their outputs, or pass the references as input parameters.