Skip to content

Commit 5aaf299

Browse files
committed
feat(tfsearch): TF-26847 TF-27288: Added: dynamic schema for provider block
1 parent cfb1a68 commit 5aaf299

File tree

6 files changed

+108
-57
lines changed

6 files changed

+108
-57
lines changed

internal/features/search/decoder/path_reader.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ func searchPathContext(record *state.SearchRecord, stateReader CombinedReader) (
8787
sm.SetStateReader(stateReader)
8888

8989
meta := &tfsearch.Meta{
90-
Path: record.Path(),
91-
Lists: record.Meta.Lists,
92-
Variables: record.Meta.Variables,
93-
Filenames: record.Meta.Filenames,
90+
Path: record.Path(),
91+
Lists: record.Meta.Lists,
92+
Variables: record.Meta.Variables,
93+
Filenames: record.Meta.Filenames,
94+
ProviderReferences: record.Meta.ProviderReferences,
95+
ProviderRequirements: record.Meta.ProviderRequirements,
9496
}
9597

9698
mergedSchema, err := sm.SchemaForSearch(meta)

internal/features/search/events.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ import (
1010

1111
lsctx "github.com/hashicorp/terraform-ls/internal/context"
1212
"github.com/hashicorp/terraform-ls/internal/document"
13-
"github.com/hashicorp/terraform-ls/internal/eventbus"
1413
"github.com/hashicorp/terraform-ls/internal/features/search/ast"
1514
"github.com/hashicorp/terraform-ls/internal/features/search/jobs"
16-
"github.com/hashicorp/terraform-ls/internal/features/search/state"
1715
"github.com/hashicorp/terraform-ls/internal/job"
1816
"github.com/hashicorp/terraform-ls/internal/lsp"
1917
"github.com/hashicorp/terraform-ls/internal/protocol"
@@ -190,7 +188,7 @@ func (f *SearchFeature) decodeSearch(ctx context.Context, dir document.DirHandle
190188
metaId, err := f.stateStore.JobStore.EnqueueJob(ctx, job.Job{
191189
Dir: dir,
192190
Func: func(ctx context.Context) error {
193-
return jobs.LoadSearchMetadata(ctx, f.store, path)
191+
return jobs.LoadSearchMetadata(ctx, f.store, f.moduleFeature, f.logger, path)
194192
},
195193
Type: operation.OpTypeLoadSearchMetadata.String(),
196194
DependsOn: job.IDs{parseId},
@@ -202,25 +200,13 @@ func (f *SearchFeature) decodeSearch(ctx context.Context, dir document.DirHandle
202200
f.logger.Printf("loading module metadata returned error: %s", jobErr)
203201
}
204202

205-
smIds, err := loadSearchModuleSources(ctx, f.store, f.bus, path)
206-
if err != nil {
207-
return deferIds, err
208-
}
209-
deferIds = append(deferIds, smIds...)
210-
211-
// while we now have the job ids in here, depending on the metaId job is not enough
212-
// to await these spawned jobs, so we will need to move all depending jobs to this function
213-
// as well. e.g. LoadSearchComponentSources, PreloadEmbeddedSchema (because future ref collection jobs depend on it), etc.
214-
// we might just move all in here for simplicity
215-
216203
// Reference collection jobs will depend on this one, so we move it here in advance
217204
eSchemaId, err := f.stateStore.JobStore.EnqueueJob(ctx, job.Job{
218205
Dir: dir,
219206
Func: func(ctx context.Context) error {
220207
return jobs.PreloadEmbeddedSchema(ctx, f.logger, schemas.FS,
221208
f.store, f.stateStore.ProviderSchemas, path)
222209
},
223-
// DependsOn: none required, since we are inside
224210
Type: operation.OpTypeSearchPreloadEmbeddedSchema.String(),
225211
IgnoreState: ignoreState,
226212
})
@@ -235,7 +221,7 @@ func (f *SearchFeature) decodeSearch(ctx context.Context, dir document.DirHandle
235221
return jobs.DecodeReferenceTargets(ctx, f.store, f.moduleFeature, f.rootFeature, path)
236222
},
237223
Type: operation.OpTypeDecodeReferenceTargets.String(),
238-
DependsOn: append(job.IDs{eSchemaId}, smIds...),
224+
DependsOn: job.IDs{eSchemaId},
239225
IgnoreState: ignoreState,
240226
})
241227
if err != nil {
@@ -249,7 +235,7 @@ func (f *SearchFeature) decodeSearch(ctx context.Context, dir document.DirHandle
249235
return jobs.DecodeReferenceOrigins(ctx, f.store, f.moduleFeature, f.rootFeature, path)
250236
},
251237
Type: operation.OpTypeDecodeReferenceOrigins.String(),
252-
DependsOn: append(job.IDs{eSchemaId}, smIds...),
238+
DependsOn: job.IDs{eSchemaId},
253239
IgnoreState: ignoreState,
254240
})
255241
if err != nil {
@@ -298,16 +284,3 @@ func (f *SearchFeature) removeIndexedSearch(rawPath string) {
298284
return
299285
}
300286
}
301-
302-
func loadSearchModuleSources(ctx context.Context, testStore *state.SearchStore, bus *eventbus.EventBus, testPath string) (job.IDs, error) {
303-
ids := make(job.IDs, 0)
304-
305-
_, err := testStore.SearchRecordByPath(testPath)
306-
if err != nil {
307-
return ids, err
308-
}
309-
310-
// TODO load the adjacent Terraform module (usually ./)
311-
312-
return ids, nil
313-
}

internal/features/search/jobs/metadata.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,23 @@ package jobs
55

66
import (
77
"context"
8+
"log"
89

910
"github.com/hashicorp/terraform-ls/internal/document"
1011
"github.com/hashicorp/terraform-ls/internal/features/search/ast"
12+
searchDecoder "github.com/hashicorp/terraform-ls/internal/features/search/decoder"
1113
"github.com/hashicorp/terraform-ls/internal/features/search/state"
1214
"github.com/hashicorp/terraform-ls/internal/job"
1315
globalAst "github.com/hashicorp/terraform-ls/internal/terraform/ast"
1416
"github.com/hashicorp/terraform-ls/internal/terraform/module/operation"
1517
earlydecoder "github.com/hashicorp/terraform-schema/earlydecoder/search"
18+
tfsearch "github.com/hashicorp/terraform-schema/search"
1619
)
1720

1821
// LoadSearchMetadata loads data about the search in a version-independent
1922
// way that enables us to decode the rest of the configuration,
2023
// e.g. by knowing provider versions, etc.
21-
func LoadSearchMetadata(ctx context.Context, searchStore *state.SearchStore, searchPath string) error {
24+
func LoadSearchMetadata(ctx context.Context, searchStore *state.SearchStore, moduleFeature searchDecoder.ModuleReader, logger *log.Logger, searchPath string) error {
2225
record, err := searchStore.SearchRecordByPath(searchPath)
2326
if err != nil {
2427
return err
@@ -38,6 +41,11 @@ func LoadSearchMetadata(ctx context.Context, searchStore *state.SearchStore, sea
3841

3942
meta, diags := earlydecoder.LoadSearch(record.Path(), record.ParsedFiles.AsMap())
4043

44+
err = loadSearchModuleSources(meta, moduleFeature, searchPath)
45+
if err != nil {
46+
logger.Printf("loading search module sources returned error: %s", err)
47+
}
48+
4149
var mErr error
4250
sErr := searchStore.UpdateMetadata(searchPath, meta, mErr)
4351
if sErr != nil {
@@ -72,3 +80,29 @@ func LoadSearchMetadata(ctx context.Context, searchStore *state.SearchStore, sea
7280

7381
return mErr
7482
}
83+
84+
func loadSearchModuleSources(searchMeta *tfsearch.Meta, moduleFeature searchDecoder.ModuleReader, path string) error {
85+
// load metadata from the adjacent Terraform module
86+
modMeta, err := moduleFeature.LocalModuleMeta(path)
87+
if err != nil {
88+
return err
89+
}
90+
91+
if modMeta != nil {
92+
// Convert from module provider references to search provider references
93+
for moduleProviderRef, provider := range modMeta.ProviderReferences {
94+
searchProviderRef := tfsearch.ProviderRef{
95+
LocalName: moduleProviderRef.LocalName,
96+
Alias: moduleProviderRef.Alias,
97+
}
98+
searchMeta.ProviderReferences[searchProviderRef] = provider
99+
}
100+
101+
// Copy provider requirements
102+
for provider, constraints := range modMeta.ProviderRequirements {
103+
searchMeta.ProviderRequirements[provider] = constraints
104+
}
105+
}
106+
107+
return nil
108+
}

internal/features/search/jobs/schema.go

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,27 @@ func PreloadEmbeddedSchema(ctx context.Context, logger *log.Logger, fs fs.ReadDi
3333
}
3434
defer searchStore.SetPreloadEmbeddedSchemaState(searchPath, operation.OpStateLoaded)
3535

36-
// TODO: get providerrequirements from *.tf files
37-
/*
38-
pReqs := make(map[tfaddr.Provider]version.Constraints, len(record.Meta.ProviderRequirements))
39-
for _, req := range record.Meta.ProviderRequirements {
40-
pReqs[req.Source] = req.VersionConstraints
41-
}
36+
pReqs, err := searchStore.ProviderRequirementsForModule(searchPath)
37+
if err != nil {
38+
return err
39+
}
40+
41+
missingReqs, err := schemaStore.MissingSchemas(pReqs)
42+
if err != nil {
43+
return err
44+
}
45+
46+
if len(missingReqs) == 0 {
47+
// avoid preloading any schemas if we already have all
48+
return nil
49+
}
4250

43-
missingReqs, err := schemaStore.MissingSchemas(pReqs)
51+
for _, pAddr := range missingReqs {
52+
err := globalState.PreloadSchemaForProviderAddr(ctx, pAddr, fs, schemaStore, logger)
4453
if err != nil {
4554
return err
4655
}
47-
48-
if len(missingReqs) == 0 {
49-
// avoid preloading any schemas if we already have all
50-
return nil
51-
}
52-
53-
for _, pAddr := range missingReqs {
54-
err := globalState.PreloadSchemaForProviderAddr(ctx, pAddr, fs, schemaStore, logger)
55-
if err != nil {
56-
return err
57-
}
58-
} */
56+
}
5957

6058
return nil
6159

internal/features/search/state/search_meta.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package state
55

66
import (
7+
tfaddr "github.com/hashicorp/terraform-registry-address"
78
tfsearch "github.com/hashicorp/terraform-schema/search"
89
)
910

@@ -14,6 +15,9 @@ type SearchMetadata struct {
1415

1516
Lists map[string]tfsearch.List
1617
Variables map[string]tfsearch.Variable
18+
19+
ProviderReferences map[tfsearch.ProviderRef]tfaddr.Provider
20+
ProviderRequirements tfsearch.ProviderRequirements
1721
}
1822

1923
func (sm SearchMetadata) Copy() SearchMetadata {
@@ -35,5 +39,20 @@ func (sm SearchMetadata) Copy() SearchMetadata {
3539
}
3640
}
3741

42+
if sm.ProviderReferences != nil {
43+
newSm.ProviderReferences = make(map[tfsearch.ProviderRef]tfaddr.Provider, len(sm.ProviderReferences))
44+
for ref, provider := range sm.ProviderReferences {
45+
newSm.ProviderReferences[ref] = provider
46+
}
47+
}
48+
49+
if sm.ProviderRequirements != nil {
50+
newSm.ProviderRequirements = make(tfsearch.ProviderRequirements, len(sm.ProviderRequirements))
51+
for provider, vc := range sm.ProviderRequirements {
52+
// version.Constraints is never mutated in this context
53+
newSm.ProviderRequirements[provider] = vc
54+
}
55+
}
56+
3857
return newSm
3958
}

internal/features/search/state/search_store.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,11 @@ func (s *SearchStore) UpdateMetadata(path string, meta *tfsearch.Meta, mErr erro
296296

297297
record := oldRecord.Copy()
298298
record.Meta = SearchMetadata{
299-
Lists: meta.Lists,
300-
Variables: meta.Variables,
301-
Filenames: meta.Filenames,
299+
Lists: meta.Lists,
300+
Variables: meta.Variables,
301+
Filenames: meta.Filenames,
302+
ProviderReferences: meta.ProviderReferences,
303+
ProviderRequirements: meta.ProviderRequirements,
302304
}
303305
record.MetaErr = mErr
304306

@@ -518,3 +520,26 @@ func (s *SearchStore) queueRecordChange(oldRecord, newRecord *SearchRecord) erro
518520
func (s *SearchStore) ProviderSchema(modPath string, addr tfaddr.Provider, vc version.Constraints) (*tfschema.ProviderSchema, error) {
519521
return s.providerSchemasStore.ProviderSchema(modPath, addr, vc)
520522
}
523+
524+
func (s *SearchStore) ProviderRequirementsForModule(modPath string) (tfsearch.ProviderRequirements, error) {
525+
return s.providerRequirementsForModule(modPath, 0)
526+
}
527+
528+
func (s *SearchStore) providerRequirementsForModule(searchPath string, level int) (tfsearch.ProviderRequirements, error) {
529+
mod, err := s.SearchRecordByPath(searchPath)
530+
if err != nil {
531+
// It's possible that the configuration contains a module with an
532+
// invalid local source, so we just ignore it if it can't be found.
533+
// This allows us to still return provider requirements for other modules
534+
return tfsearch.ProviderRequirements{}, nil
535+
}
536+
537+
level++
538+
539+
requirements := make(tfsearch.ProviderRequirements, 0)
540+
for k, v := range mod.Meta.ProviderRequirements {
541+
requirements[k] = v
542+
}
543+
544+
return requirements, nil
545+
}

0 commit comments

Comments
 (0)