Error message while deleting google_kms_crypto_key resource - terraform

I am managing kms keys and key rings with gcp terraform provider
resource "google_kms_key_ring" "vault" {
name = "vault"
location = "global"
}
resource "google_kms_crypto_key" "vault_init" {
name = "vault"
key_ring = google_kms_key_ring.vault.self_link
rotation_period = "100000s" #
}
When I ran this for the first time, I was able to create the keys and keyrings successfully and doing a terraform destroy allows the terraform code to execute successfully with out any errors.
The next time I do a terraform apply, I just use terraform import to import the resources from GCP and the code execution works fine.
But after a while, certain key version 1 was destroyed. Now everytime I do a terrafrom destroy, I get the below error
module.cluster_vault.google_kms_crypto_key.vault_init: Destroying... [id=projects/<MY-PROJECT>/locations/global/keyRings/vault/cryptoKeys/vault]
Error: googleapi: Error 400: The request cannot be fulfilled. Resource projects/<MY-PROJECT>/locations/global/keyRings/vault/cryptoKeys/vault/cryptoKeyVersions/1 has value DESTROYED in field crypto_key_version.state., failedPrecondition
Is there was way to suppress this particular error ? KeyVersions 1-3 are destroyed.

At present, Cloud KMS resources cannot be deleted. This is against Terraform's desired behavior to be able to completely destroy and re-create resources. You will need to use a different key name or key ring name to proceed.

Related

Syncing terraform resource creation with manual creation

I have a use-case where we have two ways of allowing resource creation:
With the help of terraform
manual creation.
for example (this is just an example resource, not the actual one we are using):
resource "aws_codestarconnections_connection" "example" {
name = "example-connection"
provider_type = "GitHub"
}
Using the UI also we can create the same connection.
If the resource is already there, I do not want terraform to attempt the creation again.
If it was earlier created by terraform only, it stays in the terraform state, and terraform won't create this resource.
But, if it was a manual creation, is there a way to avoid the creation?
Option tried:
Fetching the data source first and then using count while resource creation.
Eg.
resource "aws_codestarconnections_connection" "example" {
count = number_of_fetched_resources == 0 ? 1 : number_of_fetched_resources
name = "example-connection"
provider_type = "GitHub"
}
Now, if there was no resource available, it works fine. Because it creates 1 resource in that case. But if there was already a manual creation, I want, terraform shouldn't attempt resource creation (leave it at the same number of resources). But terraform takes it as if I am asking to create a resource because in the state it has 0.
Also
count = number_of_fetched_resources == 0 ? 1 : 0
doesn't work because now it will delete the existing resource also, in case terraform created it earlier.
So is there a way to sync the state using terraform code (I cannot use commands like terraform import as running commands is done in a different environment)?

Diagnostic Settings - Master" already exists - to be managed via Terraform this resource needs to be imported into the State

I have a diagnostic setting configured on my master db. As shown below in my main.tf
resource "azurerm_monitor_diagnostic_setting" "main" {
name = "Diagnostic Settings - Master"
target_resource_id = "${azurerm_mssql_server.main.id}/databases/master"
log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id
log {
category = "SQLSecurityAuditEvents"
enabled = true
retention_policy {
enabled = false
}
}
metric {
category = "AllMetrics"
retention_policy {
enabled = false
}
}
lifecycle {
ignore_changes = [log, metric]
}
}
If I don't delete it before in the resource group before I run the Terraform, I get the error:
Diagnostic Settings - Master" already exists - to be managed via
Terraform this resource needs to be imported into the State
I know that if I delete the SQL Server the diagnostic setting remains - but I don't know why that is a problem with Terraform. I have also noticed that it is in my tfplan.
What could be the problem?
If I don't delete it before in the resource group before I run the
Terraform, I get the error:
Diagnostic Settings - Master" already exists - to be managed via Terraform this resource needs to be imported into the State
I know that if I delete the SQL Server the diagnostic setting remains but I don't know why that is a problem with Terraform.
If you have created the resource in Azure from a different way (i.e. Portal/Templates/CLI/Powershell), that means Terraform is not aware of resource already existing in Azure. So, during Terraform Plan, it shows you the plan what will be created from what you have written in main.tf. But when you run Terraform Apply the azurerm provider checks the resources names with the existing resources of the same resource providers and result in giving an error that it already exists and needs to be imported to be managed by Terraform.
Also if you have created everything from Terraform then doing a Terraform destroy deletes all the resources present on the main.tf.
Well, it's in the .tfplan and also it's in main.tf - so it's imported, right ?
If you mention the resource and its details in main.tf and .tfplan, it doesn't mean that you have imported the resource or Terraform gets aware of the resource. Terraform is only aware of the resources that are stored in the Terraform state file i.e. .tfstate.
So , to overcome the error that you get without deleting the resource from Portal, you will have to add the resource in the main.tf as you have already done and then use Terraform import command to import the Azure resource to Terraform State file like below:
terraform import azurerm_monitor_diagnostic_setting.example "{resourceID}|{DiagnosticsSettingsName}"
So, for you it will be like:
terraform import azurerm_monitor_diagnostic_setting.main "/subscriptions/<SubscriptionID>/resourceGroups/<ResourceGroupName>/providers/Microsoft.Sql/servers/<SQLServerName>/databases/master|Diagnostic Settings - Master"
After the Import is done, any changes you make from Terraform to that resource will get reflected in portal as well and you will be able to destroy the resource from terraform as well.

Accessing existing resource info from new resources

My header might not have summed up correctly my question.
So I have a terraform stack that creates a resource group, and a keyvault, amongst other things. This has already been ran and the resources exist.
I am now adding another resource to this same terraform stack. Namely a mysql server. Now I know if I just re-run the stack it will check the state file and just add my mysql server.
However as part of this mysql server creation I am providing a password and I want to write this password to the keyvault that already exists.
if I was doing this from the start my terraform would look like:
resource "azurerm_key_vault_secret" "sqlpassword" {
name = "flagr-mysql-password"
value = random_password.sqlpassword.result
key_vault_id = azurerm_key_vault.shared_kv.id
depends_on = [
azurerm_key_vault.shared_kv
]
}
however I believe as the keyvault already exists this would error as it wouldn't know this value azurerm_key_vault.shared_kv.id unless I destroy the keyvault and allow terraform to recreate it. is that correct?
I could replace azurerm_key_vault.shared_kv.id with the actual resource ID from azure, but then if I were to ever run this stack to create a new environment it would be writing the value into my old keyvault I presume?
I have done this recently for AWS deployment, you would do terraform import on azurerm_key_vault.shared_kv resource to bring it under terraform management and then you would be able to able to deploy azurerm_key_vault_secret
To import: you will need to build the resource azurerm_key_vault.shared_kv (this will require a few iterations).

Azure :: Terraform fails on azure keyvault secrets

I am noticing this wierd error since I moved whole of my code from 1.42.0 provider version to 2.19.0. I am creating several keyvault secrets. Earlier it when I try to execute a plan after appplying once, it used to refresh the state and proceed, but now after updating the provider version, I am noticing the below error.
Error: A resource with the ID "https://mytestingvault.vault.azure.net/secrets/hub-access/060e71ecd1084cb5a6a496f77a2aea5c" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_key_vault_secret" for more information.
Additionally I have added lifecycle ignore changes to see if it could skip reading the vault secret changes but unfortunately the same error is shown. Only way to get rid of the error is to delete the secret. What am i wrong here?
lifecycle {
ignore_changes = [
value,name
]
}
The Terraform key vault documentation says:
Terraform will automatically recover a soft-deleted Key Vault during
Creation if one is found - you can opt out of this using the features
block within the Provider block.
You should configure your Terraform to stop recovering the softly deleted Key Vault like this:
provider "azurerm" {
features {
key_vault {
recover_soft_deleted_key_vaults = false
}
}
}
If you want Terraform to purge any softly deleted Key Vaults when using terraform destroy use this additional line:
provider "azurerm" {
features {
key_vault {
purge_soft_delete_on_destroy = true
recover_soft_deleted_key_vaults = false
}
}
}
You probably need to read up on the general topic of Terraform state management. This is not specific to your Key Vault secret. Some resource (your secret) exists that was not created by the terraform workspace that you are just executing. TF does not like that. So you either need to import this pre-existing resource into the state of this workspace, or delete it so that it can be re-created (and thereby managed)
The issue was that keyvault even though was deleted, we had to purge it via cli using aws cli purge.

How to ignore duplicate resource error during terraform apply?

I am trying to reapply my changes using terraform apply but when I am doing it again , it gives me error with resource already exists and stops the deployment .
Example:
Error: AlreadyExistsException: An alias with the name arn:aws:kms:us-east-1:490449857273:alias/continuedep-cmk-us-east-1 already exists
status code: 400, request id: 4447fd20-d33b-4c87-891e-cc5e09cc6108
on ../../../modules/kms_cmk/main.tf line 11, in resource "aws_kms_alias" "keyalias":
11: resource "aws_kms_alias" "keyalias" {
Error: Error creating DB Subnet Group: DBSubnetGroupAlreadyExists: The DB subnet group 'continuedep-sbg' already exists.
status code: 400, request id: 97d662b6-79d4-4fde-aaf7-a2f3e5a0bd9e
on ../../../modules/rds-postgres/main.tf line 2, in resource "aws_db_subnet_group" "generic_db_subnet_group":
2: resource "aws_db_subnet_group" "generic_db_subnet_group" {
Likewise i get errors with many other existing resources.I want to avoid/ignore such errors and continue my deployment .
What other way i can use from which I can restart my terraform resource deployment from where it is interrupted in the middle.
My terraform version is :
Terraform v0.12.9
The errors are returned by the API the Terraform provider is calling.
Possible causes of this could be:
you ( or someone else ) have executed your Terraform code and you don't have a shared / updated state
someone have created them manually
a Terraform destroy failed in a way that deleted the resources for the API but failed to save the update state
solutions depends on what you need. You can:
delete those resources from your Terraform code to stop managing them with it
delete those resources from the API ( cloud provider ) and recreate them with Terraform
Perform a terraform import of those resources and remove the terraform code that is trying to recreate them (NOT RECOMMENDED)
use terraform apply --target=xxx to apply only resources you need to apply (NOT RECOMMENDED)

Resources