【ハンズオン】 Terraform で Oracle Enterprise Database Service を 構築する 手順

# はじめに

前回、『[【LiveLabs】Terraform を 使用して OracleCloud で Compute を構築してみた](https://qiita.com/yama6/items/7898fe304efc1bf50fff "【LiveLabs】Terraform を 使用して OracleCloud で Compute を構築してみた")』と題して、TerraformでComputeを構築しました。
今回は、前回の資産を活かし、DBCS ([Oracle Enterprise Database Service](https://www.oracle.com/jp/database/enterprise/ "Oracle Enterprise Database Service"))をTerraformで構築してみました。

# Oracle Enterprise Database Service とは？

**Oracle Enterprise Database Serviceとは、Oracle Database Enterprise Editionに相当するデータベースサービスです。** これまで、DBCS EE（Oracle Database Cloud Service Enterprise Edition）というサービス名でしたが、最近サービス名アップデートがありました。
旧サービス名：DBCSと、新サービス名の対応表は下記の通りです。

| 新サービス名 | 旧サービス名 | Edition | 使用可能なオプション | 
|:--:|:--:|:--:|:--:|
|[Oracle Standard Database Service](https://www.oracle.com/jp/database/standard/ "Oracle Standard Database Service")|Oracle Database Cloud Service Standard Edition |Oracle Database Standard Edition SE2|表領域暗号化, Multitenant (3PDBまで)|
|[Oracle Enterprise Database Service](https://www.oracle.com/jp/database/enterprise/ "Oracle Enterprise Database Service")|Oracle Database Cloud Service Enterprise Edition |Oracle Database Enterprise Edition|上記に加え、EE標準機能（Data Guard, HCC, パラレル処理 etc）, Data Masking and Subsetting Pack, Diagnostics and Tuning Packs, Real Application Testing|
|[Oracle Enterprise Database Service - High Performance](https://www.oracle.com/jp/database/enterprise/ "Oracle Enterprise Database Service- High Performance")|Oracle Database Cloud Service Enterprise Edition - High Performance |Oracle Database Enterprise Edition|上記に加え、Multitenant, Partitioning, Advanced Compression, Advanced Security, Label Security, Database Vault, OLAP, Management Packs|
|[Oracle Enterprise Database Service - Extreme Performance](https://www.oracle.com/jp/database/enterprise/ "Oracle Enterprise Database Service- Extreme Performance")|Oracle Database Cloud Service Enterprise Edition - Extreme Performance |Oracle Database Enterprise Edition|上記に加え、Real Application Clusters(RAC), DB In-Memory, Active Data Guard|

オンプレミスのOracle Databaseと比較したときに、Oracle CloudのDatabase Serviceの何が優れているかという話ですが、**クラウドならではの拡張性**という観点から、私は機能の豊富さに魅力を感じています。
これまでオンプレOracleでは、上記表の4列目、「使用可能なオプション」を個々に購入する必要がありました。どれも数十万、数百万の初期費用を支払う必要があったため、コストの観点から導入検討が難しい側面がありましたが、Oracle Cloud Infrastructureでは、従量課金制及びEditionという単位でオプションをパッケージ提供してくれるので、選定しやすくなりました。
また、コストの観点からは、オンプレでは毎年複利で上がっていく「[更新時調整料金（Price Adjustment）](https://xn--w8j8bac3czf5bl7e.com/2021/08/17/oracle%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E4%BF%9D%E5%AE%88%E6%9B%B4%E6%96%B0%E3%81%AE%E3%81%A8%E3%81%8D%E3%81%AB%E3%81%8B%E3%81%8B%E3%82%8B%E3%80%8C%E6%9B%B4%E6%96%B0%E6%99%82%E8%AA%BF/ "更新時調整料金（Price Adjustment）")」がOracle Cloud Infrastructureでは発生しません。
というわけで、クラウド化したいけど、お得にオンプレOracleをそのまま利用したい、将来的なワークロードの拡張も考慮したい、という場合に、Oracle Enterprise Database Serviceは有効な手段の一つになりえます。

# なぜTerraformが構築に有効なの？
Oracle Enterprise Database Serviceを選定する動機として、オンプレでOracleを使用しており、クラウドでも運用を変えたくない、処理性能を劣化させたくないというものが考えられます。
しかし、Oracle Cloud Infrastructureが後発のため検討の俎上に上がらなかった、他クラウドにOracle Databaseを載せるとライセンス費用が高くなってしまうといった理由から、アプリケーションレイヤーはクラウドに移行したが、DBはオンプレミスのまま運用を続けるケースも多いのではないでしょうか。
この場合、App層はAWSやAzure、DB層はOCIというマルチクラウド構成のアプローチとなりますが、管理するパブリッククラウドが増えることや、開発、検証、本番など、複数環境を構築、移行して管理するコストが懸念されます。
そこで、IaC(Infrastructure as Code)として、Terraform によるコードベースの構築が有効となります。
Terraform であれば、複数環境の構築にコードを使いまわし、環境ごとに１から構築する手間を省くことができます。また、AWSやAzureなどのパブリッククラウドにも対応しているため、マルチクラウド構成における管理の手間を大きく削減することが可能です。

# 構築するもの

VCNと、Public Subnetの中に、Oracle Enterprise Database Service を構築します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/a09e756c-b3b5-2073-d76d-269e62b43b20.png)


# 構築手順
1. ベースとなるソースコードの選定
2. ソースコードの編集
3. Oracle Cloud Shellを使用したSSHキーの作成
4. TerraformによるVCNとOracle Enterprise Database Serviceのデプロイ
5. お片付け

# 1. ベースとなるソースコードの選定

Oracle Cloud Infrastructure では、Terraformで構築可能なサービスのソースコードをGitHubに公開しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/e09a8dd9-b077-2ffe-1144-5a2c1ee199e7.png)
今回は、下記より Oracle Enterprise Database Service のソースコードを参照します。
https://github.com/oracle/terraform-provider-oci/blob/master/examples/database/db_systems/db_vm/db_vm_amd/main.tf


<details><summary>Oracle Enterprise Database Service Terraform ベースコード</summary><div>

```
// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0
variable "tenancy_ocid" {
}

variable "user_ocid" {
}

variable "fingerprint" {
}

variable "private_key_path" {
}

variable "region" {
}

#variable "kms_key_id" {
#}
#
#variable "kms_key_version_id" {
#}
#
#variable "vault_id" {
#}

variable "compartment_ocid" {
}

variable "ssh_public_key" {
}

variable "ssh_private_key" {
}

# DBSystem specific
variable "db_system_shape" {
  default = "VM.Standard.E4.Flex"
}

variable "cpu_core_count" {
  default = "2"
}

variable "db_system_storage_volume_performance_mode" {
  default = "BALANCED"
}

variable "db_edition" {
  default = "ENTERPRISE_EDITION"
}

variable "db_admin_password" {
  default = "BEstrO0ng_#12"
}

variable "db_version" {
  default = "19.0.0.0"
}

variable "db_disk_redundancy" {
  default = "NORMAL"
}

variable "sparse_diskgroup" {
  default = true
}

variable "hostname" {
  default = "myoracledb"
}

variable "host_user_name" {
  default = "opc"
}

variable "n_character_set" {
  default = "AL16UTF16"
}

variable "character_set" {
  default = "AL32UTF8"
}

variable "db_workload" {
  default = "OLTP"
}

variable "pdb_name" {
  default = "pdbName"
}

variable "data_storage_size_in_gb" {
  default = "256"
}

variable "license_model" {
  default = "LICENSE_INCLUDED"
}

variable "node_count" {
  default = "1"
}

variable "test_database_software_image_ocid" {

}

provider "oci" {
#  version = "4.70.0"
  tenancy_ocid     = var.tenancy_ocid
  user_ocid        = var.user_ocid
  fingerprint      = var.fingerprint
  private_key_path = var.private_key_path
  region           = var.region
}

data "oci_identity_availability_domain" "ad" {
  compartment_id = var.tenancy_ocid
  ad_number      = 1
}

# Get DB node list
data "oci_database_db_nodes" "db_nodes" {
  compartment_id = var.compartment_ocid
  db_system_id   = oci_database_db_system.test_db_system.id
}

# Get DB node details
data "oci_database_db_node" "db_node_details" {
  db_node_id = data.oci_database_db_nodes.db_nodes.db_nodes[0]["id"]
}

# Gets the OCID of the first (default) vNIC
#data "oci_core_vnic" "db_node_vnic" {
#    vnic_id = data.oci_database_db_node.db_node_details.vnic_id
#}

data "oci_database_db_homes" "db_homes" {
  compartment_id = var.compartment_ocid
  db_system_id   = oci_database_db_system.test_db_system.id
}

data "oci_database_databases" "databases" {
  compartment_id = var.compartment_ocid
  db_home_id     = data.oci_database_db_homes.db_homes.db_homes[0].db_home_id
}

data "oci_database_db_versions" "test_db_versions_by_db_system_id" {
  compartment_id = var.compartment_ocid
  db_system_id   = oci_database_db_system.test_db_system.id
}

resource "oci_database_backup" "test_backup" {
  database_id = "${data.oci_database_databases.databases.databases.0.id}"
  display_name = "Monthly Backup"
}

data "oci_database_db_system_shapes" "test_db_system_shapes" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  compartment_id      = var.compartment_ocid

  filter {
    name   = "shape"
    values = [var.db_system_shape]
  }
}

data "oci_database_db_systems" "db_systems" {
  compartment_id = var.compartment_ocid

  filter {
    name   = "id"
    values = [oci_database_db_system.test_db_system.id]
  }
}

resource "oci_core_vcn" "vcn" {
  cidr_block     = "10.1.0.0/16"
  compartment_id = var.compartment_ocid
  display_name   = "TFExampleVCNDBSystem"
  dns_label      = "tfexvcndbsys"
}

resource "oci_core_subnet" "subnet" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  cidr_block          = "10.1.20.0/24"
  display_name        = "TFExampleSubnetDBSystem"
  dns_label           = "tfexsubdbsys"
  security_list_ids   = [oci_core_security_list.ExampleSecurityList.id]
  compartment_id      = var.compartment_ocid
  vcn_id              = oci_core_vcn.vcn.id
  route_table_id      = oci_core_route_table.route_table.id
  dhcp_options_id     = oci_core_vcn.vcn.default_dhcp_options_id
}

resource "oci_core_subnet" "subnet_backup" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  cidr_block          = "10.1.1.0/24"
  display_name        = "TFExampleSubnetDBSystemBackup"
  dns_label           = "tfexsubdbsysbp"
  security_list_ids   = [oci_core_security_list.ExampleSecurityList.id]
  compartment_id      = var.compartment_ocid
  vcn_id              = oci_core_vcn.vcn.id
  route_table_id      = oci_core_route_table.route_table_backup.id
  dhcp_options_id     = oci_core_vcn.vcn.default_dhcp_options_id
}

resource "oci_core_internet_gateway" "internet_gateway" {
  compartment_id = var.compartment_ocid
  display_name   = "TFExampleIGDBSystem"
  vcn_id         = oci_core_vcn.vcn.id
}

resource "oci_core_route_table" "route_table" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "TFExampleRouteTableDBSystem"

  route_rules {
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = oci_core_internet_gateway.internet_gateway.id
  }
}

resource "oci_core_route_table" "route_table_backup" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "TFExampleRouteTableDBSystemBackup"

  route_rules {
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = oci_core_internet_gateway.internet_gateway.id
  }
}

resource "oci_core_security_list" "ExampleSecurityList" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "TFExampleSecurityList"

  // allow outbound tcp traffic on all ports
  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "6"
  }

  // allow outbound udp traffic on a port range
  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "17" // udp
    stateless   = true
  }

  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "1"
    stateless   = true
  }

  // allow inbound ssh traffic from a specific port
  ingress_security_rules {
    protocol  = "6" // tcp
    source    = "0.0.0.0/0"
    stateless = false
  }

  // allow inbound icmp traffic of a specific type
  ingress_security_rules {
    protocol  = 1
    source    = "0.0.0.0/0"
    stateless = true
  }
}

resource "oci_core_network_security_group" "test_network_security_group" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "displayName"
}

resource "oci_core_network_security_group" "test_network_security_group_backup" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "displayName"
}

resource "oci_database_db_system" "test_db_system" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  compartment_id      = var.compartment_ocid
  database_edition    = var.db_edition

  db_home {
    database {
      admin_password = var.db_admin_password
#      kms_key_version_id    = var.kms_key_version_id
#      kms_key_id     = var.kms_key_id
#      vault_id       = var.vault_id
      db_name        = "aTFdbVm"
      character_set  = var.character_set
      ncharacter_set = var.n_character_set
      db_workload    = var.db_workload
      pdb_name       = var.pdb_name

      db_backup_config {
        auto_backup_enabled = false
      }
    }

    db_version   = "19.15.0.0"
    display_name = "MyTFDBHomeVm"
  }

  db_system_options {
    storage_management = "LVM"
  }

  disk_redundancy         = var.db_disk_redundancy
  shape                   = var.db_system_shape
  cpu_core_count          = var.cpu_core_count
  storage_volume_performance_mode = var.db_system_storage_volume_performance_mode
  subnet_id               = oci_core_subnet.subnet.id
  ssh_public_keys         = [var.ssh_public_key]
  display_name            = "MyTFDBSystemVM"
  hostname                = var.hostname
  data_storage_size_in_gb = var.data_storage_size_in_gb
  license_model           = var.license_model
  node_count              = data.oci_database_db_system_shapes.test_db_system_shapes.db_system_shapes[0]["minimum_node_count"]
  nsg_ids                 = [oci_core_network_security_group.test_network_security_group_backup.id, oci_core_network_security_group.test_network_security_group.id]

  #To use defined_tags, set the values below to an existing tag namespace, refer to the identity example on how to create tag namespaces
  #defined_tags  = {"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}" = "value"}

  freeform_tags = {
    "Department" = "Finance"
  }
}

resource "oci_database_db_system" "db_system_bkup" {
  source = "DB_BACKUP"
  availability_domain = data.oci_identity_availability_domain.ad.name
  compartment_id = var.compartment_ocid
  subnet_id = oci_core_subnet.subnet.id
  database_edition = var.db_edition
  disk_redundancy = var.db_disk_redundancy
  shape = var.db_system_shape
  cpu_core_count= var.cpu_core_count
  storage_volume_performance_mode= var.db_system_storage_volume_performance_mode
  ssh_public_keys         = [var.ssh_public_key]
  hostname = var.hostname
  data_storage_size_in_gb = var.data_storage_size_in_gb
  license_model = var.license_model
  node_count = data.oci_database_db_system_shapes.test_db_system_shapes.db_system_shapes[0]["minimum_node_count"]
  display_name = "tfDbSystemFromBackupWithCustImg"

  db_home {
    db_version = "19.15.0.0"
#    database_software_image_id = var.test_database_software_image_ocid
    database {
      admin_password = "BEstrO0ng_#11"
      backup_tde_password = "BEstrO0ng_#11"
      backup_id = "${oci_database_backup.test_backup.id}"
      db_name = "dbback"
    }
  }
}
```
</div></details>

※注意：そのまま元ソースをコピーした場合は、149行目と153行目が改行されてdとataが離れてしまっているので、実行した場合、エラーとなります。くっつけてあげてください。

また、今回も前回同様、CloudShell上から実行するため、ユーザの定義情報を表記するソースが必要です。
**terraform.tfvars**という名前で、下記ファイルを作成ください。
```
## Copyright (c) 2021, Oracle and/or its affiliates.
## All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl

# Authentication
tenancy_ocid         = "XXXXXXXX"

# SSH Keys
ssh_public_key  = ""

# Region
region = "XXXXXXXX"

# Compartment
compartment_ocid = "XXXXXXXX"

```
# 2. ソースコードの編集

**terraform.tfvars**
"XXXXXXXX"部分に、上からテナンシOCID、Terraformを実行するリージョン、コンパートメントIDを入力してください。

**main.tf**
このファイルは、ローカルPCにTerraformをインストールして実行すること、terraform.tfvarsにユーザ定義情報を書かずにmain.tfでべた書きすることを前提として用意されています。
今回は、CloudShell上からTerraformコマンドを実行し、terraform.tfvarsにユーザ定義情報を書いて、それをmain.tfのインプット情報とするため、必要のない変数のコメントアウトと、これから作成するsshキーを取得する実装が必要となります。
結論、下記のように編集します。

<details><summary>Oracle Enterprise Database Service Terraform 編集後のコード</summary><div>

```
// Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
// Licensed under the Mozilla Public License v2.0
variable "tenancy_ocid" {
}

variable "user_ocid" {
}

#variable "fingerprint" {
#}

#variable "private_key_path" {
#}

variable "region" {
}

#variable "kms_key_id" {
#}
#
#variable "kms_key_version_id" {
#}
#
#variable "vault_id" {
#}

variable "compartment_ocid" {
}

variable "ssh_public_key" {
  default = ""
}

variable "ssh_private_key" {
}

# DBSystem specific
variable "db_system_shape" {
  default = "VM.Standard.E4.Flex"
}

variable "cpu_core_count" {
  default = "2"
}

variable "db_system_storage_volume_performance_mode" {
  default = "BALANCED"
}

variable "db_edition" {
  default = "ENTERPRISE_EDITION"
}

variable "db_admin_password" {
  default = "BEstrO0ng_#12"
}

variable "db_version" {
  default = "19.0.0.0"
}

variable "db_disk_redundancy" {
  default = "NORMAL"
}

variable "sparse_diskgroup" {
  default = true
}

variable "hostname" {
  default = "myoracledb"
}

variable "host_user_name" {
  default = "opc"
}

variable "n_character_set" {
  default = "AL16UTF16"
}

variable "character_set" {
  default = "AL32UTF8"
}

variable "db_workload" {
  default = "OLTP"
}

variable "pdb_name" {
  default = "pdbName"
}

variable "data_storage_size_in_gb" {
  default = "256"
}

variable "license_model" {
  default = "LICENSE_INCLUDED"
}

variable "node_count" {
  default = "1"
}

variable "test_database_software_image_ocid" {

}

provider "oci" {
#  version = "4.70.0"
  tenancy_ocid     = var.tenancy_ocid
  user_ocid        = var.user_ocid
#  fingerprint      = var.fingerprint
#  private_key_path = var.private_key_path
  region           = var.region
}

data "oci_identity_availability_domain" "ad" {
  compartment_id = var.tenancy_ocid
  ad_number      = 1
}

# Get DB node list
data "oci_database_db_nodes" "db_nodes" {
  compartment_id = var.compartment_ocid
  db_system_id   = oci_database_db_system.test_db_system.id
}

# Get DB node details
data "oci_database_db_node" "db_node_details" {
  db_node_id = data.oci_database_db_nodes.db_nodes.db_nodes[0]["id"]
}

# Gets the OCID of the first (default) vNIC
#data "oci_core_vnic" "db_node_vnic" {
#    vnic_id = data.oci_database_db_node.db_node_details.vnic_id
#}

data "oci_database_db_homes" "db_homes" {
  compartment_id = var.compartment_ocid
  db_system_id   = oci_database_db_system.test_db_system.id
}

data "oci_database_databases" "databases" {
  compartment_id = var.compartment_ocid
  db_home_id     = data.oci_database_db_homes.db_homes.db_homes[0].db_home_id
}

data "oci_database_db_versions" "test_db_versions_by_db_system_id" {
  compartment_id = var.compartment_ocid
  db_system_id   = oci_database_db_system.test_db_system.id
}

resource "oci_database_backup" "test_backup" {
  database_id = "${data.oci_database_databases.databases.databases.0.id}"
  display_name = "Monthly Backup"
}

data "oci_database_db_system_shapes" "test_db_system_shapes" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  compartment_id      = var.compartment_ocid

  filter {
    name   = "shape"
    values = [var.db_system_shape]
  }
}

data "oci_database_db_systems" "db_systems" {
  compartment_id = var.compartment_ocid

  filter {
    name   = "id"
    values = [oci_database_db_system.test_db_system.id]
  }
}

resource "oci_core_vcn" "vcn" {
  cidr_block     = "10.1.0.0/16"
  compartment_id = var.compartment_ocid
  display_name   = "TFExampleVCNDBSystem"
  dns_label      = "tfexvcndbsys"
}

resource "oci_core_subnet" "subnet" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  cidr_block          = "10.1.20.0/24"
  display_name        = "TFExampleSubnetDBSystem"
  dns_label           = "tfexsubdbsys"
  security_list_ids   = [oci_core_security_list.ExampleSecurityList.id]
  compartment_id      = var.compartment_ocid
  vcn_id              = oci_core_vcn.vcn.id
  route_table_id      = oci_core_route_table.route_table.id
  dhcp_options_id     = oci_core_vcn.vcn.default_dhcp_options_id
}

resource "oci_core_subnet" "subnet_backup" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  cidr_block          = "10.1.1.0/24"
  display_name        = "TFExampleSubnetDBSystemBackup"
  dns_label           = "tfexsubdbsysbp"
  security_list_ids   = [oci_core_security_list.ExampleSecurityList.id]
  compartment_id      = var.compartment_ocid
  vcn_id              = oci_core_vcn.vcn.id
  route_table_id      = oci_core_route_table.route_table_backup.id
  dhcp_options_id     = oci_core_vcn.vcn.default_dhcp_options_id
}

resource "oci_core_internet_gateway" "internet_gateway" {
  compartment_id = var.compartment_ocid
  display_name   = "TFExampleIGDBSystem"
  vcn_id         = oci_core_vcn.vcn.id
}

resource "oci_core_route_table" "route_table" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "TFExampleRouteTableDBSystem"

  route_rules {
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = oci_core_internet_gateway.internet_gateway.id
  }
}

resource "oci_core_route_table" "route_table_backup" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "TFExampleRouteTableDBSystemBackup"

  route_rules {
    destination       = "0.0.0.0/0"
    destination_type  = "CIDR_BLOCK"
    network_entity_id = oci_core_internet_gateway.internet_gateway.id
  }
}

resource "oci_core_security_list" "ExampleSecurityList" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "TFExampleSecurityList"

  // allow outbound tcp traffic on all ports
  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "6"
  }

  // allow outbound udp traffic on a port range
  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "17" // udp
    stateless   = true
  }

  egress_security_rules {
    destination = "0.0.0.0/0"
    protocol    = "1"
    stateless   = true
  }

  // allow inbound ssh traffic from a specific port
  ingress_security_rules {
    protocol  = "6" // tcp
    source    = "0.0.0.0/0"
    stateless = false
  }

  // allow inbound icmp traffic of a specific type
  ingress_security_rules {
    protocol  = 1
    source    = "0.0.0.0/0"
    stateless = true
  }
}

resource "oci_core_network_security_group" "test_network_security_group" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "displayName"
}

resource "oci_core_network_security_group" "test_network_security_group_backup" {
  compartment_id = var.compartment_ocid
  vcn_id         = oci_core_vcn.vcn.id
  display_name   = "displayName"
}

# DBSystem ssh_public_key
resource "tls_private_key" "public_private_key_pair" {
  algorithm = "RSA"
}

resource "oci_database_db_system" "test_db_system" {
  availability_domain = data.oci_identity_availability_domain.ad.name
  compartment_id      = var.compartment_ocid
  database_edition    = var.db_edition

  db_home {
    database {
      admin_password = var.db_admin_password
#      kms_key_version_id    = var.kms_key_version_id
#      kms_key_id     = var.kms_key_id
#      vault_id       = var.vault_id
      db_name        = "aTFdbVm"
      character_set  = var.character_set
      ncharacter_set = var.n_character_set
      db_workload    = var.db_workload
      pdb_name       = var.pdb_name

      db_backup_config {
        auto_backup_enabled = false
      }
    }

    db_version   = "19.15.0.0"
    display_name = "MyTFDBHomeVm"
  }

  db_system_options {
    storage_management = "LVM"
  }

  disk_redundancy         = var.db_disk_redundancy
  shape                   = var.db_system_shape
  cpu_core_count          = var.cpu_core_count
  storage_volume_performance_mode = var.db_system_storage_volume_performance_mode
  subnet_id               = oci_core_subnet.subnet.id
  ssh_public_keys         = [tls_private_key.public_private_key_pair.public_key_openssh]
  display_name            = "MyTFDBSystemVM"
  hostname                = var.hostname
  data_storage_size_in_gb = var.data_storage_size_in_gb
  license_model           = var.license_model
  node_count              = data.oci_database_db_system_shapes.test_db_system_shapes.db_system_shapes[0]["minimum_node_count"]
  nsg_ids                 = [oci_core_network_security_group.test_network_security_group_backup.id, oci_core_network_security_group.test_network_security_group.id]

  #To use defined_tags, set the values below to an existing tag namespace, refer to the identity example on how to create tag namespaces
  #defined_tags  = {"${oci_identity_tag_namespace.tag-namespace1.name}.${oci_identity_tag.tag1.name}" = "value"}

  freeform_tags = {
    "Department" = "Finance"
  }
}

resource "oci_database_db_system" "db_system_bkup" {
  source = "DB_BACKUP"
  availability_domain = data.oci_identity_availability_domain.ad.name
  compartment_id = var.compartment_ocid
  subnet_id = oci_core_subnet.subnet.id
  database_edition = var.db_edition
  disk_redundancy = var.db_disk_redundancy
  shape = var.db_system_shape
  cpu_core_count= var.cpu_core_count
  storage_volume_performance_mode= var.db_system_storage_volume_performance_mode
  ssh_public_keys         = [tls_private_key.public_private_key_pair.public_key_openssh]
  hostname = var.hostname
  data_storage_size_in_gb = var.data_storage_size_in_gb
  license_model = var.license_model
  node_count = data.oci_database_db_system_shapes.test_db_system_shapes.db_system_shapes[0]["minimum_node_count"]
  display_name = "tfDbSystemFromBackupWithCustImg"

  db_home {
    db_version = "19.15.0.0"
    database_software_image_id = var.test_database_software_image_ocid
    database {
      admin_password = "BEstrO0ng_#11"
      backup_tde_password = "BEstrO0ng_#11"
      backup_id = "${oci_database_backup.test_backup.id}"
      db_name = "dbback"
    }
  }
}
```
</div></details>

**必要のない変数のコメントアウト**

fingerprint, private_key_path のvariable（変数）部分をコメントアウトします。

**これから作成するsshキーを取得する実装**

ここが一番のポイントです。
今回、Cloud Shell上で作成したsshキーを使用してOracle Enterprise Database Serviceにアクセスします。
よって、その公開キーを取得する必要があります。公開キーは必須項目です。

公開キーを取得するため、キーペアを取得する実装は下記の通りです。
```
# DBSystem ssh_public_key
resource "tls_private_key" "public_private_key_pair" {
  algorithm = "RSA"
}
```
さらに、resource "oci_database_db_system" "test_db_system" 及び resource "oci_database_db_system" "db_system_bkup" における必須項目 ssh_public_keys に公開キーを設定する実装は下記の通りです。 上記で取得したキーペアから公開キーを取得する書き方になっています。
**ssh_public_keys  = [var.ssh_public_key]** となっている部分を修正してください。

```
ssh_public_keys         = [tls_private_key.public_private_key_pair.public_key_openssh]
```
これでファイル編集は完了です。

# 3. Oracle Cloud Shellを使用したSSHキーの作成

まずはsshキーを作成します。Cloud Shellを立ち上げ、下記手順に沿ってsshキーを作成してください。
[【LiveLabs】Terraform を 使用して OracleCloud で Compute を構築してみた](https://qiita.com/yama6/items/7898fe304efc1bf50fff "【LiveLabs】Terraform を 使用して OracleCloud で Compute を構築してみた")
**1. Oracle Cloud Shellを使用したSSHキーの作成** 


# 4. TerraformによるVCNとOracle Enterprise Database Serviceのデプロイ

ローカルで編集、作成したファイルをCloud Shellにアップロードします。
GUIで簡単にアップロードする方法があるので、今回はそれをご紹介します。

**Cloud Shell**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/3bca1a6d-c100-32e7-be45-89abb45c2ca1.png)

Cloud Shell 左上のハンバーガーメニューからUploadを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/c606f956-535e-c4d3-4a7c-2127f0a8c096.png)
select from your computer から ローカルファイルの main.tf と terraform.tfvars を選択し、それぞれアップロードを行います。
ホームディレクトリにアップロードされるので、demo/dbcsというディレクトリを作り、ファイルを移動させます。
```
mkdir demo/dbcs
mv main.tf demo/dbcs/
mv terraform.tfvars demo/dbcs/
```
demo/dbcsディレクトリに移動し、Terraformコマンドを実行しましょう。
まずは初期化を行います。
```
cd demo/dbcs
terraform init
```
以下が表示されたら成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/00b10687-29ec-c003-a3d7-3c375fbf63b5.png)
次に、planコマンドを実行します。
```
terraform plan
```
下記のように、Enter a value:が表示されますが、Enterを押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/33aebc57-e61f-4d44-5f49-4e61eeda526d.png)
エラーメッセージが表示されず、下記メッセージが表示されたら成功です。

```
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
```

では、applyコマンドを実行しましょう。
```
terraform apply
```
VPCが作成された後で、Oracle Enterprise Database Service のプロビジョニングが始まります。
Oracle Enterprise Database Serviceの作成には少し時間がかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/5ae808c9-ee7d-078c-c0f9-a5fe05f01209.png)

因みに、今回作成したのはEnterprise EditionにあたるOracle Enterprise Database Serviceでしたが、
main.tfのdb_editionプロパティを変更することで、他のエディション及びOracle Standard Database Serviceの作成も可能です。
Terraformファイルで設定するプロパティ値については、下記ドキュメントに記載があるので、ご参考になれば幸いです。
https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/database_db_system#timeouts
また、コンソール画面の設定値とTerraformファイルの設定値を比較し、プロパティ値の確認を行うことで、要件に合わせて変更するべき項目を特定することができます。

しばらく待って、下記のように使用可能の状態になれば成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/6e8788a8-9cd5-3024-6671-64d544b91231.png)


# 5. お片付け

Oracle Enterprise Database Service が確認できたところで、お片付けです。
下記コマンドを実行してください。

```
terraform destroy
```
今回は、Terraformソースが公開されているGitHubからベースとなるソースを持ってきて、一部編集してからTerraformでリソースをデプロイするハンズオンを行いました。
Terraformファイルを書けてしまえば、コンソールから設定をいじらずにデプロイできてしまう利便さ、またファイルを一部編集することで要件に合わせてカスタマイズしていける汎用性をご理解いただけましたら幸いです。

次回は、デプロイしたリソースの状態を保持するtfstateファイルをオブジェクトストレージに格納するデプロイ方法、Cloud Shellから作成したsshキーをkvsに保持して、よりセキュアにデプロイする方法など、より掘り下げたTerraform構築について書きたいと思います。