Adds source context for the 'insufficient feature blocks' error (#1777)

Signed-off-by: Andrew Hayes <andrew.hayes@harness.io>
This commit is contained in:
Andrew Hayes 2024-07-09 09:56:07 +01:00 committed by GitHub
parent fcfeb6dd60
commit 3ef6d45afe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 140 additions and 2 deletions

View File

@ -18,7 +18,7 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/zclconf/go-cty/cty"
// "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2"
"github.com/opentofu/opentofu/internal/addrs"
"github.com/opentofu/opentofu/internal/checks"
@ -7327,3 +7327,89 @@ func TestContext2Plan_importResourceWithSensitiveDataSource(t *testing.T) {
}
})
}
func TestContext2Plan_insuffient_block(t *testing.T) {
type testcase struct {
filename string
start hcl.Pos
end hcl.Pos
}
tests := map[string]testcase{
"insufficient-features-blocks-aliased-provider": {
filename: "provider[\"registry.opentofu.org/hashicorp/test\"] with no configuration",
start: hcl.InitialPos,
end: hcl.InitialPos,
},
"insufficient-features-blocks-nested_module": {
filename: "provider[\"registry.opentofu.org/hashicorp/test\"] with no configuration",
start: hcl.InitialPos,
end: hcl.InitialPos,
},
"insufficient-features-blocks-no-feats": {
filename: "testdata/insufficient-features-blocks-no-feats/main.tf",
start: hcl.Pos{Line: 9, Column: 17, Byte: 146},
end: hcl.Pos{Line: 9, Column: 17, Byte: 146},
},
}
for testName, tc := range tests {
t.Run(testName, func(t *testing.T) {
m := testModule(t, testName)
p := mockProviderWithFeaturesBlock()
ctx := testContext2(t, &ContextOpts{
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})
_, diags := ctx.Plan(m, states.NewState(), DefaultPlanOpts)
var expectedDiags tfdiags.Diagnostics
expectedDiags = expectedDiags.Append(
&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Insufficient features blocks",
Detail: "At least 1 \"features\" blocks are required.",
Subject: &hcl.Range{
Filename: tc.filename,
Start: tc.start,
End: tc.end,
},
},
)
assertDiagnosticsMatch(t, diags, expectedDiags)
})
}
}
func mockProviderWithFeaturesBlock() *MockProvider {
return &MockProvider{
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
Provider: providers.Schema{Block: featuresBlockTestSchema()},
ResourceTypes: map[string]providers.Schema{
"test_object": {Block: simpleTestSchema()},
},
},
}
}
func featuresBlockTestSchema() *configschema.Block {
return &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"test_string": {
Type: cty.String,
Optional: true,
},
},
BlockTypes: map[string]*configschema.NestedBlock{
"features": {
MinItems: 1,
MaxItems: 1,
Nesting: configschema.NestingList,
},
},
}
}

View File

@ -10,9 +10,11 @@ import (
"log"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
"github.com/opentofu/opentofu/internal/addrs"
"github.com/opentofu/opentofu/internal/configs"
"github.com/opentofu/opentofu/internal/configs/hcl2shim"
"github.com/opentofu/opentofu/internal/providers"
)
@ -40,7 +42,8 @@ func buildProviderConfig(ctx EvalContext, addr addrs.AbsProviderConfig, config *
return inputBody
default:
log.Printf("[TRACE] buildProviderConfig for %s: no configuration at all", addr)
return hcl.EmptyBody()
addr := fmt.Sprintf("%s with no configuration", addr)
return hcl2shim.SynthBody(addr, make(map[string]cty.Value))
}
}

View File

@ -0,0 +1,16 @@
terraform {
required_providers {
test = {
source = "registry.opentofu.org/hashicorp/test"
}
}
}
provider "test" {
alias = "test2"
test_string = "config"
features {}
}
resource "test_object" "a" {
}

View File

@ -0,0 +1,11 @@
terraform {
required_providers {
test = {
source = "registry.opentofu.org/hashicorp/test"
}
}
}
module "nested" {
source = "./nested"
}

View File

@ -0,0 +1,8 @@
provider "test" {
alias = "test2"
test_string = "config"
features {}
}
resource "test_object" "a" {
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
test = {
source = "registry.opentofu.org/hashicorp/test"
}
}
}
provider "test" {
test_string = "config"
}
resource "test_object" "a" {
}