OCIコンピュートインスタンスのブートボリュームの設定をTerraformで変更する

OCIのブロック・ボリュームにはパフォーマンスのパラメータ（vpus_per_gb）があります。
インスタンスのブートボリュームもブロック・ボリュームなので同様にパフォーマンスの設定が可能です。
作成するインスタンスでこの設定をデフォルト設定の「バランス」から「より高いパフォーマンス」に変更する必要があったのですが、Terraformでやろうとすると一筋縄ではいかず試行錯誤したのでまとめます。


## やりたかったこと
- OCI公式のイメージからインスタンスを作成する。
- 作成したインスタンスのブートボリュームのパラメータ（vpus_per_gb）を変更する。
- 上記をTerraformで実施する。

 
## コンピュートインスタンス作成時にはブートボリュームのパラメータを設定できない
コンピュートインスタンスは以下のようなコードで作成しています。
本筋ではないところは単純化して書いてます。

```terraform
resource "oci_core_instance" "hoge" {

  availability_domain = "HAxq:AP-TOKYO-1-AD-1"
  fault_domain        = "FAULT-DOMAIN-1"
  compartment_id      = var.compartment_id
  shape               = "VM.Standard2.2"
  display_name        = "hoge"
  hostname_label      = "hoge"

  create_vnic_details {
    subnet_id        = var.subnet.private
    assign_public_ip = false
    nsg_ids          = oci_core_network_security_group.linux.id
  }

  source_details {
    source_id   = var.image_id
    source_type = "image"

    boot_volume_size_in_gbs = 100
  }

  metadata = {
    ssh_authorized_keys = var.ssh_public_key
    user_data           = filebase64("user_data.sh")
  }

  agent_config {
    is_monitoring_disabled = false
    is_management_disabled = false
  }
}
```



`source_details` 内でブートボリュームの設定を指定していますが、 `vpus_per_gb`などの細かな設定は指定できません。ドキュメントに記載があるのは以下のパラメータのみです。

[oci_core_instance](https://www.terraform.io/docs/providers/oci/r/core_instance.html#source_details "oci_core_instance")
>source_details - (Optional) Details for creating an instance. Use this parameter to specify whether a boot volume or an image should be used to launch a new instance.
>
>    boot_volume_size_in_gbs - (Applicable when source_type=image) The size of the boot volume in GBs. Minimum value is 50 GB and maximum value is 16384 GB (16TB).
>    kms_key_id - (Applicable when source_type=image) The OCID of the Key Management key to assign as the master encryption key for the boot volume.
>    source_id - (Required) The OCID of an image or a boot volume to use, depending on the value of source_type.
>    source_type - (Required) The source type for the instance. Use image when specifying the image OCID. Use bootVolume when specifying the boot volume OCID.




## ブートボリュームのリソースだけを作成する場合にはソースにイメージを指定できない
では先にブートボリュームのリソースを単独で作成しパラメータを指定するのはどうでしょうか。
ブートボリュームのリソースは`oci_core_boot_volume`で作成できます。ドキュメントを見ると`vpus_per_gb`の記載もあり今回やりたいことはできそうです。

[oci_core_boot_volume](https://www.terraform.io/docs/providers/oci/r/core_boot_volume.html "oci_core_boot_volume")
>vpus_per_gb - The number of volume performance units (VPUs) that will be applied to this boot volume per GB, representing the Block Volume service's elastic performance options. See Block Volume Elastic Performance for more information.
>
>Allowed values:
>
>    10: Represents Balanced option.
>    20: Represents Higher Performance option.



ただ、`coci_core_boot_volume`でリソースを作成する場合にはソースとして指定できるのはおなじブートボリュームかブートボリュームのバックアップのどちらかのみのようです。イメージからインスタンスを作成したいので、事前にブートボリュームを作成してパラメータを変更するという方法もできなさそうです。
>source_details - The boot volume source, either an existing boot volume in the same availability domain or a boot volume backup. If null, this means that the boot volume was created from an image.
>
>    id - The OCID of the boot volume or boot volume backup.
>    type - The type can be one of these values: `bootVolume`, `bootVolumeBackup`


## 結局どうやったのか
`oci_core_instance`で作成されたブートボリュームはTerraformのリソースとしても定義されていないので作成後に`oci_core_boot_volume`として操作することもできず、Terraformだけで完結するのは難しそうでした。
そうなるとコンソールやoci-cliで手動で設定を変更するしかないのですが、コードに何も残らないのもいやなので、最終的には`local-exec`でoci-cliのコマンドを実行してブートボリュームの設定を変更するという方法に行き着きました。
以下のようなコードでブートボリュームが作成されたあとに`local-exec`でociのコマンドを実行するように定義しています。
当然ですがTerraformを実行する環境でoci-cliのセットアップが済んでいることが前提です。

```terraform
#boot volume settingste
data "oci_core_boot_volume_attachments" "hoge" {
  availability_domain = oci_core_instance.hoge.availability_domain
  compartment_id = oci_core_instance.hoge.compartment_id
  instance_id = oci_core_instance.hoge.id
}

data "oci_core_boot_volume" "hoge" {
  boot_volume_id = data.oci_core_boot_volume_attachments.hoge.boot_volume_attachments[0].boot_volume_id
}


resource "null_resource" "boot_volume_setting" {
  triggers = {
    boot_volume = data.oci_core_boot_volume.hoge.id
  }

  provisioner "local-exec" {
    command = "oci bv boot-volume update --boot-volume-id $boot_volume_id --vpus-per-gb $vpus_per_gb > boot_volume_setting.txt"
    environment = {
      boot_volume_id = data.oci_core_boot_volume.hoge.id
      vpus_per_gb    = 20
    }
    working_dir = "/tmp"
  }
}

```

## まとめ
Terraformを使用してイメージからコンピュートインスタンスを作成する際にはブートボリュームの`vpus_per_gb`の指定ができないので、インスタンス作成後に`local-exec`でoci-cliのコマンドを実行することで変更しました。
この方法がベストなのかはわかりませんが、現時点では他の方法は思いついていません。もっといい方法があるよという方がいましたらコメントいただけると嬉しいです。

## 参考
[OCI : ブロック・ボリュームエラスティック・パフォーマンス](https://docs.cloud.oracle.com/ja-jp/iaas/Content/Block/Concepts/blockvolumeelasticperformance.htm "ブロック・ボリュームエラスティック・パフォーマンス")
[Terraform : oci_core_instance](https://www.terraform.io/docs/providers/oci/r/core_instance.html "oci_core_instance")
[Terraform : oci_core_boot_volume](https://www.terraform.io/docs/providers/oci/r/core_boot_volume.html "oci_core_boot_volume")
[Terraform : Provisioners Without a Resource](https://www.terraform.io/docs/provisioners/null_resource.html "Provisioners Without a Resource")
[Terraform : local-exec Provisioner](https://www.terraform.io/docs/provisioners/local-exec.html "local-exec Provisioner")