From b237dcc7305daea89f8d65922aac874003a96aaf Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Wed, 3 Nov 2021 16:19:24 +0000 Subject: [PATCH] schema: Use OriginForTarget to connect module inputs w/ variables --- go.mod | 2 +- go.sum | 26 ++++++++++--- schema/language_ids.go | 6 +++ schema/module_schema.go | 26 ++++++++++++- schema/module_schema_test.go | 29 +++++++++++++++ schema/schema_merge_test.go | 1 + schema/schema_merge_v015_test.go | 14 +++++++ schema/variable_schema.go | 63 +++++++++++++++++--------------- 8 files changed, 130 insertions(+), 37 deletions(-) create mode 100644 schema/language_ids.go diff --git a/go.mod b/go.mod index b12c3d76..4c7fcd2d 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.14 require ( github.com/google/go-cmp v0.5.6 github.com/hashicorp/go-version v1.3.0 - github.com/hashicorp/hcl-lang v0.0.0-20210803155453-7c098e4940bc + github.com/hashicorp/hcl-lang v0.0.0-20211118124824-da3a292c5d7a github.com/hashicorp/hcl/v2 v2.10.1 github.com/hashicorp/terraform-json v0.13.0 github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896 diff --git a/go.sum b/go.sum index 51ad9db1..d798a1c2 100644 --- a/go.sum +++ b/go.sum @@ -27,8 +27,8 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw= github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hcl-lang v0.0.0-20210803155453-7c098e4940bc h1:c0EJ6tK81OTD609/r4fgjf/SUy9A4CSUDMQL3qnt8NY= -github.com/hashicorp/hcl-lang v0.0.0-20210803155453-7c098e4940bc/go.mod h1:xzXU6Fn+TWVaZUFxV8CyAsObi2oMgSEFAmLvCx2ArzM= +github.com/hashicorp/hcl-lang v0.0.0-20211118124824-da3a292c5d7a h1:NOcXX/HO5KHrQPjClxRuHO+Hu90CDhZqM5CNKvlcRkg= +github.com/hashicorp/hcl-lang v0.0.0-20211118124824-da3a292c5d7a/go.mod h1:0W3+VP07azoS+fCX5hWk1KxwHnqf1s9J7oBg2cFXm1c= github.com/hashicorp/hcl/v2 v2.10.1 h1:h4Xx4fsrRE26ohAk/1iGF/JBqRQbyUqu5Lvj60U54ys= github.com/hashicorp/hcl/v2 v2.10.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY= @@ -63,10 +63,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.9.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0= github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= @@ -74,31 +74,45 @@ github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY3 github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= diff --git a/schema/language_ids.go b/schema/language_ids.go new file mode 100644 index 00000000..1b99bfa5 --- /dev/null +++ b/schema/language_ids.go @@ -0,0 +1,6 @@ +package schema + +const ( + ModuleLanguageID = "terraform" + VariablesLanguageID = "terraform-vars" +) diff --git a/schema/module_schema.go b/schema/module_schema.go index 0d83b2f5..2d8b127f 100644 --- a/schema/module_schema.go +++ b/schema/module_schema.go @@ -11,8 +11,32 @@ import ( ) func schemaForDependentModuleBlock(localName string, modMeta *module.Meta) (*schema.BodySchema, error) { + attributes := make(map[string]*schema.AttributeSchema, 0) + + for name, modVar := range modMeta.Variables { + aSchema := moduleVarToAttribute(modVar) + varType := typeOfModuleVar(modVar) + aSchema.Expr = convertAttributeTypeToExprConstraints(varType) + aSchema.OriginForTarget = &schema.PathTarget{ + Address: schema.Address{ + schema.StaticStep{Name: "var"}, + schema.AttrNameStep{}, + }, + Path: lang.Path{ + Path: modMeta.Path, + LanguageID: ModuleLanguageID, + }, + Constraints: schema.Constraints{ + ScopeId: refscope.VariableScope, + Type: varType, + }, + } + + attributes[name] = aSchema + } + bodySchema := &schema.BodySchema{ - Attributes: variablesToAttrSchemas(modMeta.Variables, convertAttributeTypeToExprConstraints), + Attributes: attributes, } if localName == "" { diff --git a/schema/module_schema_test.go b/schema/module_schema_test.go index 02cfeff6..63c7acb2 100644 --- a/schema/module_schema_test.go +++ b/schema/module_schema_test.go @@ -39,6 +39,7 @@ func TestSchemaForDependentModuleBlock_emptyMeta(t *testing.T) { func TestSchemaForDependentModuleBlock_basic(t *testing.T) { meta := &module.Meta{ + Path: "./local", Variables: map[string]module.Variable{ "example_var": { Description: "Test var", @@ -75,6 +76,20 @@ func TestSchemaForDependentModuleBlock_basic(t *testing.T) { Description: lang.PlainText("Test var"), IsRequired: true, IsSensitive: true, + OriginForTarget: &schema.PathTarget{ + Address: schema.Address{ + schema.StaticStep{Name: "var"}, + schema.AttrNameStep{}, + }, + Path: lang.Path{ + Path: "./local", + LanguageID: "terraform", + }, + Constraints: schema.Constraints{ + ScopeId: "variable", + Type: cty.String, + }, + }, }, "another_var": { Expr: schema.ExprConstraints{ @@ -82,6 +97,20 @@ func TestSchemaForDependentModuleBlock_basic(t *testing.T) { schema.LiteralTypeExpr{Type: cty.String}, }, IsOptional: true, + OriginForTarget: &schema.PathTarget{ + Address: schema.Address{ + schema.StaticStep{Name: "var"}, + schema.AttrNameStep{}, + }, + Path: lang.Path{ + Path: "./local", + LanguageID: "terraform", + }, + Constraints: schema.Constraints{ + ScopeId: "variable", + Type: cty.String, + }, + }, }, }, TargetableAs: []*schema.Targetable{ diff --git a/schema/schema_merge_test.go b/schema/schema_merge_test.go index 0ca3e8e2..9c45efd0 100644 --- a/schema/schema_merge_test.go +++ b/schema/schema_merge_test.go @@ -358,6 +358,7 @@ func (m *testModuleReaderStruct) ModuleCalls(modPath string) ([]module.ModuleCal func (m *testModuleReaderStruct) ModuleMeta(modPath string) (*module.Meta, error) { if modPath == "path" { return &module.Meta{ + Path: "path", Variables: map[string]module.Variable{ "test": { Type: cty.String, diff --git a/schema/schema_merge_v015_test.go b/schema/schema_merge_v015_test.go index 13f6e3ff..a0d6028f 100644 --- a/schema/schema_merge_v015_test.go +++ b/schema/schema_merge_v015_test.go @@ -526,6 +526,20 @@ var moduleWithDependency = schema.BlockSchema{ schema.LiteralTypeExpr{Type: cty.String}, }, IsRequired: true, + OriginForTarget: &schema.PathTarget{ + Address: schema.Address{ + schema.StaticStep{Name: "var"}, + schema.AttrNameStep{}, + }, + Path: lang.Path{ + Path: "path", + LanguageID: "terraform", + }, + Constraints: schema.Constraints{ + ScopeId: "variable", + Type: cty.String, + }, + }, }, }, }, diff --git a/schema/variable_schema.go b/schema/variable_schema.go index a8e1a96a..fa57cc6e 100644 --- a/schema/variable_schema.go +++ b/schema/variable_schema.go @@ -8,41 +8,46 @@ import ( ) func SchemaForVariables(vars map[string]module.Variable) (*schema.BodySchema, error) { + attributes := make(map[string]*schema.AttributeSchema) + + for name, modVar := range vars { + aSchema := moduleVarToAttribute(modVar) + aSchema.Expr = schema.LiteralTypeOnly(typeOfModuleVar(modVar)) + attributes[name] = aSchema + } + return &schema.BodySchema{ - Attributes: variablesToAttrSchemas(vars, schema.LiteralTypeOnly), + Attributes: attributes, }, nil } type exprFunc func(cty.Type) schema.ExprConstraints -func variablesToAttrSchemas(vars map[string]module.Variable, exprFunc exprFunc) map[string]*schema.AttributeSchema { - varSchemas := make(map[string]*schema.AttributeSchema) - - for name, v := range vars { - varType := v.Type - if (varType == cty.DynamicPseudoType || varType == cty.NilType) && - v.DefaultValue != cty.NilVal { - // infer type from default value if one is not specified - // or when it's "any" - varType = v.DefaultValue.Type() - } - - aSchema := &schema.AttributeSchema{ - Expr: exprFunc(varType), - IsSensitive: v.IsSensitive, - } - if v.Description != "" { - aSchema.Description = lang.PlainText(v.Description) - } - - varSchemas[name] = aSchema - - if v.DefaultValue == cty.NilVal { - varSchemas[name].IsRequired = true - } else { - varSchemas[name].IsOptional = true - } +func moduleVarToAttribute(modVar module.Variable) *schema.AttributeSchema { + aSchema := &schema.AttributeSchema{ + IsSensitive: modVar.IsSensitive, + } + + if modVar.Description != "" { + aSchema.Description = lang.PlainText(modVar.Description) + } + + if modVar.DefaultValue == cty.NilVal { + aSchema.IsRequired = true + } else { + aSchema.IsOptional = true + } + + return aSchema +} + +func typeOfModuleVar(modVar module.Variable) cty.Type { + if (modVar.Type == cty.DynamicPseudoType || modVar.Type == cty.NilType) && + modVar.DefaultValue != cty.NilVal { + // infer type from default value if one is not specified + // or when it's "any" + return modVar.DefaultValue.Type() } - return varSchemas + return modVar.Type }