はじめに
皆さん、こんにちは。
今年はありがたいことに、Japan AWS Top Engineers 2024 に選出されました。また、Top EngineersのAdvent Calendarがあるという情報を発見し、記念に参加することにしました。
偶然にも私は12月17日が誕生日なので、この日を投稿日としてエントリーしました。
今回は、 殺伐とした日々の生活に少しでも癒やしを与えるような題材 にしました。
ということで、作成されたのがこちらの記事です。
AWSを使って不特定多数の猫に誕生日を祝われたい(タイムアタック編)
よく見るとあんまりAWSに関係がありません。このままだと期中にTop Engineerをはく奪されてしまいそうなので、AWSに寄せたリファクタリングをかけようと思います。
① アプリケーション部分のIaC化
② アプリケーションリリースのCI/CD化
③ パイプラインのIaC化
前回同様、 「記事を書きながら実装をタイムアタック形式で行う」 という追い込みルールで進めたいと思います。
今回は120分でリファクタリングを書けるという目標にします!(結局タイムアタック)
またもや、21時を過ぎてから開始します。
(ここまで20分...)
作成したもの
① アプリケーション部分のIaC化
CloudFormationが好きなので、ネイティブCfn yamlで書いていきます。
対象は以下の通り。
- Lambda
- StateMachine
IaCジェネレーターに遷移します。
スキャンします。長いなぁ...
スキャンが終わりました。
テンプレートを作っていきます。
LambdaとStateMachineを選んだだけなのに、IAMやSchedulerまでレコメンドしてくれました。
とてもありがたいです。
テンプレートができました。アカウントIDとAPIキーを削除したり、名前を変えたり、順序を変えたり、余計なものを削除したyamlがこちらです。
コードを見る
Resources:
################################
# Lambda and IAM
################################
# meowAdvice function
LambdaFunctionMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
MemorySize: 128
Description: ''
TracingConfig:
Mode: PassThrough
Timeout: 10
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
Handler: lambda_function.lambda_handler
Code: ../functions/meowAdvice/
Role: !GetAtt IAMRoleLFMeowAdvice.Arn
FileSystemConfigs: []
FunctionName: meowAdvice
Runtime: python3.12
PackageType: Zip
LoggingConfig:
LogFormat: Text
LogGroup: /aws/lambda/meowAdvice
Environment:
Variables:
DEEPL_AUTH_KEY: '{{resolve:ssm-secure:/Test/DEEPL_AUTH_KEY}}'
LINE_USER_ID: '{{resolve:ssm-secure:/Test/LINE_USER_ID}}'
GEMINI_API_KEY: '{{resolve:ssm-secure:/Test/GEMINI_API_KEY}}'
LINE_ACCESS_TOKEN: '{{resolve:ssm-secure:/Test/LINE_ACCESS_TOKEN}}'
EphemeralStorage:
Size: 512
Architectures:
- x86_64
# role for meowAdvice function
IAMRoleLFMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- !Ref IAMManagedPolicyLFMeowAdvice
MaxSessionDuration: 3600
RoleName: IAMRoleLFMeowAdvice
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
IAMManagedPolicyLFMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyLFMeowAdvice
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
Action: logs:CreateLogGroup
Effect: Allow
- Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/meowAdvice:*
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Roles: []
Users: []
# findCatsGroup function
LambdaFunctionFindCatsGroup:
UpdateReplacePolicy: Retain
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
MemorySize: 128
Description: ''
TracingConfig:
Mode: PassThrough
Timeout: 3
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
Handler: lambda_function.lambda_handler
Code: ../functions/findCatsGroup/
Role: !GetAtt IAMRoleLFFindCatsGroup.Arn
FileSystemConfigs: []
FunctionName: findCatsGroup
Runtime: python3.12
PackageType: Zip
LoggingConfig:
LogFormat: Text
LogGroup: /aws/lambda/findCatsGroup
RecursiveLoop: Terminate
EphemeralStorage:
Size: 512
Architectures:
- x86_64
# role for findCatsGroup function
IAMRoleLFFindCatsGroup:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- !Ref IAMManagedPolicyLFFindCatsGroup
MaxSessionDuration: 3600
RoleName: IAMRoleLFFindCatsGroup
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
IAMManagedPolicyLFFindCatsGroup:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyLFFindCatsGroup
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
Action: logs:CreateLogGroup
Effect: Allow
- Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/findCatsGroup:*
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Roles: []
Users: []
################################
# StateMachne
################################
# statemachine GetMeowAdvicesFlow
StateMachineGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::StepFunctions::StateMachine
DeletionPolicy: Retain
Properties:
DefinitionS3Location: ../statemachine/getMeowAdvicesFlow.asl.json
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
IncludeExecutionData: false
Level: 'OFF'
StateMachineName: GetMeowAdvicesFlow
RoleArn: !GetAtt IAMRoleSFGetMeowAdvicesFlow.Arn
Tags: []
StateMachineType: STANDARD
TracingConfiguration:
Enabled: false
# role for GetMeowAdvicesFlow
IAMRoleSFGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- !Ref IAMManagedPolicyExecuteFunction
- !Ref IAMManagedPolicyXray
MaxSessionDuration: 3600
RoleName: IAMRoleSFGetMeowAdvicesFlow
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: states.amazonaws.com
IAMManagedPolicyExecuteFunction:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyExecuteFunction
Path: /service-role/
Description: Allow AWS Step Functions to invoke Lambda functions on your behalf
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:meowAdvice:*
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:findCatsGroup:*
Action:
- lambda:InvokeFunction
Effect: Allow
- Resource:
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:meowAdvice
- !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:findCatsGroup
Action:
- lambda:InvokeFunction
Effect: Allow
Roles: []
Users: []
IAMManagedPolicyXray:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyXray
Path: /service-role/
Description: Allow AWS Step Functions to call X-Ray daemon on your behalf
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- '*'
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
- xray:GetSamplingRules
- xray:GetSamplingTargets
Effect: Allow
Roles: []
Users: []
################################
# Scheduler
################################
# scheduler
SchedulerExecGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::Scheduler::Schedule
DeletionPolicy: Retain
Properties:
GroupName: default
ScheduleExpression: cron(0 0 17 12 ? *)
Target:
Arn: !Ref StateMachineGetMeowAdvicesFlow
RetryPolicy:
MaximumEventAgeInSeconds: 86400
MaximumRetryAttempts: 185
RoleArn: !GetAtt IAMRoleEBScheduler.Arn
Description: cats give advice.
State: ENABLED
FlexibleTimeWindow:
Mode: 'OFF'
ScheduleExpressionTimezone: Asia/Tokyo
Name: ExecGetMeowAdvicesFlowScheduler
IAMRoleEBScheduler:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- !Ref IAMManagedPolicyEBScheduler
MaxSessionDuration: 3600
RoleName: IAMRoleEBScheduler
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Condition:
StringEquals:
aws:SourceAccount: !Sub '${AWS::AccountId}'
Action: sts:AssumeRole
Effect: Allow
Principal:
Service: scheduler.amazonaws.com
IAMManagedPolicyEBScheduler:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyEBScheduler
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- !Ref SchedulerExecGetMeowAdvicesFlow
Action:
- states:StartExecution
Effect: Allow
Roles: []
Users: []
CI/CD化を見越して、LambdaとStepFunctionsは別ソースを指定しています。これでインフラとアプリケーションのソースコードを分離できます。
加えて、Lambdaの環境変数にはSystemsManagerのParameter Store値を指定します。
# meowAdvice function
LambdaFunctionMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
MemorySize: 128
Description: ''
TracingConfig:
Mode: PassThrough
Timeout: 10
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
Handler: lambda_function.lambda_handler
+ Code: ../functions/meowAdvice/
Role: !GetAtt IAMRoleLFMeowAdvice.Arn
FileSystemConfigs: []
FunctionName: meowAdvice
Runtime: python3.12
PackageType: Zip
LoggingConfig:
LogFormat: Text
LogGroup: /aws/lambda/meowAdvice
Environment:
Variables:
+ DEEPL_AUTH_KEY: '{{resolve:ssm-secure:/Test/DEEPL_AUTH_KEY}}'
+ LINE_USER_ID: '{{resolve:ssm-secure:/Test/LINE_USER_ID}}'
+ GEMINI_API_KEY: '{{resolve:ssm-secure:/Test/GEMINI_API_KEY}}'
+ LINE_ACCESS_TOKEN: '{{resolve:ssm-secure:/Test/LINE_ACCESS_TOKEN}}'
EphemeralStorage:
Size: 512
Architectures:
- x86_64
# statemachine GetMeowAdvicesFlow
StateMachineGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::StepFunctions::StateMachine
DeletionPolicy: Retain
Properties:
+ DefinitionS3Location: ../statemachine/getMeowAdvicesFlow.asl.json
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
IncludeExecutionData: false
Level: 'OFF'
StateMachineName: GetMeowAdvicesFlow
RoleArn: !GetAtt IAMRoleSFGetMeowAdvicesFlow.Arn
Tags: []
StateMachineType: STANDARD
TracingConfiguration:
Enabled: false
ここまでで80分かかっていました。目標はあと40分です...!
② アプリケーションリリースのCI/CD化
GitHubリポジトリを作成します。
まだ空です。
topengineer-advent-calendar-2024-meow
├ LICENSE
└ README.md
このご時世に、masterブランチで作ってしまいました。。
後で変えるとして、yamlとlambdaのソースコードをコミットします。
topengineer-advent-calendar-2024-meow
+ ├ functions
+ │ ├ findCatsGroup
+ │ │ └ lambda_function.py
+ │ └ meowAdvice
+ │ └ lambda_function.py
+ ├ iac
+ │ └ template.yaml
├ LICENSE
└ README.md
statemachineの設定をコンソールから取得します。
この時、Lambda関数のARNはDefinitionSubstitutionsを利用して外部jsonに引き渡します。
CloudFormationのyamlでは、StateMachineのDefinitionSubstitutionsをこのように指定します。
# statemachine GetMeowAdvicesFlow
StateMachineGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::StepFunctions::StateMachine
DeletionPolicy: Retain
Properties:
DefinitionS3Location: ../statemachine/getMeowAdvicesFlow.asl.json
+ DefinitionSubstitutions:
+ LambdaFunctionMeowAdviceArn: !GetAtt LambdaFunctionMeowAdvice.Arn
+ LambdaFunctionFindCatsGroupArn: !GetAtt LambdaFunctionFindCatsGroup.Arn
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
IncludeExecutionData: false
Level: 'OFF'
StateMachineName: GetMeowAdvicesFlow
RoleArn: !GetAtt IAMRoleSFGetMeowAdvicesFlow.Arn
Tags: []
StateMachineType: STANDARD
TracingConfiguration:
Enabled: false
StateMachineの定義である外部jsonは、.asl.json拡張子で定義します。
マネジメントコンソール上のDefault形式はJSONataになっていましたので、そのままJSONataで記述します。
CloudFormationから受け取る変数は、以下のハイライトのように設定します。
(後で出てきますが、この記述は間違っていますので、、Gitを参照ください)
{
"Comment": "A description of my state machine",
"StartAt": "猫の群れを探す",
"States": {
"猫の群れを探す": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Output": "{% $states.result.Payload %}",
"Arguments": {
+ "FunctionName": "{$LambdaFunctionFindCatsGroupArn}",
"Payload": "{% $states.input %}"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2,
"JitterStrategy": "FULL"
}
],
"Next": "猫の群れに入る"
},
"猫の群れに入る": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
"StartAt": "それぞれの猫にお祝いの言葉を言ってもらう",
"States": {
"それぞれの猫にお祝いの言葉を言ってもらう": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Output": "{% $states.result.Payload %}",
"Arguments": {
+ "FunctionName": "{$LambdaFunctionMeowAdviceArn}"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2,
"JitterStrategy": "FULL"
}
],
"End": true
}
}
},
"End": true,
"Items": "{% $states.input.myCats %}",
"MaxConcurrency": 3
}
},
"QueryLanguage": "JSONata"
}
statemachineのjsonファイルをGitに入れます。
topengineer-advent-calendar-2024-meow
├ functions
│ ├ findCatsGroup
│ │ └ lambda_function.py
│ └ meowAdvice
│ └ lambda_function.py
├ iac
│ └ template.yaml
+ ├ statemachine
+ │ └ getMeowAdvicesFlow.asl.json
├ LICENSE
└ README.md
この状態で、CloudFormation CLIを使ってIaCからリソースを作成してみます。
準備として、CloudShellを起動し、git clone
を実行します。
コマンドはこのページを参照して作成しました。コマンドを実行します。
aws cloudformation package --template-file ./iac/template.yaml --s3-bucket siruko-cloudformation-templetes --output-template-file packaged-template.yaml
作成されたyamlがこちらです。別ファイルで定義したLambdaのソースコードや、StepFunctionsの定義jsonが指定したS3にアップロードされ、そのURLが指定されています。
コードを見る
Resources:
LambdaFunctionMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
MemorySize: 128
Description: ''
TracingConfig:
Mode: PassThrough
Timeout: 10
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
Handler: lambda_function.lambda_handler
Code:
S3Bucket: siruko-cloudformation-templetes
S3Key: 802afc518ce90d2fbd6d590b3150333d
Role:
Fn::GetAtt:
- IAMRoleLFMeowAdvice
- Arn
FileSystemConfigs: []
FunctionName: meowAdvice
Runtime: python3.12
PackageType: Zip
LoggingConfig:
LogFormat: Text
LogGroup: /aws/lambda/meowAdvice
Environment:
Variables:
DEEPL_AUTH_KEY: '{{resolve:ssm-secure:/Test/DEEPL_AUTH_KEY}}'
LINE_USER_ID: '{{resolve:ssm-secure:/Test/LINE_USER_ID}}'
GEMINI_API_KEY: '{{resolve:ssm-secure:/Test/GEMINI_API_KEY}}'
LINE_ACCESS_TOKEN: '{{resolve:ssm-secure:/Test/LINE_ACCESS_TOKEN}}'
EphemeralStorage:
Size: 512
Architectures:
- x86_64
IAMRoleLFMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- Ref: IAMManagedPolicyLFMeowAdvice
MaxSessionDuration: 3600
RoleName: IAMRoleLFMeowAdvice
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
IAMManagedPolicyLFMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyLFMeowAdvice
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
Action: logs:CreateLogGroup
Effect: Allow
- Resource:
- Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/meowAdvice:*
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Roles: []
Users: []
LambdaFunctionFindCatsGroup:
UpdateReplacePolicy: Retain
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
MemorySize: 128
Description: ''
TracingConfig:
Mode: PassThrough
Timeout: 3
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
Handler: lambda_function.lambda_handler
Code:
S3Bucket: siruko-cloudformation-templetes
S3Key: 39a90f217524dd9b5d2ee8c7fb0d1485
Role:
Fn::GetAtt:
- IAMRoleLFFindCatsGroup
- Arn
FileSystemConfigs: []
FunctionName: findCatsGroup
Runtime: python3.12
PackageType: Zip
LoggingConfig:
LogFormat: Text
LogGroup: /aws/lambda/findCatsGroup
RecursiveLoop: Terminate
EphemeralStorage:
Size: 512
Architectures:
- x86_64
IAMRoleLFFindCatsGroup:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- Ref: IAMManagedPolicyLFFindCatsGroup
MaxSessionDuration: 3600
RoleName: IAMRoleLFFindCatsGroup
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: lambda.amazonaws.com
IAMManagedPolicyLFFindCatsGroup:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyLFFindCatsGroup
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:*
Action: logs:CreateLogGroup
Effect: Allow
- Resource:
- Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/findCatsGroup:*
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Roles: []
Users: []
StateMachineGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::StepFunctions::StateMachine
DeletionPolicy: Retain
Properties:
DefinitionS3Location:
Bucket: siruko-cloudformation-templetes
Key: 2f7f170dc9785b84b19ca51282777ef2
DefinitionSubstitutions:
LambdaFunctionMeowAdviceArn:
Fn::GetAtt:
- LambdaFunctionMeowAdvice
- Arn
LambdaFunctionFindCatsGroupArn:
Fn::GetAtt:
- LambdaFunctionFindCatsGroup
- Arn
EncryptionConfiguration:
Type: AWS_OWNED_KEY
LoggingConfiguration:
IncludeExecutionData: false
Level: 'OFF'
StateMachineName: GetMeowAdvicesFlow
RoleArn:
Fn::GetAtt:
- IAMRoleSFGetMeowAdvicesFlow
- Arn
Tags: []
StateMachineType: STANDARD
TracingConfiguration:
Enabled: false
IAMRoleSFGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- Ref: IAMManagedPolicyExecuteFunction
- Ref: IAMManagedPolicyXray
MaxSessionDuration: 3600
RoleName: IAMRoleSFGetMeowAdvicesFlow
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: states.amazonaws.com
IAMManagedPolicyExecuteFunction:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyExecuteFunction
Path: /service-role/
Description: Allow AWS Step Functions to invoke Lambda functions on your behalf
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:meowAdvice:*
- Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:findCatsGroup:*
Action:
- lambda:InvokeFunction
Effect: Allow
- Resource:
- Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:meowAdvice
- Fn::Sub: arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:findCatsGroup
Action:
- lambda:InvokeFunction
Effect: Allow
Roles: []
Users: []
IAMManagedPolicyXray:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyXray
Path: /service-role/
Description: Allow AWS Step Functions to call X-Ray daemon on your behalf
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- '*'
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
- xray:GetSamplingRules
- xray:GetSamplingTargets
Effect: Allow
Roles: []
Users: []
SchedulerExecGetMeowAdvicesFlow:
UpdateReplacePolicy: Retain
Type: AWS::Scheduler::Schedule
DeletionPolicy: Retain
Properties:
GroupName: default
ScheduleExpression: cron(0 0 17 12 ? *)
Target:
Arn:
Ref: StateMachineGetMeowAdvicesFlow
RetryPolicy:
MaximumEventAgeInSeconds: 86400
MaximumRetryAttempts: 185
RoleArn:
Fn::GetAtt:
- IAMRoleEBScheduler
- Arn
Description: cats give advice.
State: ENABLED
FlexibleTimeWindow:
Mode: 'OFF'
ScheduleExpressionTimezone: Asia/Tokyo
Name: ExecGetMeowAdvicesFlowScheduler
IAMRoleEBScheduler:
UpdateReplacePolicy: Retain
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
Path: /service-role/
ManagedPolicyArns:
- Ref: IAMManagedPolicyEBScheduler
MaxSessionDuration: 3600
RoleName: IAMRoleEBScheduler
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Condition:
StringEquals:
aws:SourceAccount:
Fn::Sub: ${AWS::AccountId}
Action: sts:AssumeRole
Effect: Allow
Principal:
Service: scheduler.amazonaws.com
IAMManagedPolicyEBScheduler:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyEBScheduler
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- Ref: SchedulerExecGetMeowAdvicesFlow
Action:
- states:StartExecution
Effect: Allow
Roles: []
Users: []
それでは、このままCloudShellでCloudFormationを実行してみましょう。
aws cloudformation deploy --template-file /home/cloudshell-user/topengineer-advent-calendar-2024-meow/packaged-template.yaml --stack-name testMeowStack
はい、エラーです。
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Circular dependency between resources: [IAMManagedPolicyEBScheduler, IAMRoleEBScheduler, SchedulerExecGetMeowAdvicesFlow]
相互参照してしまっているようですね。IaCジェネレーターにも可愛いところがあります。
と思ったら、リファクタリングでStateMachineのArnを!Ref関数に変えたところでした。
IAMManagedPolicyEBScheduler:
UpdateReplacePolicy: Retain
Type: AWS::IAM::ManagedPolicy
DeletionPolicy: Retain
Properties:
ManagedPolicyName: IAMManagedPolicyEBScheduler
Path: /service-role/
Description: ''
Groups: []
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource:
- - !Ref SchedulerExecGetMeowAdvicesFlow
+ - !Sub arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:GetMeowAdvicesFlow
Action:
- states:StartExecution
Effect: Allow
Roles: []
Users: []
もう一度実行します。
aws cloudformation package --template-file ./iac/template.yaml --s3-bucket siruko-cloudformation-templetes --output-template-file packaged-template.yaml
aws cloudformation deploy --template-file /home/cloudshell-user/topengineer-advent-calendar-2024-meow/packaged-template.yaml --stack-name testMeowStack
はい、エラーです。
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Parameters: [ssm-secure:/Test/DEEPL_AUTH_KEY ssm-secure:/Test/GEMINI_API_KEY ssm-secure:/Test/LINE_ACCESS_TOKEN ssm-secure:/Test/LINE_USER_ID] cannot be found.
SystemsManagerのParameter Store値を作っていませんでした。凡ミスですね。
作成します。
GMT表記のため少し分かりづらいですが、日本時間では23:12です。
開始から2時間が経過しつつあります。少しテンションが下がったので、ウイスキーを用意します。
もう一度実行します。
aws cloudformation deploy --template-file /home/cloudshell-user/topengineer-advent-calendar-2024-meow/packaged-template.yaml --stack-name testMeowStack
はい、エラーです。
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Requires capabilities : [CAPABILITY_NAMED_IAM]
これはもはやエラーではありません。カスタム名を持つIAMリソースをCloudFormationで作成する際のパラメータが不足しているだけです。
- aws cloudformation deploy --template-file /home/cloudshell-user/topengineer-advent-calendar-2024-meow/packaged-template.yaml --stack-name testMeowStack
+ aws cloudformation deploy --template-file /home/cloudshell-user/topengineer-advent-calendar-2024-meow/packaged-template.yaml --stack-name testMeowStack --capabilities CAPABILITY_NAMED_IAM
はい、エラーです。
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: SSM Secure reference is not supported in: [AWS::Lambda::Function/Properties/Environment/Variables/GEMINI_API_KEY,AWS::Lambda::Function/Properties/Environment/Variables/LINE_ACCESS_TOKEN,AWS::Lambda::Function/Properties/Environment/Variables/DEEPL_AUTH_KEY,AWS::Lambda::Function/Properties/Environment/Variables/LINE_USER_ID]
Lambdaの環境変数はセキュア文字列がサポートされてないんですね。すっかり忘れていました。plaintextに変更します。
CloudFormationのyamlも更新します。
# meowAdvice function
LambdaFunctionMeowAdvice:
UpdateReplacePolicy: Retain
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
MemorySize: 128
Description: ''
TracingConfig:
Mode: PassThrough
Timeout: 10
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
Handler: lambda_function.lambda_handler
Code: ../functions/meowAdvice/
Role: !GetAtt IAMRoleLFMeowAdvice.Arn
FileSystemConfigs: []
FunctionName: meowAdvice
Runtime: python3.12
PackageType: Zip
LoggingConfig:
LogFormat: Text
LogGroup: /aws/lambda/meowAdvice
Environment:
Variables:
- DEEPL_AUTH_KEY: '{{resolve:ssm-secure:/Test/DEEPL_AUTH_KEY}}'
- LINE_USER_ID: '{{resolve:ssm-secure:/Test/LINE_USER_ID}}'
- GEMINI_API_KEY: '{{resolve:ssm-secure:/Test/GEMINI_API_KEY}}'
- LINE_ACCESS_TOKEN: '{{resolve:ssm-secure:/Test/LINE_ACCESS_TOKEN}}'
+ DEEPL_AUTH_KEY: '{{resolve:ssm:/Test/DEEPL_AUTH_KEY}}'
+ LINE_USER_ID: '{{resolve:ssm:/Test/LINE_USER_ID}}'
+ GEMINI_API_KEY: '{{resolve:ssm:/Test/GEMINI_API_KEY}}'
+ LINE_ACCESS_TOKEN: '{{resolve:ssm:/Test/LINE_ACCESS_TOKEN}}'
EphemeralStorage:
Size: 512
Architectures:
- x86_64
もう一度実行します。
aws cloudformation package --template-file ./iac/template.yaml --s3-bucket siruko-cloudformation-templetes --output-template-file packaged-template.yaml
aws cloudformation deploy --template-file /home/cloudshell-user/topengineer-advent-calendar-2024-meow/packaged-template.yaml --stack-name testMeowStack --capabilities CAPABILITY_NAMED_IAM
成功しました!!
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - testMeowStack
これにてIaC化は完了しました。
② アプリケーションリリースのCI/CD化
次に、GitHubのpushをトリガーに起動するCI/CDパイプラインを作っていきます。
今回はこのようなCodePipelineを作成しました。
Source
GitHubからソースコードを取得します。
mainブランチに反応するように設定しました。
Package
前述の aws cloudformation package
コマンドをCodeBuildで実行します。
Packageの結果で生成されるpackaged-template.yamlは、BuildArtifactに格納されます。
ビルドプロジェクトの設定は以下の通りです。
buildspec.yamlはGitHubのパスを指定しておきます。現時点では未作成です。
CreateChangeset
aws cloudformation package
コマンドの結果であるpackaged-template.yamlから、CloudFormationの変更セットを作成します。
Approval
誤リリース抑止用に、変更セットの作成が成功したら一旦ストップし、手動承認を待ちます。
ExecuteChangeset
変更セットを実行します。これでLambda, StateMachine, EventBridge Schedulerがデプロイされます。
それでは、buildspec.yamlを作成します。
version: 0.2
phases:
install:
commands:
- echo Start package...
build:
commands:
- echo Packageing...
- aws cloudformation package
--template-file ./iac/template.yaml
--s3-bucket siruko-cloudformation-templetes
--output-template-file packaged-template.yaml
- ls -l packaged-template.yaml
artifacts:
files:
- packaged-template.yaml
GitHubにbuildspec.yamlをcommitしpushします。
topengineer-advent-calendar-2024-meow
├ functions
│ ├ findCatsGroup
│ │ └ lambda_function.py
│ └ meowAdvice
│ └ lambda_function.py
├ iac
+ │ ├ buldspec.yaml
│ └ template.yaml
├ statemachine
│ └ getMeowAdvicesFlow.asl.json
├ LICENSE
└ README.md
いよいよ、パイプラインを動かします。
パイプラインはmainブランチに反応するようため、mainブランチを作成します。
git checkout -b main origin/master
git push origin head
動き始めました。
色々ありましたが、なんとか成功しました!
- buildspec.yamlのファイル名を間違えていた
- CodeBuildの権限が不足していた
- mainブランチの変更に反応しない
- CloudFormation Stackの権限が足りない
- 変更セット名の大文字小文字を間違えた
- IaCジェネレータのデフォルトのDeletionPolicyがRetainのため削除が面倒だった(愚痴です)
意気揚々とStep Functionsを動かしたところ、エラー…!
jsonの記述が間違っていました。
{
"Comment": "A description of my state machine",
"StartAt": "猫の群れを探す",
"States": {
"猫の群れを探す": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Output": "{% $states.result.Payload %}",
"Arguments": {
- "FunctionName": "{$LambdaFunctionFindCatsGroupArn}",
+ "FunctionName": "${LambdaFunctionFindCatsGroupArn}",
"Payload": "{% $states.input %}"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2,
"JitterStrategy": "FULL"
}
],
"Next": "猫の群れに入る"
},
"猫の群れに入る": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
"StartAt": "それぞれの猫にお祝いの言葉を言ってもらう",
"States": {
"それぞれの猫にお祝いの言葉を言ってもらう": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Output": "{% $states.result.Payload %}",
"Arguments": {
- "FunctionName": "{$LambdaFunctionMeowAdviceArn}"
+ "FunctionName": "${LambdaFunctionMeowAdviceArn}"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2,
"JitterStrategy": "FULL"
}
],
"End": true
}
}
},
"End": true,
"Items": "{% $states.input.myCats %}",
"MaxConcurrency": 3
}
},
"QueryLanguage": "JSONata"
}
再度パイプラインからリリースを行い、Step Functionsを手動で実行したところ、成功しました!
もう2:50です。
ここまで120分を目標としていましたが、実際には終わらず330分かかってしまいました。
本日はここまでとします…。
③ パイプラインのIaC化
1週間以上間が空いてしまいましたが、前回の続きを進めます。
最後のリファクタリング作業として、パイプラインをIaC化し、可搬性や再現性を確保します。
本日も遅めの時間(21:55)スタートなので、タイムアタックです。目標は120分!
IaCジェネレータ
CloudFormationのIaCジェネレータを使用して、パイプラインのyamlを取得します。
テンプレートを作成していきます。
ここで前回の反省を活かし、削除ポリシーと置換ポリシーを「削除」に設定します。
スキャンしたリソースにパイプラインがありません。
どうやら2024年12月時点では、IaCジェネレータはCodePipelineに対応していないようです。
早くも暗雲が立ち込めました。
パイプラインをテンプレートから作成するオプションを使うことで、テンプレートの自動生成を試みます。GitHub接続は作成済なので、サクサク進みます。
この結果、なんとパイプラインのyamlテンプレートが作成されました。
このテンプレートを元に、手動で作成したCodePipelineと同じものを作成していきます。
結局、ほぼ一から作ることになりました。
- GitHub接続のARNを反映
- Stack名を修正
- ChangeSet名を修正
- 各ステージ(Build、CreateChangeSet、Approval、ExecuteChangeSet)の追加
- CodeBuildリソースの追加
- 各ロール(CodePipeline、CodeBuild、CreateChangeSet、ExecuteChangeSet)の追加
リファクタリング済のyamlは以下です。
コードを見る
Resources:
################################
# S3 Bucket
################################
CodePipelineArtifactsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub GetMeowAdvicesArtifactBucket-${AWS::AccountId}
################################
# CodePipeline
################################
CodePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
ArtifactStore:
Location: !Ref CodePipelineArtifactsBucket
Type: S3
ExecutionMode: QUEUED
Name: GetMeowAdvicesAppPipeline
PipelineType: V2
RoleArn: !GetAtt CodePipelineRole.Arn
Stages:
################################
# Get Source from GitHub
################################
- Name: Source
Actions:
- Name: CodeConnections
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeStarSourceConnection
Version: 1
Configuration:
ConnectionArn: !Sub arn:aws:codeconnections:${AWS::Region}:${AWS::AccountId}:connection/6a7eb867-8d4f-400e-b124-494d8874c175
FullRepositoryId: higurashit/topengineer-advent-calendar-2024-meow
BranchName: main
OutputArtifacts:
- Name: SourceAtf
################################
# Package CloudFormation template
################################
- Name: Build
Actions:
- Name: BuildByCodeBuild
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
Configuration:
ProjectName: !Ref CodeBuildProjectForPackageCfnTemplate
InputArtifacts:
- Name: SourceAtf
OutputArtifacts:
- Name: BuildAtf
Region: !Ref AWS::Region
Namespace: BuildByCodeBuild
################################
# Create CloudFormation changeset
################################
- Name: CreateChangeset
Actions:
- InputArtifacts:
- Name: BuildAtf
Name: CreateChangeset
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
OutputArtifacts:
- Name: BdOutput
Configuration:
ActionMode: CHANGE_SET_REPLACE
ChangeSetName: GetMeowAdvicesAppStackChangeSet
RoleArn: !GetAtt CreateChangesetRole.Arn
Capabilities: CAPABILITY_NAMED_IAM
StackName: GetMeowAdvicesAppStack
TemplatePath: BuildAtf::packaged-template.yaml
################################
# Manual Approbal
################################
- Name: Approval
Actions:
- Name: ApproveExecuteChangeset
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
################################
# Execte CloudFormation changeset
################################
- Name: Deploy
Actions:
- Name: ExecuteChangeset
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
Configuration:
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: GetMeowAdvicesAppStackChangeSet
RoleArn: !GetAtt ExecuteChangesetRole.Arn
StackName: GetMeowAdvicesAppStack
################################
# CodeBuild
################################
CodeBuildProjectForPackageCfnTemplate:
Type: AWS::CodeBuild::Project
Properties:
Name: GetMeowAdvicesBuild
Source:
BuildSpec: ./iac/buildspec.yml
InsecureSsl: false
Type: CODEPIPELINE
Artifacts:
EncryptionDisabled: false
Name: CodeBuildProjectForPackageCfnTemplate
Packaging: NONE
Type: CODEPIPELINE
Cache:
Type: NO_CACHE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux-x86_64-standard:5.0
ImagePullCredentialsType: CODEBUILD
PrivilegedMode: false
Type: LINUX_CONTAINER
ServiceRole: !GetAtt CodeBuildRole.Arn
TimeoutInMinutes: 15
QueuedTimeoutInMinutes: 480
EncryptionKey: !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3
BadgeEnabled: false
LogsConfig:
CloudWatchLogs:
Status: ENABLED
S3Logs:
Status: DISABLED
EncryptionDisabled: false
################################
# IAM Role
################################
# CodePipeline
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Resource:
- !GetAtt CodePipelineArtifactsBucket.Arn
- !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
- Effect: Allow
Action:
- s3:PutObjectAcl
- s3:PutObjectVersionAcl
Resource: !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
# CreateChangeset
CreateChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineCreateChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineCreateChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- cloudformation:CreateChangeSet
Resource:
- !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
- Effect: Allow
Action: s3:*
Resource: '*'
# ExecuteChangesetRole
ExecuteChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineExecuteChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineExecuteChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Resource: '*'
Action:
- iam:*
- Effect: Allow
Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/*
Action:
- iam:PassRole
- Effect: Allow
Resource: '*'
Action:
- states:*
- logs:*
- cloudwatch:*
- lambda:*
- events:*
- s3:*
# CodeBuild
CodeBuildRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesBuildRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesBuildRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- codebuild:BatchPutCodeCoverages
- codebuild:BatchPutTestCases
- codebuild:CreateReport
- codebuild:CreateReportGroup
- codebuild:UpdateReport
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:report-group/GetMeowAdvicesBuild-*
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/GetMeowAdvicesBuild
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/GetMeowAdvicesBuild:*
- Effect: Allow
Action:
- cloudformation:*
- codepipeline:*
- iam:PassRole
- s3:*
Resource: '*'
- Effect: Allow
Action:
- iam:PassRole
Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/*
バックアップを取ってリソースを消していきます。
作成したyamlをCloudFormationで流していきます。
ここにチェックを入れて次へ
変更セットを作ります。一発でまあまあいい感じです。
はい、エラーです。S3バケットに大文字を使っています。焦っています。
Resource handler returned message: "Bucket name should not contain uppercase characters" (RequestToken: 574a6ebb-83fb-9a8d-ff01-5a319135ef8d, HandlerErrorCode: GeneralServiceException)
CodePipelineArtifactsBucket:
Type: AWS::S3::Bucket
Properties:
- BucketName: !Sub GetMeowAdvicesArtifactBucket-${AWS::AccountId}
+ BucketName: !Sub get-meow-advices-artifact-bucket-${AWS::AccountId}
再実行したところ、エラーが発生しました。ロール名が被っていました。
コンソールからロールを削除して再実行します。現在、2時間が経過しました…。
Resource handler returned message: "Resource of type 'AWS::IAM::Role' with identifier 'GetMeowAdvicesAppPipelineRole' already exists." (RequestToken: 329744bb-d197-9e75-301d-a8c5c9e69d73, HandlerErrorCode: AlreadyExists)
パイプラインの実行
Sourceステージでエラーが起きていました。パイプラインのロール不足が起きています。
Unable to use Connection: arn:aws:codeconnections:ap-northeast-1:xxxxxxxxxxxx:connection/6a7eb867-8d4f-400e-b124-494d8874c175. The provided role does not have sufficient permissions.
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Resource:
- !GetAtt CodePipelineArtifactsBucket.Arn
- !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
- Effect: Allow
Action:
- s3:PutObjectAcl
- s3:PutObjectVersionAcl
Resource: !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
+ - Effect: Allow
+ Action: codestar-connections:*
+ Resource: !Sub arn:aws:codeconnections:${AWS::Region}:${AWS::AccountId}:connection/6a7eb867-8d4f-400e-b124-494d8874c175
CloudFormationからパイプラインを更新し、再実行します。Sourceステージはクリアし、Buildステージでエラーとなりました。
パイプラインロールにまだ権限が足りないようです。
Error calling startBuild: User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineRole/1734015821781 is not authorized to perform: codebuild:StartBuild on resource: arn:aws:codebuild:ap-northeast-1:xxxxxxxxxxxx:project/GetMeowAdvicesBuild because no identity-based policy allows the codebuild:StartBuild action (Service: AWSCodeBuild; Status Code: 400; Error Code: AccessDeniedException; Request ID: 847ed4de-d80c-4870-a73c-cc0b680e7f88; Proxy: null)
CodeBuildの実行権限を付与します。Buildジョブが増えた時のためにResourceは多少緩めにしています。
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Resource:
- !GetAtt CodePipelineArtifactsBucket.Arn
- !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
- Effect: Allow
Action:
- s3:PutObjectAcl
- s3:PutObjectVersionAcl
Resource: !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
- Effect: Allow
Action: codestar-connections:*
Resource: !Sub arn:aws:codeconnections:${AWS::Region}:${AWS::AccountId}:connection/6a7eb867-8d4f-400e-b124-494d8874c175
+ - Effect: Allow
+ Action: codebuild:*
+ Resource: !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/GetMeowAdvices*
CloudFormationからパイプラインを更新し、再実行します。
またもやBuildステージでエラーが発生しました。ファイル名の拡張子が誤っていました。
[Container] 2024/12/12 15:09:14.517515 Phase context status code: YAML_FILE_ERROR Message: stat /codebuild/output/src489700486/src/iac/buildspec.yml: no such file or directory
CodeBuildProjectForPackageCfnTemplate:
Type: AWS::CodeBuild::Project
Properties:
Name: GetMeowAdvicesBuild
Source:
- BuildSpec: ./iac/buildspec.yml
+ BuildSpec: ./iac/buildspec.yaml
InsecureSsl: false
Type: CODEPIPELINE
Artifacts:
EncryptionDisabled: false
Name: CodeBuildProjectForPackageCfnTemplate
Packaging: NONE
Type: CODEPIPELINE
Cache:
Type: NO_CACHE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/amazonlinux-x86_64-standard:5.0
ImagePullCredentialsType: CODEBUILD
PrivilegedMode: false
Type: LINUX_CONTAINER
ServiceRole: !GetAtt CodeBuildRole.Arn
TimeoutInMinutes: 15
QueuedTimeoutInMinutes: 480
EncryptionKey: !Sub arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3
BadgeEnabled: false
LogsConfig:
CloudWatchLogs:
Status: ENABLED
S3Logs:
Status: DISABLED
EncryptionDisabled: false
CloudFormationからパイプラインを更新し、再実行します。
Buildフェーズは通過しましたが、CreateChangeSetステージでエラーが発生しました。
パイプラインロールにまだ権限が足りないようです。
User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineRole/1734016376890 is not authorized to perform: cloudformation:DescribeStacks on resource: arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/GetMeowAdvicesAppStack/cc187d20-b266-11ef-957c-06871864c701 because no identity-based policy allows the cloudformation:DescribeStacks action (Service: AmazonCloudFormation; Status Code: 403; Error Code: AccessDenied; Request ID: 3ea878d6-0e03-4b1a-8e38-9f600c477739; Proxy: null)
User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineRole/1734016838437 is not authorized to perform: iam:PassRole on resource: arn:aws:iam::xxxxxxxxxxxx:role/GetMeowAdvicesAppPipelineCreateChangesetRole because no identity-based policy allows the iam:PassRole action (Service: AmazonCloudFormation; Status Code: 403; Error Code: AccessDenied; Request ID: 5a0d8225-a907-4137-8ebc-7d4439909586; Proxy: null)
アプリ側のスタック操作権限と、CreateChangesetとExecuteChangeset用のロールへのパスロール権限を与えます。
CodePipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Resource:
- !GetAtt CodePipelineArtifactsBucket.Arn
- !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
- Effect: Allow
Action:
- s3:PutObjectAcl
- s3:PutObjectVersionAcl
Resource: !Join
- /
- - !GetAtt CodePipelineArtifactsBucket.Arn
- '*'
- Effect: Allow
Action: codestar-connections:*
Resource: !Sub arn:aws:codeconnections:${AWS::Region}:${AWS::AccountId}:connection/6a7eb867-8d4f-400e-b124-494d8874c175
- Effect: Allow
Action: codebuild:*
Resource: !Sub arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/GetMeowAdvices*
+ - Effect: Allow
+ Action: cloudformation:*
+ Resource:
+ - !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack
+ - !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
+ - Effect: Allow
+ Action: iam:PassRole
+ Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/GetMeowAdvicesAppPipeline*
CloudFormationからパイプラインを更新し、再実行します。
まだCreateChangeSetでエラーが出ています。Systems ManagerのParameter Storeへのアクセス権限が足りないようです。
User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineCreateChangesetRole/AWSCloudFormation is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-northeast-1:xxxxxxxxxxxx:parameter/Test/LINE_ACCESS_TOKEN because no identity-based policy allows the ssm:GetParameters action (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: AccessDeniedException; Request ID: 7d2d28b5-d969-496f-aa16-8eb1726bec52; Proxy: null)
名前空間を/Testにしたのを後悔しつつ、権限を追加します。
CreateChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineCreateChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineCreateChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: cloudformation:CreateChangeSet
Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
- Effect: Allow
Action: s3:*
Resource: '*'
+ - Effect: Allow
+ Action: ssm:GetParameters
+ Resource: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/Test/*
CloudFormationからパイプラインを更新し、再実行します。
CreateChangeSetが成功しました!
Approvalステージのレビューウインドウで何をしたら良いかわからないため、レビュー用リンクとメッセージを設定します。
レビュー用リンクからは変更セットに遷移できるようしましょう。
以下が「変更セットのタブかつ、Stack名を絞り込んだ状態」のURLです。
https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/changesets?filteringText=GetMeowAdvicesAppStack
- Name: Approval
Actions:
- Name: ApproveExecuteChangeset
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
+ Configuration:
+ ExternalEntityLink: !Sub https://${AWS::Region}.console.aws.amazon.com/cloudformation/home?region=${AWS::Region}#/stacks/changesets?filteringText=GetMeowAdvicesAppStack
+ CustomData: レビュー用URLから変更セットを確認し、リリース承認をお願いします。
CloudFormationからパイプラインを更新し、再実行します。
レビュー用URLをクリックすると、スタック一覧画面が表示されます。
URLで指定したスタック名で絞り込まれ、スタックが未選択の状態です。
画面左側のスタック名をクリックします。
変更セットが出てきました。
アプリ側のtemplate.yamlは修正していないため、「変更はありません」と表記されています。
CodePipelineの画面に戻り、承認して先に進みます。
成功しました!!8日ぶりのリリースです。
アプリのリファクタリング
ここまでで目標120分に対し180分かかっていますが、せっかくCI/CDパイプラインができたのでリファクタリングをします。
誕生日を祝ってもらうアプリから、いつでもアドバイスをもらえるアプリに生まれ変わりました。
happybirthday系の変数名などを直していきます。
- happyMeowthdayToLine(imeowge, f'{admeowce}\n{admeowce_jp}')
+ postAdmeowceToLine(imeowge, f'{admeowce}\n{admeowce_jp}')
- def happyMeowthdayToLine(imeowge, meowssage):
- _msg = f'Happy Meowthday!!\n{meowssage}'
_url = 'https://api.line.me/v2/bot/message/push'
+ def postAdmeowceToLine(imeowge, meowssage):
+ _msg = f'あなたにアドバイスをあげるにゃん。\n{meowssage}'
_url = 'https://api.line.me/v2/bot/message/push'
"猫の群れに入る": {
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
- "StartAt": "それぞれの猫にお祝いの言葉を言ってもらう",
+ "StartAt": "それぞれの猫にアドバイスをもらう",
"States": {
- "それぞれの猫にお祝いの言葉を言ってもらう": {
+ "それぞれの猫にアドバイスをもらう": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Output": "{% $states.result.Payload %}",
"Arguments": {
"FunctionName": "${LambdaFunctionMeowAdviceArn}"
},
GitHubでmainブランチにマージをします。
パイプラインが反応しません。。
今日は一旦忘れて、パイプラインを手動で実行します。
変更セットにLambda関数とStateMachineが出てきました。
Approval -> ExecuteChangesetを実行するとエラーが発生しました。
ExecuteChangesetの実行には、CreateChangesetRoleにiam:GetRoleが必要ということです。よくわかりませんが、わかりました。
Unable to retrieve Arn attribute for AWS::IAM::Role, with error message User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineCreateChangesetRole/AWSCloudFormation is not authorized to perform: iam:GetRole on resource: role IAMRoleLFMeowAdvice because no identity-based policy allows the iam:GetRole action (Service: Iam, Status Code: 403, Request ID: 3c8e24b2-d466-4984-8da1-f407afb1c3c6)
Unable to retrieve Arn attribute for AWS::IAM::Role, with error message User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineCreateChangesetRole/AWSCloudFormation is not authorized to perform: iam:GetRole on resource: role IAMRoleLFFindCatsGroup because no identity-based policy allows the iam:GetRole action (Service: Iam, Status Code: 403, Request ID: f06bc86a-77fb-47c2-8751-8fc94defa548)
CreateChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineCreateChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineCreateChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: cloudformation:CreateChangeSet
Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
- Effect: Allow
Action: ssm:GetParameters
Resource: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/Test/*
+ - Effect: Allow
+ Action: iam:GetRole
+ Resource: '*'
再度実行しても、エラーが発生しました。
ExecuteChangesetの実行には、CreateChangesetRoleにlambda:UpdateFunctionCodeの権限が必要とのことです。
Resource handler returned message: "User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineCreateChangesetRole/AWSCloudFormation is not authorized to perform: lambda:UpdateFunctionCode on resource: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:meowAdvice because no identity-based policy allows the lambda:UpdateFunctionCode action (Service: Lambda, Status Code: 403, Request ID: e757ea4a-4b98-4a7b-ae89-b5a3695d3603)" (RequestToken: fb31b61b-519e-baef-f803-d5912c53122a, HandlerErrorCode: AccessDenied)
CreateChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineCreateChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineCreateChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: cloudformation:CreateChangeSet
Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
- Effect: Allow
Action: ssm:GetParameters
Resource: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/Test/*
- Effect: Allow
Action: iam:GetRole
Resource: '*'
+ - Effect: Allow
+ Action: lambda:UpdateFunctionCode
+ Resource: '*'
次はS3とStep Functionsでエラーが発生しました。
S3はbuildspec.yamlのpackageコマンドで指定した配置先S3バケットがテスト用のものになっていました。
パイプラインのアーティファクト用バケットに変更します。
Resource handler returned message: "Your access has been denied by S3, please make sure your request credentials have permission to GetObject for siruko-cloudformation-templetes/44ac053ec6f3eb15ffed38be576c18b8.
- Name: Build
Actions:
- Name: BuildByCodeBuild
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
Configuration:
+ EnvironmentVariables: !Sub
+ - |
+ [{
+ "name": "bucket",
+ "value": "${CodePipelineArtifactsBucket}",
+ "type": "PLAINTEXT"
+ }]
+ - Env: !Ref CodePipelineArtifactsBucket
ProjectName: !Ref CodeBuildProjectForPackageCfnTemplate
InputArtifacts:
- Name: SourceAtf
OutputArtifacts:
- Name: BuildAtf
Region: !Ref AWS::Region
Namespace: BuildByCodeBuild
version: 0.2
phases:
install:
commands:
- echo Start package...
- echo ${bucket}
build:
commands:
- echo Packageing...
- aws cloudformation package
--template-file ./iac/template.yaml
- --s3-bucket siruko-cloudformation-templetes
+ --s3-bucket ${bucket}
--output-template-file packaged-template.yaml
- ls -l packaged-template.yaml
- cat packaged-template.yaml | grep ${bucket}
artifacts:
files:
- packaged-template.yaml
次はStep Functionsの更新権限が無いとエラーが発生しました。
どうやらCreateChangesetRoleの方にリソースの作成権限、更新権限、削除権限を付けないといけないようです。
Resource handler returned message: "User: arn:aws:sts::xxxxxxxxxxxx:assumed-role/GetMeowAdvicesAppPipelineCreateChangesetRole/AWSCloudFormation is not authorized to perform: states:UpdateStateMachine on resource: arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:GetMeowAdvicesFlow because no identity-based policy allows the states:UpdateStateMachine action
CreateChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineCreateChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineCreateChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: cloudformation:CreateChangeSet
Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
- Effect: Allow
Action: ssm:GetParameters
Resource: !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/Test/*
+ - Effect: Allow
+ Action:
+ - iam:*
+ - lambda:*
+ - states:*
+ - scheduler:*
+ Resource: '*'
+ - Effect: Allow
+ Action:
+ - s3:GetObject*
+ Resource:
+ - !GetAtt CodePipelineArtifactsBucket.Arn
+ - !Join
+ - /
+ - - !GetAtt CodePipelineArtifactsBucket.Arn
+ - '*'
反対に、ExecutionChangesetには各リソースを操作する権限は不要なので、最小権限にしておきます。
ExecuteChangesetRole:
Type: AWS::IAM::Role
Properties:
RoleName: GetMeowAdvicesAppPipelineExecuteChangesetRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Path: /
Policies:
- PolicyName: GetMeowAdvicesAppPipelineExecuteChangesetRolePolicy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: cloudformation:ExecuteChangeSet
Resource: !Sub arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/GetMeowAdvicesAppStack/*
これでExecuteChangesetが正常終了し、パイプラインが成功するようになったので、Step Functionsを動かしてみます。
はい、今日も4時間かかりました。。
タイムアタックは2時間以内にしたいですね。お疲れ様でした。
ここから3日目に入ります。
まず、GitHub接続は、GitHub側で承認が必要のようです。
承認後に払い出された接続ARNに差し替えると、自動でパイプラインが起動するようになりました。
- Name: Source
Actions:
- Name: CodeConnections
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeStarSourceConnection
Version: 1
Configuration:
+ ConnectionArn: !Sub arn:aws:codeconnections:us-east-1:${AWS::AccountId}:connection/866c95b8-75a9-4c3b-bec9-1f31ed5b9b31
FullRepositoryId: higurashit/topengineer-advent-calendar-2024-meow
BranchName: main
OutputArtifacts:
- Name: SourceAtf
おまけ
呼び出した際に0匹となって寂しいことがあったのと、Mapのループが無機質だったのでfindCatsGroup関数を以下の通り改善します。
- 最小匹数を1に設定
- 猫に名前をつける
import random
def lambda_handler(event, context):
names = [
'Alice', 'Bob', 'Carol', 'Charlie', 'Dave', 'Ellen', 'Eve', 'Frank', 'Isaac', 'Ivan',
'Justin', 'Mallory', 'Marvin', 'Mallet', 'Matilda', 'Oscar', 'Pat', 'Peggy', 'Victor',
'Plod', 'Steve', 'Trent', 'Trudy', 'Walter', 'Zoe', 'Darwin'
]
my_cats = []
my_cats_length = random.randrange(6) + 1 # 1~7匹
for cat in range(my_cats_length):
name = pick_name(names, my_cats)
my_cats.append({'name': name})
return {
"my_cats": my_cats
}
def pick_name(names, ignores):
name = random.choice(names)
if name in ignores:
return pick_name(names, ignores)
return name
~~~~
def lambda_handler(event, context):
+ # 猫の名前を取得
+ name = get_name(event)
# 猫画像取得
imeowge = get_imeowge()
# アドバイス取得
admeowce = get_admeowce()
admeowce_jp = get_admeowce_jp(admeowce)
admeowce_jp = translate_meow(admeowce_jp)
+ # メッセージ
+ meowssage = f'{name}「{admeowce_jp} ({admeowce}) 」'
# LINEに送信
- post_admeowce_to_line(imeowge, f'{admeowce}\n{admeowce_jp}')
+ post_admeowce_to_line(imeowge, meowssage)
+def get_name(event):
+ default_cat_name = 'Cat'
+ return event.key('name', default_cat_name)
~~~~
StateMachineを手動実行します。
Victorという名前の1匹の猫が見つかりました。
LINEを見ると、Victorからアドバイスがきています!
Victor、いいキャラしてますね。
はい、ここまででリファクタリング(?)は一旦完了とします。
Gitにタグを打ち、次のアイデアが降りてくるのを待つことにします。
所要時間
目標を240分に設定していたのですが、実際には640分かかってしまいました。
- 序章:20分
- ① アプリケーション部分のIaC化:60分
- ② アプリケーションリリースのCI/CD化:250分
- ③ パイプラインのIaC化:180分
- アプリのリファクタリング:60分
- GitHub対応:10分
- おまけ:60分
全てにおいて見立てより遅いです。
リリースパイプラインの作成とIaC化で半分以上かかっています。うん、反省。
まとめ
これで予約投稿します。
久しぶりに作業すると、思わぬところでハマりますね。アウトプットしないと忘れてしまうということを、改めて実感できた良い機会でした。
私個人の所感として、タイムアタックは、
- 適当でも良いのでとにかくアウトプットする
- 時間をあまり使わない
という2点から、投稿のモチベーションを保つのに役立つと考えました。
今後もタイムアタックを仕掛けながら、このアプリを大きくしていこうと思います。
あとはもうちょいAWSの深淵を覗かないとな、、と思いました。
それでは皆さん、良いクリスマスを!!