Skip to content

Commit

Permalink
tfsdk: Handle Schema type deprecations
Browse files Browse the repository at this point in the history
Reference: #365
  • Loading branch information
bflad committed Aug 11, 2022
1 parent 330a87f commit fe9672b
Show file tree
Hide file tree
Showing 10 changed files with 497 additions and 256 deletions.
15 changes: 15 additions & 0 deletions .changelog/pending.txt
@@ -0,0 +1,15 @@
```release-note:breaking-change
tfsdk: The `Schema` type `AttributeAtPath()` method signature has be updated with a `path.Path` parameter and `diag.Diagnostics` return. Use the `AttributeAtTerraformPath()` method instead if `*tftypes.AttributePath` or specific `error` handling is still necessary.
```

```release-note:breaking-change
tfsdk: The previously deprecated `Schema` type `AttributeTypeAtPath()` method has been removed. Use the `TypeAtPath()` or `TypeAtTerraformPath()` method instead.
```

```release-note:breaking-change
tfsdk: The previously deprecated `Schema` type `AttributeType()` method has been removed. Use the `Type()` method instead.
```

```release-note:breaking-change
tfsdk: The previously deprecated `Schema` type `TerraformType()` method has been removed. Use `Type().TerraformType()` instead.
```
5 changes: 2 additions & 3 deletions internal/fwschema/schema.go
Expand Up @@ -17,9 +17,8 @@ type Schema interface {
tftypes.AttributePathStepper

// AttributeAtPath should return the Attribute at the given path or return
// an error. This will be added next release.
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365
// AttributeAtPath(context.Context, path.Path) (Attribute, diag.Diagnostics)
// an error.
AttributeAtPath(context.Context, path.Path) (Attribute, diag.Diagnostics)

// AttributeAtTerraformPath should return the Attribute at the given
// Terraform path or return an error.
Expand Down
20 changes: 3 additions & 17 deletions internal/fwserver/attribute_plan_modification_test.go
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/internal/privatestate"
"github.com/hashicorp/terraform-plugin-framework/internal/testing/planmodifiers"
"github.com/hashicorp/terraform-plugin-framework/internal/totftypes"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
Expand Down Expand Up @@ -2720,28 +2719,15 @@ func TestAttributeModifyPlan(t *testing.T) {
t.Parallel()

ctx := context.Background()

// TODO: Remove after schema refactoring
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365
tftypesPath, diags := totftypes.AttributePath(ctx, tc.req.AttributePath)
attribute, diags := tc.req.Config.Schema.AttributeAtPath(ctx, tc.req.AttributePath)

if diags.HasError() {
for _, diagnostic := range diags {
t.Errorf("unexpected diagnostic: %s", diagnostic)
}

return
}

attribute, err := tc.req.Config.Schema.AttributeAtTerraformPath(ctx, tftypesPath)

if err != nil {
t.Fatalf("Unexpected error getting %s", err)
t.Fatalf("Unexpected diagnostics: %s", diags)
}

tc.resp.Plan = tc.req.Plan

AttributeModifyPlan(context.Background(), attribute, tc.req, &tc.resp)
AttributeModifyPlan(ctx, attribute, tc.req, &tc.resp)

if diff := cmp.Diff(tc.expectedResp, tc.resp, cmp.AllowUnexported(privatestate.ProviderData{})); diff != "" {
t.Errorf("Unexpected response (-wanted, +got): %s", diff)
Expand Down
19 changes: 3 additions & 16 deletions internal/fwserver/attribute_validation_test.go
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/hashicorp/terraform-plugin-framework/diag"
testtypes "github.com/hashicorp/terraform-plugin-framework/internal/testing/types"
"github.com/hashicorp/terraform-plugin-framework/internal/totftypes"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand Down Expand Up @@ -1085,25 +1084,13 @@ func TestAttributeValidate(t *testing.T) {

var got tfsdk.ValidateAttributeResponse

// TODO: Remove after schema refactoring
// Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365
tftypesPath, diags := totftypes.AttributePath(ctx, tc.req.AttributePath)
attribute, diags := tc.req.Config.Schema.AttributeAtPath(ctx, tc.req.AttributePath)

if diags.HasError() {
for _, diagnostic := range diags {
t.Errorf("unexpected diagnostic: %s", diagnostic)
}

return
}

attribute, err := tc.req.Config.Schema.AttributeAtTerraformPath(ctx, tftypesPath)

if err != nil {
t.Fatalf("Unexpected error getting %s", err)
t.Fatalf("Unexpected diagnostics: %s", diags)
}

AttributeValidate(context.Background(), attribute, tc.req, &got)
AttributeValidate(ctx, attribute, tc.req, &got)

if diff := cmp.Diff(got, tc.resp); diff != "" {
t.Errorf("Unexpected response (+wanted, -got): %s", diff)
Expand Down
2 changes: 1 addition & 1 deletion internal/fwserver/server_planresourcechange_test.go
Expand Up @@ -153,7 +153,7 @@ func TestMarkComputedNilsAsUnknown(t *testing.T) {
"string-set": tftypes.NewValue(tftypes.String, "bar"),
}),
})
expected := tftypes.NewValue(s.TerraformType(context.Background()), map[string]tftypes.Value{
expected := tftypes.NewValue(s.Type().TerraformType(context.Background()), map[string]tftypes.Value{
"string-value": tftypes.NewValue(tftypes.String, "hello, world"),
"string-nil": tftypes.NewValue(tftypes.String, nil),
"string-nil-computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
Expand Down
2 changes: 1 addition & 1 deletion tfsdk/config.go
Expand Up @@ -82,7 +82,7 @@ func (c Config) getAttributeValue(ctx context.Context, path path.Path) (attr.Val
return nil, diags
}

attrType, err := c.Schema.AttributeTypeAtPath(tftypesPath)
attrType, err := c.Schema.TypeAtTerraformPath(ctx, tftypesPath)
if err != nil {
diags.AddAttributeError(
path,
Expand Down
21 changes: 3 additions & 18 deletions tfsdk/plan.go
Expand Up @@ -73,7 +73,7 @@ func (p Plan) getAttributeValue(ctx context.Context, path path.Path) (attr.Value
return nil, diags
}

attrType, err := p.Schema.AttributeTypeAtPath(tftypesPath)
attrType, err := p.Schema.TypeAtTerraformPath(ctx, tftypesPath)
if err != nil {
err = fmt.Errorf("error getting attribute type in schema: %w", err)
diags.AddAttributeError(
Expand Down Expand Up @@ -171,29 +171,14 @@ func (p *Plan) Set(ctx context.Context, val interface{}) diag.Diagnostics {
//
// Lists can only have the next element added according to the current length.
func (p *Plan) SetAttribute(ctx context.Context, path path.Path, val interface{}) diag.Diagnostics {
var diags diag.Diagnostics

ctx = logging.FrameworkWithAttributePath(ctx, path.String())

tftypesPath, tftypesPathDiags := totftypes.AttributePath(ctx, path)

diags.Append(tftypesPathDiags...)
attrType, diags := p.Schema.TypeAtPath(ctx, path)

if diags.HasError() {
return diags
}

attrType, err := p.Schema.AttributeTypeAtPath(tftypesPath)
if err != nil {
err = fmt.Errorf("error getting attribute type in schema: %w", err)
diags.AddAttributeError(
path,
"Plan Write Error",
"An unexpected error was encountered trying to write an attribute to the plan. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
return diags
}

newVal, newValDiags := reflect.FromValue(ctx, attrType, val, path)
diags.Append(newValDiags...)

Expand Down Expand Up @@ -308,7 +293,7 @@ func (p Plan) setAttributeTransformFunc(ctx context.Context, path path.Path, tfV

parentPath := path.ParentPath()
parentTftypesPath := tftypesPath.WithoutLastStep()
parentAttrType, err := p.Schema.AttributeTypeAtPath(parentTftypesPath)
parentAttrType, err := p.Schema.TypeAtTerraformPath(ctx, parentTftypesPath)

if err != nil {
err = fmt.Errorf("error getting parent attribute type in schema: %w", err)
Expand Down
53 changes: 27 additions & 26 deletions tfsdk/schema.go
Expand Up @@ -101,19 +101,6 @@ func (s Schema) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep)
return nil, fmt.Errorf("could not find attribute or block %q in schema", a)
}

// AttributeType returns a types.ObjectType composed from the schema types.
// Deprecated: Use Type() instead.
func (s Schema) AttributeType() attr.Type {
return s.Type()
}

// AttributeTypeAtPath returns the attr.Type of the attribute at the given path.
//
// Deprecated: Use the TypeAtPath() or TypeAtTerraformPath() method.
func (s Schema) AttributeTypeAtPath(path *tftypes.AttributePath) (attr.Type, error) {
return s.TypeAtTerraformPath(context.Background(), path)
}

// TypeAtPath returns the framework type at the given schema path.
func (s Schema) TypeAtPath(ctx context.Context, schemaPath path.Path) (attr.Type, diag.Diagnostics) {
var diags diag.Diagnostics
Expand All @@ -133,7 +120,7 @@ func (s Schema) TypeAtPath(ctx context.Context, schemaPath path.Path) (attr.Type
schemaPath,
"Invalid Schema Path",
"When attempting to get the framework type associated with a schema path, an unexpected error was returned. "+
"This is either an issue with the provider or terraform-plugin-framework. Please report this to the provider developers.\n\n"+
"This is always an issue with the provider. Please report this to the provider developers.\n\n"+
fmt.Sprintf("Path: %s\n", schemaPath.String())+
fmt.Sprintf("Original Error: %s", err),
)
Expand Down Expand Up @@ -198,12 +185,6 @@ func (s Schema) GetVersion() int64 {
return s.Version
}

// TerraformType returns a tftypes.Type that can represent the schema.
// Deprecated: Use Type().TerraformType() instead.
func (s Schema) TerraformType(ctx context.Context) tftypes.Type {
return s.Type().TerraformType(ctx)
}

// Type returns the framework type of the schema.
func (s Schema) Type() attr.Type {
attrTypes := map[string]attr.Type{}
Expand All @@ -222,12 +203,32 @@ func (s Schema) Type() attr.Type {
// AttributeAtPath returns the Attribute at the passed path. If the path points
// to an element or attribute of a complex type, rather than to an Attribute,
// it will return an ErrPathInsideAtomicAttribute error.
//
// Deprecated: The signature will be updated in the next release.
// Use AttributeAtTerraformPath() if the *tftypes.AttributePath parameter is
// still needed.
func (s Schema) AttributeAtPath(path *tftypes.AttributePath) (fwschema.Attribute, error) {
return s.AttributeAtTerraformPath(context.Background(), path)
func (s Schema) AttributeAtPath(ctx context.Context, schemaPath path.Path) (fwschema.Attribute, diag.Diagnostics) {
var diags diag.Diagnostics

tftypesPath, tftypesDiags := totftypes.AttributePath(ctx, schemaPath)

diags.Append(tftypesDiags...)

if diags.HasError() {
return nil, diags
}

attribute, err := s.AttributeAtTerraformPath(ctx, tftypesPath)

if err != nil {
diags.AddAttributeError(
schemaPath,
"Invalid Schema Path",
"When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+
"This is always an issue with the provider. Please report this to the provider developers.\n\n"+
fmt.Sprintf("Path: %s\n", schemaPath.String())+
fmt.Sprintf("Original Error: %s", err),
)
return nil, diags
}

return attribute, diags
}

// AttributeAtPath returns the Attribute at the passed path. If the path points
Expand Down

0 comments on commit fe9672b

Please sign in to comment.