F5Networks / terraform-provider-bigip

Terraform resources that can configure F5 BIG-IP products
https://registry.terraform.io/providers/F5Networks/bigip/latest/docs
Mozilla Public License 2.0
103 stars 119 forks source link

bigip_ltm_pool_attachment resource would not allow multiple inputs for node attribute. #476

Open sandeep444033 opened 3 years ago

sandeep444033 commented 3 years ago

Environment

Summary

The resource documentation for bigip_ltm_pool_attachment resource type, would not allow me to pass a list of objects for node argument.

To work around this I am using for_each in my resource,

resource "bigip_ltm_pool_attachment" "attach_node" {
  pool                  = bigip_ltm_pool.pool.name
  for_each          = toset (var.pool_members)
  node                  = each.key
  depends_on = [
    bigip_ltm_pool.pool,
  ]
}

The above-mentioned works fine and I am able to add multiple nodes to my pool when I pass my node value as a list of strings.

Now I am facing issue when I make this node attribute dependent on other resource output in combination with for_each,

resource "bigip_ltm_pool_attachment" "attach_node" {
  pool                  = bigip_ltm_pool.pool.*.name
  for_each          = toset (onefuse_ipam_record.ip_record.*.ip_address)
  node                  = "${each.key}:var.member_port"
  depends_on = [
    bigip_ltm_pool.pool,
    vsphere_virtual_machine.linux_vm,
    onefuse_ipam_record.ip_record,
  ]
}

This fails with the following error,

The "for_each" 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 for_each depends on.

This is expected as there are some resources that cannot be predicted during a plan phase, as in Terraform would only know their values after an apply. Those resources cannot be used in a for_each statement. Terraform might support this use-case in the future, but it is not currently being worked on at the moment. See this link: https://github.com/hashicorp/terraform/issues/4149#issuecomment-805307448

Is there a way to pass a list of strings to node attribute in bigip_ltm_pool_attachment resource type? Something like below?

resource "bigip_ltm_pool_attachment" "attach_node" {
  pool                  = bigip_ltm_pool.pool.*.name
  node                  = ["1.1.1.1:80","1.1.1.2:80"]
}
urluba commented 3 years ago

Hi,

Could you share the output of onefuse_ipam_record.ip_record ?

Moreover, if onefuse_ipam_record.ip_record.ip_address is a list of IP for a given DNS name, why don’t you use the FQDN instead with fqdn_autopopulate set? The Bigip will do the job by itself ? I’ll be happy to know as I must myself code this part in a near futur.

Also for depends_on, you don’t have to specify ressources which are explicitely used. By example, this block:

resource "bigip_ltm_pool_attachment" "attach_node" {
  pool = bigip_ltm_pool.pool.name
  for_each = toset(onefuse_ipam_record.ip_record.ip_address)
  node = "${each.key}:${var.member_port}"
  depends_on = [
    bigip_ltm_pool.pool,
    vsphere_virtual_machine.linux_vm,
    onefuse_ipam_record.ip_record,
  ]
}

Could be simplified to:

resource "bigip_ltm_pool_attachment" "attach_node" {
  pool = bigip_ltm_pool.pool.name
  for_each = toset(onefuse_ipam_record.ip_record.ip_address)
  node = "${each.key}:${var.member_port}"
  depends_on = [
    vsphere_virtual_machine.linux_vm,
  ]
}

And if the resource onefuse_ipam_record references vsphere_virtual_machine.linux_vm then you can remove all the depends_on attributes.

sandeep444033 commented 3 years ago

@urluba

Could you share the output of onefuse_ipam_record.ip_record ?

Following would be the output,

ip_address = [ "192.129.192.183", ]

Moreover, if onefuse_ipam_record.ip_record.ip_address is a list of IP for a given DNS name, why don’t you use the FQDN instead with fqdn_autopopulate set? The Bigip will do the job by itself ?

My requirement is to add IP addresses instead of FQDNs for pool members.

urluba commented 3 years ago

Hi @sandeep444033,

I was unable to reproduce your issue. The following code is working for me:

variable "member_port" {
  description = ""
  type        = number
  default     = 443
  validation {
    condition = (
      var.member_port >= 80 &&
      var.member_port <= 65535 &&
      true
    )
    error_message = "Port value must be between 80 and 65535."
  }
}

variable "ip_address" {
  description = "List of IP to add to pool"
  type        = list(string)
  default     = [ "192.129.192.183", ]
}

resource "bigip_ltm_pool" "pool" {
  name                      = "/Common/test-pool"
}

resource "bigip_ltm_pool_attachment" "attach_node" {
  pool     = bigip_ltm_pool.pool.name
  for_each = toset(var.ip_address)
  node     = "${each.key}:${var.member_port}"
}

Maybe it is related to the behavior of onefuse_ipam_record ?

sandeep444033 commented 3 years ago

@urluba

I am able to get it working when I explicitly pass what would be the node values (ip_address:port) to the node attribute in the bigip_ltm_pool_attachment resource type.

Issue here I am facing is when I make this node attribute dependent on other resource output in combination with for_each,

resource "bigip_ltm_pool_attachment" "attach_node" { pool = bigip_ltm_pool.pool..name for_each = toset (onefuse_ipam_record.ip_record.ip_address) node = "${each.key}:var.member_port" depends_on = [ bigip_ltm_pool.pool, vsphere_virtual_machine.linux_vm, onefuse_ipam_record.ip_record, ] }

This fails with the following error,

The "for_each" 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 for_each depends on.

This is expected as there are some resources that cannot be predicted during a plan phase, as in Terraform would only know their values after an apply. Those resources cannot be used in a for_each statement. Terraform might support this use-case in the future, but it is not currently being worked on at the moment. See this link: hashicorp/terraform#4149 (comment)

So now I am now looking to see if there is a way to pass a list of strings to node attribute in bigip_ltm_pool_attachment resource type (without using for_each in my resource definition)?

trinaths commented 2 years ago

Created [INFRAANO-698] for internal tracking

KrithikaChidambaram commented 1 year ago

Hi, please try to use AS3 AS3 link: https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/ and https://clouddocs.f5.com/products/orchestration/ansible/devel/f5_bigip/modules_2_0/bigip_as3_deploy_module.html#bigip-as3-deploy-module-2 Thanks!