We are facing issue when we execute terraform, then previous resources getting destroyed when running new resources . Is there way can we create multiple resources name or is there way we can disable destroy during terraform apply.
Hi @cah-chethan-hn,
Terraform should only propose to destroy something if you have removed it from the configuration. If you intend to retain an existing object when you add another, you should leave the old object in your configuration and add another resource block alongside it, so Terraform will understand that you intend to retain the existing object and create a new one.
Thank you for the reply. I am really appreciate you time to check my query.
Actually am new to terraform , i am trying to create resources using parameter passing from YAML file.
Example: If my YAML file contains
label: OKTA_SAML8
sso_url: https://example8.com
Then my terraform code contains as below
locals {
config = yamldecode(file(“app_data.yml”))
}
resource “okta_app_oauth” “OKTA_OIDC” {
label = local.config.label
login_uri = local.config.sso_url
}
First time when i execute , then above resources is created but when i modify the YAML file then above configured resources destroyed and configure only new resources .
I want to keep my old resources as well along with new resources. The challenge is , i cannot able to create resources name Dynamic based on Label in YAML file so when ever YAML file contents change then all previous resources configuration is destroyed and only current YAML configuration is created. Can you please help me to understand to keep my all previous configuration alive? is there way we can make resources name as Dynamic if possible? Please let me know how to solve this issue. Really appreciate your time and help.
Hi @cah-chethan-hn,
If keeping the settings in external YAML files is a requirement for your system then you will need to design it so that any files describing objects you want to keep will remain available for Terraform to read on future runs.
One way to do that would be to change your YAML structure so that instead of describing a single object it instead describes a map of multiple objects, like this:
example1:
label: OKTA_SAML8
sso_url: https://example8.com
example2:
label: SomethingElse
sso_url: https://example.net
Then you can tell Terraform that your desired state is for there to be one okta_app_oauth.oidc
for each of the entries in the file:
resource “okta_app_oauth” “oidc” {
for_each = local.config
label = each.value.label
login_uri = each.value.sso_url
}
This works by dynamically declaring a separate instance of this resource for each entry in the map, with addresses like this:
okta_app_oauth.oidc["example1"]
okta_app_oauth.oidc["example2"]
When you update the file in future, you can retain the example1
and example2
elements and add a third element with a new unique key. Terraform will then understand that you intend to create a new object without destroying the others. If you do later want to destroy the example1
object then you can remove it from your YAML file while keeping all of the others and then Terraform will understand that you intend to destroy just that one.
If placing all of the objects in the same file is inconvenient because of how you manage these files then there are some other alternatives which follow a similar principle but have some different details. For example, you can use Terraform’s fileset
function to find all of the .yaml
files in a particular directory and then load each one separately to construct a map inside Terraform, and then use that result as the for_each
.
All of these approaches require that you save the configuration for all objects you’ve previously created so Terraform can see that they are still present and haven’t changed on future runs.
If you don’t have any way to preserve the settings about existing objects between runs then Terraform is probably not the best tool to use to solve your problem. If your goal is to just create objects and then manage them using some other process outside Terraform then it may be better to just integrate directly with Okta’s API.
Thank you for the clarification . I am trying with fileset but unfortunately am stuck on how to load set of yaml files into config? I am trying with the below snippet but getting error. Can you please help. My end goal is to load all the yaml files from the folder into config.
locals {
for_each = fileset(“.”,“*.yml”)
config = yamldecode(file(each.value))
}
I think you are trying to use for_each as a way of repeating things, however that only works for resource, module & data source blocks. What you have here is a locals block, which is for creating local variables.
As a result you are actually creating two local variables - one called for_each and the other called config. Because there is no repetition the each.value has no meaning, so will cause an error.
Instead you should look at using a for expression - For Expressions - Configuration Language | Terraform | HashiCorp Developer