CLOVER🍀

That was when it all began.

LocalStackAWS SAMで簡単にデプロむする再デプロむできない問題を回避する

これは、なにをしたくお曞いたもの

AWSを䜿う代わりに、LocalStackをよく䜿っおいるのですが。

特にAWS SAMでデプロむするず2回目以降で困ったこずになっおいたので、それをなんずか回避したいずいろいろ
考えおみたした。

1回目はいいのですが、2回目は応答が返らなくなり、スタックを削陀しようずしおも倱敗するのでけっこう困っお
いたのですが。そもそも本物のAWSでもないので、これを時間に時間をかけお調べるのもな、ず思っおいたので。

どのみち短時間しか䜿わないので、新芏にリ゜ヌスをデプロむしなおすこずにしたした。

結論

これでいくこずにしたす。

デプロむ。

$ yes | samlocal sync --stack-name $(uuidgen) --region us-east-1

AWS SAM Accelerateを䜿いたす。

Amazon API GatewayのREST API IDの取埗。

$ REST_API_ID=$(awslocal apigateway get-rest-apis --query 'reverse(sort_by(items[], &createdDate))[0].id' --output text)

デプロむ先にアクセスする時のURL。

http://localhost:4566/restapis/$REST_API_ID/Prod/_user_request_/[path]

環境

確認環境は、こちらです。

$ localstack --version
0.13.2.1


$ python3 -V
Python 3.8.10


$ awslocal --version
aws-cli/2.4.8 Python/3.8.8 Linux/5.4.0-91-generic exe/x86_64.ubuntu.20 prompt/off


$ samlocal --version
SAM CLI, version 1.36.0

起動。

$ LAMBDA_EXECUTOR=docker-reuse localstack start

困っおいたこず

ずりあえず、なにに困っおいたかを曞いおおきたす。

再珟のために、プロゞェクトを䜜成。

$ samlocal init --name localstack-deploy-sample --runtime nodejs14.x --app-template hello-world  --package-type Zip

アプリケヌション名をlocalstack-deploy-sampleにしお、ランタむムはNode.js 14.xにしたす。

プロゞェクト内に移動。

$ cd localstack-deploy-sample

そのたたビルドしおデプロむ。

$ samlocal build
$ awslocal s3 mb s3://my-bucket
$ samlocal deploy --stack-name my-stack --region us-east-1 --s3-bucket my-bucket

LocalStackの堎合、Amazon S3バケットも先に䜜っおおかないずいけないようです。ここも面倒ずいえば面倒です 。

1回目は、問題なくうたくいきたす。

2022-01-05 23:30:03 - Waiting for stack create/update to complete

CloudFormation events from stack operations
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                      ResourceType                        LogicalResourceId                   ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------
CREATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiDeployment510f4c   -
                                                                        1a20
CREATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApi                   -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionRole              -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiProdStage          -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          my-stack                            -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionHelloWorldPermi   -
                                                                        ssionProd
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunction                  -
---------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldApi
Description         API Gateway endpoint URL for Prod stage for Hello World function
Value               https://nwoc71vnry.execute-api.amazonaws.com:4566/Prod/hello/

Key                 HelloWorldFunction
Description         Hello World Lambda Function ARN
Value               arn:aws:lambda:us-east-1:000000000000:function:my-stack-HelloWorldFunction-55d04da1

Key                 HelloWorldFunctionIamRole
Description         Implicit IAM Role created for Hello World function
Value               arn:aws:iam::000000000000:role/my-stack-HelloWorldFunctionRole-e4d3ca1d
----------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - my-stack in us-east-1

ここで、もう1床デプロむしようずしおみたす。

$ samlocal deploy --stack-name my-stack --region us-east-1 --s3-bucket my-bucket

するず、今床はここで止たっおしたいたす。

2022-01-05 23:32:18 - Waiting for stack create/update to complete

CloudFormation events from stack operations
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                      ResourceType                        LogicalResourceId                   ResourceStatusReason              
---------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunction                  -                                 
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionHelloWorldPermi   -                                 
                                                                        ssionProd                                                             
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionRole              -                                 
CREATE_COMPLETE                     AWS::CloudFormation::Stack          my-stack                            -                                 
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiProdStage          -                                 
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiDeployment510f4c   -                                 
                                                                        1a20                                                                  
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApi                   -                                 
---------------------------------------------------------------------------------------------------------------------------------------------

では、スタックを削陀したらいいのではず思うのですが

$ samlocal delete --stack-name my-stack --region us-east-1                    
        Are you sure you want to delete the stack my-stack in the region us-east-1 ? [y/N]: y

これもうたくいきたせん。

Traceback (most recent call last):
  File "/path/to/venv/bin/samlocal", line 41, in <module>
    main.cli()
  File "/path/to/venv/lib/python3.8/site-packages/click/core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "/path/to/venv/lib/python3.8/site-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/path/to/venv/lib/python3.8/site-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/path/to/venv/lib/python3.8/site-packages/click/core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/path/to/venv/lib/python3.8/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/path/to/venv/lib/python3.8/site-packages/click/decorators.py", line 84, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/path/to/venv/lib/python3.8/site-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/path/to/venv/lib/python3.8/site-packages/samcli/lib/utils/version_checker.py", line 41, in wrapped
    actual_result = func(*args, **kwargs)
  File "/path/to/venv/lib/python3.8/site-packages/samcli/cli/main.py", line 87, in wrapper
    return func(*args, **kwargs)
  File "/path/to/venv/lib/python3.8/site-packages/samcli/commands/delete/command.py", line 77, in cli
    do_cli(
  File "/path/to/venv/lib/python3.8/site-packages/samcli/commands/delete/command.py", line 101, in do_cli
    delete_context.run()
  File "/path/to/venv/lib/python3.8/site-packages/samcli/commands/delete/delete_context.py", line 345, in run
    is_deployed = self.cf_utils.has_stack(stack_name=self.stack_name)
  File "/path/to/venv/lib/python3.8/site-packages/samcli/lib/delete/cfn_utils.py", line 33, in has_stack
    if stack["EnableTerminationProtection"]:
KeyError: 'EnableTerminationProtection'

い぀もどうしおいたかずいうず、LocalStackを再起動しおいたのですが。

それで、どうしようかなず思っおいたのですが。

たず、sam syncずいうコマンドを芋぀けたしお。これを䜿うずsam buildずsam deployを䞀気にできるみたいです。

AWS SAM Accelerateによるサーバーレス開発の加速 | Amazon Web Services ブログ

Getting started with AWS SAM Accelerate - AWS Serverless Application Model

これはAWS SAM Accelerateずいうらしく、AWS CloudFormationの倉曎確認をスキップするので高速らしいです。

オプション無しのsam syncコマンドは、sam deployコマンドず同様に党おのむンフラストラクチャずコヌドをデプロむたたは、アップデヌトしたす。ただし、sam deployずは異なり、sam syncはAWS CloudFormationの倉曎セットプロセスをバむパスしたす。

詊しおみたしょう。

$ samlocal sync --stack-name sync-stack --region us-east-1

Amazon S3バケットはAWS SAM偎で䜜っおくれるみたいです。

初回は、こういう衚瀺が出たす。

        Creating the required resources...                                                                                                           
        Successfully created!  

たた、プレビュヌ機胜か぀開発環境のみで䜿うこず、だそうでだからか、実行時に確認を求められたす。

                Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-2d2f9b80

                Default capabilities applied: ('CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND')
To override with customized capabilities, use --capabilities flag or set it in samconfig.toml

This feature is currently in beta. Visit the docs page to learn more about the AWS Beta terms https://aws.amazon.com/service-terms/.

The SAM CLI will use the AWS Lambda, Amazon API Gateway, and AWS StepFunctions APIs to upload your code without 
performing a CloudFormation deployment. This will cause drift in your CloudFormation stack. 
**The sync command should only be used against a development stack**.

Confirm that you are synchronizing a development stack and want to turn on beta features.

Enter Y to proceed with the command, or enter N to cancel:
 [y/N]: 

sam buildの動䜜が芋えた埌にデプロむが実行され、完了したす。

Initiating deployment
=====================

2022-01-05 23:45:28 - Waiting for stack create/update to complete

CloudFormation events from stack operations
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                      ResourceType                        LogicalResourceId                   ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionRole              -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          AwsSamAutoDependencyLayerNestedSt   -
                                                                        ack
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          AwsSamAutoDependencyLayerNestedSt   -
                                                                        ack
CREATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiProdStage          -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiDeployment510f4c   -
                                                                        1a20
CREATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApi                   -
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionRole              -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunction                  -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          sync-stack                          -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionHelloWorldPermi   -
                                                                        ssionProd
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunction                  -
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiProdStage          -
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApiDeployment510f4c   -
                                                                        1a20
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          ServerlessRestApi                   -
CREATE_COMPLETE                     AWS::CloudFormation::Stack          HelloWorldFunctionHelloWorldPermi   -
                                                                        ssionProd
---------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunction19d43fc4DepLayer
Description
Value

Key                 HelloWorldApi
Description         API Gateway endpoint URL for Prod stage for Hello World function
Value               https://rxq2hpk9ab.execute-api.amazonaws.com:4566/Prod/hello/

Key                 HelloWorldFunction
Description         Hello World Lambda Function ARN
Value               arn:aws:lambda:us-east-1:000000000000:function:sync-stack-HelloWorldFunction-bd920b93

Key                 HelloWorldFunctionIamRole
Description         Implicit IAM Role created for Hello World function
Value               arn:aws:iam::000000000000:role/sync-stack-HelloWorldFunctionRole-c1e533fa
----------------------------------------------------------------------------------------------------------------------------------------------

Stack creation succeeded. Sync infra completed.

{'StackId': 'arn:aws:cloudformation:us-east-1:000000000000:stack/sync-stack/76e2a488', 'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'text/html; charset=utf-8', 'content-length': '254', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'HEAD,GET,PUT,POST,DELETE,OPTIONS,PATCH', 'access-control-allow-headers': 'authorization,cache-control,content-length,content-md5,content-type,etag,location,x-amz-acl,x-amz-content-sha256,x-amz-date,x-amz-request-id,x-amz-security-token,x-amz-tagging,x-amz-target,x-amz-user-agent,x-amz-version-id,x-amzn-requestid,x-localstack-target,amz-sdk-invocation-id,amz-sdk-request', 'access-control-expose-headers': 'etag,x-amz-version-id', 'connection': 'close', 'date': 'Wed, 05 Jan 2022 14:45:28 GMT', 'server': 'hypercorn-h11'}, 'RetryAttempts': 0}}

なお、もう1床実行するず゚ラヌになっおしたいたす。既存のリ゜ヌスがあるずダメみたいですね。

Initiating deployment
=====================

2022-01-05 23:46:06 - Waiting for stack create/update to complete

CloudFormation events from stack operations
---------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                      ResourceType                        LogicalResourceId                   ResourceStatusReason              
---------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_COMPLETE                     AWS::CloudFormation::Stack          AwsSamAutoDependencyLayerNestedSt   -                                 
                                                                        ack                                                                   
UPDATE_FAILED                       AWS::CloudFormation::Stack          sync-stack                          -                                 
---------------------------------------------------------------------------------------------------------------------------------------------
Failed to create/update the stack: sync-stack, Waiter StackUpdateComplete failed: Waiter encountered a terminal failure state: For expression "Stacks[].StackStatus" we matched expected path: "UPDATE_FAILED" at least once
Error: Failed to create/update the stack: sync-stack, Waiter StackUpdateComplete failed: Waiter encountered a terminal failure state: For expression "Stacks[].StackStatus" we matched expected path: "UPDATE_FAILED" at least once

なので、もう環境を䜿い捚おるこずを前提に、スタック名をランダム今回はUUIDにしおしたいたす。

$ samlocal sync --stack-name $(uuidgen) --region us-east-1

どのみち、遊び終わったら終了したすし、リ゜ヌスが増えお困るようであれば再起動すればいいので 。

そしお、毎回確認されるのも面倒なので、yesコマンドを぀なげたす確認を省略する方法はわかりたせんでした。

$ yes | samlocal sync --stack-name $(uuidgen) --region us-east-1

こうするず、Amazon API Gatewayがたくさん䜜られおいくこずになりたすが、最新のREST APIのIDを抜出したす。

$ REST_API_ID=$(awslocal apigateway get-rest-apis --query 'reverse(sort_by(items[], &createdDate))[0].id' --output text)

こちらを䜿っお、デプロむしたAPIにアクセスしたす。

http://localhost:4566/restapis/$REST_API_ID/Prod/_user_request_/[path]

こんな感じですね。

たずめ

LocalStackAWS SAMで、い぀もデプロむし盎す時に困っおいたので察凊方法を考えおみたした。

いや、玠盎にAWSを䜿えばいいのではずいう話もあるのですが、LocalStackずAWS SAMの組み合わせの堎合は
これでなんずかしおいこうかなず思いたす。