Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL Database Instance does not have attribute ip_address.0.ip_address #912

Closed
genevieve opened this issue Jan 3, 2018 · 11 comments
Closed

Comments

@genevieve
Copy link

genevieve commented Jan 3, 2018

Terraform Version

Terraform v0.11.1

  • provider.google v0.1.3
  • provider.random v1.0.0
  • provider.tls v1.0.0

Affected Resource(s)

  • google_sql_database_instance

Terraform Configuration Files

resource "google_sql_database_instance" "master" {
  region           = "${var.region}"
  database_version = "MYSQL_5_6"
  name             = "${var.env_name}-${replace(lower(random_id.db-name.b64), "_", "-")}"

  settings {
    tier = "${var.sql_db_tier}"

    ip_configuration = {
      ipv4_enabled = true

      authorized_networks = [
        {
          name  = "all"
          value = "0.0.0.0/0"
        },
      ]
    }
  }

  count = "${var.count}"
}

output "sql_db_ip" {
  value = "${google_sql_database_instance.master.*.ip_address.0.ip_address}"
}

Debug Output

* module.external_database.output.sql_db_ip: Resource 'google_sql_database_instance.master' does not have attribute 'ip_address.0.ip_address' for variable 'google_sql_database_instance.master.*.ip_address.0.ip_address'

Expected & Actual Behavior

If I were to change the output value to:

output "sql_db_ip" {
  value = "${google_sql_database_instance.master.*.ip_address}"
}

I get:

sql_db_ip = [
    [
        map[ip_address:35.184.66.76 time_to_retire:]
    ]
]

I expect that in the former version of the output syntax (as is specified in the docs), it would print 35.184.66.76 and not an error that the attribute is not available. I additionally expect the output not to cause an error when the instance was not created.

It seems that trying to use the splat syntax and asking for nested attributes (conditionally) is not possible in terraform. If there is a single ip address assigned, why does the attribute have to be gathered by indexing with ip_address.0.ip_address? Could the instance have a single, non-nested attribute for returning the address?

Other Attempts

  • Using the element syntax is not possible as master.*.ip_address will return a nested map and not a flat list. We can flatten this list with flatten(google_sql_database_instance.master.*.ip_address) but this is a list of maps and so we cannot select the first map with element(). We can't element(concat(flatten(...), list(SOMETHING))) because you need to concat the flatted list with another list of maps. list() only takes strings.

  • We cannot do conditionals because they are not lazily evaluated and for the case where the instance is not created (count == 0), it still tries to get attributes.

  value = "${length(google_sql_database_instance.master.*.ip_address) > 0 ? lookup(google_sql_database_instance.master.*.ip_address[0], "ip_address", "") : ""}"

Steps to Reproduce

  1. terraform apply
@danawillow
Copy link
Contributor

I can get to the "why was it implemented that way?" questions tomorrow, but for now- is it possible to just output the working value and then when you're trying to use it in a resource, grab the value you need from the list of maps? (does that make sense? I can try to come up with a sample config if not)

@genevieve
Copy link
Author

When this instance has a count of 1, we want to grab the value of it's ip address and expose it as a terraform output. It's possible to get that value when the instance is present, but we haven't yet found a way to make the output "empty" so that terraform does not fail.

If we know the instance is there, we tired to say google_sql_db_instance.master.0.ip_address.0.ip_address but that also returns an error.

@genevieve
Copy link
Author

genevieve commented Jan 4, 2018

It seems like the combination of splat syntax + nested map attributes is hard for terraform to follow. We tried splitting it into multiple small local vars:

(This code might be a little off, I checked out the changes and am trying to remember one of dozens of things we tried 😄.)

locals {
  thing = "${google_sql_db_instance.master.*.ip_address}" // so we get the list of maps
  thing2 = "${local.thing[0]}" // To get the first map
  thing3 = "${local.thing2.ip_address}" //To get the ip addr
}

output "ip" {
  value = "${var.count == 0 ? "" : local.thing3}"
}

And this will fail when the count is 0.

@genevieve
Copy link
Author

This is obviously only breaking us since the v0.11.0 change to terraform output errors when empty (and forcing the splat syntax).

@danawillow
Copy link
Contributor

Ah, ok. In that case I'd recommend filing an issue in the core repository: github.com/hashicorp/terraform, since even though you're using the Google provider, the actual problem could have happened with any of them if they followed this pattern. Probably best to make a note that you filed here first and I sent you there, so they don't try to send you back here.

As for why we use a nested resource for ip addresses, that's just to mirror what the GCP API gives us: https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances. Since that documentation makes it sound like there could be more than one value in the list, we allow for more than one value in Terraform as well.

@genevieve
Copy link
Author

Thanks Dana! Will do!

@genevieve
Copy link
Author

@rosbo Would it be possible to re-open this issue as there is something that can be done in this provider that would fix the issue and also be convenient for users?

The suggestion is from this comment: hashicorp/terraform#17048 (comment)

To work around the current limitations of the language, in principle the Google Cloud provider could export a simple attribute like first_ip_address that provides a convenience syntax for the presumably-common case of accessing the IP address in the first element of that list, which we could discuss with the team working on terraform-provider-google to see if they'd be interested in supporting such a thing.

@rosbo
Copy link
Contributor

rosbo commented Jan 12, 2018

Oh. I missed that part. Reopening.

@rosbo rosbo reopened this Jan 12, 2018
@genevieve
Copy link
Author

@danawillow Would you be interested in a PR that added a first_ip_address to the sql db instance resource to provide a convenient syntax for accessing the first ip in the list?

@genevieve
Copy link
Author

Going to close this since the above PR got merged!

@ghost
Copy link

ghost commented Nov 19, 2018

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 [email protected]. Thanks!

@ghost ghost locked and limited conversation to collaborators Nov 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants