terraform-provider-gitea/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema/shims.go
Tobias Trabelsi e1266ebf64
Some checks reported errors
continuous-integration/drone/pr Build encountered an error
continuous-integration/drone/push Build encountered an error
updated GHA
Update to v2 SDK
updated dependencies
2022-08-06 16:21:18 +02:00

131 lines
4.1 KiB
Go

package schema
import (
"context"
"encoding/json"
"github.com/hashicorp/go-cty/cty"
ctyjson "github.com/hashicorp/go-cty/cty/json"
"github.com/hashicorp/terraform-plugin-sdk/v2/internal/configs/configschema"
"github.com/hashicorp/terraform-plugin-sdk/v2/internal/configs/hcl2shim"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)
// DiffFromValues takes the current state and desired state as cty.Values and
// derives a terraform.InstanceDiff to give to the legacy providers. This is
// used to take the states provided by the new ApplyResourceChange method and
// convert them to a state+diff required for the legacy Apply method.
func DiffFromValues(ctx context.Context, prior, planned, config cty.Value, res *Resource) (*terraform.InstanceDiff, error) {
return diffFromValues(ctx, prior, planned, config, res, nil)
}
// diffFromValues takes an additional CustomizeDiffFunc, so we can generate our
// test fixtures from the legacy tests. In the new provider protocol the diff
// only needs to be created for the apply operation, and any customizations
// have already been done.
func diffFromValues(ctx context.Context, prior, planned, config cty.Value, res *Resource, cust CustomizeDiffFunc) (*terraform.InstanceDiff, error) {
instanceState, err := res.ShimInstanceStateFromValue(prior)
if err != nil {
return nil, err
}
instanceState.RawConfig = config
instanceState.RawPlan = planned
instanceState.RawState = prior
configSchema := res.CoreConfigSchema()
cfg := terraform.NewResourceConfigShimmed(planned, configSchema)
removeConfigUnknowns(cfg.Config)
removeConfigUnknowns(cfg.Raw)
diff, err := schemaMap(res.Schema).Diff(ctx, instanceState, cfg, cust, nil, false)
if err != nil {
return nil, err
}
return diff, err
}
// During apply the only unknown values are those which are to be computed by
// the resource itself. These may have been marked as unknown config values, and
// need to be removed to prevent the UnknownVariableValue from appearing the diff.
func removeConfigUnknowns(cfg map[string]interface{}) {
for k, v := range cfg {
switch v := v.(type) {
case string:
if v == hcl2shim.UnknownVariableValue {
delete(cfg, k)
}
case []interface{}:
for _, i := range v {
if m, ok := i.(map[string]interface{}); ok {
removeConfigUnknowns(m)
}
}
case map[string]interface{}:
removeConfigUnknowns(v)
}
}
}
// ApplyDiff takes a cty.Value state and applies a terraform.InstanceDiff to
// get a new cty.Value state. This is used to convert the diff returned from
// the legacy provider Diff method to the state required for the new
// PlanResourceChange method.
func ApplyDiff(base cty.Value, d *terraform.InstanceDiff, schema *configschema.Block) (cty.Value, error) {
return d.ApplyToValue(base, schema)
}
// StateValueToJSONMap converts a cty.Value to generic JSON map via the cty JSON
// encoding.
func StateValueToJSONMap(val cty.Value, ty cty.Type) (map[string]interface{}, error) {
return stateValueToJSONMap(val, ty, false)
}
func stateValueToJSONMap(val cty.Value, ty cty.Type, useJSONNumber bool) (map[string]interface{}, error) {
js, err := ctyjson.Marshal(val, ty)
if err != nil {
return nil, err
}
var m map[string]interface{}
if useJSONNumber {
if err := unmarshalJSON(js, &m); err != nil {
return nil, err
}
} else {
if err := json.Unmarshal(js, &m); err != nil {
return nil, err
}
}
return m, nil
}
// JSONMapToStateValue takes a generic json map[string]interface{} and converts it
// to the specific type, ensuring that the values conform to the schema.
func JSONMapToStateValue(m map[string]interface{}, block *configschema.Block) (cty.Value, error) {
var val cty.Value
js, err := json.Marshal(m)
if err != nil {
return val, err
}
val, err = ctyjson.Unmarshal(js, block.ImpliedType())
if err != nil {
return val, err
}
return block.CoerceValue(val)
}
// StateValueFromInstanceState converts a terraform.InstanceState to a
// cty.Value as described by the provided cty.Type, and maintains the resource
// ID as the "id" attribute.
func StateValueFromInstanceState(is *terraform.InstanceState, ty cty.Type) (cty.Value, error) {
return is.AttrsAsObjectValue(ty)
}