前回投稿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用のリストは別に分ける必要がある。


関連がありそうな記事