I created some crypto-keys manually and now wanted to import them to terraform state so that it's managed by terraform, which I did using following command which completes successfully:
$ terraform import google_kms_crypto_key.some-key some-gcp-project-id/us/some-keyring/some-key
google_kms_crypto_key.some-key: Refreshing state... [id=projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
Even after the import, on doing terraform apply I am still getting resource already exists error:
Error: Error creating CryptoKey: googleapi: Error 409: CryptoKey projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key already exists.
Since this resource has been imported, I believe I shouldn't be getting this "Error 409". In terrform plan steps, it first destroys the existing key contents and then tries to re-create the key - which leads to error since the key already exists. Since I have already imported the key I do not want terraform to destroy the key. Why is terraform trying to destroy a key which has already been imported?
This is the relevant part of terrform plan output
# google_kms_crypto_key.some-key[1] will be destroyed
- resource "google_kms_crypto_key" "some-key" {
- destroy_scheduled_duration = "86400s" -> null
- id = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring/cryptoKeys/some-key" -> null
- import_only = false -> null
- key_ring = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring" -> null
- labels = {} -> null
- name = "some-key" -> null
- purpose = "ENCRYPT_DECRYPT" -> null
- rotation_period = "2592000s" -> null
- skip_initial_version_creation = false -> null
- timeouts {}
- version_template {
- algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" -> null
- protection_level = "SOFTWARE" -> null
}
}
# google_kms_crypto_key.some-key["some-key"] will be created
+ resource "google_kms_crypto_key" "some-key" {
+ destroy_scheduled_duration = (known after apply)
+ id = (known after apply)
+ import_only = (known after apply)
+ key_ring = "projects/some-gcp-project-id/locations/us/keyRings/some-keyring"
+ name = "some-key"
+ purpose = "ENCRYPT_DECRYPT"
+ rotation_period = "2592000s"
+ version_template {
+ algorithm = (known after apply)
+ protection_level = (known after apply)
}
}
Related
We are testing reusable terraform module to create GCP resources and same we are able to achieve using count variable. now we have an challenge to decommission/destroy one/two of the in between created resources. while destroying previously created resources making other resources to be recreated.
Terraform will perform the following actions:
# google_service_account.sa_npe_policy[1] must be replaced
-/+ resource "google_service_account" "sa_npe_policy" {
~ account_id = "sa-test13" -> "sa-test11" # forces replacement
~ display_name = "sa-test13" -> "sa-test11"
~ email = "sa-test13#gcp-prj-npe.iam.gserviceaccount.com" -> (known after apply)
~ id = "projects/gcp-prj-npe/serviceAccounts/sa-tegcp-prj-npe.iam.gserviceaccount.com" -> (known after apply)
~ name = "projects/gcp-prj-npe/serviceAccounts/sa-test13#gcp-prj-npe.iam.gserviceaccount.com" -> (known after apply)
project = "gcp-prj-npe"
~ unique_id = "111295737867502004228" -> (known after apply)
}
# google_service_account.sa_npe_policy[2] will be created
+ resource "google_service_account" "sa_npe_policy" {
+ account_id = "sa-test13"
+ display_name = "sa-test13"
+ email = (known after apply)
+ id = (known after apply)
+ name = (known after apply)
+ project = "gcp-prj-npe"
+ unique_id = (known after apply)
}
Plan: 2 to add, 0 to change, 1 to destroy.
Here we are trying to remove sa-test11 which is impacting next resource sa-test13 to be replaced with sa-test11.
something we are looking for without recreate/replace with already created resource we need to delete any one of the resource in middle.
Despite the fact that the output you posted suggests that you are trying to add a third resource instead of deleting one, I will try to explain the general approach you could take.
Assuming your initial code looks simlar like the folowing and you now want to remove satest12:
variable "sa_name" {
type = list(string)
default = ["satest11", "satest12", "satest13"]
}
resource "google_service_account" "sa_npe_policy" {
count = length(var.sa_name)
account_id = var.sa_name[count.index]
display_name = var.sa_name[count.index]
project = "gcp-prj-npe"
}
If you just remove "satest12" from the list Terraform will suggest you to delete satest12 and satest13 and afterwards recreate satest13.
Why is that?
Terraform internally stores the state of your resources and each of your resources will be assigned an internal address. satest12 has the address google_service_account.sa_npe_policy[1] and satest13 has the address google_service_account.sa_npe_policy[2]. Now if you remove "satest12" the resource list only comprises two elements and thus satest13 will get the address google_service_account.sa_npe_policy[1].
Terraform - for whatever reasons - is not capable to recognize that the resource already exists at the other address, so it suggests to delete two resources and create another.
How could you circumvent that?
Fortunately, Terraform gives us the means to manipulate its internal state. So after removing "satest12" do not execute terraform apply immediately.
Instead execute
tf state mv 'google_service_account.sa_npe_policy[1]' 'google_service_account.choose_an_unused_name'
tf state mv 'google_service_account.sa_npe_policy[2]' 'google_service_account.sa_npe_policy[1]'
This way you
readdress satest12 to an unused address
readdress satest13 to the address previously used by satest12
If you now run terraform apply, Terraform will recognize that there is no need to recreate satest13 and will only destroy satest12.
What happens if running "terraform apply" twice?
Does it create all the resources twice?
I'm assuming that when you say "terraform deploy" here you mean running the terraform apply command.
The first time you run terraform apply against an entirely new configuration, Terraform will propose to create new objects corresponding with each of the resource instances you declared in the configuration. If you accept the plan and thus allow Terraform to really apply it, Terraform will create each of those objects and record information about them in the Terraform state.
If you then run terraform apply again, Terraform will compare your configuration with the state to see if there are any differences. This time, Terraform will propose changes only if the configuration doesn't match the existing objects that are recorded in the state. If you accept that plan then Terraform will take each of the actions it proposed, which can be a mixture of different action types: update, create, destroy.
This means that in order to use Terraform successfully you need to make sure to keep the state snapshots safe between Terraform runs. With no special configuration at all Terraform will by default save the state in a local file called terraform.tfstate, but when you are using Terraform in production you'll typically use remote state, which is a way to tell Terraform to store state snapshots in a remote data store separate from the computer where you are running Terraform. By storing the state in a location that all of your coworkers can access, you can collaborate together.
If you use Terraform Cloud, a complementary hosted service provided by HashiCorp, you can configure Terraform to store the state snapshots in Terraform Cloud itself. Terraform Cloud has various other capabilities too, such as running Terraform in a remote execution environment so that everyone who uses that environment can be sure to run Terraform with a consistent set of environment variables stored remotely.
If you run the terraform apply command first time, it will create the necessary resource which was in terraform plan.
If you run the terraform apply command second time, it will try to check if that resource already exist there or not. If found then will not create any duplicate resource.
Before running the terraform apply for the second time, if you run terraform plan you will get the list of change/create/delete list.
Apr, 2022 Update:
The first run of "terraform apply" creates(adds) resources.
The second or later run of "terraform apply" creates(adds), updates(changes) or deletes(destroys) existed resources if there are changes for them. Plus, basically when changing the mutable value of an existed resource, its existed resource is updated rather than deleted then created and basically when changing the immutable value of an existed resource, its existed resource is deleted then created rather than updated.
*A mutable value is the value which can change after creating a resource.
*An immutable values is the value which cannot change after creating a resource.
For example, I create(add) the Cloud Storage bucket "kai_bucket" with the Terraform code below:
resource "google_storage_bucket" "bucket" {
name = "kai_bucket"
location = "ASIA-NORTHEAST1"
force_destroy = true
uniform_bucket_level_access = true
}
So, do the first run of the command below:
terraform apply -auto-approve
Then, one resource "kai_bucket" is created(added) as shown below:
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:
# google_storage_bucket.bucket will be created
+ resource "google_storage_bucket" "bucket" {
+ force_destroy = true
+ id = (known after apply)
+ location = "ASIA-NORTHEAST1"
+ name = "kai_bucket"
+ project = (known after apply)
+ self_link = (known after apply)
+ storage_class = "STANDARD"
+ uniform_bucket_level_access = true
+ url = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
google_storage_bucket.bucket: Creating...
google_storage_bucket.bucket: Creation complete after 1s [id=kai_bucket]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Now, I change the mutable value "uniform_bucket_level_access" from "true" to "false":
resource "google_storage_bucket" "bucket" {
name = "kai_bucket"
location = "ASIA-NORTHEAST1"
force_destroy = true
uniform_bucket_level_access = false # Here
}
Then, do the second run of the command below:
terraform apply -auto-approve
Then, "uniform_bucket_level_access" is updated(changed) from "true" to "false" as shown below:
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:
# google_storage_bucket.bucket will be updated in-place
~ resource "google_storage_bucket" "bucket" {
id = "kai_bucket"
name = "kai_bucket"
~ uniform_bucket_level_access = true -> false
# (9 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
google_storage_bucket.bucket: Modifying... [id=kai_bucket]
google_storage_bucket.bucket: Modifications complete after 1s [id=kai_bucket]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
Now, I change the immutable value "location" from "ASIA-NORTHEAST1" to "US-EAST1":
resource "google_storage_bucket" "bucket" {
name = "kai_bucket"
location = "US-EAST1" # Here
force_destroy = true
uniform_bucket_level_access = false
}
Then, do the third run of the command below:
terraform apply -auto-approve
Then, one resource "kai_bucket" with "ASIA-NORTHEAST1" is deleted(destroyed) then one resource "kai_bucket" with "US-EAST1" is created(added) as shown below:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# google_storage_bucket.bucket must be replaced
-/+ resource "google_storage_bucket" "bucket" {
- default_event_based_hold = false -> null
~ id = "kai_bucket" -> (known after apply)
- labels = {} -> null
~ location = "ASIA-NORTHEAST1" -> "US-EAST1" # forces replacement
name = "kai_bucket"
~ project = "myproject-272234" -> (known after apply)
- requester_pays = false -> null
~ self_link = "https://www.googleapis.com/storage/v1/b/kai_bucket" -> (known after apply)
~ url = "gs://kai_bucket" -> (known after apply)
# (3 unchanged attributes hidden)
}
Plan: 1 to add, 0 to change, 1 to destroy.
google_storage_bucket.bucket: Destroying... [id=kai_bucket]
google_storage_bucket.bucket: Destruction complete after 1s
google_storage_bucket.bucket: Creating...
google_storage_bucket.bucket: Creation complete after 1s [id=kai_bucket]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
First of all, I am surprised that I have found very few resources on Google that mention this issue with Terraform.
This is an essential feature for optimizing the cost of cloud instances though, so I'm probably missing out on a few things, thanks for your tips and ideas!
I want to create an instance and manage its start and stop daily, programmatically.
The resource "google_compute_resource_policy" seems to meet my use case. However, when I change the stop or start time, Terraform plans to destroy and recreate the instance... which I absolutely don't want!
The resource "google_compute_resource_policy" is attached to the instance via the argument resource_policies where it is specified: "Modifying this list will cause the instance to recreate."
I don't understand why Terraform handles this simple update so badly. It is true that it is not possible to update a scheduler, whereas it is perfectly possible to detach it manually from the instance, then to destroy it before recreating it with the new stop/start schedule and the attach to the instance again.
Is there a workaround without going through a null resource to run a gcloud script to do these steps?
I tried to add an "ignore_changes" lifecycle on the "resource_policies" argument of my instance, Terraform no longer wants to destroy my instance, but it gives me the following error:
Error when reading or editing ResourcePolicy: googleapi: Error 400: The resource_policy resource 'projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule' is already being used by 'projects/my-project-id/zones/europe-west1-b/instances/my-instance', resourceInUseByAnotherResource"
Here is my Terraform code
resource "google_compute_resource_policy" "instance_schedule" {
name = "my-instance-schedule"
region = var.region
description = "Start and stop instance"
instance_schedule_policy {
vm_start_schedule {
schedule = var.vm_start_schedule
}
vm_stop_schedule {
schedule = var.vm_stop_schedule
}
time_zone = "Europe/Paris"
}
}
resource "google_compute_instance" "my-instance" {
// ******** This is my attempted workaround ********
lifecycle {
ignore_changes = [resource_policies]
}
name = "my-instance"
machine_type = var.machine_type
zone = "${var.region}-b"
allow_stopping_for_update = true
resource_policies = [
google_compute_resource_policy.instance_schedule.id
]
boot_disk {
device_name = local.ref_name
initialize_params {
image = var.boot_disk_image
type = var.disk_type
size = var.disk_size
}
}
network_interface {
network = data.google_compute_network.default.name
access_config {
nat_ip = google_compute_address.static.address
}
}
}
If it can be useful, here is what the terraform apply returns
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
- destroy
-/+ destroy and then create replacement
Terraform will perform the following actions:
# google_compute_resource_policy.instance_schedule must be replaced
-/+ resource "google_compute_resource_policy" "instance_schedule" {
~ id = "projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule" -> (known after apply)
name = "my-instance-schedule"
~ project = "my-project-id" -> (known after apply)
~ region = "https://www.googleapis.com/compute/v1/projects/my-project-id/regions/europe-west1" -> "europe-west1"
~ self_link = "https://www.googleapis.com/compute/v1/projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule" -> (known after apply)
# (1 unchanged attribute hidden)
~ instance_schedule_policy {
# (1 unchanged attribute hidden)
~ vm_start_schedule {
~ schedule = "0 9 * * *" -> "0 8 * * *" # forces replacement
}
# (1 unchanged block hidden)
}
}
Plan: 1 to add, 0 to change, 1 to destroy.
Do you want to perform these actions in workspace "prd"?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
google_compute_resource_policy.instance_schedule: Destroying... [id=projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule]
Error: Error when reading or editing ResourcePolicy: googleapi: Error 400: The resource_policy resource 'projects/my-project-id/regions/europe-west1/resourcePolicies/my-instance-schedule' is already being used by 'projects/my-project-id/zones/europe-west1-b/instances/my-instance', resourceInUseByAnotherResource
NB: I am working with Terraform 0.14.7 and I am using google provider version 3.76.0
An instance inside GCP can be power off without destroy it with the module google_compute_instance using the argument desired_status, keep in mind that if you are creating the instance for the first time this argument needs to be on “RUNNING”. This module can be used as the following.
resource "google_compute_instance" "default" {
name = "test"
machine_type = "f1-micro"
zone = "us-west1-a"
desired_status = "RUNNING"
}
You can also modify your “main.tf” file if you need to stop the VM first and then started creating a dependency in terraform with depends_on.
As you can see in the following comment, the service account will be created but the key will be assigned until the first sentence is done.
resource "google_service_account" "service_account" {
account_id = "terraform-test"
display_name = "Service Account"
}
resource "google_service_account_key" "mykey" {
service_account_id = google_service_account.service_account.id
public_key_type = "TYPE_X509_PEM_FILE"
depends_on = [google_service_account.service_account]
}
If the first component already exists, terraform only deploys the dependent.
I faced same problem with snapshot policy.
I controlled resource policy creation using a flag input variable and using count. For the first time, I created policy resource using flag as 'true'. When I want to change schedule time, I change the flag as 'false' and apply the plan. This will detach the resource.
I then make flag as 'true' again and apply the plan with new time.
This worked for me for snapshot policy. Hope it could solve yours too.
I solved the "resourceInUseByAnotherResource" error by adding the following lifecycle to the google_compute_resource_policy resource:
lifecycle {
create_before_destroy = true
}
Also, this requires to have a unique name with each change, otherwise, the new resource can't be created, because the resource with the same name already exists. So I appended a random ID to the end of the schedule name:
resource "random_pet" "schedule" {
keepers = {
start_schedule = "${var.vm_start_schedule}"
stop_schedule = "${var.vm_stop_schedule}"
}
}
...
resource "google_compute_resource_policy" "schedule" {
name = "schedule-${random_pet.schedule.id}"
...
lifecycle {
create_before_destroy = true
}
}
I added a json file that contains all the tables i want to create :
tables.json
"tables": {
"table1": {
"dataset_id": "dataset1",
"table_id": "table1",
"schema_path": "folder/table1.json"
},
"table2": {
"dataset_id": "dataset2",
"table_id": "table2",
"schema_path": "folder/table2.json"
}
}
Then with a foreach on a Terraform resource, i want to create these tables dynamically :
local.tf file
locals {
tables = jsondecode(file("${path.module}/resource/tables.json"))["tables"]
}
variables.tf file
variable "project_id" {
description = "Project ID, used to enforce providing a project id."
type = string
}
variable "time_partitioning" {
description = "Configures time-based partitioning for this table."
type = map(string)
default = {
type = "DAY"
field = "my_field"
}
}
main.tf file
resource "google_bigquery_table" "tables" {
for_each = local.tables
project = var.project_id
dataset_id = each.value["dataset_id"]
table_id = each.value["table_id"]
dynamic "time_partitioning" {
for_each = [
var.time_partitioning
]
content {
type = try(each.value["partition_type"], time_partitioning.value["type"])
field = try(each.value["partition_field"], time_partitioning.value["field"])
expiration_ms = try(time_partitioning.value["expiration_ms"], null)
require_partition_filter = try(time_partitioning.value["require_partition_filter"], null)
}
}
schema = file("${path.module}/resource/schema/${each.value["schema_path"]}")
}
The schema files contains classic bigquery schema, for example :
[
{
"name": "field",
"type": "STRING",
"mode": "NULLABLE",
"description": "My field"
}
]
The creation of tables works well, but when i add a new nullable field on a schema, Terraform proposes to "replace table" (destroy and recreate) instead of "update table".
The normal behaviour in this case for native Bigquery and Terraform is to update the table.
When a do the same test with the same Terraform resource but without forEach, Terraform has the expected behaviour and proposes to update the table.
An example of the Terraform log with "forEach" :
# google_bigquery_table.tables["table1"] must be replaced
-/+ resource "google_bigquery_table" "tables" {
~ creation_time = 1616764894477 -> (known after apply)
dataset_id = "dataset1"
deletion_protection = true
~ etag = "G9qwId8jgQS8nN4N61zqcA==" -> (known after apply)
~ expiration_time = 0 -> (known after apply)
~ id = "projects/my-project/datasets/dataset1/tables/table1" -> (known after apply)
- labels = {} -> null
~ last_modified_time = 1617075251337 -> (known after apply)
~ location = "EU" -> (known after apply)
~ num_bytes = 0 -> (known after apply)
~ num_long_term_bytes = 0 -> (known after apply)
~ num_rows = 0 -> (known after apply)
project = "project"
~ schema = jsonencode(
~ [ # forces replacement
{
description = "Field"
mode = "NULLABLE"
name = "field"
type = "STRING"
}
.....
+ {
+ description = "Field"
+ mode = "NULLABLE"
+ name = "newField"
+ type = "STRING"
}
Terraform displays and detects correctly the new column to add for a table, but indicates a replace instead of an edition.
I repeat that, the exact same test with a the same Terraform resource without forEach and on a single Bigquery table, works well (same schema, same change). I create the table and when a add a new nullable column, Terraform proposes an edition (the expected behaviour).
I checked on Terraform doc and web, i didn't saw some examples to manage a list of table with Terraform.
Is it not possible to create and update tables with configured tables and foreach ?
Thanks for your help.
This sounded like a provider bug. I found this issue in the terraform-provider-google repository that seems related to your issue. The fix was merged just 13 hours ago (at the time of writing). So, maybe you can wait for the next release (v3.63.0) and see if it fixes your issue.
Just FYI: You might want to verify that the fix commit was actually included in the next release. It happened to me before that something that was merged in master before a released was not actually released.
Thanks so much #Alessandro, the problem was indeed due to the Terraform provide Google version.
I used the v3.62.0 version of Google provider, and you target me to the good direction.
I saw this link too : https://github.com/hashicorp/terraform-provider-google/issues/8503
There is a very useful comment by "tpolekhin" (thanks to him) :
Hopefully im not beating a dead horse commenting on the closed issue, but I did some testing with various versions on the provider, and it behaves VERY differently each time.
So, our terraform code change was pretty simple: add 2 new columns to existing BigQuery table SCHEDULE
Nothing changes between runs - only provider version
v3.52.0
Plan: 0 to add, 19 to change, 0 to destroy.
Mostly adds + mode = "NULLABLE" to fields in bunch of tables, and adds 2 new fields in SCHEDULE table
v3.53.0
Plan: 0 to add, 2 to change, 0 to destroy.
Adds 2 new fields to SCHEDULE table, and moves one field in another table in a different place (sorting?)
v3.54.0
Plan: 1 to add, 1 to change, 1 to destroy.
Adds 2 new fields to SCHEDULE table, and moves one field in another table in a different place (sorting?) but now with table re-creation for some reason
v3.55.0
Plan: 0 to add, 2 to change, 0 to destroy.
Adds 2 new fields to SCHEDULE table, and moves one field in another table in a different place (sorting?)
behaves exactly like v3.53.0
v3.56.0
Plan: 1 to add, 0 to change, 1 to destroy.
In this comment, we can see that some versions have the problem.
For example this works with v3.55.0 but not with v3.56.0
I temporary downgrade the version to v3.55.0 and when the next release will solve this issue, i will upgrade it.
provider.tf :
provider "google" {
version = "= 3.55.0"
}
I am very familiar with Terraform against AWS. Trying to port a project over to using GCP now.
I have a fairly simple .tf file:
resource "google_compute_network" "vpc" {
name = "${local.resource_prefix}-vpc"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "public_subnet_1" {
name = "${local.resource_prefix}-public-subnet-1"
ip_cidr_range = local.subnet_public_1_cidr
network = google_compute_network.vpc.id
region = local.gcp_region
private_ip_google_access = false
}
This creates fine on the first apply, but on every subsequent apply, it asks me to force replace the subnet:
# google_compute_subnetwork.private_subnet_1 must be replaced
-/+ resource "google_compute_subnetwork" "private_subnet_1" {
~ creation_timestamp = "2020-06-11T08:12:27.002-07:00" -> (known after apply)
+ enable_flow_logs = (known after apply)
+ fingerprint = (known after apply)
~ gateway_address = "10.1.100.1" -> (known after apply)
~ id = "projects/(project-id)/regions/us-east1/subnetworks/foo-private-subnet-1" -> (known after apply)
ip_cidr_range = "10.1.100.0/24"
name = "foo-private-subnet-1"
~ network = "https://www.googleapis.com/compute/v1/projects/(project-name)/global/networks/foo-vpc" -> "projects/(project-id)/global/networks/foo-vpc" # forces replacement
private_ip_google_access = false
~ project = "(project-id)" -> (known after apply)
region = "us-east1"
~ secondary_ip_range = [] -> (known after apply)
~ self_link = "https://www.googleapis.com/compute/v1/projects/(project-name)/regions/us-east1/subnetworks/foo-private-subnet-1" -> (known after apply)
}
The network of the subnet appears to be what's forcing the replacement, but this is coming from the VPC attributes, and as best I can tell I'm following every online example I can find.
What am I missing? Why the mismatch between name and id in the network, or is it something else?
I believe the answer is simply to replace:
network = google_compute_network.vpc.id
with
network = google_compute_network.vpc.self_link
self_link is a bit of an odd name for this, and not what I've seen in a couple of tutorials so far, but it seems to be working fine.
Please remove .tfstate file and .tfstate.backup file after each apply