-
Notifications
You must be signed in to change notification settings - Fork 94
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
Define State type #20
Conversation
Start building out the schema type, leaving some TODOs for things I'm still mulling over and thinking about. This also brings in the StringKind type, which is a pattern I'm not thrilled about and we should probably think about it some more. I also included the AttributeType and AttributeValue types, which I'll add a package with some builtins for in a future commit, to show off how they're used.
Add implementations of lists and strings, so we can see what an actual type may look like under this system, and to make sure that complex types still work under this system.
This is not in any way ready to merge, but I'm setting it to ready to review now because I don't want it to block anything while I'm away. Feel free to add/change commits on this branch. I think the best API for We should also have a State function that returns a With these two in place, we probably don't need |
if err != nil { | ||
return ret, fmt.Errorf("error converting from tftypes.Value: %s", err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this all be replaced with a call to Get
?
attrValue, err := s.Get(ctx, attributePath, types.StringType{}) | |
if err != nil { | |
return ret, err | |
} |
return attrValue, nil | ||
} | ||
|
||
func (s *State) Set(ctx context.Context, attributePath *tftypes.AttributePath, val interface{}) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we expect an AttributeValue
here?
func (s *State) Set(ctx context.Context, attributePath *tftypes.AttributePath, val interface{}) error { | |
func (s *State) Set(ctx context.Context, attributePath *tftypes.AttributePath, val AttributeValue) error { |
@@ -0,0 +1,98 @@ | |||
package tf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use tf_test
as the package name to avoid import loops, I think.
}, tftypes.NewValue(tftypes.Object{ | ||
AttributeTypes: map[string]tftypes.Type{ | ||
"my_string": tftypes.String, | ||
"id": tftypes.String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe id
would need to be part of the object type, too.
Value: "katy", | ||
} | ||
|
||
if actualStr != expectedStr { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think you want
if actualStr != expectedStr { | |
if !actualStr.Equal(expectedStr) { |
I also think that's an interesting direction. #25 has the beginnings of a stab at that approach, built on #12. Specifically commit 2085e26 implements the approach in
I'm not sure I disagree, but just know that we can't have the map values be types from the schema, they would need to be In theory, we could have something like.... type State struct {
// ....
}
// Get populates the struct passed as `target` with the entire state. No type assertion necessary.
func (s *State) Get(ctx context.Context, target interface{}) error {}
// GetAttribute retrieves the attribute found at `path` and returns it as an attr.Value,
// which provider developers need to assert the type of
func (s *State) GetAttribute(ctx context.Context, path attr.Path) (attr.Value, error) {}
// Set replaces the entire state with the values of the struct passed as `value`.
func (s *State) Set(ctx context.Context, value attr.Value) error {}
// SetAttribute sets the attribute found at `path` with the value passed as `value`
func (s *State) SetAttribute(ctx context.Context, path attr.Path, value attr.Value) error {} And then if users want to translate the state to provider-defined Go types at the boundaries and work with only compiler-checked types internally and not have any chance of a typo not getting caught and causing a bug, they can use |
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. |
WIP, also contains req/resp types for now
extends from #11
Summary:
There's also an example of a type-specific
Get
helper,GetString
, which returns atypes.String
. We could have one of these for each primitive type, but it's not possible for structural types due to the need to specifyElemType
.Puzzle:
It would be nice if users didn't have to make type assertions against values they get from state. I couldn't figure out how to make a version of
Get
which took atarget *attribute.AttributeValue
ortarget interface{}
(pointer) and just marshalled the value into that, sinceAttributeValue
is an interface.Still thinking:
.Get()
and.Set()
calls will concern top-level attributes, so we should either have:Attr(attributeName string) tftypes.AttributePath
to plug into state methods, ortftypes.AttributePath
, e.g.Get(context.Context, string, *tftypes.AttributePath) (attribute.AttributeValue, error)