AWSリソースをTerraformにImportする（Network関連_main.tf）

# 前提
[全体の概略はこちらから](https://qiita.com/hrkkanda/items/1ef47fd6213547396c99)

# 構成図
![architecture4.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2705595/54909891-bbff-a718-1e3c-c3e53fe95cca.png)

👆の図のように、
- インターネットへの通信はTransit Gatewayを使用した集約型
    (インターネットへの通信の集約化は[こちらの記事がおすすめ](https://dev.classmethod.jp/articles/tgw-outbound-aggregation-in-an-account/))
- Internet Gatewayのあるインターネットへの通信を集約するVPCは1つのみで開発、テスト、ステージングで共有
    (以下、internet VPCと呼びます)
- 同様にdatabaseがあるVPCは1つのみで開発、テスト、ステージングで共有
    (以下、database VPCと呼びます)
- マイクロサービスのVPCは開発用、テスト用、ステージング用にそれぞれ構築。
    (以下、micro VPCと呼びます)

# Moduleのフォルダ構成
```
modules/
　└ network/
        └ vpc_database/
            └ main.tf
            └ outputs.tf
            └ variable.tf
        └ vpc_internet/
        └ vpc_endpoint/
        └ vpc_micro/
        └ tgw/
        └ tgw_attach/
```
👆のフォルダ構成の通り、
- Software Engineer等のアプリ、データベース担当に素早くdatabase VPCを提供するため、database VPCのmoduleを分離
- 上記構成でコストがかかるリソースは下記2つ。極力アプリ開発にライフサイクルを合わせるため、internet VPCとTransit Gateway Attachmentのmoduleを分離
    - NAT Gateway
    - Transit Gateway Attachment
- vpc endpointのmoduleを分けた理由は後述

# 環境構築用のmain.tf, variable.tf
## main.tf
```tf
#region取得
data "aws_region" "current" {}
#account_id
data "aws_caller_identity" "now" {}
locals {
  region          = data.aws_region.current.name
  aws_account_id  = data.aws_caller_identity.now.account_id
}

#vpc_database
module "vpc_database"{
  source = "../../modules/network/vpc_database"
  env               = "dev"
  account           = var.account
  project           = var.project
  region            = local.region
  vpc_cidr_database       = var.vpc_cidr_database
  subnet_cidr_database1a  = var.subnet_cidr_database1a
  subnet_cidr_database1c  = var.subnet_cidr_database1c
  subnet_cidr_database1d  = var.subnet_cidr_database1d
  subnet_cidr_compute1a   = var.subnet_cidr_compute1a
  subnet_cidr_compute1c   = var.subnet_cidr_compute1c
  subnet_cidr_eni1a       = var.subnet_cidr_eni1a
  subnet_cidr_eni1c       = var.subnet_cidr_eni1c
}

#vpc_internet
module "vpc_internet"{
  source = "../../modules/network/vpc_internet"
  env               = "dev"
  account           = var.account
  project           = var.project
  region            = local.region
  vpc_cidr_internet =  var.vpc_cidr_internet
  subnet_cidr_public1a  = var.subnet_cidr_public1a
  subnet_cidr_public1c  = var.subnet_cidr_public1c
  subnet_cidr_private1a = var.subnet_cidr_private1a
  subnet_cidr_private1c = var.subnet_cidr_private1c
}

# vpc microservice
module "vpc_micro" {
  source    = "../../modules/network/vpc_micro"
  for_each  = var.micro
  env       = each.key
  account   = var.account
  project   = var.project
  region    = local.region
  vpc_cidr_microservice = each.value.vpc
  subnet_cidr_microservice1a  = each.value.subnet_a
  subnet_cidr_microservice1c  = each.value.subnet_c
}

# tgw
module "tgw" {
  source    = "../../modules/network/tgw"
  env       = "dev"
  account   = var.account
  project   = var.project
  vpc_cidr_database     = var.vpc_cidr_database
  vpc_database_id       = module.vpc_database.vpc_database_id
  subnet_database_id    = [
    module.vpc_database.subnet_eni1a_id, 
    module.vpc_database.subnet_eni1c_id
  ]
  vpc_internet_id       = module.vpc_internet.vpc_internet_id
  subnet_internet_id    = [
    module.vpc_internet.subnet_private1a_id,
    module.vpc_internet.subnet_private1c_id
  ]
  rtb_database_id       = module.vpc_database.rtb_compute_id
  rtb_internet_id       = module.vpc_internet.rtb_public_id
  depends_on = [ 
    module.vpc_database, 
    module.vpc_internet 
  ]
}

# tgw attachment
module "tgw_attachment_micro" {
  source    = "../../modules/network/tgw_attach"
  for_each  = var.micro
  env       = each.key
  account   = var.account
  project   = var.project
  tgw_id    = module.tgw.tgw_id
  tgw_rtb_to_internet_id    = module.tgw.tgw_rtb_to_internet_id
  tgw_rtb_from_internet_id  = module.tgw.tgw_rtb_from_internet_id
  vpc_micro_id              = module.vpc_micro[each.key].vpc_microservice_id
  vpc_cidr_micro            = each.value.vpc
  subnet_micro_id           = [
    module.vpc_micro[each.key].subnet_microservice1a_id,
    module.vpc_micro[each.key].subnet_microservice1c_id
  ]
  prefixlist_id             = module.tgw.prefixlist_id
  depends_on = [
    module.vpc_micro
  ]
}
```

## variable.tf
VPC, SubnetのCIDRを定義。
```tf
# common variable 
variable "project" {
    type        = string
    default     = "ramen"
    description = "project name"
}
variable "account" {
    type        = string
    default     = "no-prod"
    description = "prod or no-prod"
}
variable "env" {    
    type        = string
    default     = "dev"
    description = "dev, test, stage or prod"
}

# variables of cidr
## cidr of vpc associated with database
variable "vpc_cidr_database" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_database1a" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_database1c" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_database1d" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_compute1a" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_compute1c" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_eni1a" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_eni1c" {
    type    = string
    default = "**.***.**.**/**"
}
## cidr of proxy vpc
variable "vpc_cidr_internet" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_public1a" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_public1c" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_private1a" {
    type    = string
    default = "**.***.**.**/**"
}
variable "subnet_cidr_private1c" {
    type    = string
    default = "**.***.**.**/**"
}

# variables of microservice
variable "micro" {
    default = {
        dev ={
            vpc      = "**.***.**.**/**"
            subnet_a = "**.***.**.**/**"
            subnet_c = "**.***.**.**/**"
            storage = 512
            memory  = 128
        }
        test = {
            vpc      = "**.***.**.**/**"
            subnet_a = "**.***.**.**/**"
            subnet_c = "**.***.**.**/**"
            storage = 512
            memory  = 128
        }
        stage = {
            vpc      = "**.***.**.**/**"
            subnet_a = "**.***.**.**/**"
            subnet_c = "**.***.**.**/**"
            storage = 1024
            memory  = 256
        }
    }
}
```

# for_each
開発、テスト、ステージング環境の繰り返しは`for_each`で実施。
対象はmicro VPCとmicro VPCにアタッチするTransit Gateway Attachment.

```tf
# vpc microservice
module "vpc_micro" {
  source    = "../../modules/network/vpc_micro"
  for_each  = var.micro
  env       = each.key
  // ... 略
  vpc_cidr_microservice = each.value.vpc
  // ... 略
}
```

```tf
# variables of microservice
variable "micro" {
    default = {
        dev ={
            vpc      = "**.***.**.**/**"
            subnet_a = "**.***.**.**/**"
            subnet_c = "**.***.**.**/**"
            storage = 512
            memory  = 128
        }
        test = {
            vpc      = "**.***.**.**/**"
            subnet_a = "**.***.**.**/**"
            subnet_c = "**.***.**.**/**"
            storage = 512
            memory  = 128
        }
        stage = {
            vpc      = "**.***.**.**/**"
            subnet_a = "**.***.**.**/**"
            subnet_c = "**.***.**.**/**"
            storage = 1024
            memory  = 256
        }
    }
}
```
for_eachの変数は開発のライフサイクルが同じもの同士で共有すると、別のfor_eachで繰り返されているmoduleに出力を変数として渡すことが可能になります。以下の例だと、`vpc_micro`とfor_eachに同じ変数`micro`を使用する`tgw_attachment_micro`は`vpc_micro`の出力を使用可能になります。

```tf
# tgw attachment
module "tgw_attachment_micro" {
  source    = "../../modules/network/tgw_attach"
  for_each  = var.micro
  // ... 略
  vpc_micro_id              = module.vpc_micro[each.key].vpc_microservice_id
  // ... 略
  subnet_micro_id           = [
    module.vpc_micro[each.key].subnet_microservice1a_id,
    module.vpc_micro[each.key].subnet_microservice1c_id
  ]
  // ... 略
}
```

# Import するコマンド
Importは`import` コマンドで実施。moduleで定義されたterraformにリソースをimportする場合
```tf
$ terraform import module.{module名}.{resourceタイプ}.{resource名} {importするresourceのID}
```
例えば、database VPCのmoduleで定義されたVPC`vpc_database`をimportする場合、
```tf
$ terraform import module.vpc_database.aws_vpc.vpc_database vpc-***
```
for_eachで繰り返されたmodule化terraformにimportする場合、
```tf
$ terraform import module.{module名}["each_key"].{resourceタイプ}.{resource名} {imporyするresourceのID}
```
例えば、開発環境用のmicro VPCのmoduleで定義されtたVPC`vpc_microservice`をimportする場合、
```tf
$ terraform import module.vpc_micro[\"dev\"].aws_vpc.vpc_microservice vpc-***
```
※`import`コマンドでfor_eachで繰り返されたmodule化terraformにimportする場合、ターミナルでコマンドの細部が異なるので注意されたし。
[Example: Import into Resource configured with for_each](https://developer.hashicorp.com/terraform/cli/commands/import#example-import-into-resource-configured-with-for_each)

# 各moduleの設計思想
- database VPCは[こちらから](https://qiita.com/hrkkanda/items/21a31ae0842ae989460f)
- internet VPCは[こちらから](https://qiita.com/hrkkanda/items/11a2c8ea0ebd872bf98a)
- micro VPCは[こちらから](https://qiita.com/hrkkanda/items/b651ab37d31f0f31f63e)
- Transit Gatewayは[こちらから](https://qiita.com/hrkkanda/items/d36ce3f4f220bb3be3d0)
- Transit Gateway Attachmentは[こちらから](https://qiita.com/hrkkanda/items/4cb23effb0b4b120b8d3)