aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.1k stars 53 forks source link

[AWS::Serverless::Api] BinaryMediaTypes does not delete items #1894

Closed FarrOut closed 5 months ago

FarrOut commented 6 months ago

Name of the resource

AWS::ApiGateway::RestApi

Resource Name

No response

Issue Description

Cloudformation can add, but not remove items from the list of BinaryMediaTypes. For both the BinaryMediaTypes property and when defined via DefinitionBody.

Expected Behavior

When delete items from BinaryMediaTypes, either from property or via Definition body, items should be removed from actual RestApi resource to align with state of template and stack.

Observed Behavior

Items can be added, but not removed.

Test Cases

Prep

  1. Create definition

Example definition body Save to ./definitions/pet-store.json

  1. Deploy

sam build sam deploy --guided

  1. Check resource

aws apigateway get-rest-api --rest-api-id xxxxxxxxx

{
    "id": "dosawg2e52",
    "name": "Example Pet Store",
    "description": "A Pet Store API.",
    "createdDate": "2024-01-10T08:31:26+02:00",
    "version": "1.0",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "ApiGatewayApi",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:eu-west-1:000000000000:stack/sam/db6b5330-af81-11ee-a8c4-06f5a3d9b00f",
        "aws:cloudformation:stack-name": "sam"
    },
    "disableExecuteApiEndpoint": false
}

No BinaryMediaTypes.

Tests

via DefinitionBody

  1. Add "x-amazon-apigateway-binary-media-types" node to definition
    "x-amazon-apigateway-binary-media-types":[        
        "text/plain",
        "application/json"
    ],
  1. sam build
  2. Update stack with same deploy
  3. Check resource

aws apigateway get-rest-api --rest-api-id xxxxxxxxx

{
    "id": "dosawg2e52",
    "name": "Example Pet Store",
    "description": "A Pet Store API.",
    "createdDate": "2024-01-10T08:31:26+02:00",
    "version": "1.0",
    "binaryMediaTypes": [
        "text/plain",
        "application/json"
    ],
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "ApiGatewayApi",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:eu-west-1:000000000000:stack/sam/db6b5330-af81-11ee-a8c4-06f5a3d9b00f",
        "aws:cloudformation:stack-name": "sam"
    },
    "disableExecuteApiEndpoint": false
}

Both BinaryMediaTypes present. As expected.

  1. Remove an item from BinaryMediaTypes in definition

Before

    "x-amazon-apigateway-binary-media-types":[        
        "text/plain",
        "application/json"
    ],

After

    "x-amazon-apigateway-binary-media-types":[        
        "application/json"
    ],
  1. Update stack

sam build sam deploy

  1. Check resource

aws apigateway get-rest-api --rest-api-id xxxxxxxxx

{
    "id": "dosawg2e52",
    "name": "Example Pet Store",
    "description": "A Pet Store API.",
    "createdDate": "2024-01-10T08:31:26+02:00",
    "version": "1.0",
    "binaryMediaTypes": [
        "text/plain",
        "application/json"
    ],
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "ApiGatewayApi",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:eu-west-1:000000000000:stack/sam/db6b5330-af81-11ee-a8c4-06f5a3d9b00f",
        "aws:cloudformation:stack-name": "sam"
    },
    "disableExecuteApiEndpoint": false
}

Both BinaryMediaTypes still there. "text/plain" was NOT removed!

via BinaryMediaTypes property

  1. Add items to BinaryMediaTypes property
      BinaryMediaTypes:
        - text/plain      
        - application/json
  1. sam build
  2. Update stack with same deploy
  3. Check resource

aws apigateway get-rest-api --rest-api-id xxxxxxxxx

{
    "id": "dosawg2e52",
    "name": "Example Pet Store",
    "description": "A Pet Store API.",
    "createdDate": "2024-01-10T08:31:26+02:00",
    "version": "1.0",
    "binaryMediaTypes": [
        "text/plain",
        "application/json"
    ],
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "ApiGatewayApi",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:eu-west-1:000000000000:stack/sam/db6b5330-af81-11ee-a8c4-06f5a3d9b00f",
        "aws:cloudformation:stack-name": "sam"
    },
    "disableExecuteApiEndpoint": false
}

Both BinaryMediaTypes present, as expected.

  1. Remove an item from BinaryMediaTypes property

Before

      BinaryMediaTypes:
        - text/plain      
        - application/json

After

      BinaryMediaTypes:
        - application/json
  1. Update stack

sam build sam deploy

  1. Check resource

aws apigateway get-rest-api --rest-api-id xxxxxxxxx

{
    "id": "dosawg2e52",
    "name": "Example Pet Store",
    "description": "A Pet Store API.",
    "createdDate": "2024-01-10T08:31:26+02:00",
    "version": "1.0",
    "binaryMediaTypes": [
        "text/plain",
        "application/json"
    ],
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "ApiGatewayApi",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:eu-west-1:000000000000:stack/sam/db6b5330-af81-11ee-a8c4-06f5a3d9b00f",
        "aws:cloudformation:stack-name": "sam"
    },
    "disableExecuteApiEndpoint": false
}

Both BinaryMediaTypes still there. "text/plain" was NOT removed!

Other Details

No response

BenoitLarouche27 commented 6 months ago

Hi,

We're not able to reproduce the issue you see. Are you sure your new Api definition is really updated and pushed to S3, or that your local file was correctly saved and/or built before being deployed?

Here's what we see:

For the sake of removing that S3 possibility, we applied the BodyDefinition directly on the SAM template, and using BinaryMediaTypes property:

Initial template with 2 BinaryMediaTypes

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  basic-aws-apigateway-demo
  Sample SAM Template for basic-aws-apigateway-demo

Resources:
  BasicAWSApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Staging
      BinaryMediaTypes:
      - text/plain
      - application/json
      DefinitionBody:
        swagger: '2.0'
        info:
          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'
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock

After a sam build and sam deploy:

% aws apigateway get-rest-api --rest-api-id 4uomb37w84
{
    "id": "4uomb37w84",
    "name": "PetStore",
    "createdDate": "2024-01-12T10:18:32-05:00",
    "binaryMediaTypes": [
        "application/json",
        "text/plain"
    ],
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "BasicAWSApiGateway",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-east-1:xxx:stack/basic-aws-apigateway-demo2/8baf7230-b15d-11ee-ae40-0a7d0d91019d",
        "aws:cloudformation:stack-name": "basic-aws-apigateway-demo2"
    },
    "disableExecuteApiEndpoint": false
}

Let's remove one from the template (here text/plain):

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  basic-aws-apigateway-demo
  Sample SAM Template for basic-aws-apigateway-demo

Resources:
  BasicAWSApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Staging
      BinaryMediaTypes:
      - application/json
      DefinitionBody:
        swagger: '2.0'
        info:
          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'
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                type: mock

Another sam build and sam deploy later, it's correctly removed from the API:

% aws apigateway get-rest-api --rest-api-id 4uomb37w84
{
    "id": "4uomb37w84",
    "name": "PetStore",
    "createdDate": "2024-01-12T10:18:32-05:00",
    "binaryMediaTypes": [
        "application/json"
    ],
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "EDGE"
        ]
    },
    "tags": {
        "aws:cloudformation:logical-id": "BasicAWSApiGateway",
        "aws:cloudformation:stack-id": "arn:aws:cloudformation:us-east-1:xxx:stack/basic-aws-apigateway-demo2/8baf7230-b15d-11ee-ae40-0a7d0d91019d",
        "aws:cloudformation:stack-name": "basic-aws-apigateway-demo2"
    },
    "disableExecuteApiEndpoint": false
}

I also tested the same thing in the region you used (eu-west-1) in case there was a regional difference, and I got the exact same result, and the BinaryMediaType was correctly removed by the update.

Could you validate your steps, retry and make sure that your template was correctly updated after your sam build commands? Please, also make sure you're not putting configuring the BinaryMediaType in both the Template-Definition and in the SAM Property, as this can lead to a weird state.