oracle / terraform-provider-oci

Terraform Oracle Cloud Infrastructure provider
https://www.terraform.io/docs/providers/oci/
Mozilla Public License 2.0
760 stars 677 forks source link

Make cross region data guard deployment code work in terraform way #2046

Open luckeyca opened 8 months ago

luckeyca commented 8 months ago

Community Note

Description

Currently to deploy a cross region data guard, it's required to create one resource for primary and 2nd for cross region standby, given the code for primary and standby are not the same, once database fails over, the code becomes invalid and cannot be re-run. Given terraform is declarative programming language, this should NOT happen. The current deployment coding have multiple issues. see the example for the the current deployment

resource "oci_database_autonomous_database" "primary" {
  count          = var.autonomous_database_deploy ? 1 : 0
  compartment_id = "ocid1.compartment.oc1..xxx"
  db_name        = "testadb1"
  display_name   = "test autonomous database primary"
  is_free_tier   = false
  db_workload    = "DW"
  license_model  = "LICENSE_INCLUDED"
  db_version     = "19c"
  compute_model  = "ECPU"
  compute_count  = 2
  is_auto_scaling_enabled             = true
  data_storage_size_in_tbs            = 1
  is_auto_scaling_for_storage_enabled = true
  is_local_data_guard_enabled         = true
  is_dedicated                        = false
  source                              = "NONE"
  whitelisted_ips                     = null
  subnet_id                           = "ocid1.subnet.oc1.ca-toronto-1.xxx"
  nsg_ids                             = ["ocid1.networksecuritygroup.oc1.ca-toronto-1.xxx"]
  admin_password                      = "Testpassword@213234"

  database_management_status = "ENABLED"
  operations_insights_status = "ENABLED"
}

resource "oci_database_autonomous_database" "standby" {
  count          = var.standby_autonomous_database_deploy ? 1 : 0
  provider       = oci.montreal
  compartment_id = "ocid1.compartment.oc1..xxx"
  db_name        = "testadb1"
  display_name   = "test autonomous database standby"
  is_free_tier   = false
  db_workload    = "DW"
  license_model  = "LICENSE_INCLUDED"
  db_version     = "19c"
  compute_model  = "ECPU"
  compute_count  = 2
  is_auto_scaling_enabled             = true
  data_storage_size_in_tbs            = 1
  is_auto_scaling_for_storage_enabled = true
  is_dedicated                        = false
  source                              = "CROSS_REGION_DATAGUARD"
  source_id                           = oci_database_autonomous_database.primary[0].id
  whitelisted_ips                     = null
  subnet_id                           = "ocid1.subnet.oc1.ca-montreal-1."
  nsg_ids                             = ["ocid1.networksecuritygroup.oc1.ca-montreal-1.xxx"]
}
  1. the most important one is that it's NOT following the declarative programming approach because terraform code should be able to re-run as many time as you want in any situation. However, the current way of coding will cause failure on re-run with the standby node given change on standby is not allowed.
  2. duplication of many arguments on the cross region standby code. Given the primary database source id is already defined in the standby deployment code, there is no reason to force the following arguments because they would be identical to primary.
    compartment_id = "ocid1.compartment.oc1.."
    db_name        = "testadb1"
    is_free_tier   = false
    db_workload    = "DW"
    license_model  = "LICENSE_INCLUDED"
    db_version     = "19c"
    compute_model  = "ECPU"
    compute_count  = 2
    is_auto_scaling_enabled             = true
    data_storage_size_in_tbs            = 1
    is_auto_scaling_for_storage_enabled = true
    is_dedicated                        = false
  3. the cloud metadata freeform_tags cannot be set different between primary and standby. NOTE: tag is NOT a database setting, but a cloud setting which has nothing to do with database operations, but an important asset to help manage cloud resources. So database should NOT blocking changes to tags even if it's standby.

New or Affected Resource(s)

oci_database_autonomous_database

Potential Terraform Configuration

With the pseudo code below, it will address all the issues mentioned above.


resource "oci_database_autonomous_database" "adb" {
  count          = var.autonomous_database_deploy ? 1 : 0
  compartment_id = "ocid1.compartment.oc1..xxx"
  db_name        = "testadb1"
  display_name   = "test autonomous database primary"
  is_free_tier   = false
  db_workload    = "DW"
  license_model  = "LICENSE_INCLUDED"
  db_version     = "19c"
  compute_model  = "ECPU"
  compute_count  = 2
  is_auto_scaling_enabled             = true
  data_storage_size_in_tbs            = 1
  is_auto_scaling_for_storage_enabled = true
  is_local_data_guard_enabled         = true
  is_dedicated                        = false
  source                              = "NONE"
  whitelisted_ips                     = null
  subnet_id                           = "ocid1.subnet.oc1.ca-toronto-1.xxx"
  nsg_ids                             = ["ocid1.networksecuritygroup.oc1.ca-toronto-1.xxx"]
  admin_password                      = "Testpassword@213234"

  database_management_status = "ENABLED"
  operations_insights_status = "ENABLED"

  freeform_tags = { location = toronto }

### If this block exists, create cross region data guard. 
### Given it's in the same deployment resource, source type and source id are no longer required
### For deployment location/region, either have a new argument called location,
### or determine the location based on the subnet_id and nsg_id which are region specific.

  cross_region_data_guard {                       

        location                              = ca-montreal-1 (optional)
        whitelisted_ips                   = null
        subnet_id                           = "ocid1.subnet.oc1.ca-montreal-1.xxx"
        nsg_ids                               = ["ocid1.networksecuritygroup.oc1.ca-montreal-1.xxx"]

        freeform_tags                     = { location = montreal }

  }
}

References

luckeyca commented 8 months ago

also open SR: 3-35781677651

luckeyca commented 3 months ago

the bottom line is in the terraform resource, database binary install and database instance provision should be separated, either in the same resource like the pseudo code above, or like other CSPs, such azure/gcp/aws, using multiple resources because database binary install is tied to one VM/location, but database is not. As long as the code is changed like this. the terraform code will be idempotent as it should be.