mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
dcab82e897
Send Private data blob through ReadResource as well. This will allow for extra flexibility for future providers that may want to pass data out of band through to their resource Read functions.
107 lines
2.9 KiB
Go
107 lines
2.9 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/providers"
|
|
"github.com/hashicorp/terraform/states"
|
|
"github.com/hashicorp/terraform/tfdiags"
|
|
)
|
|
|
|
// EvalRefresh is an EvalNode implementation that does a refresh for
|
|
// a resource.
|
|
type EvalRefresh struct {
|
|
Addr addrs.ResourceInstance
|
|
ProviderAddr addrs.AbsProviderConfig
|
|
Provider *providers.Interface
|
|
ProviderSchema **ProviderSchema
|
|
State **states.ResourceInstanceObject
|
|
Output **states.ResourceInstanceObject
|
|
}
|
|
|
|
// TODO: test
|
|
func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) {
|
|
state := *n.State
|
|
absAddr := n.Addr.Absolute(ctx.Path())
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
// If we have no state, we don't do any refreshing
|
|
if state == nil {
|
|
log.Printf("[DEBUG] refresh: %s: no state, so not refreshing", n.Addr.Absolute(ctx.Path()))
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|
|
|
|
schema, _ := (*n.ProviderSchema).SchemaForResourceAddr(n.Addr.ContainingResource())
|
|
if schema == nil {
|
|
// Should be caught during validation, so we don't bother with a pretty error here
|
|
return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type)
|
|
}
|
|
|
|
// Call pre-refresh hook
|
|
err := ctx.Hook(func(h Hook) (HookAction, error) {
|
|
return h.PreRefresh(absAddr, states.CurrentGen, state.Value)
|
|
})
|
|
if err != nil {
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|
|
|
|
// Refresh!
|
|
priorVal := state.Value
|
|
req := providers.ReadResourceRequest{
|
|
TypeName: n.Addr.Resource.Type,
|
|
PriorState: priorVal,
|
|
Private: state.Private,
|
|
}
|
|
|
|
provider := *n.Provider
|
|
resp := provider.ReadResource(req)
|
|
diags = diags.Append(resp.Diagnostics)
|
|
if diags.HasErrors() {
|
|
return nil, diags.Err()
|
|
}
|
|
|
|
if resp.NewState == cty.NilVal {
|
|
// This ought not to happen in real cases since it's not possible to
|
|
// send NilVal over the plugin RPC channel, but it can come up in
|
|
// tests due to sloppy mocking.
|
|
panic("new state is cty.NilVal")
|
|
}
|
|
|
|
for _, err := range resp.NewState.Type().TestConformance(schema.ImpliedType()) {
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
tfdiags.Error,
|
|
"Provider produced invalid object",
|
|
fmt.Sprintf(
|
|
"Provider %q planned an invalid value for %s during refresh: %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
|
|
n.ProviderAddr.ProviderConfig.Type, absAddr, tfdiags.FormatError(err),
|
|
),
|
|
))
|
|
}
|
|
if diags.HasErrors() {
|
|
return nil, diags.Err()
|
|
}
|
|
|
|
newState := state.DeepCopy()
|
|
newState.Value = resp.NewState
|
|
newState.Private = resp.Private
|
|
|
|
// Call post-refresh hook
|
|
err = ctx.Hook(func(h Hook) (HookAction, error) {
|
|
return h.PostRefresh(absAddr, states.CurrentGen, priorVal, newState.Value)
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if n.Output != nil {
|
|
*n.Output = newState
|
|
}
|
|
|
|
return nil, diags.ErrWithWarnings()
|
|
}
|