When Terraform creates a new infrastructure object represented by a resource block, the identifier for that real object is saved in a Terraform state file, allowing it to be updated and destroyed in response to future changes. For resource blocks that already have an associated infrastructure saved as a state file, Terraform compares the actual configuration of the object with the arguments given in the configuration and, if necessary, updates the object to match the configuration.
provider "oci" {}
resource "oci_nosql_table" "terraform" {
compartment_id = "ocid1.compartment.oc1..aaaaaaaa4mlehopmvdluv2wjcdp4tnh2ypjz3nhhpahb4ss7yvxaa3be3diq"
ddl_statement = "CREATE TABLE terraform(id INTEGER, doc JSON, newfield JSON, PRIMARY KEY(SHARD(id)))"
name = "terraform"
table_limits {
capacity_mode = "PROVISIONED"
max_read_units = "10"
max_storage_in_gbs = "12"
max_write_units = "10"
}
}
While using Terraform scripts with NoSQL tables, the table schema can be updated based on the new version of create table DDL statement instead of an alter table statement. To update the definition of a table, you use a new CREATE TABLE as the ddl_statement and internally the compiler parses the DDL and compares that with the existing table definition and generates an equivalent alter table statement and applies it to the NoSQL table.
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# oci_nosql_table.test_terraform will be updated in-place
~ resource "oci_nosql_table" "test_terraform" {
~ ddl_statement = "CREATE TABLE test_terraform(id INTEGER, doc JSON, newfield JSON, PRIMARY KEY(SHARD(id)))"" -> ""CREATE TABLE IF NOT EXISTS test_terraform(id INTEGER, doc JSON, PRIMARY KEY(SHARD(id)))"
id = "ocid1.nosqltable.oc1.iad.amaaaaaaknuwtjiawvwomi3rc6wk5cuey4x34sxgqvn7cnnv74girpe3akfa"
name = "test_terraform"
# (10 unchanged attributes hidden)
# (1 unchanged block hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
oci_nosql_table.test_terraform: Modifying... [id=ocid1.nosqltable.oc1.iad.amaaaaaaknuwtjiawvwomi3rc6wk5cuey4x34sxgqvn7cnnv74girpe3akfa]
oci_nosql_table.test_terraform: Modifications complete after 4s [id=ocid1.nosqltable.oc1.iad.amaaaaaaknuwtjiawvwomi3rc6wk5cuey4x34sxgqvn7cnnv74girpe3akfa]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
If your state and configuration do not match your infrastructure, Terraform will attempt to reconcile your infrastructure, which may unintentionally modify the resources. Depending on how you are managing your terraform, latest could mean the ddl in the state file or the ddl from the real resources. If you make changes outside of Terraform, you will create a difference in what Terraform thinks is correct. You need to Manage Resource Drift in Terraform. You should not make manual changes to resources controlled by Terraform, because the state file will be out of sync, or “drift,” from the real infrastructure.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
oci_nosql_table.test_terraform: Refreshing state... [id=ocid1.nosqltable.oc1.iad.amaaaaaaknuwtjiawvwomi3rc6wk5cuey4x34sxgqvn7cnnv74girpe3akfa]
Note: Objects have changed outside of Terraform
Terraform detected the following changes made outside of Terraform since the
last "terraform apply"
# oci_nosql_table.test_terraform has been changed
~ resource "oci_nosql_table" "test_terraform" {
~ ddl_statement = "CREATE TABLE IF NOT EXISTS test_terraform(id INTEGER, doc JSON, newfield JSON, PRIMARY KEY(SHARD(id)))""
-> ""CREATE TABLE IF NOT EXISTS test_terraform(id INTEGER, doc JSON, newfield JSON, console STRING, PRIMARY KEY(SHARD(id)))"
id = "ocid1.nosqltable.oc1.iad.amaaaaaaknuwtjiawvwomi3rc6wk5cuey4x34sxgqvn7cnnv74girpe3akfa"
name = "test_terraform"
~ schema = [
~ {
~ columns = [
# (4 unchanged elements hidden)
{
default_value = ""
is_as_uuid = false
is_generated = false
is_nullable = true
name = "newfield"
type = "JSON"
},
+ {
+ default_value = ""
+ is_as_uuid = false
+ is_generated = false
+ is_nullable = true
+ name = "console"
+ type = "STRING"
},
]
# (4 unchanged elements hidden)
},
]
~ time_updated = "2023-07-04 17:08:10.89 +0000 UTC"" -> ""2023-07-05 05:43:27.197 +0000 UTC"
# (8 unchanged attributes hidden)
# (1 unchanged block hidden)
}
Unless you have made equivalent changes to your configuration, or ignored the
relevant attributes using ignore_changes, the following plan may include
actions to undo or respond to these changes.
My recommendation is always to run a drift or a plan to validate that everything is SYNC. Your configuration file is now idempotent. And please avoid making manual changes to resources controlled by Terraform.
If you execute an apply in the example above the column console will be dropped because it is not part of the ddl_statement in the configuration file – new resource block.
At the same time, when deploying NoSQL tables, there are tasks modifying the object outside of Terraform. The behavior described above can be customized using the special nested lifecycle block within a resource block. ddl_statement is not the only attribute in the resource block.
The ignore_changes feature is intended to be used when a resource is created with references to data that may change in the future, but should not affect said resource after its creation. In some rare cases, settings of a remote object are modified by processes outside of Terraform, which Terraform would then attempt to “fix” on the next run. In order to make Terraform share management responsibilities of a single object with a separate process, the ignore_changes meta-argument specifies resource attributes that Terraform should ignore when planning updates to the associated remote object.
When deploying NoSQL tables, it is possible to modify the object outside of Terraform. For example, altering the reserved capacity is a task often executed outside Terraform. We would like to inform terraform that another process is managing a parameter and ignore modification when planning updates to the associated remote object.
My recommendation for those tasks happening outside terraform is to use ignore_changes to inform terraform on this:
provider "oci" {}
resource "oci_nosql_table" "terraform" {
compartment_id = "ocid1.compartment.oc1..aaaaaaaa4mlehopmvdluv2wjcdp4tnh2ypjz3nhhpahb4ss7yvxaa3be3diq"
ddl_statement = "CREATE TABLE terraform(id INTEGER, name STRING, PRIMARY KEY(SHARD(id)))"
name = "terraform"
table_limits {
capacity_mode = "PROVISIONED"
max_read_units = "10"
max_storage_in_gbs = "12"
max_write_units = "10"
}
lifecycle {
ignore_changes = [ table_limits, "freeform_tags", "defined_tags" ]
}
}
If you don’t set the lifecycle block, Terraform will apply modifications to your table limits – it is the default and expected behavior.
Terraform will perform the following actions:
# oci_nosql_table.terraform will be updated in-place
~ resource "oci_nosql_table" "terraform" {
id = "ocid1.nosqltable.oc1.iad.amaaaaaaknuwtjiax67vzyr2ee7euhc7cipo243f3ppgnoxngx4xhheywura"
name = "terraform"
# (11 unchanged attributes hidden)
~ table_limits {
~ max_read_units = 15 -> 10
~ max_write_units = 15 -> 10
# (2 unchanged attributes hidden)
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
