Skip to content

Commit d079957

Browse files
committed
command: Providers schema shows required_providers
The providers schema command is using the Config.ProviderTypes method, which had not been kept up to date with the changes to provider requirements detection made in Config.ProviderRequirements. This resulted in any currently-unused providers being omitted from the output. This commit changes the ProviderTypes method to use the same underlying logic as ProviderRequirements, which ensures that `required_providers` blocks are taken into account. Includes an integration test case to verify that this fixes the provider schemas command bug.
1 parent 921f36a commit d079957

File tree

5 files changed

+89
-55
lines changed

5 files changed

+89
-55
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"format_version": "0.1",
3+
"provider_schemas": {
4+
"registry.terraform.io/hashicorp/test": {
5+
"provider": {
6+
"version": 0,
7+
"block": {
8+
"attributes": {
9+
"region": {
10+
"description_kind": "plain",
11+
"optional": true,
12+
"type": "string"
13+
}
14+
},
15+
"description_kind": "plain"
16+
}
17+
},
18+
"resource_schemas": {
19+
"test_instance": {
20+
"version": 0,
21+
"block": {
22+
"attributes": {
23+
"ami": {
24+
"type": "string",
25+
"optional": true,
26+
"description_kind": "plain"
27+
},
28+
"id": {
29+
"type": "string",
30+
"optional": true,
31+
"computed": true,
32+
"description_kind": "plain"
33+
}
34+
},
35+
"description_kind": "plain"
36+
}
37+
}
38+
}
39+
}
40+
}
41+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
terraform {
2+
required_providers {
3+
test = {
4+
source = "hashicorp/test"
5+
}
6+
}
7+
}

configs/config.go

Lines changed: 32 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -226,33 +226,36 @@ func (c *Config) addProviderRequirements(reqs getproviders.Requirements, recurse
226226
var diags hcl.Diagnostics
227227

228228
// First we'll deal with the requirements directly in _our_ module...
229-
for _, providerReqs := range c.Module.ProviderRequirements.RequiredProviders {
230-
fqn := providerReqs.Type
231-
if _, ok := reqs[fqn]; !ok {
232-
// We'll at least have an unconstrained dependency then, but might
233-
// add to this in the loop below.
234-
reqs[fqn] = nil
235-
}
236-
// The model of version constraints in this package is still the
237-
// old one using a different upstream module to represent versions,
238-
// so we'll need to shim that out here for now. The two parsers
239-
// don't exactly agree in practice 🙄 so this might produce new errors.
240-
// TODO: Use the new parser throughout this package so we can get the
241-
// better error messages it produces in more situations.
242-
constraints, err := getproviders.ParseVersionConstraints(providerReqs.Requirement.Required.String())
243-
if err != nil {
244-
diags = diags.Append(&hcl.Diagnostic{
245-
Severity: hcl.DiagError,
246-
Summary: "Invalid version constraint",
247-
// The errors returned by ParseVersionConstraint already include
248-
// the section of input that was incorrect, so we don't need to
249-
// include that here.
250-
Detail: fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
251-
Subject: providerReqs.Requirement.DeclRange.Ptr(),
252-
})
229+
if c.Module.ProviderRequirements != nil {
230+
for _, providerReqs := range c.Module.ProviderRequirements.RequiredProviders {
231+
fqn := providerReqs.Type
232+
if _, ok := reqs[fqn]; !ok {
233+
// We'll at least have an unconstrained dependency then, but might
234+
// add to this in the loop below.
235+
reqs[fqn] = nil
236+
}
237+
// The model of version constraints in this package is still the
238+
// old one using a different upstream module to represent versions,
239+
// so we'll need to shim that out here for now. The two parsers
240+
// don't exactly agree in practice 🙄 so this might produce new errors.
241+
// TODO: Use the new parser throughout this package so we can get the
242+
// better error messages it produces in more situations.
243+
constraints, err := getproviders.ParseVersionConstraints(providerReqs.Requirement.Required.String())
244+
if err != nil {
245+
diags = diags.Append(&hcl.Diagnostic{
246+
Severity: hcl.DiagError,
247+
Summary: "Invalid version constraint",
248+
// The errors returned by ParseVersionConstraint already include
249+
// the section of input that was incorrect, so we don't need to
250+
// include that here.
251+
Detail: fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
252+
Subject: providerReqs.Requirement.DeclRange.Ptr(),
253+
})
254+
}
255+
reqs[fqn] = append(reqs[fqn], constraints...)
253256
}
254-
reqs[fqn] = append(reqs[fqn], constraints...)
255257
}
258+
256259
// Each resource in the configuration creates an *implicit* provider
257260
// dependency, though we'll only record it if there isn't already
258261
// an explicit dependency on the same provider.
@@ -323,11 +326,11 @@ func (c *Config) addProviderRequirements(reqs getproviders.Requirements, recurse
323326
// provider version selection in an earlier step and have identified suitable
324327
// versions for each provider.
325328
func (c *Config) ProviderTypes() []addrs.Provider {
326-
m := make(map[addrs.Provider]struct{})
327-
c.gatherProviderTypes(m)
329+
// Ignore diagnostics here because they relate to version constraints
330+
reqs, _ := c.ProviderRequirements()
328331

329-
ret := make([]addrs.Provider, 0, len(m))
330-
for k := range m {
332+
ret := make([]addrs.Provider, 0, len(reqs))
333+
for k := range reqs {
331334
ret = append(ret, k)
332335
}
333336
sort.Slice(ret, func(i, j int) bool {
@@ -336,32 +339,6 @@ func (c *Config) ProviderTypes() []addrs.Provider {
336339
return ret
337340
}
338341

339-
func (c *Config) gatherProviderTypes(m map[addrs.Provider]struct{}) {
340-
if c == nil {
341-
return
342-
}
343-
344-
for _, pc := range c.Module.ProviderConfigs {
345-
fqn := c.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{LocalName: pc.Name})
346-
m[fqn] = struct{}{}
347-
}
348-
for _, rc := range c.Module.ManagedResources {
349-
providerAddr := rc.ProviderConfigAddr()
350-
fqn := c.Module.ProviderForLocalConfig(providerAddr)
351-
m[fqn] = struct{}{}
352-
}
353-
for _, rc := range c.Module.DataResources {
354-
providerAddr := rc.ProviderConfigAddr()
355-
fqn := c.Module.ProviderForLocalConfig(providerAddr)
356-
m[fqn] = struct{}{}
357-
}
358-
359-
// Must also visit our child modules, recursively.
360-
for _, cc := range c.Children {
361-
cc.gatherProviderTypes(m)
362-
}
363-
}
364-
365342
// ResolveAbsProviderAddr returns the AbsProviderConfig represented by the given
366343
// ProviderConfig address, which must not be nil or this method will panic.
367344
//

configs/config_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func TestConfigProviderTypes(t *testing.T) {
3232
addrs.NewDefaultProvider("aws"),
3333
addrs.NewDefaultProvider("null"),
3434
addrs.NewDefaultProvider("template"),
35+
addrs.NewDefaultProvider("test"),
3536
}
3637
for _, problem := range deep.Equal(got, want) {
3738
t.Error(problem)

configs/testdata/valid-files/providers-explicit-implied.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ resource "aws_instance" "foo" {
1313
resource "null_resource" "foo" {
1414

1515
}
16+
17+
terraform {
18+
required_providers {
19+
test = {
20+
source = "hashicorp/test"
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)