Skip to content

Start supplying attr.Type to reflection.#41

Merged
paddycarver merged 1 commit intomainfrom
paddy_reflect_shenanigans
Jun 8, 2021
Merged

Start supplying attr.Type to reflection.#41
paddycarver merged 1 commit intomainfrom
paddy_reflect_shenanigans

Conversation

@paddycarver
Copy link
Contributor

@paddycarver paddycarver commented Jun 3, 2021

Reflection has A Problem:

We want to support using attr.Values inside of structs, slices, etc. and just having the reflection package Do The Right Thing. This means the reflection package needs to be able to create them.

We originally solved that in #30 by just instantiating empty values of their type, and then calling a SetTerraformValue method on that value. This was super annoying, because then we needed two methods for getting an attr.Value set to the right values: attr.Type.ValueFromTerraform and attr.Value.SetTerraformValue were basically the same thing. But whatever, it worked.

Except, no it didn't.

Complex types like lists and maps store their element/attribute types as properties on their structs. It's important that these be set. Only the attr.Type has this information, it's not passed in as part of the tftypes.Value. So reflect couldn't set those values, and produced broken attr.Values as a result. (Their ToTerraformValue methods would run into trouble, because they wouldn't know what tftypes.Type to use for elements or attributes).

To solve this problem, we decided to supply the attr.Type from the schema to the reflect package, wiring it through so that we could instantiate new attr.Values when the opportunity presented itself.

This solves our problem, because we got rid of the attr.Value.SetTerraformValue method and used the attr.Type.ValueFromTerraform directly to just instantiate a new value, which made sure it was set up correctly. But now we have a new problem: what if the attr.Type in the schema doesn't produce the attr.Value they're trying to assign to? We decided to just throw an error on that one, because there's no reasonable way around it.

Depends on #44.

@paddycarver paddycarver force-pushed the paddy_reflect_shenanigans branch from 422e52c to 3c0addf Compare June 8, 2021 01:59
@paddycarver paddycarver added the bug Something isn't working label Jun 8, 2021
@paddycarver paddycarver added this to the v0.1.0 milestone Jun 8, 2021
@paddycarver paddycarver marked this pull request as ready for review June 8, 2021 02:23
@paddycarver paddycarver requested a review from a team June 8, 2021 02:23
@kmoe kmoe mentioned this pull request Jun 8, 2021
Copy link
Member

@kmoe kmoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM depending on #44

@kmoe
Copy link
Member

kmoe commented Jun 8, 2021

Actually, I'm not sure I like having to duplicate our type implementations inside the reflect package with testStringType etc. Why not just use a reflect_test package?

@paddycarver
Copy link
Contributor Author

Actually, I'm not sure I like having to duplicate our type implementations inside the reflect package with testStringType etc. Why not just use a reflect_test package?

Same, but the point of these tests is to test unexported functions, which we can't do if we use a reflect_test package. :( But no amount of package shenanigans will get us around this one, because types has to rely on these functions and these functions have to have concrete types. We could combine them into a single package, but then we can't reuse them in Get, etc. We could move the type implementations internal, and reference them from the types package, but I have a hunch that's gonna get messy real quick.

I don't particularly like the copying, either, but I couldn't think of something that was less bad.

@kmoe
Copy link
Member

kmoe commented Jun 8, 2021

Yes, good point. I suppose the only other option is to make those functions exported, which has no user impact because the reflect package is internal.

@kmoe
Copy link
Member

kmoe commented Jun 8, 2021

This just came up because I'm having to copy my ApplyTerraform5AttributePathStep implementations everywhere.

@paddycarver
Copy link
Contributor Author

Hm, let me give it a shot and see how we like the result.

@paddycarver paddycarver force-pushed the paddy_reflect_shenanigans branch from 1f156ae to b017c7e Compare June 8, 2021 10:19
@kmoe
Copy link
Member

kmoe commented Jun 8, 2021

Looks good!

@paddycarver
Copy link
Contributor Author

Doing some last tweaking of comments in the reflect package to make golint happy, then I'll rebase and squash it all down with a nice commit message.

@paddycarver
Copy link
Contributor Author

Okay, golint wanted some pretty invasive changes, but I think we're good now if you're still happy, @kmoe

Reflection has A Problem:

We want to support using `attr.Value`s inside of structs, slices, etc.
and just having the reflection package Do The Right Thing. This means
the reflection package needs to be able to create them.

We originally solved that in #30 by just instantiating empty values of
their type, and then calling a `SetTerraformValue` method on that value.
This was super annoying, because then we needed two methods for getting
an `attr.Value` set to the right values: `attr.Type.ValueFromTerraform`
and `attr.Value.SetTerraformValue` were basically the same thing. But
whatever, it worked.

Except, no it didn't.

Complex types like lists and maps store their element/attribute types as
properties on their structs. It's important that these be set. Only the
`attr.Type` has this information, it's not passed in as part of the
`tftypes.Value`. So reflect couldn't set those values, and produced
broken `attr.Value`s as a result. (Their `ToTerraformValue` methods
would run into trouble, because they wouldn't know what `tftypes.Type`
to use for elements or attributes).

To solve this problem, we decided to supply the `attr.Type` from the
schema to the reflect package, wiring it through so that we could
instantiate new `attr.Value`s when the opportunity presented itself.

This solves our problem, because we got rid of the
`attr.Value.SetTerraformValue` method and used the
`attr.Type.ValueFromTerraform` directly to just instantiate a new value,
which made sure it was set up correctly. But now we have a new problem:
what if the `attr.Type` in the schema doesn't produce the `attr.Value`
they're trying to assign to? We decided to just throw an error on that
one, because there's no reasonable way around it.

Depends on #44.
@paddycarver paddycarver force-pushed the paddy_reflect_shenanigans branch from 3a8147a to 0fe3b76 Compare June 8, 2021 11:07
@paddycarver paddycarver merged commit f431af6 into main Jun 8, 2021
@paddycarver paddycarver deleted the paddy_reflect_shenanigans branch June 8, 2021 11:08
@github-actions
Copy link

github-actions bot commented Jul 9, 2021

I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants