Terraformer インストール・利用方法 (Google Cloud, AWS, Azure, Datadog), gcloud での terraform code 生成

## はじめに
[Terraformer](https://github.com/GoogleCloudPlatform/terraformer#terraformer) というクラウドの既存状態から Terraform Code を生成してくれるツールがある (作成は Google 傘下の Waze 社 SRE チーム)
ここでは、インストール方法の確認と各クラウド (Google Cloud, AWS, Azure, Datadog) で動作確認をしたので、その内容をまとめる
また、Google Cloud は [gcloud で Terraform Code 生成](https://cloud.google.com/docs/terraform/resource-management/export?hl=ja)もプレビュー版で提供しているのでそちらも合わせて記載する

## Terraformer インストール
[ドキュメントのインストール](https://github.com/GoogleCloudPlatform/terraformer#installation)箇所を参照して実施する
github から最新のバイナリを取得してリネーム・パスへ配置する

### 実施環境 OS
Rocky Linux release 9.1 (Blue Onyx)

### インストール手順 (Shell)

```sh
export PROVIDER=all
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64
chmod +x terraformer-${PROVIDER}-linux-amd64
sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer
```

### インストール方法 (Ansible Tasks)

```yaml:roles/terraformer/tasks.yaml
# https://github.com/GoogleCloudPlatform/terraformer#installation
## 0.8.22 = tag_name / latest check "curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name"
- name: install terraformer 0.8.22
  get_url:
    url: https://github.com/GoogleCloudPlatform/terraformer/releases/download/0.8.22/terraformer-all-linux-amd64
    dest: /usr/local/bin/terraformer
    mode: "+x"
  become: yes
```

※ `0.8.22` は記載時点でのバージョン


### terraformer インストール確認
インストールしたらコマンドを打って入っていることを確認する

```sh
$ terraformer -v
version v0.8.22
```

## (Google Cloud のみ) google-cloud-sdk-config-connector (gcloud terraform コード生成拡張) インストール
インストールスクリプトやリポジトリでのインストール方法が用意されている
ここでは、リポジトリを使用したインストールを記載する

### インストール方法 (手動)
[ドキュメント1](https://cloud.google.com/sdk/docs/install?hl=ja#rpm), [ドキュメント2](https://cloud.google.com/docs/terraform/resource-management/export?hl=ja#before-you-begin)に倣って設定する
サービスアカウントが自動で生成されない場合があるので、生成コマンドを追加している ([ドキュメント](https://cloud.google.com/sdk/gcloud/reference/beta/services/identity/create))

```sh
sudo tee -a /etc/yum.repos.d/google-cloud-sdk.repo << EOM
[google-cloud-cli]
name=Google Cloud CLI
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el8-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOM
sudo dnf install google-cloud-cli

export PROJECT_ID=[]
export PROJECT_NUMBER=[]
gcloud components install config-connector
gcloud services enable cloudasset.googleapis.com --project $PROJECT_ID
gcloud beta services identity create --service=cloudasset.googleapis.com --project $PROJECT_ID
gcloud --project $PROJECT_ID projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com \
  --role=roles/servicenetworking.serviceAgent
gcloud --project $PROJECT_ID projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com \
  --role=roles/storage.objectAdmin
```

### インストール方法 (Ansible, Terraform)
ローカル側のインストールを Ansible 、クラウド側の設定を Terraform で実施

```yaml:ansible/role/gcloud/tasks/task.yml
 name: install yum repository
  yum_repository:
    name: google-cloud-sdk
    description: "Google Cloud SDK repo"
    baseurl: https://packages.cloud.google.com/yum/repos/cloud-sdk-el8-x86_64
    enabled: no
    gpgcheck: yes
    repo_gpgcheck: yes
    gpgkey:
      - https://packages.cloud.google.com/yum/doc/yum-key.gpg
      - https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
  become: true

- name: install google cloud sdk
  dnf:
    name: google-cloud-sdk
    state: latest
    enablerepo: "google-cloud-sdk"
  become: true

- name: install google-cloud-sdk components
  dnf:
    name: "{{ packages }}"
    state: latest
    update_cache: yes
    enablerepo: "google-cloud-sdk"
  vars:
    packages:
      - google-cloud-sdk-config-connector
  become: true

```

```tf
resource "google_project_service" "cloudasset_api_enable" {
  project                    = google_project.main.id
  disable_dependent_services = true
  service = "cloudasset.googleapis.com"
}

resource "google_project_service_identity" "cloudasset_sa" {
  provider = google-beta
  project = google_project.main.name

  service = "cloudasset.googleapis.com"
  depends_on = [
    google_project_service.cloudasset_api_enable,
  ]
}

resource "google_project_iam_binding" "servicenetworking_serviceagent" {
  project = google_project.main.id

  role = "roles/servicenetworking.serviceAgent"

  members = [
    "serviceAccount:service-${google_project.main.number}@gcp-sa-cloudasset.iam.gserviceaccount.com"
  ]
  depends_on = [
    google_project_service_identity.cloudasset_sa,
  ]
}

resource "google_project_iam_binding" "storage_objectadmin" {
  project = google_project.main.id

  role = "roles/storage.objectAdmin"

  members = [
    "serviceAccount:service-${google_project.main.number}@gcp-sa-cloudasset.iam.gserviceaccount.com"
  ]
  depends_on = [
    google_project_service_identity.cloudasset_sa,
  ]
}
```


## Google Cloud での利用方法
Google Cloud は Terraformer と gcloud の 2つの方法で Terraform Code を生成できるので分けて記載する

### Terraformer
Terraoform 実行環境を整えるために、`version.tf`で`provider`と`version`を指定する

```sh
mkdir google-terraformer
cd google-terraformer
vi version.tf
```

```tf:version.tf
terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
      version = "4.52.0"
    }
  }
  required_version = ">= 0.13"
}
```

実行に必要な権限を含むサービスアカウントキー、対象プロジェクトを環境変数で作成して、`terraform init`で初期化する
(`GOOGLE_APPLICATION_CREDENTIALS`の説明は省略([ドキュメント](https://cloud.google.com/docs/authentication/production?hl=ja#automatically)))

```sh
export GOOGLE_APPLICATION_CREDENTIALS=[YOUR TERRORM SERVICE ACCOUT KEY JSON]
export GCP_PROJECT=[YOUR GCP PROJECT ID]
terraform init
```

下記で`terraformer import`を試す
IAM 実行には参照者とサービスアカウントの参照権限が必要

```sh
terraformer import google -r project,iam --projects=$GCP_PROJECT
```

実施すると下記のような構成で Terraform Code が生成される
`-z [region]`のオプションを指定しないとデフォルト`global`となるので、リージョンリソースを取得するには`-z asia-northeast1`のようなオプション追加が必要

```sh
|-- generated
|   `-- google
|       `-- [GCP_PROJECT]
|           |-- iam
|           |   `-- global
|           |       |-- outputs.tf
|           |       |-- project_iam_member.tf
|           |       |-- provider.tf
|           |       `-- terraform.tfstate
|           `-- project
|               `-- global
|                   |-- outputs.tf
|                   |-- project.tf
|                   |-- provider.tf
|                   `-- terraform.tfstate
`-- version.tf
```

全てを対象としたい場合は、下記のように `-r="*"` で可能
(ただし Terraformer 対応サービス全てにアクセスするため時間と IAM 次第ではエラーが頻発するので`*`にする場合は `roles/owner` で実施したほうが良さそう)

```
terraformer import google -r="*" --projects=$GCP_PROJECT
```

リソース全てで実施すると下記のようなフォルダ構成で作成される
(リソースが無いと`provider.tf`と`terraform.tfstate`の2ファイルが作成され provider と version が指定されるのみとなる)

```sh
$ ls generated/google/$GCP_PROJECT/
addresses        dns                    healthChecks           instances                nodeGroups             regionHealthChecks           resourcePolicies  targetHttpProxies   vpnTunnels
autoscalers      externalVpnGateways    httpHealthChecks       interconnectAttachments  nodeTemplates          regionInstanceGroupManagers  routers           targetHttpsProxies
backendBuckets   firewall               httpsHealthChecks      kms                      packetMirrorings       regionInstanceGroups         routes            targetInstances
backendServices  forwardingRules        iam                    logging                  project                regionSslCertificates        schedulerJobs     targetPools
bigQuery         gcs                    images                 memoryStore              pubsub                 regionTargetHttpProxies      securityPolicies  targetSslProxies
cloudFunctions   gke                    instanceGroupManagers  monitoring               regionAutoscalers      regionTargetHttpsProxies     sslCertificates   targetTcpProxies
dataProc         globalAddresses        instanceGroups         networkEndpointGroups    regionBackendServices  regionUrlMaps                sslPolicies       targetVpnGateways
disks            globalForwardingRules  instanceTemplates      networks                 regionDisks            reservations                 subnetworks       urlMaps

$ ls generated/google/$GCP_PROJECT/cloudFunctions/global/
provider.tf  terraform.tfstate
```

生成されたコードを実行するには対象のフォルダに移動して実行する
そのまま実行すると下記のようなエラーとなる

```sh:error
$ cd generated/google/$GCP_PROJECT/iam/global/
$ terraform init
Initializing the backend...
╷
│ Error: Invalid legacy provider address
│ 
│ This configuration or its associated state refers to the unqualified provider "google".
│ 
│ You must complete the Terraform 0.13 upgrade process before upgrading to later versions.
```

terraformer は terraform version 0.13 ベースのため[ドキュメント](https://github.com/GoogleCloudPlatform/terraformer#migration-state-version)の通りリプレイスコマンドを実施する

```sh:replace
$ terraform state replace-provider registry.terraform.io/-/google hashicorp/google
Terraform will perform the following actions:

  ~ Updating provider:
    - registry.terraform.io/-/google
    + registry.terraform.io/hashicorp/google
...省略...
```

再実施すると問題なく利用できる

```sh
$ terraform init
Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/google versions matching "~> 4.52.0"...
- Installing hashicorp/google v4.52.0...
- Installed hashicorp/google v4.52.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

...省略...

$ terraform plan
...省略...
No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
```

下記、出力コード例 (project, ユーザドメイン名はマスク)

```tf
resource "google_project_iam_member" "tfer--roles-002F-owneruser-003A-suzuyu-0040-xxxxx-002E-xxxxx-002E-xxxxx" {
  member  = "user:suzuyu@xxxxx.xxxxx.xxx"
  project = "suzuyu-xxx-xxx-xxx"
  role    = "roles/owner"
}
```

### gcloud resource-config bulk-export　--resource-format=terraform

[ドキュメント](https://cloud.google.com/docs/terraform/resource-management/export?hl=ja#export_multiple_resource_types)に従って下記のように出力先フォルダを指定して、生成リソースを絞って実行が可能

```sh
mkdir tf-output 
export GCP_PROJECT=[YOUR GCP PROJECT ID]
gcloud auth activate-service-account [YOUR TERRAFORM SERVICE ACCOUNT] --key-file=[YOUR TERRAFORM SERVICE ACCOUNT KEY FILE]
gcloud beta resource-config bulk-export \
  --resource-types=Project,IAMServiceAccount \
  --project=$GCP_PROJECT \
  --resource-format=terraform \
  --path=tf-output
```

```sh:出力例
$ gcloud beta resource-config bulk-export \
  --resource-types=Project,IAMServiceAccount \
  --project=$GCP_PROJECT \
  --resource-format=terraform \
  --path=tf-output

Exporting resource configurations to [tf-output]...done.                                                                                                                                
Exported resource configuration(s) to [tf-output].

$ cd tf-output; tree
|-- [MASK Folder Number]
|   `-- Project
|       `-- [MASK PROJECT ID].tf
`-- projects
    `-- [MASK PROJECT ID]
        `-- IAMServiceAccount
            |-- [MASK PROJECT NUMBER]-compute.tf
            `-- [MASK ACCOUNT ID].tf
```

上記出力より、生成されるコードは`.tf`コードのみで、 terraformer と違って**state ファイルなどは生成されない**

対応しているリソースタイプ・タイプ名は下記コマンドで確認可能

```sh
% gcloud beta resource-config list-resource-types

┌──────────────────────────────────────┬──────────────┬─────────┬──────┐
│               KRM KIND               │ BULK EXPORT? │ EXPORT? │ IAM? │
├──────────────────────────────────────┼──────────────┼─────────┼──────┤
│ AccessContextManagerAccessLevel      │              │         │      │
│ AccessContextManagerAccessPolicy     │              │         │ x    │
│ AccessContextManagerServicePerimeter │              │         │      │
│ ArtifactRegistryRepository           │ x            │ x       │ x    │
│ BigQueryDataset                      │ x            │ x       │      │
│ BigQueryJob                          │              │ x       │      │
│ BigQueryTable                        │ x            │ x       │ x    │
│ BigtableAppProfile                   │ x            │ x       │      │
│ BigtableGCPolicy                     │              │         │      │
│ BigtableInstance                     │ x            │ x       │ x    │
│ BigtableTable                        │ x            │ x       │ x    │
│ CloudBuildTrigger                    │              │         │      │
│ CloudIdentityGroup                   │              │         │      │
│ ComputeAddress                       │ x            │ x       │      │
│ ComputeAddress                       │ x            │ x       │      │
│ ComputeBackendBucket                 │ x            │ x       │ x    │
│ ComputeBackendService                │ x            │ x       │      │
│ ComputeBackendService                │ x            │ x       │      │
│ ComputeDisk                          │ x            │ x       │ x    │
│ ComputeDisk                          │ x            │ x       │ x    │
│ ComputeExternalVPNGateway            │ x            │ x       │      │
│ ComputeFirewall                      │ x            │ x       │      │
│ ComputeForwardingRule                │ x            │ x       │      │
│ ComputeForwardingRule                │ x            │ x       │      │
│ ComputeHTTPHealthCheck               │ x            │ x       │      │
│ ComputeHTTPSHealthCheck              │ x            │ x       │      │
│ ComputeHealthCheck                   │ x            │ x       │      │
│ ComputeHealthCheck                   │ x            │ x       │      │
│ ComputeImage                         │ x            │ x       │ x    │
│ ComputeInstance                      │ x            │ x       │ x    │
│ ComputeInstance                      │ x            │         │ x    │
│ ComputeInstanceGroup                 │ x            │ x       │      │
│ ComputeInstanceTemplate              │ x            │ x       │      │
│ ComputeInterconnectAttachment        │ x            │ x       │      │
│ ComputeNetwork                       │ x            │ x       │      │
│ ComputeNetworkEndpointGroup          │ x            │ x       │      │
│ ComputeNetworkPeering                │              │         │      │
│ ComputeNodeGroup                     │ x            │ x       │      │
│ ComputeNodeTemplate                  │ x            │ x       │      │
│ ComputeProjectMetadata               │              │         │      │
│ ComputeRegionNetworkEndpointGroup    │              │         │      │
│ ComputeReservation                   │ x            │ x       │      │
│ ComputeResourcePolicy                │ x            │ x       │      │
│ ComputeRoute                         │ x            │ x       │      │
│ ComputeRouter                        │ x            │ x       │      │
│ ComputeRouterInterface               │              │         │      │
│ ComputeRouterNAT                     │              │         │      │
│ ComputeRouterPeer                    │              │         │      │
│ ComputeSSLCertificate                │ x            │ x       │      │
│ ComputeSSLCertificate                │ x            │ x       │      │
│ ComputeSSLPolicy                     │ x            │ x       │      │
│ ComputeSecurityPolicy                │ x            │ x       │      │
│ ComputeSharedVPCHostProject          │              │         │      │
│ ComputeSharedVPCServiceProject       │              │         │      │
│ ComputeSnapshot                      │ x            │ x       │ x    │
│ ComputeSubnetwork                    │ x            │ x       │ x    │
│ ComputeTargetGRPCProxy               │              │ x       │      │
│ ComputeTargetHTTPProxy               │ x            │ x       │      │
│ ComputeTargetHTTPProxy               │ x            │ x       │      │
│ ComputeTargetHTTPSProxy              │ x            │ x       │      │
│ ComputeTargetHTTPSProxy              │ x            │ x       │      │
│ ComputeTargetInstance                │ x            │ x       │      │
│ ComputeTargetPool                    │ x            │ x       │      │
│ ComputeTargetSSLProxy                │              │ x       │      │
│ ComputeTargetTCPProxy                │ x            │ x       │      │
│ ComputeTargetVPNGateway              │ x            │ x       │      │
│ ComputeURLMap                        │ x            │ x       │      │
│ ComputeURLMap                        │ x            │ x       │      │
│ ComputeVPNGateway                    │ x            │ x       │      │
│ ComputeVPNTunnel                     │ x            │ x       │      │
│ ContainerCluster                     │ x            │ x       │      │
│ ContainerNodePool                    │ x            │         │      │
│ DataflowFlexTemplateJob              │              │         │      │
│ DataflowJob                          │              │         │      │
│ DNSManagedZone                       │ x            │ x       │      │
│ DNSPolicy                            │ x            │ x       │      │
│ DNSRecordSet                         │              │         │      │
│ FirestoreIndex                       │              │         │      │
│ IAMCustomRole                        │ x            │         │      │
│ IAMServiceAccount                    │ x            │         │ x    │
│ IAMServiceAccountKey                 │              │         │      │
│ KMSCryptoKey                         │ x            │         │ x    │
│ KMSKeyRing                           │ x            │ x       │ x    │
│ LoggingLogSink                       │ x            │         │      │
│ MemcacheInstance                     │ x            │ x       │      │
│ MonitoringAlertPolicy                │ x            │         │      │
│ MonitoringNotificationChannel        │              │         │      │
│ PubSubSchema                         │              │ x       │      │
│ PubSubSubscription                   │ x            │ x       │ x    │
│ PubSubTopic                          │ x            │ x       │ x    │
│ RedisInstance                        │ x            │ x       │      │
│ Folder                               │ x            │ x       │ x    │
│ Project                              │ x            │ x       │ x    │
│ ResourceManagerLien                  │              │         │      │
│ ResourceManagerPolicy                │              │         │      │
│ SecretManagerSecret                  │ x            │ x       │ x    │
│ SecretManagerSecretVersion           │ x            │         │      │
│ ServiceDirectoryEndpoint             │              │ x       │      │
│ ServiceDirectoryNamespace            │ x            │ x       │ x    │
│ ServiceDirectoryService              │              │ x       │ x    │
│ ServiceNetworkingConnection          │              │         │      │
│ Service                              │ x            │ x       │      │
│ SourceRepoRepository                 │ x            │ x       │ x    │
│ SpannerDatabase                      │ x            │ x       │ x    │
│ SpannerInstance                      │ x            │ x       │ x    │
│ SQLDatabase                          │              │ x       │      │
│ SQLInstance                          │ x            │ x       │      │
│ SQLSSLCert                           │              │         │      │
│ SQLUser                              │              │         │      │
│ StorageBucket                        │ x            │         │ x    │
│ StorageBucketAccessControl           │              │         │      │
│ StorageDefaultObjectAccessControl    │              │         │      │
│ StorageNotification                  │              │         │      │
│ StorageTransferJob                   │              │         │      │
└──────────────────────────────────────┴──────────────┴─────────┴──────┘
```

対応している全てのリソースに対して実行するには`--resource-types`を指定しなければ実施可能
ただし Cloud Storage バケットを作成するようで、組織ポリシーでリージョン `us` を許可してないと下記のようにエラーとなる
```sh
Exporting resource configurations to [tf-output]...done.                                                                                                                                
ERROR: (gcloud.beta.resource-config.bulk-export) Error executing export:: [error in 'config-connector' version '1.93.0': error creating temporary bucket and prefix: error creating bucket 'export-cftg36ie05dncbtar7q0': googleapi: Error 412: 'us' violates constraint 'constraints/gcp.resourceLocations', conditionNotMet
]
```

これは事前にバケットを作成して`--storage-path` で指定することで回避できた
(バケットではサービスアカウント`"serviceAccount:service-${google_project.main.number}@gcp-sa-cloudasset.iam.gserviceaccount.com"`に`Storage レガシー オブジェクト / バケット オーナー`権限を付与して実施した)

```sh
$ export STORAGE_NAME=[YOUR STORAGE NAME]
$ gcloud beta resource-config bulk-export \
  --project=$GCP_PROJECT \
  --resource-format=terraform \
  --storage-path=gs://$STORAGE_NAME/ --path=tf-output
Exporting resource configurations to [tf-output]...done.                                                                                                                                
Exported resource configuration(s) to [tf-output].
```

## AWS での利用方法
Terraoform 実行環境を整えるために、`version.tf`で`provider`と`version`を指定する

```sh
mkdir ~/aws-terraformer
cd ~/aws-terraformer
vi version.tf
```

```tf:version.tf
terraform {
  required_providers {
    google = {
      source = "hashicorp/aws"
      version = "4.56.0"
    }
  }
  required_version = ">= 0.13"
}
```

実行に必要な権限を含むアクセス ID, アクセス KEY, を環境変数で作成して、`terraform init`で初期化する
(`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` の説明は省略([ドキュメント](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#environment-variables)))

```sh
export AWS_ACCESS_KEY_ID="anaccesskey"
export AWS_SECRET_ACCESS_KEY="asecretkey"
terraform init
```

```sh
terraformer import aws --resources=s3,vpc --regions=ap-northeast-1 --profile=""
```

```sh:tree
$ tree                                                                           
.
|-- generated
|   `-- aws
|       |-- s3
|       |   |-- outputs.tf
|       |   |-- provider.tf
|       |   |-- s3_bucket.tf
|       |   `-- terraform.tfstate
|       `-- vpc
|           |-- outputs.tf
|           |-- provider.tf
|           |-- terraform.tfstate
|           `-- vpc.tf
`-- version.tf
```

生成ファイルの動作確認を実施する
State ファイルの Migration を実施してから実施します ([ドキュメント](https://github.com/GoogleCloudPlatform/terraformer#migration-state-version))

```sh
cd ~/aws-terraformer/generated/aws/s3/
terraform state replace-provider -auto-approve "registry.terraform.io/-/aws" "hashicorp/aws"
terraform init
terraform plan
```

実行すると`No changes. Your infrastructure matches the configuration.`と出力される
`Warning: Argument is deprecated` と出たりするので、terraformer 出力コードが古いバージョンをサポートしてそう

すべてのリソースを対象に実行すると下記のようなリソースが生成される

```sh
$ terraformer import aws --resources="*" --regions=ap-northeast-1 --profile="" 
...出力省略...
$ ls generated/aws/
acm           cloud9          codecommit        devicefarm    ecs                emr       iot            msk           resourcegroups  ses     swf              waf_regional
alb           cloudformation  codedeploy        docdb         efs                eni       kinesis        nacl          route53         sfn     transit_gateway  wafv2_regional
api_gateway   cloudfront      codepipeline      dynamodb      eip                es        kms            nat           route_table     sg      vpc              workspaces
appsync       cloudhsm        cognito           ebs           eks                firehose  lambda         opsworks      s3              sns     vpc_peering      xray
auto_scaling  cloudtrail      config            ec2_instance  elastic_beanstalk  glue      logs           organization  secretsmanager  sqs     vpn_connection
batch         cloudwatch      customer_gateway  ecr           elasticache        iam       media_package  qldb          securityhub     ssm     vpn_gateway
budgets       codebuild       datapipeline      ecrpublic     elb                igw       media_store    rds           servicecatalog  subnet  waf
```


## Azure での利用方法
Terraoform 実行環境を整えるために、`version.tf`で`provider`と`version`を指定する

```sh
mkdir ~/azure-terraformer
cd ~/azure-terraformer
vi version.tf
```

```tf:version.tf
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "3.45.0"
    }
  }
  required_version = ">= 0.13"
}
```

実行に必要な権限を環境変数で作成して、`terraform init`で初期化する
([ドキュメント](https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/azure.md#examples)参照)

```sh:パラメータは環境による
export ARM_SUBSCRIPTION_ID=12345678-abcd-efgh-ijkl-123456789abc
export ARM_CLIENT_ID=87654321-4321-abcd-efgh-123456789abc
export ARM_CLIENT_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
export ARM_TENANT_ID=abcdefgh-abcd-4321-efgh-123456789abc
terraform init
```

対象リソースグループについてリソースを指定して`terraformer import`を実施する

```sh
export RGNAME="[YOUR RG NAME]"
terraformer import azure -r resource_group
terraformer import azure -R $RGNAME -r virtual_network,resource_group
terraformer import azure -r resource_group --filter=resource_group=/subscriptions/$ARM_SUBSCRIPTION_ID/resourceGroups/$RGNAME
```

下記のような構成で生成される

```sh:tree
$ tree
.
|-- generated
|   `-- azurerm
|       |-- resource_group
|       |   |-- outputs.tf
|       |   |-- provider.tf
|       |   |-- resource_group.tf
|       |   `-- terraform.tfstate
|       `-- virtual_network
|           |-- outputs.tf
|           |-- provider.tf
|           |-- terraform.tfstate
|           |-- variables.tf
|           `-- virtual_network.tf
`-- version.tf
```

生成ファイルの動作確認を実施する
State ファイルの Migration をしてから実施する ([ドキュメント](https://github.com/GoogleCloudPlatform/terraformer#migration-state-version))

```sh
cd ~/azure-terraformer/generated/azurerm/resource_group/
terraform state replace-provider -auto-approve "registry.terraform.io/-/azurerm" "hashicorp/azurerm"
terraform init
terraform plan
```

```sh:error

│ Error: Insufficient features blocks
│ 
│   on provider.tf line 1, in provider "azurerm":
│    1: provider "azurerm" {
│ 
│ At least 1 "features" blocks are required.
╵
```

上記エラーとなり、`features` が無いので追加する

```diff_terraform:provider.tf
provider "azurerm" {
  version = "~> 3.45.0"
+ features {}
}

terraform {
	required_providers {
		azurerm = {
	    version = "~> 3.45.0"
		}
  }
}
```

もう一度実施すると実行可能となる

```sh
$ terraform plan

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
╷
│ Warning: Version constraints inside provider configuration blocks are deprecated
│ 
│   on provider.tf line 2, in provider "azurerm":
│    2:   version = "~> 3.45.0"
│ 
│ Terraform 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is now deprecated and will be removed in a future version of
│ Terraform. To silence this warning, move the provider version constraint into the required_providers block.
╵
```

`Warning`が出るが一応動作した

すべてのリソースを対象に出力した場合は、下記のようなリソースが出力される

```sh:all_resources
$ terraformer import azure -r "*"
...出力省略...
$ ls generated/azurerm/
analysis             cosmosdb      disk      load_balancer           network_watcher   purview         security_center_contact               storage_container  virtual_network
app_service          data_factory  dns       management_lock         private_dns       resource_group  security_center_subscription_pricing  subnet
application_gateway  database      eventhub  network_interface       private_endpoint  route_table     ssh_public_key                        synapse
container            databricks    keyvault  network_security_group  public_ip         scaleset        storage_account                       virtual_machine
```

## Datadog での利用方法
Terraoform 実行環境を整えるために、`provider.tf`で`provider`と`version`を指定する

```sh
mkdir ~/datadog-terraformer
cd ~/datadog-terraformer
vi provider.tf
```

```tf:provider.tf
# https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/datadog.md#2-set-up-a-template-terraform-workspace
terraform {
  required_providers {
    datadog = {
      source  = "DataDog/datadog"
      # https://registry.terraform.io/providers/DataDog/datadog/latest
      version = "3.21.0"
    }
  }
}

provider "datadog" {
  # Configuration options
}
```

実行に必要な権限を環境変数で作成して、`terraform init`で初期化する
([ドキュメント](https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/datadog.md#3-run-terraformer)参照)

```sh
terraform init
```

環境変数を設定して、terraformer ですべてのリソースをターゲットで実施する

```sh
export DATADOG_API_KEY=[Datadog API key] # More information on this at https://docs.datadoghq.com/account_management/api-app-keys/ 
export DATADOG_HOST=[Datadog API host] # https://api.datadoghq.eu which can be found at https://docs.datadoghq.com/getting_started/site/#access-the-datadog-site
export DATADOG_APP_KEY=[Datadog APP key] # More information on this at https://docs.datadoghq.com/account_management/api-app-keys/

terraformer import datadog --resources="*"
```

実施後は下記のような種別で生成される

```sh
$ ls generated/datadog/                   
dashboard       downtime                   logs_archive          logs_index                 logs_pipeline_order  role                        synthetics_private_location
dashboard_json  integration_gcp            logs_archive_order    logs_index_order           metric_metadata      service_level_objective     synthetics_test
dashboard_list  integration_slack_channel  logs_custom_pipeline  logs_integration_pipeline  monitor              synthetics_global_variable  user
```

下記は生成コード例 ([手動設定](https://qiita.com/suzuyui/items/50ace200cb030cfed363#bgp-%E7%9B%A3%E8%A6%96))

```terraform:generated/datadog/monitor/monitor.tf
resource "datadog_monitor" "tfer--monitor_25024807" {
  escalation_message = ""
  evaluation_delay   = "0"
  include_tags       = "true"
  locked             = "false"
  message            = "{{#is_alert}} BGP Neighbor down {{/is_alert}}\n{{#is_alert_recovery}} BGP Neighbor Up {{/is_alert_recovery}}\n@slack-HomeLab-datadog-monitoring"

  monitor_thresholds {
    critical = "1"
  }

  name                 = "GCP BGP Session State Change Project Name [ {{project_id}} ]"
  new_group_delay      = "0"
  new_host_delay       = "300"
  no_data_timeframe    = "0"
  notify_audit         = "false"
  notify_no_data       = "false"
  priority             = "0"
  query                = "min(last_5m):avg:gcp.router.bgp.session_up{project_id:suzuyu-project} < 1"
  renotify_interval    = "0"
  renotify_occurrences = "0"
  require_full_window  = "false"
  timeout_h            = "0"
  type                 = "metric alert"
}
```

動作確認を実施する
state ファイルの provider をリプレイスして、`provider.tf` の `source` を指定しないとエラーとなるので追加する


```sh
cd ~/datadog-terraformer/generated/datadog/monitor/
terraform state replace-provider -auto-approve  "registry.terraform.io/-/datadog" "DataDog/datadog"
vi provider.tf 
```

```diff_terraform:provider.tf
terraform {
	required_providers {
		datadog = {
+ 	    source = "Datadog/datadog"
	    version = "~> 3.21.0"
		}
  }
}
```

`terraform plan` で動作することを確認する

```sh
export DD_API_KEY=$DATADOG_API_KEY
export DD_HOST=$DATADOG_HOST
export DD_APP_KEY=$DATADOG_APP_KEY
terraform init
terraform plan
```

## まとめ
Terraformer をインストールして各クラウドでコード生成・動作する修正まで実施した
Terraformer 生成コードが古めのバージョンを前提で生成されるので、生成後に修正などが必要そうだが、
参考に利用したり、IaC 化されてないクラウドの対応に有用そうなことがわかった

gcloud での生成は、Terraformer と違って、APIの有効化・サービスアカウント生成・権限付与・テンポラリバケットへのリージョン対応などが必要で環境により使い勝手が変わりそうだが、プレビュー版なので今後の対応をウォッチしてくのが良さそう

## 参考
https://github.com/GoogleCloudPlatform/terraformer

https://cloud.google.com/docs/terraform/resource-management/export?hl=ja