diff --git a/.changes/v1.14/BUG FIXES-20251104-122322.yaml b/.changes/v1.14/BUG FIXES-20251104-122322.yaml new file mode 100644 index 0000000000..f8475db0aa --- /dev/null +++ b/.changes/v1.14/BUG FIXES-20251104-122322.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'query: improve error handling for missing identity schemas' +time: 2025-11-04T12:23:22.096828+01:00 +custom: + Issue: "37863" diff --git a/internal/plugin/grpc_provider.go b/internal/plugin/grpc_provider.go index 3f8251b4a1..9874b1abdf 100644 --- a/internal/plugin/grpc_provider.go +++ b/internal/plugin/grpc_provider.go @@ -1321,7 +1321,7 @@ func (p *GRPCProvider) ListResource(r providers.ListResourceRequest) providers.L resourceSchema, ok := schema.ResourceTypes[r.TypeName] if !ok || resourceSchema.Identity == nil { - resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("identity schema not found for resource type %s", r.TypeName)) + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("Identity schema not found for resource type %s; this is a bug in the provider - please report it there", r.TypeName)) return resp } diff --git a/internal/plugin6/grpc_provider.go b/internal/plugin6/grpc_provider.go index 0ab7da98b1..b01aca3f99 100644 --- a/internal/plugin6/grpc_provider.go +++ b/internal/plugin6/grpc_provider.go @@ -1317,7 +1317,7 @@ func (p *GRPCProvider) ListResource(r providers.ListResourceRequest) providers.L resourceSchema, ok := schema.ResourceTypes[r.TypeName] if !ok || resourceSchema.Identity == nil { - resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("identity schema not found for resource type %s", r.TypeName)) + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("Identity schema not found for resource type %s; this is a bug in the provider - please report it there", r.TypeName)) return resp } diff --git a/internal/terraform/context_plan_query_test.go b/internal/terraform/context_plan_query_test.go index 75b016003f..79e4f304f3 100644 --- a/internal/terraform/context_plan_query_test.go +++ b/internal/terraform/context_plan_query_test.go @@ -683,12 +683,10 @@ func TestContext2Plan_queryList(t *testing.T) { if tc.transformSchema != nil { tc.transformSchema(provider.GetProviderSchemaResponse) } - var requestConfigs = make(map[string]cty.Value) provider.ListResourceFn = func(request providers.ListResourceRequest) providers.ListResourceResponse { if request.Config.IsNull() || request.Config.GetAttr("config").IsNull() { t.Fatalf("config should never be null, got null for %s", request.TypeName) } - requestConfigs[request.TypeName] = request.Config return listResourceFn(request) } @@ -948,6 +946,55 @@ func TestContext2Plan_queryListArgs(t *testing.T) { } } +func TestContext2Plan_queryListDiags(t *testing.T) { + configFiles := map[string]string{} + configFiles["main.tf"] = ` + terraform { + required_providers { + test = { + source = "hashicorp/test" + version = "1.0.0" + } + } + }` + configFiles["main.tfquery.hcl"] = ` + list "test_resource" "test1" { + provider = test + }` + mod := testModuleInline(t, configFiles, configs.MatchQueryFiles()) + + providerAddr := addrs.NewDefaultProvider("test") + provider := testProvider("test") + provider.ConfigureProvider(providers.ConfigureProviderRequest{}) + provider.GetProviderSchemaResponse = getListProviderSchemaResp() + provider.ListResourceFn = func(request providers.ListResourceRequest) providers.ListResourceResponse { + if request.Config.IsNull() || request.Config.GetAttr("config").IsNull() { + t.Fatalf("config should never be null, got null for %s", request.TypeName) + } + + resp := providers.ListResourceResponse{} + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("Identity schema not found for resource type %s; this is a bug in the provider - please report it there", request.TypeName)) + + return resp + } + + ctx, diags := NewContext(&ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + providerAddr: testProviderFuncFixed(provider), + }, + }) + tfdiags.AssertNoDiagnostics(t, diags) + + _, diags = ctx.Plan(mod, states.NewState(), &PlanOpts{ + Mode: plans.NormalMode, + SetVariables: testInputValuesUnset(mod.Module.Variables), + Query: true, + }) + if len(diags) != 1 { + t.Fatalf("expected 1 diagnostics, got %d \n - diags: %s", len(diags), diags) + } +} + // getListProviderSchemaResp returns a mock provider schema response for testing list resources. // THe schema returned here is a mock of what the internal protobuf layer would return // for a provider that supports list resources. diff --git a/internal/terraform/node_resource_plan_instance_query.go b/internal/terraform/node_resource_plan_instance_query.go index c1ddf131fc..6e099b14f7 100644 --- a/internal/terraform/node_resource_plan_instance_query.go +++ b/internal/terraform/node_resource_plan_instance_query.go @@ -113,6 +113,10 @@ func (n *NodePlannableResourceInstance) listResourceExecute(ctx EvalContext) (di Limit: limit, IncludeResourceObject: includeRsc, }) + diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config, n.Addr.String())) + if diags.HasErrors() { + return diags + } results := plans.QueryResults{ Value: resp.Result, } @@ -132,10 +136,6 @@ func (n *NodePlannableResourceInstance) listResourceExecute(ctx EvalContext) (di ctx.Hook(func(h Hook) (HookAction, error) { return h.PostListQuery(rId, results, identityVersion) }) - diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config, n.Addr.String())) - if diags.HasErrors() { - return diags - } query := &plans.QueryInstance{ Addr: n.Addr,