TerraformでBTPトライアルアカウントの初期設定を自動化する

## 背景
BTPのトライアルアカウントの有効期間は90日です。これを過ぎるとアカウントが削除されるので、毎回新しいアカウントを作り直す必要があります。新たに作成したアカウントに対して、私の場合以下のような作業が発生します。
- HANA Cloudのインスタンス作成
- Automation Pilotによりインスタンスの自動起動をスケジュールする（※）
- SAP Build Work Zoneのサブスクライブ
- その他サービスのサブスクライブ

これら毎回発生する作業を自動化できないかと思ったことが今回の記事を書くきっかけです。
※Terraformではサービスのサブスクライブやサービスインスタンスの作成はできますが、サービスの中での設定はできないので今回の自動化の対象はAutomation Pilotをサブスクライブするところまでとなります

## Terraformとは
HashiCorp社が提供するInfrastructure as Code (IaC) ツールです。設定ファイルを使用してインフラを自動で構築することができます。AWS, Azureなど、各社がそれぞれのプラットフォームを操作するための「プロバイダー」と呼ばれるプラグインを提供します。

https://developer.hashicorp.com/terraform/intro

## Terraform provider for SAP BTP
2024年の2月にTerraform provider for SAP BTPがリリースされ、公式にTerraformを使ったBTP環境の構築ができるようになりました。

https://community.sap.com/t5/technology-blogs-by-sap/here-we-go-the-terraform-provider-for-sap-btp-release-1-0-0-is-available/ba-p/13592448

以下がTerraform Provider for SAP BTPのドキュメントです。
https://registry.terraform.io/providers/SAP/btp/latest/docs

以下のリポジトリでユースケースやサンプルファイルが公開されています。
https://github.com/SAP-samples/btp-terraform-samples

まずは触ってみたいという方は、こちらのチュートリアルから。
https://developers.sap.com/tutorials/btp-terraform-get-started.html

※これまでにも[btp-setup-automator](https://github.com/SAP-samples/btp-setup-automator?tab=readme-ov-file)というIaCツールが存在しました。Terraform provider for SAP BTPの登場に伴い、2024年2月をもってこちらのツールはアーカイブされています。

## 基本的な設定
前提：Terraform CLIのインストール
https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

まずは[チュートリアル](https://developers.sap.com/tutorials/btp-terraform-get-started.html)を参照して基本的な設定について理解します。

### 最小限の構成
最小限のプロジェクト構成は以下のようになります。

```
.
├── main.tf
└── provider.tf
```
provider.tfで使用するプロバイダおよびバージョンを指定し、main.tfでプラットフォームに対して行いたい操作を記述します。

```terraform:provider.tf
terraform {
  required_providers {
    btp = {
      source  = "SAP/btp"
      version = "~>1.0.0"
    }
  }
}

provider "btp" {
  globalaccount = "804dddfftrial-ga"
}
```

```terraform:main.tf
# サブアカウント作成
resource "btp_subaccount" "miyasuta_terraform" {
  name      = "Created by Terraform"
  subdomain = "miyasuta-terraform"
  region    = "us10"
}

# エンタイトルメント割り当て
resource "btp_subaccount_entitlement" "alert_notification_service" {
  subaccount_id = btp_subaccount.miyasuta_terraform.id
  service_name  = "alert-notification"
  plan_name     = "standard"
}
```
main.tfで何をしているかは一目瞭然ですね。resourceというのが何らかのリソースを作成する命令です。作成できるリソースは以下のページで確認できます。
https://registry.terraform.io/providers/SAP/btp/latest/docs

### 実行方法
設定ファイルを作成したら、以下の順序でコマンドを実行します。

#### BTPユーザ、パスワードの設定
環境変数にBTPユーザ、パスワードを設定します。

```:linux
export BTP_USERNAME=ユーザ名
export BTP_PASSWORD=パスワード
```

※Terraformのバージョン1.3.0からは、以下の環境変数を設定することでブラウザからSSOが可能です。
```:linux
export BTP_ENABLE_SSO=true
```
https://community.sap.com/t5/technology-blogs-by-sap/terraform-provider-for-sap-btp-version-1-3-0-what-s-new/ba-p/13692505

#### 初期化
以下のコマンドでプロバイダプラグインをダウンロードします。初期化は最初に1回行えばよいですが、provider.tfファイルを変更した場合は再度初期化が必要です。
```
terraform init
```

#### 適用
main.tfで指定したリソースを作成します。適用する前に`terraform plan`でTerraformが行う変更を確認することも可能です。
```
terraform apply
```

#### 破棄
作成したリソースを破棄します。
```
terraform destroy
```


## TerraformでBTPトライアルアカウントの初期設定を自動化する
ここからが本題です。Terraformで以下のタスクを自動化します。

1. HANA Cloudのインスタンス作成
1. SAP Build Work Zoneのサブスクライブ
1. Automation Pilot用のサブアカウントを作成し、Automation Pilotをサブスクライブ
※trialのサブアカウントはUS Eastに作成しているが、そこではAutomation Pilotが利用できないためSingaporeリージョンでサブアカウントを作成

設定に当たっては、以下のリポジトリにあるプロジェクトを参考にしました。
https://github.com/SAP-samples/btp-terraform-samples/tree/main/released/usecases/genai-setup

今回作成したプロジェクトは以下のリポジトリにあります。
https://github.com/miyasuta/terraform-btp-trial

### プロジェクト構成
プロジェクト構成は以下のようになっています。「基本的な設定」の内容と比べてフォルダやファイルが増えています。それぞれの役割について以降で説明します。

```
.
├── main.tf
├── modules
│   ├── automation-pilot
│   │   ├── automation_pilot.tf
│   │   └── automation_pilot_variables.tf
│   ├── hana-cloud
│   │   ├── hana_cloud.tf
│   │   └── hana_cloud_variables.tf
│   └── workzone
│       ├── workzone.tf
│       └── workzone_variables.tf
├── provider.tf
├── terraform.tfvars
└── variables.tf
```

各ファイルが実施しているタスクは以下の通りです。
#### main.tf
- 3つのモジュール（hana-cloud、workzone、automation-pilot）を呼び出す
- automation-pilotを呼び出す前に、Singaporeリージョンのサブアカウントを作成する

#### hana_cloud.tf
- HANA Cloud (tools) をサブスクライブ
- 管理者ロールをユーザに割り当て
- HANA Cloudのインスタンスを作成
- HANA Cloudのサービスバインディングを作成
- Service Managerのサービスインスタンスを作成（Automation PilotからHANA Cloudのインスタンスを操作するために必要）
- Service Managerのサービスバインディングを作成

#### workzone.tf
- SAP Build Work Zone, standard editionをサブスクライブ
- 管理者ロールをユーザに割り当て

#### automation_pilot.tf
- Automation Pilotをサブスクライブ
- 管理者ロールをユーザに割り当て

### modulesの役割
main.tfの中ですべての処理を行おうとするとソースが長くなってしまうので、モジュールという形でファイルを分割しています。
※`terraform init`を実行したあとでモジュールを追加した場合、再度初期化をする必要があります。

main.tfからは以下のようにモジュールを呼び出しています。

```terraform:main.tf
module "hana_cloud_setup" {
  source = "./modules/hana-cloud"

  subaccount_id        = var.subaccount_id
  hana_system_password = var.hana_system_password
  admins               = var.admins
}
```

モジュール側の.tfファイルでは、先頭でプロバイダーを宣言したあと、リソースの作成を行います。

```terraform:modules/hana-cloud/hana_cloud.tf（抜粋）
terraform {
  required_providers {
    btp = {
      source  = "sap/btp"
      version = "~> 1.2.0"
    }
  }
}

resource "btp_subaccount_entitlement" "hana_cloud_tools" {
  subaccount_id = var.subaccount_id
  service_name  = "hana-cloud-tools-trial"
  plan_name     = "tools"
}

resource "btp_subaccount_subscription" "hana_cloud_tools" {
  subaccount_id = var.subaccount_id
  app_name      = "hana-cloud-tools-trial"
  plan_name     = "tools"
  depends_on    = [btp_subaccount_entitlement.hana_cloud_tools]
}
```

### 変数の利用
グローバルアカウントやサブアカウントのIDなどは、ソースに直接書くのではなく外部から設定したいので、変数として定義します。

#### 変数の定義
変数は、variables.tfというファイルで定義します。

```terraform:variables.tf（抜粋）
variable "globalaccount" {
  type        = string
  description = "The globalaccount subdomain where the sub account shall be created."
}

variable "region" {
  type        = string
  description = "The region where the sub account shall be created in."
  default     = "ap21"

  # Checkout https://github.com/SAP-samples/btp-service-metadata/blob/main/v0/developer/aicore.json for the latest list of regions
  # supported by the AI Core service.
  validation {
    condition     = contains(["eu10-canary", "ap10", "eu10", "eu11", "jp10", "us10", "ap21"], var.region)
    error_message = "Please enter a valid region for the sub account. Checkout https://github.com/SAP-samples/btp-service-metadata/blob/main/v0/developer/aicore.json for regions providing the AI Core service."
  }  
}

variable "subaccount_id" {
  type        = string
  description = "The subaccount id."
}
```

#### 変数を使用
変数は`var.<変数名>`という形で使用することができます。

```terraform
module "hana_cloud_setup" {
  source = "./modules/hana-cloud"

  subaccount_id        = var.subaccount_id
  hana_system_password = var.hana_system_password
  admins               = var.admins
}
```

#### 変数に値を設定
変数に設定する値は`terraform.tfvars`というファイルで定義します。**このファイルはGitHubにはアップロードされていないため、自分で用意する必要があります**。

```:terraform.tfvars
# Your global account subdomain
globalaccount = "804dddfftrial-ga"

# The admin users
admins  = ["管理者ユーザのメールアドレス"]

# Comment out the next line if you want to provide the password here instead of typing it in the console (not recommended for security reasons)
hana_system_password = "パスワード"

# ID of trial subaccount
subaccount_id = "c6a435d9-067b-422b-bef8-cc460cd6f294"
```

#### modulesの中のvariablesファイルについて
modulesフォルダの中にも`_variables.tf`とつくファイルがあります。ここには、各モジュール内で使用する変数が定義されています。モジュールで使用する変数はすべてルートのvariables.tfでも定義されているので冗長に思えますが、同じ階層に変数の定義がないとモジュール側がエラーになってしまいます。モジュールはルート側に何があるかは関係なく、独立して動くようになっている必要があるのだと思われます。

```
.
├── main.tf
├── modules
│   ├── automation-pilot
│   │   ├── automation_pilot.tf
│   │   └── automation_pilot_variables.tf <-これは？
```

実行時にはmain.tfから変数に値が渡されます。main.tfから渡している変数は、ルートで定義されたものです。

```terraform
module "hana_cloud_setup" {
  source = "./modules/hana-cloud"

  subaccount_id        = var.subaccount_id
  hana_system_password = var.hana_system_password
  admins               = var.admins
}
```

### 実行結果
`terraform apply`を実行すると、指定したリソースが作成されます。1回目は時間がかかりますが、以降は差分のみの適用になるので早いです。

- trialサブアカウント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/7bdaaafc-2970-f788-0fd4-959c3546a58f.png)

- Automation Pilot用のサブアカウント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/4887daa4-5a45-2446-598d-789b1d00d677.png)

## おわりに
Terraformの設定は少し手間ですが、今後も3か月ごとに発生する作業がコマンド一つでできるようになるので、やってよかったと思います。追加したいサービスなどはmodulesに追加することで簡単に増やせるので、今後も拡張していこうと思います。