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

Question on importing a resource #52

Open
robwolff3 opened this issue Sep 30, 2021 · 3 comments
Open

Question on importing a resource #52

robwolff3 opened this issue Sep 30, 2021 · 3 comments

Comments

@robwolff3
Copy link

Looking at the Terraform import command usage: terraform import [options] ADDRESS ID the one thing I I'm not sure about is the ID field. In the Terraform documentation they give an example of an AWS EC2 instance and the id in that case would be the instance id from AWS and they say "Please reference the provider documentation for details on the ID format."

With a resource deployed using this provider, I opened up the state file and see an ID for the resource I created and it looks to be a random number? "id": "2745262606" Is there anyway to know this id before importing a resource created outside of Terraform?

Thanks!

@robwolff3 robwolff3 changed the title Question on imporing a resource Question on importing a resource Sep 30, 2021
@sullivtr
Copy link
Owner

sullivtr commented Oct 8, 2021

@robwolff3 So there is one really tricky thing about a generic provider such as this one. That is, the resources it manages are arbitrary, so there is no standard for what a resource's id might represent. In hindsight, I could have made that a parameter for users to pass in to tell which property to use, but that is not the case right now. Right now, the id is generated using a CRC-32 checksum of graphql mutation's create response data.

The relevant code is here:
https://github.com/sullivtr/terraform-provider-graphql/blob/master/graphql/resource_graphql_mutation.go#L117-L118

and hash impl here:

func hash(v []byte) int {
queryResponseObj := make(map[string]interface{})
_ = json.Unmarshal(v, &queryResponseObj)
out, err := json.Marshal(queryResponseObj)
if err != nil {
panic(err)
}
return hashCodeString(string(out))
}
// hashCodeString hashes a string to a unique hashcode.
//
// crc32 returns a uint32, but for our use we need
// and non negative integer. Here we cast to an integer
// and invert it if the result is negative.
func hashCodeString(s string) int {
v := int(crc32.ChecksumIEEE([]byte(s)))
if v >= 0 {
return v
}
if -v >= 0 {
return -v
}
// v == MinInt
return 0
}

In hindsight this was a mistake, but that is how it works now. You could get the ID by passing a []byte representation of the graphql create mutation response to the hash function.

Here is a Go Playground where you can do this right in your browser using the same code I use to generate the ID:

https://play.golang.org/p/3O_qMVfmlb_x

Just fill in the resJsonData part with what your create mutation response would look like, and it will generate the ID.

@QuingKhaos
Copy link

QuingKhaos commented Nov 23, 2021

@sullivtr What do you think about having something like id_attribute to configure the resources ID (compare to restapi_object) set in the state? And or additionally an importer function which would handle the ID supplied on the import command then?

Thinking for now an importer function accepting the expected create mutation response to compute the CRC-32 checksum, set the ID and then execute the read query could also be very helpful.

@sullivtr
Copy link
Owner

@QuingKhaos The id_attribute route is what I was thinking is most sound. My only reservation about this now is backward compatibility. I have to ensure the IDs do not change for existing users after an upgrade. I'm thinking we could have an optional id_attribute going forward that will be used to get the resource's ID from the response and set the ID in state using its value, but if the id_attribute is unset, it will continue using the CRC_32 hash. It's been a while since I wrote the current ID logic, so I can't remember exactly why I implemented it this way (but there was a good reason at the time). I will keep you all posted when I come of with a good backward compatible design for this.

I also think your other suggestion:

an importer function accepting the expected create mutation response to compute the CRC-32 checksum

would be a decent workaround if the other solution does not work out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants