oracle-devrel/terraform-oci-ocloud-foundation

Make application_host - session.enable dependent from network_domain - bastion.create

Closed this issue · 7 comments

In application_host/ssh.tf the resource "oci_bastion_session" "ssh" only verifies whether var.session.enable has been set to true or false.
To avoid unnecessary troubleshooting sessions it would be helpful to make sessions dependent on the existence of a bastion service. This could be either done by checking the bastion.create value or by querying for the bastion service.

Suggestion:

Return the ID directly from the app_domain output, so you would not have to navigate inside a null value in case the bastion service has not been deployed when bastion.create is false:

output "bastion_id" {
  description = "Bastion Service OCID"
  value       = length(data.oci_bastion_bastions.domain.bastions) > 0 ? data.oci_bastion_bastions.domain.bastions[0].id : null
}

Replace the data source element in application_host/config.tf to use the plural, not the singular version:

data "oci_bastion_bastions" "hosts" {
  compartment_id    = < id of compartment of the bastion service, should be outputted from the app_domain module >
  bastion_id              = var.config.bastion_id
}

Then we can set up in application_host/ssh.tf for the count parameter:

resource "oci_bastion_session" "ssh" {
  depends_on                                   = [ oci_core_instance.instance[0] ]
  count                                        = (var.session.enable ? 1 : 0) * length(data.oci_bastion_bastions.hosts)
  bastion_id                                   = length(data.oci_bastion_bastions.hosts) > 0 ? data.oci_bastion_bastions.hosts[0].id : null
  (...)
hcops commented

Please review the code, I dopted ingo's proposal with a few adjustments

Terraform apply fails with the current error message:

The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.
It seems that datasource elements are not allowed in the count expressions, Terraform expects to be able to know the number of instances of a resource to be built already at the plan phase, but can evaluate the datasource element only during the apply phase.

I tried with several alternatives to "hide" the data element away from count through a local variable. It always leads to the same error.

So I guess we need to evaluate a different way to detect whether a bastion host exists or not, so use some explizit Boolean variable similar to session.enable.

hcops commented

I'm afraid I have to drop the second conditional to make it work. At least that is suggested here: hashicorp/terraform#26078 and here: hashicorp/terraform#22131

var.session.enable ? 1 : 0

Ingo, can you check?

Same problem:

Error: Invalid count argument on component/application_host/ssh.tf line 6, in resource "oci_bastion_session" "ssh" 6: count =(var.session.enable?1 0) * (var.config.bastion_id != "" ?1 0) The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.

var.config.bastion_id gets defined in application.tf line 90

bastion_id = module.app_domain.bastion.id

module.app_domain.bastion.id gets defined in component/network_domain/output.tf line 45

output "bastion" { description = "Bastion Service" value = length(data.oci_bastion_bastions.domain.bastions) > 0 ? data.oci_bastion_bastions.domain.bastions[0] : null }

So at the end: the variable gets defined from a datasources element. And it seems that datasources are not allowed to be used for the count parameter, because Terraform cannot determine in the plan phase how many instances controlled by this count parameter should be initialized. The datasource elements can only be evaluated during the apply phase.

So we need to get away to use a datasource element (direct or indirect) inside an expression for the cloud parameter.

hcops commented

Yepp, came to the same conclusion - dropped the line entirely and running the tests right now

hcops commented

I'm afraid verifying the bastion existence directly in the statement that creates the session is not working. There is an indirect check returning the ID though.
' bastion_id = length(data.oci_bastion_bastions.host.bastions) > 0 ? data.oci_bastion_bastions.host.bastions[0].id : null'
@calorbeer can you check whether this addresses the troubleshooting requirement sufficiently?