-
Notifications
You must be signed in to change notification settings - Fork 93
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
tfsdk: Allow Plan and State SetAttribute to create attribute paths #165
Conversation
} | ||
|
||
var parentTfVal tftypes.Value | ||
parentPath := path.WithoutLastStep() |
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.
If this is the root, and has no parent, parentPath
will be nil
.
tfsdk/plan.go
Outdated
if parentValue.Equal(tftypes.NewValue(tftypes.Object{}, nil)) { | ||
// NewValue will panic if required attributes are missing in the | ||
// tftypes.Object. | ||
vals := map[string]tftypes.Value{} | ||
for name, t := range parentTfType.(tftypes.Object).AttributeTypes { | ||
vals[name] = tftypes.NewValue(t, nil) | ||
} | ||
parentValue = tftypes.NewValue(parentTfType, vals) | ||
} else if parentValue.Equal(tftypes.Value{}) { | ||
parentValue = tftypes.NewValue(parentTfType, nil) | ||
} |
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.
if parentValue.Equal(tftypes.NewValue(tftypes.Object{}, nil)) { | |
// NewValue will panic if required attributes are missing in the | |
// tftypes.Object. | |
vals := map[string]tftypes.Value{} | |
for name, t := range parentTfType.(tftypes.Object).AttributeTypes { | |
vals[name] = tftypes.NewValue(t, nil) | |
} | |
parentValue = tftypes.NewValue(parentTfType, vals) | |
} else if parentValue.Equal(tftypes.Value{}) { | |
parentValue = tftypes.NewValue(parentTfType, nil) | |
} | |
if parentValue.IsNull() || !parentValue.IsKnown() { | |
var elementVal interface{} | |
if !parentValue.IsKnown() { | |
elementVal = tftypes.UnknownValue | |
} | |
switch { | |
case parentValue.Type().Is(tftypes.Object{}): | |
vals := map[string]tftypes.Value{} | |
for name, t := range parentTfType.(tftypes.Object).AttributeTypes { | |
vals[name] = tftypes.NewValue(t, elementVal) | |
} | |
parentValue = tftypes.NewValue(parentTfType, vals) | |
case parentValue.Type().Is(tftypes.List{}), parentValue.Type().Is(tftypes.Set{}): | |
parentValue = tftypes.NewValue(parentTfType, []tftypes.Value{}) | |
case parentValue.Type().Is(tftypes.Map{}): | |
parentValue = tftypes.NewValue(parentTfType, map[string]tftypes.Value{}) | |
case parentValue.Type().Is(tftypes.Tuple{}): | |
vals := []tftypes.Value{} | |
for _, t := range parentTfType.(tftypes.Tuple).ElementTypes { | |
vals = append(vals, tftypes.NewValue(t, elementVal) | |
} | |
parentValue = tftypes.NewValue(parentTfType, vals) | |
default: | |
panic("cry about it I guess?") | |
} | |
} |
Also maybe we want this as a helper function? idk
Makes it more unit testable, at least.
Hopefully this is much more understandable now. Please let me know if you want anything else adjusted. |
return false, diags | ||
} | ||
|
||
return len(remaining.Steps()) == 0, diags |
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.
Not a request for a change, just noting here that this shouldn't be necessary, it should always be true when there's no error. I think it's good to check it anyways, just wanted to surface that context on WalkAttributePath.
tfsdk/tftypes_value.go
Outdated
// children. List, Map, and Set are created with empty elements. | ||
// | ||
// The parentType parameter ensures that the value will match the current | ||
// schema, not what is currently stored in the parentValue. |
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 think we would actually like this to actively not be the case; the schema represents type constraints (could be DynamicPseudoType, could be an object with optional attributes) but the value represents a concrete type (any non-DynamicPseudoType type, could be an object without optional attributes, respectively). So when modifying a value, I think we want to stick with the value's interpretation of what the type is supposed to be, not the schema's, so the value can stay internally consistent and match its type. Technically, it may even panic in situations where the value and type of the value start deviating.
tfsdk/tftypes_value.go
Outdated
// Lists can only have the next element added according to the current length. | ||
// | ||
// The parentType parameter ensures that the value will match the current | ||
// schema, not what is currently stored in the parentValue. |
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.
Same thing here.
tfsdk/tftypes_value.go
Outdated
parentPath, | ||
"Value Conversion Error", | ||
"An unexpected error was encountered trying to create a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+ | ||
fmt.Sprintf("Unknown parent type %T to create value.", parentValue.Type()), |
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.
fmt.Sprintf("Unknown parent type %T to create value.", parentValue.Type()), | |
fmt.Sprintf("Unknown parent type %s to create value.", parentValue.Type()), |
This will give us a friendlier output of what the type actually is semantically, not what the Go implementation of it is.
tfsdk/plan_test.go
Outdated
}), | ||
Schema: Schema{ | ||
Attributes: map[string]Attribute{ | ||
"test": { |
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.
This should appear in Raw
as nil
, I believe?
tfsdk/plan_test.go
Outdated
}), | ||
Schema: Schema{ | ||
Attributes: map[string]Attribute{ | ||
"tags": { |
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.
Same, these attributes would be in the Plan's Raw
, set to null
, not omitted from it.
…eturned in SetAttribute handling Previously: ``` --- FAIL: TestPlanSetAttribute (0.01s) --- FAIL: TestPlanSetAttribute/write-List-AttrTypeWithValidateWarning-Element (0.00s) plan_test.go:2949: unexpected diagnostics (+wanted, -got): diag.Diagnostics( - nil, + { + diag.AttributeWarningDiagnostic{ + WarningDiagnostic: diag.WarningDiagnostic{detail: "This is a warning.", summary: "Warning Diagnostic"}, + path: s`AttributeName("test")`, + }, + }, ) --- FAIL: TestPlanSetAttribute/write-Map-AttrTypeWithValidateWarning-Element (0.00s) plan_test.go:2949: unexpected diagnostics (+wanted, -got): diag.Diagnostics( - nil, + { + diag.AttributeWarningDiagnostic{ + WarningDiagnostic: diag.WarningDiagnostic{detail: "This is a warning.", summary: "Warning Diagnostic"}, + path: s`AttributeName("test")`, + }, + }, ) --- FAIL: TestPlanSetAttribute/write-Set-AttrTypeWithValidateWarning-Element (0.00s) plan_test.go:2949: unexpected diagnostics (+wanted, -got): diag.Diagnostics( - nil, + { + diag.AttributeWarningDiagnostic{ + WarningDiagnostic: diag.WarningDiagnostic{detail: "This is a warning.", summary: "Warning Diagnostic"}, + path: s`AttributeName("test")`, + }, + }, ) --- FAIL: TestStateSetAttribute (0.01s) --- FAIL: TestStateSetAttribute/write-Map-AttrTypeWithValidateWarning-Element (0.00s) state_test.go:4349: unexpected diagnostics (+wanted, -got): diag.Diagnostics( - nil, + { + diag.AttributeWarningDiagnostic{ + WarningDiagnostic: diag.WarningDiagnostic{detail: "This is a warning.", summary: "Warning Diagnostic"}, + path: s`AttributeName("test")`, + }, + }, ) --- FAIL: TestStateSetAttribute/write-List-AttrTypeWithValidateWarning-Element (0.00s) state_test.go:4349: unexpected diagnostics (+wanted, -got): diag.Diagnostics( - nil, + { + diag.AttributeWarningDiagnostic{ + WarningDiagnostic: diag.WarningDiagnostic{detail: "This is a warning.", summary: "Warning Diagnostic"}, + path: s`AttributeName("test")`, + }, + }, ) --- FAIL: TestStateSetAttribute/write-Set-AttrTypeWithValidateWarning-Element (0.00s) state_test.go:4349: unexpected diagnostics (+wanted, -got): diag.Diagnostics( - nil, + { + diag.AttributeWarningDiagnostic{ + WarningDiagnostic: diag.WarningDiagnostic{detail: "This is a warning.", summary: "Warning Diagnostic"}, + path: s`AttributeName("test")`, + }, + }, ) FAIL ```
39520c6
to
daf8676
Compare
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.
LGTM, let's ship it, great work 👍 🚀
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. |
Closes #148