mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Fix: Global provider schema cache is never used (#719)
Signed-off-by: RLRabinowitz <rlrabinowitz2@gmail.com>
This commit is contained in:
parent
f661d47a29
commit
03c8f6cebd
@ -78,8 +78,8 @@ func (p *GRPCProvider) GetProviderSchema() (resp providers.GetProviderSchemaResp
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// check the global cache if we can
|
||||
if !p.Addr.IsZero() && resp.ServerCapabilities.GetProviderSchemaOptional {
|
||||
// check the global cache
|
||||
if !p.Addr.IsZero() {
|
||||
if resp, ok := providers.SchemaCache.Get(p.Addr); ok {
|
||||
return resp
|
||||
}
|
||||
@ -141,7 +141,7 @@ func (p *GRPCProvider) GetProviderSchema() (resp providers.GetProviderSchemaResp
|
||||
}
|
||||
|
||||
// set the global cache if we can
|
||||
if !p.Addr.IsZero() {
|
||||
if !p.Addr.IsZero() && resp.ServerCapabilities.GetProviderSchemaOptional {
|
||||
providers.SchemaCache.Set(p.Addr, resp)
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
|
||||
@ -125,6 +127,100 @@ func TestGRPCProvider_GetSchema_GRPCError(t *testing.T) {
|
||||
checkDiagsHasError(t, resp.Diagnostics)
|
||||
}
|
||||
|
||||
func TestGRPCProvider_GetSchema_GlobalCacheEnabled(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
client := mockproto.NewMockProviderClient(ctrl)
|
||||
// The SchemaCache is global and is saved between test runs
|
||||
providers.SchemaCache = providers.NewMockSchemaCache()
|
||||
|
||||
providerAddr := addrs.Provider{
|
||||
Namespace: "namespace",
|
||||
Type: "type",
|
||||
}
|
||||
|
||||
mockedProviderResponse := &proto.Schema{Version: 2, Block: &proto.Schema_Block{}}
|
||||
|
||||
client.EXPECT().GetSchema(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(1).Return(&proto.GetProviderSchema_Response{
|
||||
Provider: mockedProviderResponse,
|
||||
ServerCapabilities: &proto.GetProviderSchema_ServerCapabilities{GetProviderSchemaOptional: true},
|
||||
}, nil)
|
||||
|
||||
// Run GetProviderTwice, expect GetSchema to be called once
|
||||
// Re-initialize the provider before each run to avoid usage of the local cache
|
||||
p := &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp := p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
|
||||
p = &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp = p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGRPCProvider_GetSchema_GlobalCacheDisabled(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
client := mockproto.NewMockProviderClient(ctrl)
|
||||
// The SchemaCache is global and is saved between test runs
|
||||
providers.SchemaCache = providers.NewMockSchemaCache()
|
||||
|
||||
providerAddr := addrs.Provider{
|
||||
Namespace: "namespace",
|
||||
Type: "type",
|
||||
}
|
||||
|
||||
mockedProviderResponse := &proto.Schema{Version: 2, Block: &proto.Schema_Block{}}
|
||||
|
||||
client.EXPECT().GetSchema(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&proto.GetProviderSchema_Response{
|
||||
Provider: mockedProviderResponse,
|
||||
ServerCapabilities: &proto.GetProviderSchema_ServerCapabilities{GetProviderSchemaOptional: false},
|
||||
}, nil)
|
||||
|
||||
// Run GetProviderTwice, expect GetSchema to be called once
|
||||
// Re-initialize the provider before each run to avoid usage of the local cache
|
||||
p := &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp := p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
|
||||
p = &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp = p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that provider error diagnostics are returned early.
|
||||
// Reference: https://github.com/hashicorp/terraform/issues/31047
|
||||
func TestGRPCProvider_GetSchema_ResponseErrorDiagnostic(t *testing.T) {
|
||||
|
@ -78,8 +78,8 @@ func (p *GRPCProvider) GetProviderSchema() (resp providers.GetProviderSchemaResp
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
// check the global cache if we can
|
||||
if !p.Addr.IsZero() && resp.ServerCapabilities.GetProviderSchemaOptional {
|
||||
// check the global cache
|
||||
if !p.Addr.IsZero() {
|
||||
if resp, ok := providers.SchemaCache.Get(p.Addr); ok {
|
||||
return resp
|
||||
}
|
||||
@ -141,7 +141,7 @@ func (p *GRPCProvider) GetProviderSchema() (resp providers.GetProviderSchemaResp
|
||||
}
|
||||
|
||||
// set the global cache if we can
|
||||
if !p.Addr.IsZero() {
|
||||
if !p.Addr.IsZero() && resp.ServerCapabilities.GetProviderSchemaOptional {
|
||||
providers.SchemaCache.Set(p.Addr, resp)
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
@ -163,6 +165,100 @@ func TestGRPCProvider_GetSchema_ResponseErrorDiagnostic(t *testing.T) {
|
||||
checkDiagsHasError(t, resp.Diagnostics)
|
||||
}
|
||||
|
||||
func TestGRPCProvider_GetSchema_GlobalCacheEnabled(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
client := mockproto.NewMockProviderClient(ctrl)
|
||||
// The SchemaCache is global and is saved between test runs
|
||||
providers.SchemaCache = providers.NewMockSchemaCache()
|
||||
|
||||
providerAddr := addrs.Provider{
|
||||
Namespace: "namespace",
|
||||
Type: "type",
|
||||
}
|
||||
|
||||
mockedProviderResponse := &proto.Schema{Version: 2, Block: &proto.Schema_Block{}}
|
||||
|
||||
client.EXPECT().GetProviderSchema(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(1).Return(&proto.GetProviderSchema_Response{
|
||||
Provider: mockedProviderResponse,
|
||||
ServerCapabilities: &proto.GetProviderSchema_ServerCapabilities{GetProviderSchemaOptional: true},
|
||||
}, nil)
|
||||
|
||||
// Run GetProviderTwice, expect GetSchema to be called once
|
||||
// Re-initialize the provider before each run to avoid usage of the local cache
|
||||
p := &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp := p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
|
||||
p = &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp = p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGRPCProvider_GetSchema_GlobalCacheDisabled(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
client := mockproto.NewMockProviderClient(ctrl)
|
||||
// The SchemaCache is global and is saved between test runs
|
||||
providers.SchemaCache = providers.NewMockSchemaCache()
|
||||
|
||||
providerAddr := addrs.Provider{
|
||||
Namespace: "namespace",
|
||||
Type: "type",
|
||||
}
|
||||
|
||||
mockedProviderResponse := &proto.Schema{Version: 2, Block: &proto.Schema_Block{}}
|
||||
|
||||
client.EXPECT().GetProviderSchema(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Times(2).Return(&proto.GetProviderSchema_Response{
|
||||
Provider: mockedProviderResponse,
|
||||
ServerCapabilities: &proto.GetProviderSchema_ServerCapabilities{GetProviderSchemaOptional: false},
|
||||
}, nil)
|
||||
|
||||
// Run GetProviderTwice, expect GetSchema to be called once
|
||||
// Re-initialize the provider before each run to avoid usage of the local cache
|
||||
p := &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp := p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
|
||||
p = &GRPCProvider{
|
||||
client: client,
|
||||
Addr: providerAddr,
|
||||
}
|
||||
resp = p.GetProviderSchema()
|
||||
|
||||
checkDiags(t, resp.Diagnostics)
|
||||
if !cmp.Equal(resp.Provider.Version, mockedProviderResponse.Version) {
|
||||
t.Fatal(cmp.Diff(resp.Provider.Version, mockedProviderResponse.Version))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGRPCProvider_PrepareProviderConfig(t *testing.T) {
|
||||
client := mockProviderClient(t)
|
||||
p := &GRPCProvider{
|
||||
|
9
internal/providers/mock_schema_cache.go
Normal file
9
internal/providers/mock_schema_cache.go
Normal file
@ -0,0 +1,9 @@
|
||||
package providers
|
||||
|
||||
import "github.com/opentofu/opentofu/internal/addrs"
|
||||
|
||||
func NewMockSchemaCache() *schemaCache {
|
||||
return &schemaCache{
|
||||
m: make(map[addrs.Provider]ProviderSchema),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user