Stack Refactoring は擬似パラメータを引き継いだまま移動できるのか調べてみた

Stack Refactoring は擬似パラメータを引き継いだまま移動できるのか調べてみた

Clock Icon2025.02.12

こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。

先日、CloudFormation がスタックの分割や論理ID の変更を助力する stack refactoring 機能をリリースしました。

https://aws.amazon.com/jp/about-aws/whats-new/2025/02/reshape-aws-cloudformation-stack-refactoring/

この機能を見た時、 AWS::StackName を利用しているリソースへの影響はどうなるんだろう?と疑問に思ったので試してみました。

AWS::StackName を利用するリソースは引っ越しできない

ドキュメントに書いてありました。特定の擬似パラメータを利用しているリソースは引っ越しができないようです。

You cannot refactor a resource to a new stack if that stack uses certain pseudo parameters (Example: AWS::StackName).

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stack-refactoring.html

特定の と言われると具体的に何なの?となってしまう性なので、今回は試してみようと思います。

結論

具体的には以下の擬似パラメーターを利用するケースにおいて、リファクタが出来ない or 支障がありました。

  • AWS::NotificationARNs
    • 引っ越し先に通知オプションを作成できないため
  • AWS::StackName
  • AWS::StackId

やってみた

今回は擬似パラメーターを利用している SNS トピックをいくつか用意し、どれが移行できるのか検証してみます。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html

sns.yaml
Resources:
  TopicNotificationARNs:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Select ['0', !Ref AWS::NotificationARNs]
  TopicAccountId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::AccountId}
  TopicNoValue:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Ref AWS::NoValue
  TopicPartition:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Partition}
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}

AWS::NotificationARNs

まず初めに Notification ARN です。引っ越し先と引っ越し元の変更後のテンプレートを用意します。

moved_notification_arns.yaml
Resources:
  TopicNotificationARNs:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Select ['0', !Ref AWS::NotificationARNs]
removed_notification_arns.yaml
Resources:
  TopicAccountId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::AccountId}
  TopicNoValue:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Ref AWS::NoValue
  TopicPartition:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Partition}
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}

合わせて引っ越しするリソースのマッピングファイルを作成します。

refactor_notification_arns.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicNotificationARNs"
      },
      "Destination": {
          "StackName": "MovedNotificationARNs",
          "LogicalResourceId": "TopicNotificationARNs"
      }
  }
]

create-stack-refactor を行います。

aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_notification_arns.yaml StackName=MovedNotificationARNs,TemplateBody@=file://removed_notification_arns.yaml --enable-stack-creation --resource-mappings file://refactor_notification_arns.json
{
    "StackRefactorId": "566e740e-4b7b-4db4-96b1-49237bc1c8e4"
}

describe-stack-refactor を見てみます。Select できないと怒られていますね。

aws cloudformation describe-stack-refactor --stack-refactor-id 566e740e-4b7b-4db4-96b1-49237bc1c8e4
{
    "StackRefactorId": "566e740e-4b7b-4db4-96b1-49237bc1c8e4",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "MovedNotificationARNs"
    ],
    "ExecutionStatus": "UNAVAILABLE",
    "Status": "CREATE_FAILED",
    "StatusReason": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777: Template error: Fn::Select  cannot select nonexistent value at index 0"
}

移行先の Stack で通知オプションを指定できないため、失敗してしまいました。AWS::NotificationARNs は新規 Stack の場合、難しいと思われます。refactor.json の充実に期待ですね。

  create-stack-refactor
[--description <value>]
[--enable-stack-creation | --no-enable-stack-creation]
[--resource-mappings <value>]
--stack-definitions <value>
[--cli-input-json <value>]
[--generate-cli-skeleton <value>]
[--debug]
[--endpoint-url <value>]
[--no-verify-ssl]
[--no-paginate]
[--output <value>]
[--query <value>]
[--profile <value>]
[--region <value>]
[--version <value>]
[--color <value>]
[--no-sign-request]
[--ca-bundle <value>]
[--cli-read-timeout <value>]
[--cli-connect-timeout <value>]

https://docs.aws.amazon.com/cli/latest/reference/cloudformation/create-stack-refactor.html

AWS::AccountId

続いてアカウント ID です。元スタックで NotificationARN の部分を削除し、再デプロイしておきます。

sns.yaml
Resources:
  TopicAccountId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::AccountId}
  TopicNoValue:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Ref AWS::NoValue
  TopicPartition:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Partition}
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}

移行する MovedAccountId スタックのテンプレートは以下に設定します。

moved_account_id.yaml
Resources:
  TopicAccountId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::AccountId}

移行元のテンプレートも TopicAccountId を削除した状態にします。

removed_account_id.yaml
Resources:
  TopicNoValue:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Ref AWS::NoValue
  TopicPartition:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Partition}
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
refactor_account_id.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicAccountId"
      },
      "Destination": {
          "StackName": "MovedAccountId",
          "LogicalResourceId": "TopicAccountId"
      }
  }
]

こちらはうまく起動しているようです。

aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_account_id.yaml StackName=MovedAccountId,TemplateBody@=file://moved_account_id.yaml --enable-stack-creation --resource-mappings file://refactor_account_id.json
{
    "StackRefactorId": "11b3e56f-0970-4958-a100-d5b4f854fe77"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 11b3e56f-0970-4958-a100-d5b4f854fe77
{
    "StackRefactorId": "11b3e56f-0970-4958-a100-d5b4f854fe77",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedAccountId/42e670a0-e918-11ef-8529-066bc8b29dd1"
    ],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"
}

execute-stack-refactor でお引越しを実行します。

aws cloudformation execute-stack-refactor --stack-refactor-id 11b3e56f-0970-4958-a100-d5b4f854fe77

うまくお引越しできているようですね。

aws cloudformation execute-stack-refactor --stack-refactor-id 11b3e56f-0970-4958-a100-d5b4f854fe77
aws cloudformation describe-stack-refactor --stack-refactor-id 11b3e56f-0970-4958-a100-d5b4f854fe77
{
    "StackRefactorId": "11b3e56f-0970-4958-a100-d5b4f854fe77",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedAccountId/42e670a0-e918-11ef-8529-066bc8b29dd1"
    ],
    "ExecutionStatus": "EXECUTE_IN_PROGRESS",
    "Status": "CREATE_COMPLETE",
    "StatusReason": "User Initiated"
}

# 数分後

aws cloudformation describe-stack-refactor --stack-refactor-id 11b3e56f-0970-4958-a100-d5b4f854fe77
{
    "StackRefactorId": "11b3e56f-0970-4958-a100-d5b4f854fe77",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedAccountId/42e670a0-e918-11ef-8529-066bc8b29dd1"
    ],
    "ExecutionStatus": "EXECUTE_COMPLETE",
    "Status": "CREATE_COMPLETE"
}

AWS::NoValue

続いて NoValue です。同じく移行元/先のリソース定義を行いマッピングファイルも作成します。

moved_novalue.yaml
Resources:
  TopicNoValue:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: !Ref AWS::NoValue
removed_novalue.yaml
Resources:
  TopicPartition:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Partition}
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
refactor_novalue.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicNoValue"
      },
      "Destination": {
          "StackName": "MovedNovalue",
          "LogicalResourceId": "TopicNoValue"
      }
  }
]

はい、うまく動いていますね。

aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_novalue.yaml StackName=MovedNovalue,TemplateBody@=file://moved_novalue.yaml --enable-stack-creation --resource-mappings file://refactor_novalue.json
{
    "StackRefactorId": "b704e5a7-5046-4873-bbd8-0103c4148da7"
}
aws cloudformation describe-stack-refactor --stack-refactor-id b704e5a7-5046-4873-bbd8-0103c4148da7
{
    "StackRefactorId": "b704e5a7-5046-4873-bbd8-0103c4148da7",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedNovalue/34fbdbf0-e919-11ef-b5ad-062f8f02a6a1"
    ],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"
}
aws cloudformation execute-stack-refactor --stack-refactor-id b704e5a7-5046-4873-bbd8-0103c4148da7
aws cloudformation describe-stack-refactor --stack-refactor-id b704e5a7-5046-4873-bbd8-0103c4148da7
{
    "StackRefactorId": "b704e5a7-5046-4873-bbd8-0103c4148da7",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedNovalue/34fbdbf0-e919-11ef-b5ad-062f8f02a6a1"
    ],
    "ExecutionStatus": "EXECUTE_IN_PROGRESS",
    "Status": "CREATE_COMPLETE",
    "StatusReason": "User Initiated"
}
aws cloudformation describe-stack-refactor --stack-refactor-id b704e5a7-5046-4873-bbd8-0103c4148da7
{
    "StackRefactorId": "b704e5a7-5046-4873-bbd8-0103c4148da7",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedNovalue/34fbdbf0-e919-11ef-b5ad-062f8f02a6a1"
    ],
    "ExecutionStatus": "EXECUTE_COMPLETE",
    "Status": "CREATE_COMPLETE"
}

AWS::Partition, AWS::Region もうまく動いています。

AWS::Partition

moved_partition.yaml
Resources:
  TopicPartition:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Partition}
removed_partition.yaml
Resources:
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
refactor_partition.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicPartition"
      },
      "Destination": {
          "StackName": "MovedPartition",
          "LogicalResourceId": "TopicPartition"
      }
  }
]
aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_partition.yaml StackName=MovedPartition,TemplateBody@=file://moved_partition.yaml --enable-stack-creation --resource-mappings file://refactor_partition.json
{
    "StackRefactorId": "af10cab1-b67a-4584-b424-27077667573f"
}
aws cloudformation describe-stack-refactor --stack-refactor-id af10cab1-b67a-4584-b424-27077667573f
{
    "StackRefactorId": "af10cab1-b67a-4584-b424-27077667573f",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedPartition/50569dd0-e91a-11ef-b46c-06d64fd9cbf7"
    ],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"
}
aws cloudformation execute-stack-refactor --stack-refactor-id af10cab1-b67a-4584-b424-27077667573f
aws cloudformation describe-stack-refactor --stack-refactor-id af10cab1-b67a-4584-b424-27077667573f
{
    "StackRefactorId": "af10cab1-b67a-4584-b424-27077667573f",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedPartition/50569dd0-e91a-11ef-b46c-06d64fd9cbf7"
    ],
    "ExecutionStatus": "EXECUTE_IN_PROGRESS",
    "Status": "CREATE_COMPLETE"
}
aws cloudformation describe-stack-refactor --stack-refactor-id af10cab1-b67a-4584-b424-27077667573f
{
    "StackRefactorId": "af10cab1-b67a-4584-b424-27077667573f",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedPartition/50569dd0-e91a-11ef-b46c-06d64fd9cbf7"
    ],
    "ExecutionStatus": "EXECUTE_COMPLETE",
    "Status": "CREATE_COMPLETE"
}

AWS::Region

moved_region.yaml
Resources:
  TopicRegion:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::Region}
removed_region.yaml
Resources:
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
refactor_region.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicRegion"
      },
      "Destination": {
          "StackName": "MovedRegion",
          "LogicalResourceId": "TopicRegion"
      }
  }
]
aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_region.yaml StackName=MovedRegion,TemplateBody@=file://moved_region.yaml --enable-stack-creation --resource-mappings file://refactor_region.json
{
    "StackRefactorId": "5179bf65-5b8c-49bc-9760-fcf7075116a2"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 5179bf65-5b8c-49bc-9760-fcf7075116a2
{
    "StackRefactorId": "5179bf65-5b8c-49bc-9760-fcf7075116a2",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedRegion/71630bc0-e91b-11ef-bbcb-0ae1f3fc1ead"
    ],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"
}
aws cloudformation execute-stack-refactor --stack-refactor-id 5179bf65-5b8c-49bc-9760-fcf7075116a2 
aws cloudformation describe-stack-refactor --stack-refactor-id 5179bf65-5b8c-49bc-9760-fcf7075116a2
{
    "StackRefactorId": "5179bf65-5b8c-49bc-9760-fcf7075116a2",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedRegion/71630bc0-e91b-11ef-bbcb-0ae1f3fc1ead"
    ],
    "ExecutionStatus": "EXECUTE_IN_PROGRESS",
    "Status": "CREATE_COMPLETE"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 5179bf65-5b8c-49bc-9760-fcf7075116a2
{
    "StackRefactorId": "5179bf65-5b8c-49bc-9760-fcf7075116a2",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedRegion/71630bc0-e91b-11ef-bbcb-0ae1f3fc1ead"
    ],
    "ExecutionStatus": "EXECUTE_COMPLETE",
    "Status": "CREATE_COMPLETE"
}

AWS::StackId

続いて StackId です。本命ですね。

moved_stackid.yaml
Resources:
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
removed_stackid.yaml
Resources:
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
refactor_stackid.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicStackId"
      },
      "Destination": {
          "StackName": "MovedStackId",
          "LogicalResourceId": "TopicStackId"
      }
  }
]

実行すると Resource TopicStackId in stack arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777 does not match the destination resource's properties と、プロパティが一致しないと怒られていますね。想定通りです。

aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_stackid.yaml StackName=MovedStackId,TemplateBody@=file://moved_stackid.yaml --enable-stack-creation --resource-mappings file://refactor_stackid.json
{
    "StackRefactorId": "08148538-a15f-4ac2-9fae-7874c9a3192d"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 08148538-a15f-4ac2-9fae-7874c9a3192d
{
    "StackRefactorId": "08148538-a15f-4ac2-9fae-7874c9a3192d",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedStackId/178912b0-e91c-11ef-ada8-0eacca462481"
    ],
    "ExecutionStatus": "UNAVAILABLE",
    "Status": "CREATE_FAILED",
    "StatusReason": "`Resource TopicStackId in stack arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777 does not match the destination resource's properties`."
}

AWS::StackName

続いて StackName です。こちらもどうなるのでしょうか。

moved_stackname.yaml
Resources:
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
removed_stackname.yaml
Resources:
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
refactor_stackname.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicStackName"
      },
      "Destination": {
          "StackName": "MovedStackName",
          "LogicalResourceId": "TopicStackName"
      }
  }
]

おなじく、プロパティが一致しないエラーが発生しています。

aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_stackname.yaml StackName=MovedStackName,TemplateBody@=file://moved_stackname.yaml --enable-stack-creation --resource-mappings file://refactor_stackname.json
{
    "StackRefactorId": "2a50920d-9cc6-4aa6-b363-c82a55c0e461"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 2a50920d-9cc6-4aa6-b363-c82a55c0e461
{
    "StackRefactorId": "2a50920d-9cc6-4aa6-b363-c82a55c0e461",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedStackName/d0bba810-e91c-11ef-8c15-064dd119df7d"
    ],
    "ExecutionStatus": "UNAVAILABLE",
    "Status": "CREATE_FAILED",
    "StatusReason": "Resource TopicStackName in stack arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777 does not match the destination resource's properties."
}

AWS::URLSuffix

最後に URLSuffix です。

moved_urlsuffix.yaml
Resources:
  TopicURLSuffix:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::URLSuffix}
removed_urlsuffix.yaml
Resources:
  TopicStackName:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackName}
  TopicStackId:
    Type: AWS::SNS::Topic
    Properties:
      Tags:
        - Key: Presudo
          Value: !Sub puresudo-topic-${AWS::StackId}
refactor_urlsuffix.json
[
  {
      "Source": {
          "StackName": "sns",
          "LogicalResourceId": "TopicURLSuffix"
      },
      "Destination": {
          "StackName": "MovedURLSuffix",
          "LogicalResourceId": "TopicURLSuffix"
      }
  }
]

こちらは問題なく移動ができていますね。

aws cloudformation create-stack-refactor --stack-definitions StackName=sns,TemplateBody@=file://removed_urlsuffix.yaml StackName=MovedURLSuffix,TemplateBody@=file://moved_urlsuffix.yaml --enable-stack-creation --resource-mappings file://refactor_urlsuffix.json
{
    "StackRefactorId": "1f039bef-5640-405c-831e-79ffd012640e"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 1f039bef-5640-405c-831e-79ffd012640e
{
    "StackRefactorId": "1f039bef-5640-405c-831e-79ffd012640e",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedURLSuffix/4312be80-e91d-11ef-86e9-0a73a9754cb5"
    ],
    "ExecutionStatus": "AVAILABLE",
    "Status": "CREATE_COMPLETE"
}
aws cloudformation execute-stack-refactor --stack-refactor-id 1f039bef-5640-405c-831e-79ffd012640e 
aws cloudformation describe-stack-refactor --stack-refactor-id 1f039bef-5640-405c-831e-79ffd012640e
{
    "StackRefactorId": "1f039bef-5640-405c-831e-79ffd012640e",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedURLSuffix/4312be80-e91d-11ef-86e9-0a73a9754cb5"
    ],
    "ExecutionStatus": "EXECUTE_IN_PROGRESS",
    "Status": "CREATE_COMPLETE",
    "StatusReason": "User Initiated"
}
aws cloudformation describe-stack-refactor --stack-refactor-id 1f039bef-5640-405c-831e-79ffd012640e
{
    "StackRefactorId": "1f039bef-5640-405c-831e-79ffd012640e",
    "StackIds": [
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/sns/245220e0-e912-11ef-b334-0ec6a293c777",
        "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/MovedURLSuffix/4312be80-e91d-11ef-86e9-0a73a9754cb5"
    ],
    "ExecutionStatus": "EXECUTE_COMPLETE",
    "Status": "CREATE_COMPLETE"
}

まとめ

以上、「Stack Refactoring は擬似パラメータを引き継いだまま移動できるのか調べてみた」でした。

余談ですが CloudFormation のコンソールをみると、プロパティが一致しなかった StackName と StackId の移行先スタックが REVIEW_IN_PROGRESS で止まっていました。(適宜、削除してあげましょう)

2025-02-12 at 18.33.43-CloudFormation - スタック MovedStackName.png

なお、リファクタを実行しても、以下のエラーを出力していました。.

An error occurred (ValidationError) when calling the ExecuteStackRefactor operation: Cannot execute stack refactor [2a50920d-9cc6-4aa6-b363-c82a55c0e461] in its current status of [CREATE_FAILED]

このブログがどなたかの参考になれば幸いです。クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.