Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanck committed Oct 25, 2024
1 parent d73372a commit 4e1c213
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 3 deletions.
22 changes: 22 additions & 0 deletions internal/configs/named_values.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ type Output struct {
Sensitive bool
Ephemeral bool

Deprecated bool
DeprecatedMessage string

Preconditions []*CheckRule

DescriptionSet bool
Expand Down Expand Up @@ -402,6 +405,22 @@ func decodeOutputBlock(block *hcl.Block, override bool) (*Output, hcl.Diagnostic
o.EphemeralSet = true
}

if attr, exists := content.Attributes["deprecated"]; exists {
msg, msgDiags := attr.Expr.Value(nil)
diags = append(diags, msgDiags...)
if msg.Type() != cty.String || !msg.IsWhollyKnown() || msg.IsNull() {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Deprecated message must be a known, non-empty string",
Detail: "The deprecated argument must be a known, non-empty string.",
Subject: &attr.Range,
})
} else {
o.DeprecatedMessage = msg.AsString()
o.Deprecated = true
}
}

if attr, exists := content.Attributes["depends_on"]; exists {
deps, depsDiags := DecodeDependsOn(attr)
diags = append(diags, depsDiags...)
Expand Down Expand Up @@ -525,6 +544,9 @@ var outputBlockSchema = &hcl.BodySchema{
{
Name: "ephemeral",
},
{
Name: "deprecated",
},
},
Blocks: []hcl.BlockHeaderSchema{
{Type: "precondition"},
Expand Down
27 changes: 27 additions & 0 deletions internal/configs/named_values_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,30 @@ func TestVariableInvalidDefault(t *testing.T) {
}
}
}

func TestOutputDeprecation(t *testing.T) {
src := `
output "foo" {
value = "bar"
deprecated = "This output is deprecated"
}
`

hclF, diags := hclsyntax.ParseConfig([]byte(src), "test.tf", hcl.InitialPos)
if diags.HasErrors() {
t.Fatal(diags.Error())
}

b, diags := parseConfigFile(hclF.Body, nil, false, false)
if diags.HasErrors() {
t.Fatalf("unexpected error: %q", diags)
}

if b.Outputs[0].Deprecated != true {
t.Fatalf("expected output to be deprecated")
}

if b.Outputs[0].DeprecatedMessage != "This output is deprecated" {
t.Fatalf("expected output to have deprecation message")
}
}
56 changes: 56 additions & 0 deletions internal/terraform/context_plan2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6068,3 +6068,59 @@ data "test_data_source" "foo" {
_, diags := ctx.Plan(m, states.NewState(), SimplePlanOpts(plans.NormalMode, testInputValuesUnset(m.Module.Variables)))
assertNoErrors(t, diags)
}

func TestContext2Plan_deprecated_output(t *testing.T) {
m := testModuleInline(t, map[string]string{
"mod/main.tf": `
output "old" {
deprecated = "Please stop using this"
value = "old"
}
output "old-and-unused" {
deprecated = "This should not show up in the errors, we are not using it"
value = "old"
}
output "new" {
value = "foo"
}
`,
"main.tf": `
module "mod" {
source = "./mod"
}
resource "test_resource" "test" {
attr = module.mod.old
}
resource "test_resource" "test2" {
attr = module.mod.new
}
`,
})

p := new(testing_provider.MockProvider)
p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(&providerSchema{
ResourceTypes: map[string]*configschema.Block{
"test_resource": {
Attributes: map[string]*configschema.Attribute{
"attr": {
Type: cty.String,
Computed: true,
},
},
},
},
})

ctx := testContext2(t, &ContextOpts{
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
})

_, diags := ctx.Plan(m, states.NewState(), SimplePlanOpts(plans.NormalMode, testInputValuesUnset(m.Module.Variables)))
assertDiagnosticsMatch(t, diags, []tfdiags.Diagnostic{})
}
24 changes: 24 additions & 0 deletions internal/terraform/node_resource_abstract.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,30 @@ func (n *NodeAbstractResource) readResourceInstanceStateDeposed(ctx EvalContext,
return obj, diags
}

func (n *NodeAbstractResource) validateUsageOfDeprecatedOutputs(ctx EvalContext) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics

fmt.Printf("\n\t n.References() --> %#v \n", n.References())
for _, ref := range n.References() {
fmt.Printf("\n\t ref --> %#v \n", ref)
if out, ok := ref.Subject.(addrs.ModuleCallInstanceOutput); ok {
fmt.Printf("\n\t out --> %#v \n", out)

// TODO: Find the configuration for the output
// Check if the output is deprecated and emit this diagnostic

// diags = diags.Append(&hcl.Diagnostic{
// Severity: hcl.DiagWarning,
// Summary: "Usage of deprecated output",
// Detail: n.Config.DeprecatedMessage,
// Subject: ref.SourceRange.ToHCL().Ptr(),
// })
}
}

return diags
}

// graphNodesAreResourceInstancesInDifferentInstancesOfSameModule is an
// annoyingly-task-specific helper function that returns true if and only if
// the following conditions hold:
Expand Down
1 change: 1 addition & 0 deletions internal/terraform/node_resource_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func (n *nodeExpandPlannableResource) DynamicExpand(ctx EvalContext) (*Graph, tf

g, expandDiags := n.dynamicExpand(ctx, moduleInstances, imports)
diags = diags.Append(expandDiags)

return g, diags
}

Expand Down
10 changes: 7 additions & 3 deletions internal/terraform/node_resource_plan_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,18 @@ var (
func (n *NodePlannableResourceInstance) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
addr := n.ResourceInstanceAddr()

var diags tfdiags.Diagnostics
// TODO: Find better place
diags = diags.Append(diags, n.validateUsageOfDeprecatedOutputs(ctx))

// Eval info is different depending on what kind of resource this is
switch addr.Resource.Resource.Mode {
case addrs.ManagedResourceMode:
return n.managedResourceExecute(ctx)
return diags.Append(diags, n.managedResourceExecute(ctx))
case addrs.DataResourceMode:
return n.dataResourceExecute(ctx)
return diags.Append(diags, n.dataResourceExecute(ctx))
case addrs.EphemeralResourceMode:
return n.ephemeralResourceExecute(ctx)
return diags.Append(diags, n.ephemeralResourceExecute(ctx))
default:
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
}
Expand Down
2 changes: 2 additions & 0 deletions internal/terraform/node_resource_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,8 @@ func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diag
diags = diags.Append(resp.Diagnostics.InConfigBody(n.Config.Config, n.Addr.String()))
}

diags = diags.Append(diags, n.validateUsageOfDeprecatedOutputs(ctx))

return diags
}

Expand Down

0 comments on commit 4e1c213

Please sign in to comment.