前回投稿Terraform loop処理の応用編 の続き。CodeDeployを作成するTerraformコードに、CodeCommit, CodePipelineを追加して通して作ってみる。
cicd.tf
####################################
# CodeCommit
####################################
resource "aws_codecommit_repository" "codecommit_repos" {
for_each = var.codecommit_param_list
repository_name = lookup(each.value, "repository_name")
description = lookup(each.value, "description")
}
####################################
# CodeDeploy Application
####################################
resource "aws_codedeploy_app" "codedeploy" {
for_each = var.deploy_param_list
name = lookup(each.value, "name")
compute_platform = "Server"
}
####################################
# CodeDeploy Deployment Group
####################################
resource "aws_codedeploy_deployment_group" "codedeploy_grp" {
for_each = var.deploy_param_list
app_name = lookup(each.value, "name")
deployment_group_name = lookup(each.value, "deployment_group_name")
depends_on = [aws_codedeploy_app.codedeploy]
service_role_arn = var.deploy_role
deployment_config_name = "CodeDeployDefault.AllAtOnce"
ec2_tag_set {
ec2_tag_filter {
key = "Name"
type = "KEY_AND_VALUE"
value = lookup(each.value, "value")
}
}
deployment_style {
deployment_option = "WITHOUT_TRAFFIC_CONTROL"
deployment_type = "IN_PLACE"
}
auto_rollback_configuration {
enabled = true
events = ["DEPLOYMENT_FAILURE"]
}
}
####################################
# CodePipeline
####################################
resource "aws_codepipeline" "pipeline" {
for_each = var.pipeline_param_list
name = lookup(each.value, "name")
role_arn = var.pipeline_role
artifact_store {
location = var.bucket
type = "S3"
}
stage {
name = "Source"
action {
category = "Source"
configuration = {
BranchName = "master"
PollForSourceChanges = "true"
RepositoryName = lookup(each.value, "repository_name")
}
input_artifacts = []
name = "Source"
namespace = "SourceVariables"
output_artifacts = ["SourceArtifact"]
owner = "AWS"
provider = "CodeCommit"
region = var.region
run_order = 1
version = "1"
}
}
stage {
name = "Deploy"
action {
category = "Deploy"
configuration = {
ApplicationName = lookup(each.value, "app_name")
DeploymentGroupName = lookup(each.value, "deployment_group_name")
}
input_artifacts = ["SourceArtifact"]
name = "Deploy"
namespace = "DeployVariables"
output_artifacts = []
owner = "AWS"
provider = "CodeDeploy"
region = var.region
run_order = 1
version = "1"
}
}
}
cicd.auto.tfvars
########################################
# codecommit repos vars
########################################
codecommit_param_list = {
param1 = {
repository_name = "repo001"
description = "desciption for repo001"
}
param2 = {
repository_name = "repo002"
description = "desciption for repo002"
}
param3 = {
repository_name = "repo003"
description = "desciption for repo003"
}
}
########################################
# codedeploy vars
########################################
deploy_param_list = {
param1 = {
name = "deploy_app001"
deployment_group_name = "deploy_grp001"
value = "ec2-tag001"
}
param2 = {
name = "deploy_app002"
deployment_group_name = "deploy_grp002"
value = "ec2-tag002"
}
param3 = {
name = "deploy_app003"
deployment_group_name = "deploy_grp003"
value = "ec2-tag003"
}
}
########################################
# codedeploy vars
########################################
pipeline_param_list = {
param1 = {
name = "pipeline001"
app_name = "deploy_app001"
deployment_group_name = "deploy_grp001"
repository_name = "repo001"
}
param2 = {
name = "pipeline002"
app_name = "deploy_app002"
deployment_group_name = "deploy_grp002"
repository_name = "repo002"
}
param3 = {
name = "pipeline003"
app_name = "deploy_app003"
deployment_group_name = "deploy_grp003"
repository_name = "repo003"
}
}
########################################
# CI/CD IAM role vars
########################################
deploy_role = "arn:aws:iam::[aws-account-id]:role/CodeDeployRole"
pipeline_role = "arn:aws:iam::[aws-account-id]:role/PipelineRole"
########################################
# S3 vars
########################################
bucket = "codepipeline-bucket-name"
variables.tf (宣言のみ)
#################
# main
#################
variable "region" {
type = string
description = ""
}
#################
# IAM
#################
variable "deploy_role" {
type = string
description = ""
}
variable "pipeline_role" {
type = string
description = ""
}
#################
# S3
#################
variable "bucket" {
type = string
description = ""
}
#################
# codecommit
#################
variable "codecommit_param_list" {
type = map(map(string))
description = ""
}
#################
# codedeploy
#################
variable "deploy_param_list" {
type = map(map(string))
description = ""
}
#################
# codepipeline
#################
variable "pipeline_param_list" {
type = map(map(string))
description = ""
}
cicd.tfのPollForSourceChangesはトリガーの定義だが、EventBridgeルール経由でやるのが望ましいから本来はfalseにする想定。ルールを別途作成する必要があるが、それが面倒なので一旦trueにしておいた。(関連付けたルールが存在しない場合、勝手に作成される)
これで実行したところ、一応期待値になった。ルールは、各パイプラインとルールがペアになるように個別に作成する。ルールが使用するIAMロールは共通のひとつでよい。このIAMの権限はコードパイプラインをスタートするだけなのだが、リソースを*にして共通で使えばよい。
ところでtfvarsでloop処理が参照するmap変数をサービス毎に分割しているが、分ける必要ないんじゃね?と思った。重複している値が複数あって、冗長だ。key名を適当に変えれば、同じparam_listで全部賄えそうな気がしてきた。次回の課題。
追記
後日param_listを全部まとめるバージョンでやってみたところ、期待値になった。だからリソース毎に個別にリストを作成する必要はない。ただし、それは参照されるリストの要素の数が全部揃っている場合。
例えばloopで作成するCodeCommitリポジトリの数が10でCodeDeploy、CodePipelineの数は8、とかだったら共通のリストにすると失敗する。このようなケースでは、CodeCommitのリストとCodeDeploy/CodePipeline用のリストは別に分ける必要がある。