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.

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.
