OM The Eternity
OM The Eternity

Reputation: 16204

CloudFormation Template is invalid: Template format error: Every Outputs member must contain a Value object

I have an AWS IoT Chat Application whose UI is on React and to do the AWS configuration I have a setup which is executed using "serverless deploy" command. When executed, a serverless.yml gets executed, and it breaks at a point where it throws an error as CloudFormation Template is invalid: Template format error: Every Outputs member must contain a Value object

the serverless.yml code is given below:

resources:
  Resources:
    UserTable:
      Type: "AWS::DynamoDB::Table"
      Properties:
        TableName: "IotChatUsers"
        AttributeDefinitions:
          - AttributeName: identityId
            AttributeType: S
        KeySchema:
          - AttributeName: identityId
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5

    ChatTable:
      Type: "AWS::DynamoDB::Table"
      Properties:
        TableName: "IotChatChats"
        AttributeDefinitions:
          - AttributeName: name
            AttributeType: S
        KeySchema:
          - AttributeName: name
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5

    ConnectPolicy:
      Type: "AWS::IoT::Policy"
      Properties:
        PolicyName: IotChatConnectPolicy
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
              - "iot:Connect"
            Resource:
              - "*"

    PublicSubscribePolicy:
      Type: "AWS::IoT::Policy"
      Properties:
        PolicyName: IotChatPublicSubscribePolicy
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
              - "iot:Subscribe"
            Resource: { "Fn::Join" : ["",["arn:aws:iot:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":topicfilter/room/public/*"]] }

    PublicReceivePolicy:
      Type: "AWS::IoT::Policy"
      Properties:
        PolicyName: IotChatPublicReceivePolicy
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
              - "iot:Receive"
            Resource: { "Fn::Join" : ["",["arn:aws:iot:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":topic/room/public/*"]] }

    UserPool:
      Type: "AWS::Cognito::UserPool"
      Properties:
        UserPoolName: iot_chat_api_user_pool
        AutoVerifiedAttributes:
          - email
        MfaConfiguration: OFF
        Schema:
          - AttributeDataType: String
            Name: email
            Required: true

    ReactAppClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
        GenerateSecret: false
        RefreshTokenValidity: 200
        UserPoolId:
          Ref: UserPool

    IdentityPool:
      Type: "AWS::Cognito::IdentityPool"
      Properties:
        IdentityPoolName: iot_chat_api_identity_pool
        AllowUnauthenticatedIdentities: false
        CognitoIdentityProviders:
          - ClientId:
              Ref: ReactAppClient
            ProviderName:
              Fn::GetAtt: UserPool.ProviderName
        SupportedLoginProviders:
          graph.facebook.com: ${self:custom.variables.facebook_app_id}
          accounts.google.com: ${self:custom.variables.google_app_id}

    IdentityPoolAuthRole:
      Type: "AWS::IAM::Role"
      Properties:
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: "Allow"
              Principal:
                Federated:
                  - "cognito-identity.amazonaws.com"
              Action:
                - "sts:AssumeRoleWithWebIdentity"
              Condition:
                StringEquals:
                  cognito-identity.amazonaws.com:aud:
                    Ref: IdentityPool
                ForAnyValue:StringLike:
                  cognito-identity.amazonaws.com:amr: authenticated
        ManagedPolicyArns:
          - arn:aws:iam::aws:policy/AWSIoTDataAccess
        Path: "/"
        Policies:
          - PolicyName: iot-chat-invoke-api-gateway
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - execute-api:Invoke
                  Resource: { "Fn::Join" : ["", ["arn:aws:execute-api:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":",{"Ref":"ApiGatewayRestApi"},"/*"]] }

    IdentityPoolRoleAttachment:
      Type: AWS::Cognito::IdentityPoolRoleAttachment
      Properties:
        IdentityPoolId:
          Ref: IdentityPool
        Roles:
          authenticated:
            Fn::GetAtt:
              - IdentityPoolAuthRole
              - Arn

    ConfirmUserInvocationPermission:
      Type: AWS::Lambda::Permission
      Properties:
        Action: lambda:InvokeFunction
        FunctionName:
          Fn::GetAtt: AutoConfirmUserLambdaFunction.Arn
        Principal: cognito-idp.amazonaws.com
        SourceArn:
          Fn::GetAtt: UserPool.Arn

  Outputs:
    UserPoolId:
      Description: "The ID of the user pool that is created."
      Value:
        Ref: UserPool

    ReactAppClientId:
      Description: "The ID of the user pool react app client id."
      Value:
        Ref: ReactAppClient

    IdentityPoolId:
      Description: "The ID of the identity pool that is created."
      Value:
        Ref: IdentityPool

    AutoConfirmUserFnArn:
      Description: "The ARN of the Auto Confirm User Lambda function"
      Value:
        Fn::GetAtt:
          - AutoConfirmUserLambdaFunction
          - Arn

    FacebookAppId:
      Description: "Facebook App Id"
      Value: ${self:custom.variables.facebook_app_id}

    GoogleAppId:
      Description: "Google App Id"
      Value: ${self:custom.variables.google_app_id}

I need some insight to figure out what is wrong with the serverless.yml which throws me this validation error.

Environment Information -----------------------------
     OS:                     win32
     Node Version:           8.9.1
     Serverless Version:     1.25.0

UPDATE:

On parsing the YAML below is the result of Outputs node:

"Outputs": {
      "IdentityPoolId": {
        "Description": "The ID of the identity pool that is created.", 
        "Value": {
          "Ref": "IdentityPool"
        }
      }, 
      "FacebookAppId": {
        "Description": "Facebook App Id", 
        "Value": "${self:custom.variables.facebook_app_id}"
      }, 
      "ReactAppClientId": {
        "Description": "The ID of the user pool react app client id.", 
        "Value": {
          "Ref": "ReactAppClient"
        }
      }, 
      "GoogleAppId": {
        "Description": "Google App Id", 
        "Value": "${self:custom.variables.google_app_id}"
      }, 
      "UserPoolId": {
        "Description": "The ID of the user pool that is created.", 
        "Value": {
          "Ref": "UserPool"
        }
      }, 
      "AutoConfirmUserFnArn": {
        "Description": "The ARN of the Auto Confirm User Lambda function", 
        "Value": {
          "Fn::GetAtt": [
            "AutoConfirmUserLambdaFunction", 
            "Arn"
          ]
        }
      }
    }

Update 2:

This is where the complete application comes from: aws-iot-chat-example

Upvotes: 2

Views: 12460

Answers (1)

Rodrigo Murillo
Rodrigo Murillo

Reputation: 13642

CloudFormation often provides vague or hard to track errors, and never reports errors with line numbers, like many interpreters/compilers/parsers. So tracking them down is often a process of trial and error.

In your case, the error message only mentioned that the error is in the Output section of the template, but it does not mention which value is the problem. You have 6 values in that section.

A good technique for troubleshooting is to remove each of the items one or 2 at a time, and re run the template. Since the output values are just that - only Outputs - they are not needed by this template, but instead expose data to other templates later in the creation process. Just remove them as suggested, and use this technique to isolate the field with the error in the value.

A good sanity check is the remove the entire Outputs section, and confirm that the reset of the template creates as expected.

Once you track down the fields(s) with the problem, you will need to track down the primary issue: Every Outputs member must contain a Value object

To resolve that, track down the object being referenced, and track back to the source resource or resource attribute. For some reason, those references do not refer to a valid object.

I will note that in your comments, you identified two fields that were both causing the error. Both seem to use a variable reference in the form of self:custom.variables.google_app_id - These value are not resolving properly. Check their source as above. I suspect they are not being parsed properly. I do not recognize that construction as valid CloudFormation syntax.

Upvotes: 4

Related Questions