Skip to content

Commit

Permalink
Support attribute nested type
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Apr 1, 2021
1 parent 18d878a commit a46eda1
Show file tree
Hide file tree
Showing 11 changed files with 738 additions and 12 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/google/go-cmp v0.5.5
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/go-version v1.3.0
github.com/hashicorp/hcl-lang v0.0.0-20210317074414-9bb6847208c3
github.com/hashicorp/hcl-lang v0.0.0-20210325104312-683155cd29b5
github.com/hashicorp/hcl/v2 v2.9.1
github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34
github.com/hashicorp/terraform-json v0.10.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+DbLISwf2B8WXEolNRA8BGCwI9jws=
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl-lang v0.0.0-20210317074414-9bb6847208c3 h1:s33G8woMGjgqckJnOXbDqRi42kNfPs0+I5TmqRU5Xts=
github.com/hashicorp/hcl-lang v0.0.0-20210317074414-9bb6847208c3/go.mod h1:ZGuDQ7IWG2eFZZJC4pBZFnbH8afJ8gyOPmlHt5lJZK0=
github.com/hashicorp/hcl-lang v0.0.0-20210325104312-683155cd29b5 h1:UtKBwxbwj9lKk8InHWRrPtBNf3dW5Vyb6EVxRtA8RYs=
github.com/hashicorp/hcl-lang v0.0.0-20210325104312-683155cd29b5/go.mod h1:ZGuDQ7IWG2eFZZJC4pBZFnbH8afJ8gyOPmlHt5lJZK0=
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac=
github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
Expand Down
2 changes: 1 addition & 1 deletion internal/schema/0.12/terraform_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func terraformBlockSchema(v *version.Version) *schema.BlockSchema {
Expr: schema.ExprConstraints{
schema.ObjectExpr{
Attributes: schema.ObjectExprAttributes{
"version": schema.ObjectAttribute{
"version": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("Version constraint specifying which subset of " +
"available provider versions the module is compatible with, e.g. `~> 1.0`"),
Expand Down
4 changes: 2 additions & 2 deletions internal/schema/0.13/terraform_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ var terraformBlockSchema = &schema.BlockSchema{
Expr: schema.ExprConstraints{
schema.ObjectExpr{
Attributes: schema.ObjectExprAttributes{
"source": schema.ObjectAttribute{
"source": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("The global source address for the provider " +
"you intend to use, such as `hashicorp/aws`"),
},
"version": schema.ObjectAttribute{
"version": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("Version constraint specifying which subset of " +
"available provider versions the module is compatible with, e.g. `~> 1.0`"),
Expand Down
4 changes: 2 additions & 2 deletions internal/schema/0.14/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ func terraformBlockSchema(v *version.Version) *schema.BlockSchema {
Expr: schema.ExprConstraints{
schema.ObjectExpr{
Attributes: schema.ObjectExprAttributes{
"source": schema.ObjectAttribute{
"source": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("The global source address for the provider " +
"you intend to use, such as `hashicorp/aws`"),
},
"version": schema.ObjectAttribute{
"version": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("Version constraint specifying which subset of " +
"available provider versions the module is compatible with, e.g. `~> 1.0`"),
Expand Down
6 changes: 3 additions & 3 deletions internal/schema/0.15/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ func patchTerraformBlockSchema(bs *schema.BlockSchema, v *version.Version) *sche
Expr: schema.ExprConstraints{
schema.ObjectExpr{
Attributes: schema.ObjectExprAttributes{
"source": schema.ObjectAttribute{
"source": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("The global source address for the provider " +
"you intend to use, such as `hashicorp/aws`"),
},
"version": schema.ObjectAttribute{
"version": &schema.AttributeSchema{
Expr: schema.LiteralTypeOnly(cty.String),
Description: lang.Markdown("Version constraint specifying which subset of " +
"available provider versions the module is compatible with, e.g. `~> 1.0`"),
},
"configuration_aliases": schema.ObjectAttribute{
"configuration_aliases": &schema.AttributeSchema{
Expr: schema.ExprConstraints{
schema.TupleConsExpr{
Name: "set of aliases",
Expand Down
66 changes: 65 additions & 1 deletion schema/schema_merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
tfjson "github.com/hashicorp/terraform-json"
"github.com/hashicorp/terraform-schema/internal/addrs"
"github.com/hashicorp/terraform-schema/internal/refdecoder"
"github.com/zclconf/go-cty/cty"
)

type SchemaMerger struct {
Expand Down Expand Up @@ -295,12 +296,75 @@ func convertAttributesFromJson(attributes map[string]*tfjson.SchemaAttribute) ma
IsComputed: attr.Computed,
IsOptional: attr.Optional,
IsRequired: attr.Required,
Expr: schema.LiteralTypeOnly(attr.AttributeType),
Expr: exprConstraintsFromAttribute(attr),
}
}
return cAttrs
}

func exprConstraintsFromAttribute(attr *tfjson.SchemaAttribute) schema.ExprConstraints {
var expr schema.ExprConstraints
if attr.AttributeType != cty.NilType {
expr = schema.LiteralTypeOnly(attr.AttributeType)
}
if attr.AttributeNestedType != nil {
switch attr.AttributeNestedType.NestingMode {
case tfjson.SchemaNestingModeSingle:
return schema.ExprConstraints{
convertJsonAttributesToObjectExprAttr(attr.AttributeNestedType.Attributes),
}
case tfjson.SchemaNestingModeList:
return schema.ExprConstraints{
schema.ListExpr{
Elem: schema.ExprConstraints{
convertJsonAttributesToObjectExprAttr(attr.AttributeNestedType.Attributes),
},
MinItems: attr.AttributeNestedType.MinItems,
MaxItems: attr.AttributeNestedType.MaxItems,
},
}
case tfjson.SchemaNestingModeSet:
return schema.ExprConstraints{
schema.SetExpr{
Elem: schema.ExprConstraints{
convertJsonAttributesToObjectExprAttr(attr.AttributeNestedType.Attributes),
},
MinItems: attr.AttributeNestedType.MinItems,
MaxItems: attr.AttributeNestedType.MaxItems,
},
}
case tfjson.SchemaNestingModeMap:
return schema.ExprConstraints{
schema.MapExpr{
Elem: schema.ExprConstraints{
convertJsonAttributesToObjectExprAttr(attr.AttributeNestedType.Attributes),
},
MinItems: attr.AttributeNestedType.MinItems,
MaxItems: attr.AttributeNestedType.MaxItems,
},
}
}
}
return expr
}

func convertJsonAttributesToObjectExprAttr(attrs map[string]*tfjson.SchemaAttribute) schema.ObjectExpr {
attributes := make(schema.ObjectExprAttributes, len(attrs))
for name, attr := range attrs {
attributes[name] = &schema.AttributeSchema{
Description: markupContent(attr.Description, attr.DescriptionKind),
IsDeprecated: attr.Deprecated,
IsComputed: attr.Computed,
IsOptional: attr.Optional,
IsRequired: attr.Required,
Expr: exprConstraintsFromAttribute(attr),
}
}
return schema.ObjectExpr{
Attributes: attributes,
}
}

func markupContent(value string, kind tfjson.SchemaDescriptionKind) lang.MarkupContent {
if value == "" {
return lang.MarkupContent{}
Expand Down
75 changes: 75 additions & 0 deletions schema/schema_merge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,78 @@ func TestMergeWithJsonProviderSchemas_v013(t *testing.T) {
t.Fatalf("schema differs: %s", diff)
}
}

func TestMergeWithJsonProviderSchemas_v015(t *testing.T) {
b, err := ioutil.ReadFile("testdata/test-config-0.15.tf")
if err != nil {
t.Fatal(err)
}
f, diags := hclsyntax.ParseConfig(b, "test.tf", hcl.InitialPos)
if len(diags) > 0 {
t.Fatal(diags)
}

ps := &tfjson.ProviderSchemas{}
b, err = ioutil.ReadFile("testdata/provider-schemas-0.15.json")
if err != nil {
t.Fatal(err)
}
err = json.Unmarshal(b, ps)
if err != nil {
t.Fatal(err)
}

testCoreSchema := &schema.BodySchema{
Blocks: map[string]*schema.BlockSchema{
"provider": {
Labels: []*schema.LabelSchema{
{Name: "name"},
},
Body: &schema.BodySchema{
Attributes: map[string]*schema.AttributeSchema{
"alias": {Expr: schema.LiteralTypeOnly(cty.String), IsOptional: true},
},
},
},
"resource": {
Labels: []*schema.LabelSchema{
{Name: "type"},
{Name: "name"},
},
Body: &schema.BodySchema{
Attributes: map[string]*schema.AttributeSchema{
"count": {Expr: schema.LiteralTypeOnly(cty.Number), IsOptional: true},
},
},
},
"data": {
Labels: []*schema.LabelSchema{
{Name: "type"},
{Name: "name"},
},
Body: &schema.BodySchema{
Attributes: map[string]*schema.AttributeSchema{
"count": {Expr: schema.LiteralTypeOnly(cty.Number), IsOptional: true},
},
},
},
},
}
sm := NewSchemaMerger(testCoreSchema)
sm.SetParsedFiles(map[string]*hcl.File{
"test.tf": f,
})

mergedSchema, err := sm.MergeWithJsonProviderSchemas(ps)
if err != nil {
t.Fatal(err)
}

opts := cmp.Options{
cmpopts.IgnoreUnexported(cty.Type{}),
}

if diff := cmp.Diff(expectedMergedSchema_v015, mergedSchema, opts); diff != "" {
t.Fatalf("schema differs: %s", diff)
}
}
Loading

0 comments on commit a46eda1

Please sign in to comment.