GitHub Actionsで実行しているTerraformをモジュール化してみた

# 背景・目的
前回、[GitHubActionsとTerraformでS3バケットを作成してみた](https://qiita.com/zumax/items/f78dd92219ecfb9503be)で構築した環境は、S3バケットを作成するものでした。

こちらは、main.tfファイルにベタで書いていましたが、今後の拡張性を見越してモジュールに書き換えておきます。


# 実践
今回は、下記のような構成に変更します。

- 変更前

    ```bash
    .
    ├── .github
    │   └── workflows
    │       └── terraform.yml
    ├── backend.hcl
    ├── backend.tf
    ├── main.tf
    └── provider.tf
    ```
- 変更後
    ```terminal
    terraform-modules/
    └── s3-bucket/
        ├── main.tf
        ├── variables.tf
        ├── outputs.tf
    root/
    ├── main.tf
    ├── variables.tf
    ├── terraform.tfvars
    ├── backend.tf
    ```

## Terraformモジュール
terraform-modulesに、各モジュールのフォルダを作成し、その配下にコードを配置します。

1. `terraform-modules` フォルダを作成します
1. `s3` フォルダを作成します
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/ab619a55-f057-65dc-a78e-acd64645cded.png)

1. `terraform-modules/s3` 配下に、`main.tf` を作成します

    ```terraform
    resource "aws_s3_bucket" "this" {
      bucket = var.bucket_name
      tags   = var.tags
    }
    
    resource "aws_s3_bucket_policy" "this" {
      bucket = var.bucket_name
    
      policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Sid       = "AllowSSLRequestsOnly"
            Effect    = "Deny"
            Principal = "*"
            Action    = "s3:*"
            Resource = [
              "arn:aws:s3:::${var.bucket_name}",
              "arn:aws:s3:::${var.bucket_name}/*"
            ]
            Condition = {
              Bool = {
                "aws:SecureTransport" = "false"
              }
            }
          }
        ]
      })
    }

    ```


1. `terraform-modules/s3` 配下に、variables.tf を作成します
    ```terraform
    variable "bucket_name" {
      description = "The name of the S3 bucket"
      type        = string
    }
    variable "tags" {
      description = "A map of tags to assign to the resource"
      type        = map(string)
      default     = {}
    }
    ```

1. `terraform-modules/s3` 配下に、`outputs.tf`を作成します
    ```terraform
    output "bucket_id" {
      description = "The ID of the bucket"
      value       = aws_s3_bucket.this.id
    }
    
    output "bucket_arn" {
      description = "The ARN of the bucket"
      value       = aws_s3_bucket.this.arn
    }
    
    output "bucket_region" {
      description = "The region of the bucket"
      value       = aws_s3_bucket.this.region
    }
    ```
## ルートモジュール
1. ルートにある`main.tf`をs3モジュールを呼び出すように修正します
    ```terraform
    data "aws_caller_identity" "this" {}
    
    module "s3" {
      source      = "./terraform-modules/s3"
      bucket_name = format("%s-%s", var.bucket_name, "${data.aws_caller_identity.this.account_id}")
      tags        = var.tags
    }
    
    output "bucket_id" {
      value = module.s3.bucket_id
    }
    
    output "bucket_arn" {
      value = module.s3.bucket_arn
    }
    
    output "bucket_region" {
      value = module.s3.bucket_region
    }
    ```
1. `variable.tf`を追加します
    ```terraform
    variable "bucket_name" {
      description = "The name of the S3 bucket"
      type        = string
    }
    
    variable "tags" {
      description = "A map of tags to assign to the resource"
      type        = map(string)
      default     = {}
    }

    ```

1. `terraform.tfvars`を追加します
    ```terraform
    bucket_name = "my-unique-bucket-name"
    tags = {
      "Environment" = "prod"
      "Project"     = "TerraformExample"
    }
    ```
## 実行確認
1. Pushします。成功しました
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206276/2f9e4a2f-a5a5-10a2-e282-0d2594bcb6d5.png)


# 考察
今回、Terraformをモジュール化しました。今後は、これを前提にNW等を構築します。

# 参考
https://qiita.com/zumax/items/01c7c78dfbf4a2335cf2

https://qiita.com/zumax/items/f78dd92219ecfb9503be