Skip to content

Commit

Permalink
use cty for tags search
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Guibert committed Apr 16, 2021
1 parent 58131b5 commit 82ec691
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 46 deletions.
56 changes: 24 additions & 32 deletions pkg/dctlcty/cty_attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ package dctlcty

import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/zclconf/go-cty/cty"
ctyjson "github.com/zclconf/go-cty/cty/json"
)
Expand All @@ -29,6 +26,7 @@ func AsAttrs(val *cty.Value, terraformType string) *CtyAttributes {

attributes := &CtyAttributes{
attrs,
val,
&metadata,
}

Expand All @@ -41,6 +39,7 @@ func AsAttrs(val *cty.Value, terraformType string) *CtyAttributes {

type CtyAttributes struct {
Attrs map[string]interface{}
value *cty.Value
metadata *Metadata
}

Expand Down Expand Up @@ -88,43 +87,36 @@ func (a *CtyAttributes) SafeSet(path []string, value interface{}) error {
}

func (a *CtyAttributes) Tags(path []string) reflect.StructTag {
if a.metadata == nil || a.Attrs == nil {
if a.metadata == nil || a.value == nil {
return ""
}

var current interface{} = a.Attrs
realPath := ""
for _, part := range path {
if current == nil {
logrus.Debugf("Failed to find tag for path %+v", path)
return ""
}
kind := reflect.TypeOf(current).Kind()
switch kind {
case reflect.Array:
fallthrough
case reflect.Slice:
index, err := strconv.ParseUint(part, 10, 64)
if err != nil {
logrus.Debugf("Failed to find tag for path %+v", path)
return ""
}
current = current.([]interface{})[index]
currentType := a.value.Type()
var realPath []string
for i, part := range path {

if currentType.IsListType() || currentType.IsSetType() || currentType.IsTupleType() {
currentType = currentType.ElementType()
continue
case reflect.Map:
current = current.(map[string]interface{})[part]
default:
logrus.Debugf("Failed to find tag for path %+v", path)
return ""
}
if realPath != "" {
realPath = fmt.Sprintf("%s.%s", realPath, part)
continue

if currentType.IsCollectionType() {
currentType = currentType.ElementType()
}

if currentType.IsObjectType() {
currentType = currentType.AttributeType(part)
}

if currentType.IsPrimitiveType() {
if i < len(path)-1 {
return "" // Should not happen path leads to a non existing field
}
}
realPath = part
realPath = append(realPath, part)
}

fieldTags, exists := a.metadata.tags[realPath]
fieldTags, exists := a.metadata.tags[strings.Join(realPath, ".")]
if !exists {
return ""
}
Expand Down
58 changes: 44 additions & 14 deletions pkg/dctlcty/cty_attribute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/zclconf/go-cty/cty/gocty"
)

func TestCtyAttributes_SafeDelete(t *testing.T) {
Expand Down Expand Up @@ -220,16 +221,21 @@ func TestCtyAttributes_SafeSet(t *testing.T) {
}
}

type args struct {
Attrs map[string]interface{}
metadata *Metadata
}

func TestCtyAttributes_Tags(t *testing.T) {
tests := []struct {
name string
attr *CtyAttributes
args *args
path []string
want reflect.StructTag
}{
{
"Found tags",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -248,7 +254,7 @@ func TestCtyAttributes_Tags(t *testing.T) {
},
{
"No tags found",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -271,7 +277,15 @@ func TestCtyAttributes_Tags(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.attr.Tags(tt.path); got != tt.want {
typ, _ := gocty.ImpliedType(tt.args.Attrs)
ctyVal, _ := gocty.ToCtyValue(tt.args.Attrs, typ)

attrs := CtyAttributes{
Attrs: tt.args.Attrs,
value: &ctyVal,
metadata: tt.args.metadata,
}
if got := attrs.Tags(tt.path); got != tt.want {
t.Errorf("Tags() = %v, want %v", got, tt.want)
}
})
Expand All @@ -281,13 +295,13 @@ func TestCtyAttributes_Tags(t *testing.T) {
func TestCtyAttributes_IsComputedField(t *testing.T) {
tests := []struct {
name string
attr *CtyAttributes
args *args
path []string
want bool
}{
{
"Is computed",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -309,7 +323,7 @@ func TestCtyAttributes_IsComputedField(t *testing.T) {
},
{
"Not computed",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -331,7 +345,7 @@ func TestCtyAttributes_IsComputedField(t *testing.T) {
},
{
"No tags",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -354,7 +368,15 @@ func TestCtyAttributes_IsComputedField(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.attr.IsComputedField(tt.path); got != tt.want {
typ, _ := gocty.ImpliedType(tt.args.Attrs)
ctyVal, _ := gocty.ToCtyValue(tt.args.Attrs, typ)

attrs := CtyAttributes{
Attrs: tt.args.Attrs,
value: &ctyVal,
metadata: tt.args.metadata,
}
if got := attrs.IsComputedField(tt.path); got != tt.want {
t.Errorf("IsComputedField() = %v, want %v", got, tt.want)
}
})
Expand All @@ -364,13 +386,13 @@ func TestCtyAttributes_IsComputedField(t *testing.T) {
func TestCtyAttributes_IsJsonStringField(t *testing.T) {
tests := []struct {
name string
attr *CtyAttributes
args *args
path []string
want bool
}{
{
"Is json",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -392,7 +414,7 @@ func TestCtyAttributes_IsJsonStringField(t *testing.T) {
},
{
"Not json",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -414,7 +436,7 @@ func TestCtyAttributes_IsJsonStringField(t *testing.T) {
},
{
"No tags",
&CtyAttributes{
&args{
map[string]interface{}{
"test": map[string]interface{}{
"has": map[string]interface{}{
Expand All @@ -437,7 +459,15 @@ func TestCtyAttributes_IsJsonStringField(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.attr.IsJsonStringField(tt.path); got != tt.want {
typ, _ := gocty.ImpliedType(tt.args.Attrs)
ctyVal, _ := gocty.ToCtyValue(tt.args.Attrs, typ)

attrs := CtyAttributes{
Attrs: tt.args.Attrs,
value: &ctyVal,
metadata: tt.args.metadata,
}
if got := attrs.IsJsonStringField(tt.path); got != tt.want {
t.Errorf("IsComputedField() = %v, want %v", got, tt.want)
}
})
Expand Down

0 comments on commit 82ec691

Please sign in to comment.