Skip to content
Draft
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
add deprecation marks for resource attributes and blocks
  • Loading branch information
DanielMSchmidt committed Dec 12, 2025
commit 19a73f257bea70696c1bf2434c777fcad755e252
21 changes: 0 additions & 21 deletions internal/configs/configschema/validate_traversal.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,27 +77,6 @@ func (b *Block) StaticValidateTraversal(traversal hcl.Traversal) tfdiags.Diagnos
}

if attrS, exists := b.Attributes[name]; exists {
// Check for Deprecated status of this attribute.
// We currently can't provide the user with any useful guidance because
// the deprecation string is not part of the schema, but we can at
// least warn them.
//
// This purposely does not attempt to recurse into nested attribute
// types. Because nested attribute values are often not accessed via a
// direct traversal to the leaf attributes, we cannot reliably detect
// if a nested, deprecated attribute value is actually used from the
// traversal alone. More precise detection of deprecated attributes
// would require adding metadata like marks to the cty value itself, to
// be caught during evaluation.
if attrS.Deprecated {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagWarning,
Summary: `Deprecated attribute`,
Detail: fmt.Sprintf(`The attribute %q is deprecated. Refer to the provider documentation for details.`, name),
Subject: next.SourceRange().Ptr(),
})
}

// For attribute validation we will just apply the rest of the
// traversal to an unknown value of the attribute type and pass
// through HCL's own errors, since we don't want to replicate all
Expand Down
4 changes: 0 additions & 4 deletions internal/configs/configschema/validate_traversal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,6 @@ func TestStaticValidateTraversal(t *testing.T) {
`obj.nested_map["key"].optional`,
``,
},
{
`obj.deprecated`,
`Deprecated attribute: The attribute "deprecated" is deprecated. Refer to the provider documentation for details.`,
},
}

for _, test := range tests {
Expand Down
52 changes: 52 additions & 0 deletions internal/deprecation/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package deprecation

import (
"github.com/hashicorp/terraform/internal/configs/configschema"
"github.com/hashicorp/terraform/internal/lang/marks"
"github.com/zclconf/go-cty/cty"
)

// MarkDeprecatedValues inspects the given cty.Value according to the given
// configschema.Block schema, and marks any deprecated attributes or blocks
// found within the value with deprecation marks.
// It works based on the given cty.Value's structure matching the given schema.
func MarkDeprecatedValues(val cty.Value, schema *configschema.Block) cty.Value {
if schema == nil {
return val
}
newVal := val

// Check if the block is deprecated
if schema.Deprecated {
newVal = newVal.Mark(marks.NewDeprecation("deprecated resource block used"))
}

if !newVal.IsKnown() {
return newVal
}

// Even if the block itself is not deprecated, its attributes might be
// deprecated as well
if val.Type().IsObjectType() || val.Type().IsMapType() || val.Type().IsCollectionType() {
// We ignore the error, so errors are not allowed in the transform function
newVal, _ = cty.Transform(newVal, func(p cty.Path, v cty.Value) (cty.Value, error) {

attr := schema.AttributeByPath(p)
if attr != nil && attr.Deprecated {
v = v.Mark(marks.NewDeprecation("deprecated resource attribute used"))
}

block := schema.BlockByPath(p)
if block != nil && block.Deprecated {
v = v.Mark(marks.NewDeprecation("deprecated resource block used"))
}

return v, nil
})
}

return newVal
}
Loading
Loading