Terraformを使用してOCIのリソースを一括削除する

# はじめに
Terraformを使用して、OCIに作成したリソースを一括削除します。
やりたいことは、コンパートメントに作成したリソースをリージョン単位で削除することです。

以下の内容を参考にしました。

https://docs.oracle.com/ja-jp/iaas/developer-tutorials/tutorials/tf-resource-discovery-setup/01-summary.htm

https://docs.oracle.com/ja-jp/iaas/developer-tutorials/tutorials/tf-resource-discovery/01-summary.htm

https://registry.terraform.io/providers/oracle/oci/latest/docs/guides/resource_discovery.html#supported-resources

# Terrafrom OCI Providerのインストール
今回はTerraformをインストール済みのOracle Linuxサーバを使用します。
このサーバにTerrafrom OCI Providerをインストールします。

[こちら](https://releases.hashicorp.com/terraform-provider-oci/)でTerrafrom OCI Providerの最新版（今回はv5.20）を確認し、ダウンロードします。

```
$ wget https://releases.hashicorp.com/terraform-provider-oci/5.20.0/terraform-provider-oci_5.20.0_linux_amd64.zip
--2023-11-09 05:39:37--  https://releases.hashicorp.com/terraform-provider-oci/5.20.0/terraform-provider-oci_5.20.0_linux_amd64.zip
Resolving releases.hashicorp.com (releases.hashicorp.com)... 13.35.147.43, 13.35.147.59, 13.35.147.41, ...
Connecting to releases.hashicorp.com (releases.hashicorp.com)|13.35.147.43|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 46637041 (44M) [application/zip]
Saving to: ‘terraform-provider-oci_5.20.0_linux_amd64.zip’

terraform-provider-oci_5.20.0_linux_amd64.z 100%[==========================================================================================>]  44.48M  47.0MB/s    in 0.9s    

2023-11-09 05:39:38 (47.0 MB/s) - ‘terraform-provider-oci_5.20.0_linux_amd64.zip’ saved [46637041/46637041]
```

解凍して確認します。

```
$ unzip -q terraform-provider-oci_5.20.0_linux_amd64.zip 
$ ls -l
total 220952
-rw-r--r--. 1 opc opc    133427 Nov  8 03:54 CHANGELOG.md
-rw-r--r--. 1 opc opc     16725 Nov  8 03:54 LICENSE.txt
-rw-r--r--. 1 opc opc      2967 Nov  8 03:54 README.md
-rw-rw-r--. 1 opc opc  46637041 Nov  8 05:07 terraform-provider-oci_5.20.0_linux_amd64.zip
-rwxr-xr-x. 1 opc opc 179458048 Nov  8 02:30 terraform-provider-oci_v5.20.0
```

バイナリをPATHの通ったディレクトリに移動して、シンボリックリンクを作成します。

```
$ sudo mv terraform-provider-oci_v5.20.0 /usr/local/bin/
$ cd /usr/local/bin
$ sudo ln -s terraform-provider-oci_v5.20.0 terraform-provider-oci
```

バージョンを確認します。

```
$ terraform-provider-oci
2023/11/13 05:00:44 [INFO] terraform-provider-oci 5.20.0
2023/11/13 05:00:44 Executable runs in Terraform plugin mode by default. For additional usage options, please run with the '-help' flag.
This binary is a plugin. These are not meant to be executed directly.
Please execute the program that consumes these plugins, which will
load any plugins automatically
```

## 認証情報の設定
任意のPATHの通ったディレクトリに認証情報を記載したスクリプトを作成します。

```
$ cd ~/bin
$ touch provider-oci.sh
$ chmod 755 provider-oci.sh
```

（各値は記載しています）

```provider-oci.sh
#!/bin/bash
export TF_VAR_tenancy_ocid=
export TF_VAR_user_ocid=
export TF_VAR_fingerprint=
export TF_VAR_private_key_path=
export TF_VAR_region=
```

このスクリプトを実行して環境変数を有効にして、`.bashrc`ファイルに追記します。
（マニュアルの通りの手順ですが、`.bashrc`ファイルに直接書いてもいいと思います。）

```
$ source provider-oci.sh
$ echo "source ~/bin/provider-oci.sh" >> ~/.bashrc
```

# リソース検出とStateファイルの作成

Terrafrom OCI Providerを実行して、`provider-oci.sh`で設定したリージョンのリソースを検出し、tfファイルとStateファイルを作成します。

- -command=export
    - 検出したリソースをtfファイルとして出力
- -compartment_name=コンパートメント名
    - リソース検出するコンパートメント
- -generate_state
    - Stateファイルを出力
    - これを指定しない場合、tfファイルのみ作成する
- -output_path=$HOME/iad
    - 指定したディレクトリに各ファイルを保存

```
$ terraform-provider-oci -command=export -compartment_name=コンパートメント名 -generate_state -output_path=$HOME/iad
・・・
INFO 2023/11/14 01:37:18.672046 ========= PERFORMANCE SUMMARY New Branch==========
INFO 2023/11/14 01:37:18.672053 Total resources: 62
INFO 2023/11/14 01:37:18.672061 Total time taken for discovering all services: 2m39.645891985s
INFO 2023/11/14 01:37:18.672068 Total time taken for generating state of all services: 2m41.474913831s
INFO 2023/11/14 01:37:18.672075 Total time taken by entire export: 5m21.151042363s
```

実行結果から指定したリージョンには62個のリソースがあることがわかります。

作成されたファイルを確認します。

```
$ ls -l iad/
total 608
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 adm.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 ai_anomaly_detection.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 ai_document.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 ai_language.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 ai_vision.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 analytics.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 announcements_service.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 apigateway.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 apm_config.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 apm_synthetics.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 apm.tf
-rw-rw-r--. 1 opc opc    668 Nov 14 01:37 artifacts.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 auto_scaling.tf
-rw-rw-r--. 1 opc opc    615 Nov 14 01:37 availability_domain.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 bastion.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 bds.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 blockchain.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 certificates_management.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 cloud_bridge.tf
-rw-rw-r--. 1 opc opc   4181 Nov 14 01:37 cloud_guard.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 cloud_migrations.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 compute_cloud_at_customer.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 containerengine.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 container_instances.tf
-rw-rw-r--. 1 opc opc  21556 Nov 14 01:37 core.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 database_migration.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 database.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 database_tools.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 datacatalog.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 dataflow.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 dataintegration.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 data_labeling_service.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 data_safe.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 datascience.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 devops.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 disaster_recovery.tf
-rw-rw-r--. 1 opc opc   6407 Nov 14 01:37 dns.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 email.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 em_warehouse.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 events.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 file_storage.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 functions.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 fusion_apps.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 golden_gate.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 health_checks.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 identity_data_plane.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 integration.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 jms.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 kms.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 license_manager.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 load_balancer.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 log_analytics.tf
-rw-rw-r--. 1 opc opc   2996 Nov 14 01:37 logging.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 management_agent.tf
-rw-rw-r--. 1 opc opc   2011 Nov 14 01:37 marketplace.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 media_services.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 monitoring.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 mysql.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 network_firewall.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 network_load_balancer.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 nosql.tf
-rw-rw-r--. 1 opc opc   3254 Nov 14 01:37 object_storage.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 oce.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 ocvp.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 oda.tf
-rw-rw-r--. 1 opc opc    785 Nov 14 01:37 ons.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 opa.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 opensearch.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 operator_access_control.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 opsi.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 os_management_hub.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 osmanagement.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 osp_gateway.tf
-rw-rw-r--. 1 opc opc     38 Nov 14 01:37 provider.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 queue.tf
-rw-rw-r--. 1 opc opc   2543 Nov 14 01:37 recovery.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 redis.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 resourcemanager.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 sch.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 service_mesh.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 stack_monitoring.tf
-rw-rw-r--. 1 opc opc   1045 Nov 14 01:37 streaming.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 tagging.tf
-rw-rw-r--. 1 opc opc 109662 Nov 14 01:37 terraform.tfstate
-rw-rw-r--. 1 opc opc 107755 Nov 14 01:37 terraform.tfstate.tmp.backup
-rw-rw-r--. 1 opc opc    171 Nov 14 01:37 vars.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 vault.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 visual_builder.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 vn_monitoring.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 vulnerability_scanning.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 waas.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 waa.tf
-rw-rw-r--. 1 opc opc     51 Nov 14 01:34 waf.tf
```

リソースが作られていなくてもtfファイルは作成されています。
このファイルはコメントが書かれているだけで中身は空です。

```waf.tf
## This is tmp config to run import for resources

```

リソースがあるものは、ファイルの中身がこのようになっています。

```ons.tf
## This configuration was generated by terraform-provider-oci

resource oci_ons_subscription export_subscription {
  compartment_id = oci_artifacts_container_configuration.export_container_configuration.id
  defined_tags = {
  }
  delivery_policy = "{\"backoffRetryPolicy\":{\"maxRetryDuration\":7200000,\"policyType\":\"EXPONENTIAL\"}}"
  endpoint        = "xxxxxxxx@oracle.com"
  freeform_tags = {
  }
  protocol = "EMAIL"
  topic_id = oci_ons_notification_topic.export_devops-handson.id
}

resource oci_ons_notification_topic export_devops-handson {
  compartment_id = oci_artifacts_container_configuration.export_container_configuration.id
  defined_tags = {
  }
  #description = <<Optional value not found in discovery>>
  freeform_tags = {
  }
  name = "devops-handson"
}
```

# リソース削除
作成されたファイルを使用して、Terraformで削除します。

```
$ cd iad
$ terraform destroy
・・・
Plan: 0 to add, 0 to change, 58 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
・・・  
```

Terrafrom OCI Providerで検出されたリソースは62個ですが、削除されるのは58個となっています。
ログを確認できていないのですが、Data Sourceで定義されるAvailability Domain（3つ）とObject Storage Namespace（1つ）が除外されていると思います。

https://developer.hashicorp.com/terraform/language/data-sources

## エラーの確認
エラーが5つ出ましたので確認します。

```
│ Error: 405-MethodNotAllowed, Cannot delete an Oracle Predefined resource
│ Suggestion: Please retry or contact support for help with service: Recovery Protection Policy
│ Documentation: https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/recovery_protection_policy 
│ API Reference: https://docs.oracle.com/iaas/api/#/en/recovery-service/20210216/ProtectionPolicy/DeleteProtectionPolicy 
│ Request Target: DELETE https://recovery.us-ashburn-1.oci.oraclecloud.com/20210216/protectionPolicies/ocid1.recoveryservicepolicy.region1..aaaaaaaam22xkw32t524xvst7dbxz4qsxtwetmfnnxfsgslbq664vya5jbkq 
│ Provider version: 5.20.0, released on 2023-11-08.  
│ Service: Recovery Protection Policy 
│ Operation Name: DeleteProtectionPolicy 
│ OPC request ID: b25e72902d793960ec1133593919bf27/73A25D7046FFF2A0055AA9FB58B0677B/E092D0F0D31E787CB4A083E66463E15F 
```

こちらはデータベースサービスのバックアップの保護ポリシーです。同様のエラーが4つありました。
コンパートメントから参照できますが、Oracleが定義しているポリシーですので、削除する権限がないためエラーになっています。

![スクリーンショット 2023-11-14 13.11.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/8a12974c-b7b9-bc0e-bc46-0b5d7d6cd840.png)


```
╷
│ Error: 400-InvalidParameter, compartmentId is not available
│ Suggestion: Please update the parameter(s) in the Terraform config as per error message compartmentId is not available
│ Documentation: https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/cloud_guard_security_recipe 
│ API Reference: https://docs.oracle.com/iaas/api/#/en/cloud-guard/20200131/SecurityRecipe/DeleteSecurityRecipe 
│ Request Target: DELETE https://cloudguard-cp-api.us-ashburn-1.oci.oraclecloud.com/20200131/securityRecipes/ocid1.securityzonessecurityrecipe.oc1..aaaaaaaath2pdgqo7ufq4kuseqitcst2nzlihh3ux67o5uqeu2247dvvexia 
│ Provider version: 5.20.0, released on 2023-11-08.  
│ Service: Cloud Guard Security Recipe 
│ Operation Name: DeleteSecurityRecipe 
│ OPC request ID: 71c5566eb233d273570f820facbd4e03/F31A880302C17173BC18BC146EE981DE/B71A7F7B72E26122E9FE0173A94CCFE8 
```

こちらのエラーはセキュリティゾーンのレシピです。こちらもOracleが定義しているため、削除する権限がありません。
（ただ、エラーメッセージがコンパートメントIDが有効ではないとなっているので、わかりにくいです）

![スクリーンショット 2023-11-14 13.11.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/b7ad86c9-69b1-93a1-2209-ca1743bd3cb2.png)

`terraform destroy`実行後の環境を確認してみましたが、上記エラー以外のすべてのリソースが削除されていることが確認できました。
Terrafrom OCI Providerがコンパートメント内のリソースをスキャンしてくれますので、自分でもいつ作ったかわからないリソースも検出してくれて漏れなく削除できました。