👻

[Cfn] APIGatewayで消したはずのOpenAPI定義が残っちゃう

2021/05/07に公開

問題

template.yaml
# 中略
Resources:
  Api:
    Type: AWS::ApiGateway::RestApi
    Properties:
      BodyS3Location:
        Bucket: 'bucket-name'
        Key: 'key'
      # 他省略
openapi.yaml
# 簡略化してます
openapi: 3.0.2
info:
  version: 0.0.1
paths:
  /v1/hoge/{hoge-id}:
    get:
      summary: get hoge api

openapi.yamlファイルがS3バケットに保存されており、そのOpenAPI定義を使ってRestApiリソースを作成します。
このテンプレートを元にスタックを作詞するとAPIGatewayには以下のようなリソースが作成されると思います。

/
  /v1
    /hoge
      /{hoge-id}
        GET

しかしその後hogeという名称がそぐわなかったのでfugaに変更しました

openapi.yaml
openapi: 3.0.2
info:
  version: 0.0.2
paths:
  /v1/fuga/{fuga-id}:
    get:
      summary: get fuga api

上記yamlファイルを再度S3に配置しなおしてスタックを更新します。

そうすると期待値として、APIGatewayのリソースは以下のようになってほしいです。

/
  /v1
    /fuga
      /{fuga-id}
        GET

しかし実際には以下のようになっていました。

/
  /v1
    /hoge
      /{hoge-id}
        GET
    /fuga
      /{fuga-id}
        GET

消したはずのhogeリソースが残ってしまっています。困った。

解決策

AWS::ApiGateway::RestApiドキュメントModeというプロパティの説明があります。

Mode
This property applies only when you use OpenAPI to define your REST API. The Mode determines how API Gateway handles resource updates.

「このプロパティは、OpenAPIを使用してRESTAPIを定義する場合にのみ適用されます。モードは、APIGatewayがリソースの更新を処理する方法を決定します。」 by google翻訳

Modeoverwriteを指定すると新しいOpenAPI定義で全てのリソースが上書きされ、mergeにすると既存のAPIと新しいAPIがマージされてしまいます。これっぽいです。

重要なのはその下の記述

If you don't specify this property, a default value is chosen. For REST APIs created before March 29, 2021, the default is overwrite. Otherwise, the default value is merge.

「このプロパティを指定しない場合は、デフォルト値が選択されます。 2021年3月29日より前に作成されたRESTAPIの場合、デフォルトは上書き(overwrite)です。それ以外の場合、デフォルト値はマージ(merge)です。」


というわけで4月に入ってからRestAPIを作成していたので、Modeプロパティはデフォルトのmergeが設定されていました。
mergeだと困る場合(たいてい困るのでは???)は明示的にoverwriteを指定するようにしましょう。

template.yaml
# 中略
Resources:
  Api:
    Type: AWS::ApiGateway::RestApi
    Properties:
      BodyS3Location:
        Bucket: 'bucket-name'
        Key: 'key'
      Mode: overwrite
      # 他省略

Discussion