Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add missing provider schema versions #1060

Merged
merged 4 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestLangServer_workspaceExecuteCommand_terraformVersion_basic(t *testing.T)
t.Fatal(err)
}

err = s.Modules.UpdateTerraformVersion(modDir, ver, map[tfaddr.Provider]*version.Version{}, nil)
err = s.Modules.UpdateTerraformAndProviderVersions(modDir, ver, map[tfaddr.Provider]*version.Version{}, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
7 changes: 6 additions & 1 deletion internal/state/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,11 @@ func (s *ModuleStore) UpdateInstalledProviders(path string, pvs map[tfaddr.Provi
return err
}

err = updateProviderVersions(txn, path, pvs)
if err != nil {
return err
}

txn.Commit()
return nil
}
Expand Down Expand Up @@ -738,7 +743,7 @@ func (s *ModuleStore) FinishProviderSchemaLoading(path string, psErr error) erro
return nil
}

func (s *ModuleStore) UpdateTerraformVersion(modPath string, tfVer *version.Version, pv map[tfaddr.Provider]*version.Version, vErr error) error {
func (s *ModuleStore) UpdateTerraformAndProviderVersions(modPath string, tfVer *version.Version, pv map[tfaddr.Provider]*version.Version, vErr error) error {
txn := s.db.Txn(true)
txn.Defer(func() {
s.SetTerraformVersionState(modPath, op.OpStateLoaded)
Expand Down
2 changes: 1 addition & 1 deletion internal/state/module_changes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func TestModuleChanges_AwaitNextChangeBatch_multipleChanges(t *testing.T) {
t.Fatal(err)
}

err = ss.Modules.UpdateTerraformVersion(modPath, testVersion(t, "1.0.0"), map[tfaddr.Provider]*version.Version{}, nil)
err = ss.Modules.UpdateTerraformAndProviderVersions(modPath, testVersion(t, "1.0.0"), map[tfaddr.Provider]*version.Version{}, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/state/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestModuleStore_ModuleByPath(t *testing.T) {
}

tfVersion := version.Must(version.NewVersion("1.0.0"))
err = s.Modules.UpdateTerraformVersion(modPath, tfVersion, nil, nil)
err = s.Modules.UpdateTerraformAndProviderVersions(modPath, tfVersion, nil, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -287,7 +287,7 @@ func TestModuleStore_UpdateMetadata(t *testing.T) {
}
}

func TestModuleStore_UpdateTerraformVersion(t *testing.T) {
func TestModuleStore_UpdateTerraformAndProviderVersions(t *testing.T) {
s, err := NewStateStore()
if err != nil {
t.Fatal(err)
Expand All @@ -301,7 +301,7 @@ func TestModuleStore_UpdateTerraformVersion(t *testing.T) {

vErr := customErr{}

err = s.Modules.UpdateTerraformVersion(tmpDir, testVersion(t, "0.12.4"), nil, vErr)
err = s.Modules.UpdateTerraformAndProviderVersions(tmpDir, testVersion(t, "0.12.4"), nil, vErr)
if err != nil {
t.Fatal(err)
}
Expand Down
30 changes: 24 additions & 6 deletions internal/state/provider_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,19 @@ func (s *ProviderSchemaStore) schemaExists(addr tfaddr.Provider, pCons version.C
if !ok {
continue
}
if ps.Schema == nil || ps.Version == nil {
// Incomplete entries may result from the provider version being
// sourced earlier where the schema is yet to be sourced,
// or vice versa, or sourcing failed.
if ps.Schema == nil {
// Incomplete entry may be a result of provider version being
// sourced earlier where schema is yet to be sourced or sourcing failed.
continue
}
if ps.Version == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// Obtaining schema is always done *after* getting the version.
// Therefore, this can only happen in a rare case when getting
// provider versions fails but getting schema was successful.
// e.g. custom plugin cache location in combination with 0.12
// (where lock files didn't exist) [1], or user-triggered race
// condition when the lock file is deleted/created.
// [1] See https://github.com/hashicorp/terraform-ls/issues/24
continue
}

Expand Down Expand Up @@ -373,11 +382,12 @@ func (ss sortableSchemas) Len() int {
func (ss sortableSchemas) Less(i, j int) bool {
var leftRank, rightRank int

// TODO: Rank by version constraints match
leftRank += ss.rankByVersionMatch(ss.schemas[i].Version)
rightRank += ss.rankByVersionMatch(ss.schemas[j].Version)

// TODO: Rank by hierarchy proximity

// TODO: Rank by version
// TODO: Rank by version (higher wins)

leftRank += ss.rankBySource(ss.schemas[i].Source)
rightRank += ss.rankBySource(ss.schemas[j].Source)
Expand All @@ -404,6 +414,14 @@ func (ss sortableSchemas) rankBySource(src SchemaSource) int {
return 0
}

func (ss sortableSchemas) rankByVersionMatch(v *version.Version) int {
if v != nil && ss.requiredVersion.Check(v) {
return 2
}

return 0
}

func (ss sortableSchemas) Swap(i, j int) {
ss.schemas[i], ss.schemas[j] = ss.schemas[j], ss.schemas[i]
}
Expand Down
10 changes: 5 additions & 5 deletions internal/state/provider_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestStateStore_IncompleteSchema_legacyLookup(t *testing.T) {
// obtaining versions typically takes less time than schema itself
// so we test that "incomplete" state is handled correctly too

err = s.Modules.UpdateTerraformVersion(modPath, testVersion(t, "0.13.0"), pvs, nil)
err = s.Modules.UpdateTerraformAndProviderVersions(modPath, testVersion(t, "0.13.0"), pvs, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -173,7 +173,7 @@ func TestStateStore_AddLocalSchema_duplicateWithVersion(t *testing.T) {
pv := map[tfaddr.Provider]*version.Version{
addr: testVersion(t, "1.2.0"),
}
err = s.Modules.UpdateTerraformVersion(modPath, testVersion(t, "0.12.0"), pv, nil)
err = s.Modules.UpdateTerraformAndProviderVersions(modPath, testVersion(t, "0.12.0"), pv, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -233,7 +233,7 @@ func TestStateStore_AddLocalSchema_duplicateWithVersion(t *testing.T) {
pv = map[tfaddr.Provider]*version.Version{
addr: testVersion(t, "1.5.0"),
}
err = s.Modules.UpdateTerraformVersion(modPath, testVersion(t, "0.12.0"), pv, nil)
err = s.Modules.UpdateTerraformAndProviderVersions(modPath, testVersion(t, "0.12.0"), pv, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -281,7 +281,7 @@ func TestStateStore_AddLocalSchema_versionFirst(t *testing.T) {
pv := map[tfaddr.Provider]*version.Version{
addr: testVersion(t, "1.2.0"),
}
err = s.Modules.UpdateTerraformVersion(modPath, testVersion(t, "0.12.0"), pv, nil)
err = s.Modules.UpdateTerraformAndProviderVersions(modPath, testVersion(t, "0.12.0"), pv, nil)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1009,7 +1009,7 @@ func addAnySchema(t testOrBench, ss *ProviderSchemaStore, ms *ModuleStore, ps *P
pVersions := map[tfaddr.Provider]*version.Version{
ps.Address: ps.Version,
}
err = ms.UpdateTerraformVersion(s.ModulePath, testVersion(t, "0.14.0"), pVersions, nil)
err = ms.UpdateTerraformAndProviderVersions(s.ModulePath, testVersion(t, "0.14.0"), pVersions, nil)
if err != nil {
t.Fatal(err)
}
Expand Down
11 changes: 9 additions & 2 deletions internal/terraform/module/module_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,24 @@ func GetTerraformVersion(ctx context.Context, modStore *state.ModuleStore, modPa

tfExec, err := TerraformExecutorForModule(ctx, mod.Path)
if err != nil {
sErr := modStore.UpdateTerraformVersion(modPath, nil, nil, err)
sErr := modStore.UpdateTerraformAndProviderVersions(modPath, nil, nil, err)
if err != nil {
return sErr
}
return err
}

v, pv, err := tfExec.Version(ctx)

// TODO: Remove and rely purely on ParseProviderVersions
// In most cases we get the provider version from the datadir/lockfile
// but there is an edge case with custom plugin location
// when this may not be available, so leveraging versions
// from "terraform version" accounts for this.
// See https://github.com/hashicorp/terraform-ls/issues/24
pVersions := providerVersionsFromTfVersion(pv)

sErr := modStore.UpdateTerraformVersion(modPath, v, pVersions, err)
sErr := modStore.UpdateTerraformAndProviderVersions(modPath, v, pVersions, err)
if sErr != nil {
return sErr
}
Expand Down
Loading