-
Notifications
You must be signed in to change notification settings - Fork 9.6k
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
Looking for help rehydrating OpenStack terraform.tfstate file data (bug?, misunderstanding?) #3405
Comments
Digging more, I've come to suspect that the info in the state file has been mangled by some part of the terraform/helper/schema world and not terraform/flatmap. I'd love any hints or mentoring I could get on supported ways of working with it. Thanks, |
@hartzell the encoding and decoding of complex data structures into the flat map is handled at a higher level of abstraction, inside helper/schema. Unfortunately this thing doesn't directly expose its decoding logic, since its interface is around diffing/applying changes to resources, with the data handling as an implementation detail. ResourceData is the key type, but its important fields are private and the function that instantiates it wants the schema map that you can't easily get from outside. It looks like there is one possible entry point in instantiating a MapFieldReader directly: stateReader := &schema.MapFieldReader{
Schema: ???,
Map: schema.BasicMapReader(stateAttributes),
} But as you can see above you still need to get hold of the resource schema, which requires interacting with the provider directly. Again the provider interface is at the wrong level of abstraction for what you want to do, so it'd be necessary to depend on some implemention details: provider := openstack.Provider().(*schema.Provider)
instanceSchema := provider.ResourcesMap["openstack_compute_instance_v2"].Schema
stateReader := &schema.MapFieldReader{
Schema: instanceSchema,
Map: schema.BasicMapReader(stateAttributes),
}
metadataResult := stateReader.ReadField([]string{"metadata"})
...but by this point we've depended on a whole bunch of things that the interface doesn't guarantee, so I wouldn't recommend doing anything like the above in any production code as it's likely to break in future versions of Terraform. |
Good question @hartzell and great breakdown @apparentlymart. This will ultimately be solved by a first class feature once #581 is done. Closing this thread for now - feel free to follow up if you'd like to keep it open. |
@apparentlymart -- Thanks for that breakdown. I'd gotten to the point where I decided that there wasn't a proper way to do what I was aiming at. It's great to have someone who knows the codebase confirm my reverse-engineered understanding. I appreciate the time you invested. |
@apparentlymart -- one more bit of followup. The above suggestion works, and I'm not sure it's any more of a violation of any promises the system has made that it would be for me to chop up the state file and parse it by "hand". One small correction, ReadField seems to return two values, a result and an error, so: metadataResult, err := stateReader.ReadField([]string{"metadata"}) and your snippet works like a charm. Thanks! |
Use real, if not-really-public, terraform code for handling the state file. See hashicorp/terraform#3405
Ah, rereading the original post - I think I may have read too much into your title. I thought you started down this path because were looking for the ability to populate a statefile with details gleaned from the environment - which is what So maybe you can help clarify and we can figure out the best path - what's the target use case? |
@phinze -- The use case is roster, a dynamic inventory provider for Ansible that reads Terraform state. In the current version I parse the state using the approach that @apparentlymart suggested above. So far it's working well. This is the very first release of my very first go appilcation, so I'd love any feedback you can offer. I'll mention it on the terraform and ansible lists (and perhaps go-nuts). |
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 have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
I'm trying to work with data from a terraform.tfstate file using terraform routines instead of guessing at what things mean and parsing it by hand. I have a piece of code like this:
and I'm able to get at the resource's info.
I'd like to work with the metadata from an OpenStack compute instance. Here a portion of a state file for a comput instance.
The attributes have been flattened, and for example, I can use
flatmap.Expand
to expand the network section (which is an array).But,
flatmap.Expand
fails on the metadata section. Looking at the code I see around line 24 ofexpand.go
that it check for a '.#' and if one is found then it assumes there is a flattened array.Even though metadata is mappish, the OpenStack metadata section has
"metadata.#": "4",
soexpandArray()
gets called, which panics.I discovered that if I edit the
terraform.tfstate
file and remove themetadata.#
line, then flatmap.Expand callsexpandMap
and things work out perfectly.So, several questions:
flatmap
?Thanks for any clarifications!
The text was updated successfully, but these errors were encountered: