Skip to content

Commit

Permalink
helper/terraformtype/helper/schema: Ensure CustomizeDiffFunc handling…
Browse files Browse the repository at this point in the history
… supports Terraform Plugin SDK v2

Reference: #178
  • Loading branch information
bflad committed Aug 5, 2020
1 parent d9660b6 commit 5b4f6fd
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 24 deletions.
48 changes: 39 additions & 9 deletions helper/terraformtype/helper/schema/type_customizedifffunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,28 @@ func IsFuncTypeCustomizeDiffFunc(node ast.Node, info *types.Info) bool {
return false
}

return isFuncTypeCustomizeDiffFuncV1(funcType, info) || isFuncTypeCustomizeDiffFuncV2(funcType, info)
}

// IsTypeCustomizeDiffFunc returns if the type is CustomizeDiffFunc from the customdiff package
func IsTypeCustomizeDiffFunc(t types.Type) bool {
switch t := t.(type) {
case *types.Named:
return IsNamedType(t, TypeNameCustomizeDiffFunc)
case *types.Pointer:
return IsTypeCustomizeDiffFunc(t.Elem())
default:
return false
}
}

// isFuncTypeCustomizeDiffFuncV1 returns true if the FuncType matches expected parameters and results types of V1
func isFuncTypeCustomizeDiffFuncV1(funcType *ast.FuncType, info *types.Info) bool {
if !astutils.HasFieldListLength(funcType.Params, 2) {
return false
}

if !astutils.IsFieldListTypePackageType(funcType.Params, 0, info, PackagePath, TypeNameResourceDiff) {
if !astutils.IsFieldListTypePackageType(funcType.Params, 0, info, PackagePathVersion(1), TypeNameResourceDiff) {
return false
}

Expand All @@ -39,16 +56,29 @@ func IsFuncTypeCustomizeDiffFunc(node ast.Node, info *types.Info) bool {
return astutils.IsFieldListType(funcType.Results, 0, astutils.IsExprTypeError)
}

// IsTypeCustomizeDiffFunc returns if the type is CustomizeDiffFunc from the customdiff package
func IsTypeCustomizeDiffFunc(t types.Type) bool {
switch t := t.(type) {
case *types.Named:
return IsNamedType(t, TypeNameCustomizeDiffFunc)
case *types.Pointer:
return IsTypeCustomizeDiffFunc(t.Elem())
default:
// isFuncTypeCustomizeDiffFuncV2 returns true if the FuncType matches expected parameters and results types of V2
func isFuncTypeCustomizeDiffFuncV2(funcType *ast.FuncType, info *types.Info) bool {
if !astutils.HasFieldListLength(funcType.Params, 3) {
return false
}

if !astutils.IsFieldListTypePackageType(funcType.Params, 0, info, "context", "Context") {
return false
}

if !astutils.IsFieldListTypePackageType(funcType.Params, 1, info, PackagePathVersion(2), TypeNameResourceDiff) {
return false
}

if !astutils.IsFieldListType(funcType.Params, 2, astutils.IsExprTypeInterface) {
return false
}

if !astutils.HasFieldListLength(funcType.Results, 1) {
return false
}

return astutils.IsFieldListType(funcType.Results, 0, astutils.IsExprTypeError)
}

// CustomizeDiffFuncInfo represents all gathered CustomizeDiffFunc data for easier access
Expand Down
90 changes: 75 additions & 15 deletions helper/terraformtype/helper/schema/type_customizedifffunc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,70 @@ func TestIsFuncTypeCustomizeDiffFunc(t *testing.T) {
boolIdent := &ast.Ident{
Name: types.Typ[types.Bool].String(),
}
contextIdent := &ast.Ident{
Name: "context",
}
contextContextIdent := &ast.Ident{
Name: "Context",
}
errorIdent := &ast.Ident{
Name: "error",
}
interfaceAst := &ast.InterfaceType{
Methods: &ast.FieldList{},
}
packageIdent := &ast.Ident{
packageIdentV1 := &ast.Ident{
Name: PackageName,
}
packageType := types.NewPackage(PackagePath, PackageName)
packageNameType := types.NewPkgName(token.NoPos, packageType, packageType.Name(), packageType)
packageIdentV2 := &ast.Ident{
Name: PackageName + `2`,
}
contextType := types.NewPackage("context", "context")
packageTypeV1 := types.NewPackage(PackagePathVersion(1), PackageName)
packageTypeV2 := types.NewPackage(PackagePathVersion(2), PackageName)
contextNameType := types.NewPkgName(token.NoPos, contextType, contextType.Name(), contextType)
packageNameTypeV1 := types.NewPkgName(token.NoPos, packageTypeV1, packageTypeV1.Name(), packageTypeV1)
packageNameTypeV2 := types.NewPkgName(token.NoPos, packageTypeV2, packageTypeV2.Name(), packageTypeV2)
packageFuncIdent := &ast.Ident{
Name: TypeNameResourceDiff,
}
packageSelectorExpr := &ast.SelectorExpr{
contextContextSelectorExpr := &ast.SelectorExpr{
Sel: contextContextIdent,
X: contextIdent,
}
packageSelectorExprV1 := &ast.SelectorExpr{
Sel: packageFuncIdent,
X: packageIdent,
X: packageIdentV1,
}
packageSelectorExprV2 := &ast.SelectorExpr{
Sel: packageFuncIdent,
X: packageIdentV2,
}
typesInfo := &types.Info{
Types: map[ast.Expr]types.TypeAndValue{
boolIdent: types.TypeAndValue{
boolIdent: {
Type: types.Typ[types.Bool],
},
errorIdent: types.TypeAndValue{
contextContextSelectorExpr: {
Type: types.NewNamed(types.NewTypeName(token.NoPos, contextType, contextContextIdent.Name, nil), nil, nil),
},
errorIdent: {
Type: types.NewNamed(types.NewTypeName(token.NoPos, nil, "error", nil), nil, nil),
},
interfaceAst: types.TypeAndValue{
interfaceAst: {
Type: types.NewInterfaceType(nil, nil),
},
packageSelectorExpr: types.TypeAndValue{
Type: types.NewNamed(types.NewTypeName(token.NoPos, packageType, TypeNameResourceDiff, nil), nil, nil),
packageSelectorExprV1: {
Type: types.NewNamed(types.NewTypeName(token.NoPos, packageTypeV1, TypeNameResourceDiff, nil), nil, nil),
},
packageSelectorExprV2: {
Type: types.NewNamed(types.NewTypeName(token.NoPos, packageTypeV2, TypeNameResourceDiff, nil), nil, nil),
},
},
Uses: map[*ast.Ident]types.Object{
packageIdent: packageNameType,
contextIdent: contextNameType,
packageIdentV1: packageNameTypeV1,
packageIdentV2: packageNameTypeV2,
},
}

Expand All @@ -57,14 +86,14 @@ func TestIsFuncTypeCustomizeDiffFunc(t *testing.T) {
Expected bool
}{
{
Name: fmt.Sprintf("func(*%s.%s, interface{}) bool", PackagePath, TypeNameResourceDiff),
Name: fmt.Sprintf("func(*%s.%s, interface{}) bool", PackagePathVersion(1), TypeNameResourceDiff),
Node: &ast.FuncLit{
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{
{
Type: &ast.StarExpr{
X: packageSelectorExpr,
X: packageSelectorExprV1,
},
},
{
Expand All @@ -85,14 +114,45 @@ func TestIsFuncTypeCustomizeDiffFunc(t *testing.T) {
Expected: false,
},
{
Name: fmt.Sprintf("func(*%s.%s, interface{}) error", PackagePath, TypeNameResourceDiff),
Name: fmt.Sprintf("func(*%s.%s, interface{}) error", PackagePathVersion(1), TypeNameResourceDiff),
Node: &ast.FuncLit{
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{
{
Type: &ast.StarExpr{
X: packageSelectorExprV1,
},
},
{
Type: interfaceAst,
},
},
},
Results: &ast.FieldList{
List: []*ast.Field{
{
Type: errorIdent,
},
},
},
},
},
Info: typesInfo,
Expected: true,
},
{
Name: fmt.Sprintf("func(context.Context, *%s.%s, interface{}) error", PackagePathVersion(2), TypeNameResourceDiff),
Node: &ast.FuncLit{
Type: &ast.FuncType{
Params: &ast.FieldList{
List: []*ast.Field{
{
Type: contextContextSelectorExpr,
},
{
Type: &ast.StarExpr{
X: packageSelectorExpr,
X: packageSelectorExprV2,
},
},
{
Expand Down

0 comments on commit 5b4f6fd

Please sign in to comment.