How to use Terraform to automate Oracle Autonomous Database deployments

October 27, 2023 | 13 minute read
Manuela Mustatea
Autonomous Database Specialist
Text Size 100%:

Terraform is an open source tool that allows you to programmatically manage, version, and persist infrastructure through the "infrastructure-as-code" model. It’s great way to automate consistent, reproducible deployments - even those that need complex orchestration between services. Organizations can spin up complete environments (dev, test, production) in no time. 

In this post, we'll walk through the steps to create an Autonomous Database (ADB) with a local (in-region) Autonomous Data Guard using Terraform. The high level steps are:

  • Get an OCI account and install Terraform
  • Declaratively define the deployment
  • Deploy your Autonomous Database with Autonomous Data Guard

Prerequisites

To get started with Terraform and Autonomous Database, we need the following:

  • An OCI account
  • A Terraform installation
  • The OCI Terraform provider

We'll assume that Terraform and Oracle Cloud Infrastructure (OCI) Terraform provider are installed and configured.

Deployment

Define the infrastructure

Create a new working directory and switch to that directory.

[opc@bastiontr ~]$ mkdir mytf
[opc@bastiontr ~]$ cd mytf
[opc@bastiontr mytf]$

Create a file tf_adb.tf  with the following content:

provider "oci" {
  region = "eu-frankfurt-1"
}

resource "random_string" "password" {
  length  = 16
  special = true
  min_special = 2
  min_numeric = 2
  override_special = "#"
}

resource "oci_database_autonomous_database" "tf_database_autonomous_database" {
       admin_password = random_string.password.result
       compartment_id = var.compartment_ocid
       compute_count = var.compute_count
       compute_model = var.compute_model
       data_storage_size_in_tbs = var.data_storage_size_in_tbs
       db_name = var.db_name
       db_version = var.db_version
       db_workload = var.db_workload
       display_name = var.display_name
       is_dedicated = var.is_dedicated
       is_mtls_connection_required = var.is_mtls_connection_required
       license_model = var.license_model
       whitelisted_ips = ["0.0.0.0/0"]
       is_data_guard_enabled = var.is_data_guard_enabled
       is_local_data_guard_enabled = var.is_local_data_guard_enabled
}

Create a file called variables.tf with input variable definitions, with the following content.

# Compartment
variable "compartment_ocid" {type = string}
# ADB specific
variable "db_version" {type = string}
variable "db_name" {type = string}
variable "display_name" {type = string}
variable "db_workload" {type = string}
variable "compute_count" {type    = number}
variable "data_storage_size_in_tbs" {type    = number}
variable "compute_model" {type = string}
variable "is_dedicated" {type = string}
variable "is_mtls_connection_required" {type = string}
variable "license_model" {type = string}
variable "is_data_guard_enabled" {type = string}
variable "is_local_data_guard_enabled" {type = string}

We will use an .auto.tfvars file to supply values for the input variables. Create a file adbVars.auto.tfvars. We plan to create an autonomous data warehouse (ADW) service.

In order to provision an ADW, the workload type(db_workload) is a DW, we also set is_local_data_guard_enabled to true for a local (in-region) Autonomous Data Guard to be created.

# ADB specific
db_version = "19c"
db_name = "MyADWT"
display_name = "MyADWT"
db_workload = "DW"
compute_count = "2"
data_storage_size_in_tbs= "1"
compute_model = "ECPU"
is_dedicated = "false"
is_mtls_connection_required = "false"
license_model = "BRING_YOUR_OWN_LICENSE"
is_data_guard_enabled = "true"
is_local_data_guard_enabled = "true"

Create a file called outputs.tf, output variable definitions, with the following content. It will be used to display the name of the database, status and URLs to connect to common DB Tools.  

# Outputs

output "db_name" {
  value = oci_database_autonomous_database.tf_database_autonomous_database.display_name
}
output "db_state" {
  value = oci_database_autonomous_database.tf_database_autonomous_database.state
}
output "db_conn" {
  value = oci_database_autonomous_database.tf_database_autonomous_database.connection_urls
}
output "password" {
  value = "The password is ${oci_database_autonomous_database.tf_database_autonomous_database.admin_password}"
  sensitive = true
}

Deploy Autonomous Database with Data Guard 

Initialize the working directory using the terraform init command.

terraform init

 Use terraform plan command to check the plan. The output below has been condensed:

terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_database_autonomous_database.tf_database_autonomous_database will be created
  + resource "oci_database_autonomous_database" "tf_database_autonomous_database" {
      + actual_used_data_storage_size_in_tbs           = (known after apply)
      + admin_password                                 = (sensitive value)
      + allocated_storage_size_in_tbs                  = (known after apply)
...
      + clone_type                                     = (known after apply)
      + compartment_id                                 = " ocid1.compartment.oc1.. aaaaaaaagvXXXXXXXXXXXXXXt2222CCC "
      + compute_count                                  = 2
      + compute_model                                  = "ECPU"
      + connection_strings                             = (known after apply)
...
      + data_storage_size_in_tbs                       = 1
      + db_name                                        = "MyADWT"
      + db_version                                     = "19c"
      + db_workload                                    = "DW"
      + defined_tags                                   = (known after apply)
      + disaster_recovery_region_type                  = (known after apply)
      + display_name                                   = "MyADWT"
...
      + is_data_guard_enabled                          = true
      + is_local_data_guard_enabled                    = true
...
      + vault_id                                       = (known after apply)
      + whitelisted_ips                                = [
          + "0.0.0.0/0",
        ]
    }

  # random_string.password will be created
  + resource "random_string" "password" {
      + id               = (known after apply)
      + length           = 16
      + lower            = true
      + min_lower        = 0
      + min_numeric      = 2
      + min_special      = 2
      + min_upper        = 0
      + number           = true
      + numeric          = true
      + override_special = "#"
      + result           = (known after apply)
      + special          = true
      + upper            = true
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + db_conn  = (known after apply)
  + db_name  = "MyADWT"
  + db_state = (known after apply)
  + password = (sensitive value)

Use terraform apply to create the ADW database. After you enter the command if you go back to the OCI console, the ADW will be in provisioning state. Again, the output below has been condensed:

terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
Terraform will perform the following actions:

  # oci_database_autonomous_database.tf_database_autonomous_database will be created
  + resource "oci_database_autonomous_database" "tf_database_autonomous_database" {
      + actual_used_data_storage_size_in_tbs           = (known after apply)
      + admin_password                                 = (sensitive value)
      + allocated_storage_size_in_tbs                  = (known after apply)
...
      + compute_count                                  = 2
      + compute_model                                  = "ECPU"
...
      + data_storage_size_in_tbs                       = 1
      + dataguard_region_type                          = (known after apply)
      + db_name                                        = "MyADWT"
      + db_version                                     = "19c"
      + db_workload                                    = "DW"
      + defined_tags                                   = (known after apply)
      + disaster_recovery_region_type                  = (known after apply)
      + display_name                                   = "MyADWT"
...
      + is_data_guard_enabled                          = true
      + is_local_data_guard_enabled                    = true
      + is_mtls_connection_required                    = false
...
      + whitelisted_ips                                = [
          + "0.0.0.0/0",
        ]
    }

  # random_string.password will be created
  + resource "random_string" "password" {
      + id               = (known after apply)
      + length           = 16
      + lower            = true
      + min_lower        = 0
      + min_numeric      = 2
      + min_special      = 2
      + min_upper        = 0
      + number           = true
      + numeric          = true
      + override_special = "#"
      + result           = (known after apply)
      + special          = true
      + upper            = true
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + db_conn  = (known after apply)
  + db_name  = "MyADWT"
  + db_state = (known after apply)
  + password = (sensitive value)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

random_string.password: Creating...
random_string.password: Creation complete after 0s [id=05#7izHieRHJniy#]
oci_database_autonomous_database.tf_database_autonomous_database: Creating...
oci_database_autonomous_database.tf_database_autonomous_database: Still creating... [10s elapsed]
oci_database_autonomous_database.tf_database_autonomous_database: Still creating... [20s elapsed]
...
oci_database_autonomous_database.tf_database_autonomous_database: Creation complete after 3m59s [id= ocid1.compartment.oc1.. aaaaaaaagvXXXXXXXXXXXXXXt2222CCC]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

db_conn = tolist([
  {
    "apex_url" = "https:// XXXXXXXXXX -MYADWT.adb.eu-frankfurt-1.oraclecloudapps.com/ords/apex"
    "graph_studio_url" = "https:// XXXXXXXXXX -MYADWT.adb.eu-frankfurt-1.oraclecloudapps.com/graphstudio/"
    "machine_learning_user_management_url" = "https:// XXXXXXXXXX -MYADWT.adb.eu-frankfurt-1.oraclecloudapps.com/omlusers/"
    "sql_dev_web_url" = "https:// XXXXXXXXXX -MYADWT.adb.eu-frankfurt-1.oraclecloudapps.com/ords/sql-developer"
  },
])
db_name = "MyADWT"
db_state = "AVAILABLE"
password = <sensitive>

As the password is sensitive information, it is not hardcoded into the variables file. I added the Terraform random_password resource from the random provider, which allows to generate strings according to the properties provided. The password will be sensitive, meaning that it is protected by Terraform. We can use the result, with the result property, in the password property of a new resource or when connecting from an application, this is to prevent having the password in clear text. 

The Outputs provide the Name of the database, the Status and URLs to connect to common DB Tools like APEX, Graph Studio, Machine Learning, SQL Developer Web. 

After the apply is complete, go back to the OCI console, the ADW will be in Available state with a local Autonomous Data Guard enabled.

provisioned ADB with active data guard

Conclusion

In this post, we have seen how to leverage Terraform and the OCI Terraform provider to automate the creation of ADB. By defining your infrastructure in a declarative way using Terraform, you can easily deploy environments and make changes to your infrastructure without having to worry about the underlying implementation. This can lead to faster deployments, fewer errors and a more stable infrastructure.

Manuela Mustatea

Autonomous Database Specialist

I am part of the Autonomous Database Specialist Team.


Previous Post

Oracle Autonomous Data Warehouse is really fast. Try it for yourself.

Hermann Baer | 2 min read

Next Post


How Oracle Autonomous Database Connects with Databricks Across Clouds

Alexey Filanovskiy | 6 min read
Everything you need to know about data warehousing with the world's leading cloud solution provider