How to Solve Circular Dependency issue in Terraform Resources?

I have problem in my terraform requirement . I have resources which needs to create with test values, then i have to create another resources from the output of the first resources. After creating 2nd resources then based on that output needs to update on first resources. I am getting Error: Cycle: . Can you please help to fix this requirement .

Code Snippet

create "okta_app_saml" "idp_saml_app" {
label = "test app"
url = "https://test.com"
}

resource "okta_idp_saml_key" "okta_saml_key" {  
  x5c      = ["${okta_app_saml.idp_saml_app.certificate}"]

}

resource "okta_idp_saml" "example" {
name                     = "okta_test_app"
}

now i am trying to update first resources(okta_app_saml.idp_saml_app) from output of okta_idp_saml.example

create "okta_app_saml" "idp_saml_app" {
label = "test app"
url = "${okta_idp_saml.example.url}"
}

But, above code is getting error

Hi,

Please see Welcome to the forum - please reformat your message

This is a workflow that Terraform does not support at all. Can you elaborate on why you need to do this? If it was normal for everyone using the thing you are working with to want this, the developer of the Terraform provider would have to already have designed a workaround.

Please explain the interdependency between these objects in words, as it doesn’t seem to be shown in the sample code you have provided.

Thanks for getting back on this issue @ maxb .We have requirement as mentioned below:

  1. We have 2 OKTA Tenants, one tenant should act as SP and another tenant act as IDP .
  2. In-Order to configure IDP provider , we need to create application resources in one of the OKTA so we created dummy application initially to generate IDP information like IDP Issuer,IDP Certificate etc.
  3. Now, we will create IDP by passing those IDP Issuer and Certificate to create IDP.
  4. After creating IDP, we will update back actually ACS URL and Audience URL to IDP application back.

1.This is to create IDP Application resources with dummy values.

resource "okta_app_saml" "idp_b2e_saml_app" {

  label                    = "B2E_IDP_Test_App"
  sso_url                  = "https://example.com"
  recipient                = "https://example.com"
  destination              = "https://example.com"
  audience                 = "https://example.com/audience"
  subject_name_id_template = "$${user.email}"
  subject_name_id_format   = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
  response_signed          = true
  signature_algorithm      = "RSA_SHA256"
  digest_algorithm         = "SHA256"
  honor_force_authn        = false
  authn_context_class_ref  = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
}
  1. From the Dummy IDP application, we will create SAML IDP in another tenant by passing B2E okta tenant certificates,SSO URL and destination URL as below code.
resource "okta_idp_saml_key" "okta_b2b_saml_key" {
  
  x5c      = ["${okta_app_saml.idp_b2e_saml_app.certificate}"]
   
}

resource "okta_idp_saml" "example" {
  provider                 = okta.b2b
  name                     = "okta_b2b_test_app"
  acs_type                 = "INSTANCE"
  sso_url                  = okta_app_saml.idp_b2e_saml_app.entity_url
  sso_destination          = okta_app_saml.idp_b2e_saml_app.http_post_binding
  sso_binding              = "HTTP-POST"
  username_template        = "idpuser.subjectNameId"
  kid                      = okta_idp_saml_key.okta_b2b_saml_key.id
  issuer                   = "https://idp.example.com"
  request_signature_scope  = "REQUEST"
  response_signature_scope = "ANY"  
}
  1. Now, we need to update back actual SSO URL, audience URL from IDP (B2B Tenant) to B2E application.
resource "okta_app_saml" "idp_b2e_saml_app" {  
    label       = "B2E_IDP_Test_App"
    sso_url     = "https://b2b.okta.com/sso/saml2/${okta_idp_saml.example.id}"
    recipient   = "https://b2b.okta.com/sso/saml2/${okta_idp_saml.example.id}"
    destination = "https://b2b.okta.com/sso/saml2/${okta_idp_saml.example.id}"
    audience    = okta_idp_saml.example.audience
}

Why do you need the dummy application though? Can’t you generate those values?

You can’t have idp_b2e_saml_app assume different values during the same plan operation. Terraform needs to determine the value that will be applied during the apply phase and that value can’t change in the midst of the operation.

Dummy applications is required to get IDP information, without that IDP information we not able to get so we need to create test application with dummy values .

I believe I do now fully understand your issue - the Okta API really is such that you need to configure A, passing unique IDs generated by creating B, whilst also configuring B, passing unique IDs generated by creating A.

This is unfortunate, as under no circumstances will Terraform change the same resource twice in one plan-and-apply. This is a consequence of its fundamental design.

Therefore there’s absolutely no way to create the desired configuration in a single Terraform run.

I’m really struggling to come up with a nice way to do this… I think, as horrible as it is , you might need to write this configuration including your https://example.com URLs, apply it, and then manually update your configuration replacing the https://example.com URLs with literal values manually copied from the other object.