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.
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.
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.
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.
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.
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
Gethelper,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
Getwhich took atarget *attribute.AttributeValueortarget interface{}(pointer) and just marshalled the value into that, sinceAttributeValueis an interface.Still thinking:
.Get()and.Set()calls will concern top-level attributes, so we should either have:Attr(attributeName string) tftypes.AttributePathto plug into state methods, ortftypes.AttributePath, e.g.Get(context.Context, string, *tftypes.AttributePath) (attribute.AttributeValue, error)