Terraformの基本ブロック

# 基本ブロック（8個）

①terraformブロック ： Terraformの定義
②providerブロック ： プロバイダー（どのプラットフォームを接続するか）
③resourceブロック ： AWSリソースの定義
④moduleブロック ： Terraformモジュールの定義
⑤variableブロック ： （環境、入力）変数の定義
⑥dataブロック ： 参照するインスタンスの定義
⑦outputブロック ： 出力するインスタンスの定義
⑧localブロック ：（同一モジュール内の）ローカル変数の定義


# ブロックとは
以下のvariableブロックのように{ }に囲まれた一つのまとまりを「ブロック」と呼びます。

```
variable "test" {
  type = string
}
```

# 各ブロックについて
## ①terraformブロック
Terraform自体の定義ブロック

```terraform/main.tf
terraform {
  required_version = ">=1.1"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~>3.0"
    }
  }
  backend "s3" {
    bucket  = "manage-bucket-sample"
    key     = "terraform.tfstate"
    region  = "ap-northeast-1"
    profile = "terraform"
  }
}
```

required_version：Terraformのバージョン設定
required_providers：対象のプロバイダー（インフラのプラットフォーム）の設定
※このブロックは、ある程度定型文です。

## ②providerブロック

```terraform/main.tf
provider "aws" {
  profile    = "terraform"
  region     = var.region
  access_key = var.access_key
  secret_key = var.secret_key
}
```

profile：「$ vim ~/.aws/credential」で変更した[Tterraform]と一致させること。
※同じ値を入力する。
region：ap-northeast-1（※東京）
access_key：自分（IAMユーザー）のアクセスキー（例：AIUGW&78SA69AS
secret_key：自分（IAMユーザー）のシークレットキー（例：jr232vvrkng323bfvt2tfw4

**※参考**

https://www.terraform.io/language/providers/configuration

## ③resourceブロック
インフラのサービスリソースの定義ブロック

```terraform/modules/s3/s3.tf
resource "aws_s3_bucket" "s3-private-bucket" {
  bucket = "${var.project}-${var.enviroment}-private-bucket-328674"
  acl    = "private"
  # Manege version of S3 source
  versioning {
    enabled = false
  }
}
```

aws_s3_bucket：リソース・タイプ
指定のタイプがあり、定義したい型を記載する。
s3-private-bucket：ローカル名
タイプに対して、固有の名称を付ける。自分で名前を決めて記載する。
bucket：S3バケット名
${var.project}は変数。main.tfから渡されるprojectを参照している。
実際の値（例：terraform）はterraform.tfvarsに記載する。
main.tfはterraform.tfvarsを参照し、s3.tfへ変数を渡している。

**※参考**

https://www.terraform.io/language/resources/syntax


## ④moduleブロック
各モジュール（s3.tf, glue.tf etc）の呼び出しを行うブロック
主にmain.tfに記載する。

```terraform/main.tf
module "S3" {
  source     = "./modules/s3"
  project    = var.project
  enviroment = var.enviroment
  region     = var.region
}
```

source：モジュールの配置先のパス
※フォルダ構成例
terraform
　└main.tf
　└modules
　　└s3
　　　└s3.tf

project：プロジェクト名（例：terraform
enviroment：環境名（例：dev, stg, prod
region：リージョン名（例：ap-northeast-1（東京）

※フローは下記のイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/94001270-4f23-b4f7-a3c7-1ad72664899d.png)


**※参考**

https://www.terraform.io/language/modules/syntax


## ⑤variableブロック
（tfファイルへの）入力変数の定義ブロック
各モジュールとセットで使用する。variable.tfに記載する。
※s3.tf内に記載しても動作するが、入力変数の定義コードは、variable.tfファイルにまとめて記載した方が管理しやすい。

```terraform/variables.tf
variable "region" {
  type = string
}
```

```terraform/modules/s3/variables.tf
variable "enviroment" {
  type = string
}
```

※フローは下記のイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/17b02556-6f14-93e8-7fe6-878e80422ee2.png)


**※参考**

https://www.terraform.io/language/values/variables


## ⑥dataブロック
terraformの管理対象外のリソースをtfファイル内に取り込むブロック

```terraform/modules/lambda/lambda.tf
※aws_iam_policyリソースの読み込み
data "aws_iam_policy_document" "lambda" {
  statement {
    sid     = "LambdaAssumeRolePolicy"
    effect  = "Allow"
    actions = ["sts:AssumeRole"]
    principals {
      type      = "Service"
      identifiers = [
        "logs.${var.region}.amazonaws.com",
        "lambda.amazonaws.com"
      ]
    }
  }
}
```
↓

```terraform/modules/lambda/lambda.tf
resource "aws_iam_role" "lambda" {
  name             = "${var.enviroment}-lambda-role"
  assume_role_policy = "${data.aws_iam_policy_document.lambda.json}" #参照することができる
}
```
dataブロックの定義を、「data.aws_iam_policy_document」で（インスタンスとして）受け取ることができる。
複数個所に同様のコードを書かなくて済むようになる。

```terraform/modules/lambda/lambda.tf
※archive_fileリソース（生成したアーカイブ）を取り込む
data "archive_file" "initial_lambda_package" {
  type        = "zip"
  output_path = "./src/.temp_files/lambda.zip"
  source {
    content  = "# empty"
    filename = "main.py"
  }
}
```
AWSの「archive_file」というリソースを参照することができる。
このブロックでは「archive_file」リソースを参照し、指定ディレクトリ配下に「main.py」ファイルを作成している。

**※参考**

https://www.terraform.io/language/data-sources



## ⑦outputブロック
module内のリソースの情報を、module外へ公開するためのブロック

```terraform/modules/s3/s3.tf
resource "aws_s3_bucket" "s3-private-bucket" {
  bucket = "${var.project}-${var.enviroment}-private-bucket-105"
  acl    = "private"
}
```
↓

```terraform/modules/s3/output.tf
output "aws_s3_bucket" {
    value = aws_s3_bucket.s3-private-bucket.id
    sensitive = false # not external output
}
```
↓

```terraform/main.tf
module "sfn" {
  source                = "./modules/sfn"
  s3_private_bucket06   = module.S3.aws_s3_bucket
}
```
↓

```terraform/modules/sfn/sfn.tf
resource "aws_s3_bucket_object" "lambda_file" {
  bucket = "${var.s3_private_bucket}"
  key    = "initial.zip"
  source = "./src/.temp_files/lambda.zip"
}
```
フローは下記のイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/9a6f8c9d-1982-e4c9-9870-0f0476d003a7.png)


```terraform/output.tf
output “output_test" {
  value = "test_value"
  sensitive = true # external display ok
}

$ terraform output
> Output:
> Value = test_value
※デバッグにも使用できる
```

**※参考**

https://www.terraform.io/language/values/outputs



## ⑧localブロック
ローカル変数を定義するブロック

```terraform/modules/s3/S3.tf
locals {
  bucket_name = "terraform-dev-private-bucket-41627"
}
↓
resource "aws_s3_bucket" "s3-private-bucket" {
  cidr_block = local.bucket_name  # 参照
}
```

**※参考**

https://www.terraform.io/language/values/locals




# Terraformについての調べ方のコツ

## 文法、構文
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/3023adc8-44f4-44e3-b8c7-8ae4b67dbd43.png) 

https://www.terraform.io/language

resourceブロックの書き方を参照できる。

## プロバイダー（AWS関連の構文）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2432928/7698005d-a5b5-f882-938b-463a90acba70.png)
AWS用のモジュールの書き方を参照できる。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

## 索引ページ
下記でTerraformに関するテーマをまとめて紹介しています。

https://qiita.com/tk_tatsuro/items/94c463c14de89ebbb4d8