mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-03 20:50:59 -05:00
add deprecation singleton
This struct tracks and validates deprecations in the context of a graph walk. We need a struct to keep track of the module calls that opt-out of deprecation warnings.
This commit is contained in:
parent
5c898c6d9a
commit
af549ab8c9
6 changed files with 130 additions and 3 deletions
98
internal/deprecation/deprecation.go
Normal file
98
internal/deprecation/deprecation.go
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package deprecation
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/lang/marks"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// Deprecations keeps track of meta-information related to deprecation, e.g. which module calls
|
||||
// suppress deprecation warnings.
|
||||
type Deprecations struct {
|
||||
// Must hold this lock when accessing all fields after this one.
|
||||
mu sync.Mutex
|
||||
|
||||
suppressedModules addrs.Set[addrs.Module]
|
||||
}
|
||||
|
||||
func NewDeprecations() *Deprecations {
|
||||
return &Deprecations{
|
||||
suppressedModules: addrs.MakeSet[addrs.Module](),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deprecations) SuppressModuleCallDeprecation(addr addrs.Module) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
d.suppressedModules.Add(addr)
|
||||
}
|
||||
|
||||
func (d *Deprecations) Validate(value cty.Value, module addrs.Module, rng *hcl.Range) (cty.Value, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
deprecationMarks := marks.GetDeprecationMarks(value)
|
||||
if len(deprecationMarks) == 0 {
|
||||
return value, diags
|
||||
}
|
||||
|
||||
notDeprecatedValue := marks.RemoveDeprecationMarks(value)
|
||||
|
||||
// Check if we need to suppress deprecation warnings for this module call.
|
||||
if d.IsModuleCallDeprecationSuppressed(module) {
|
||||
return notDeprecatedValue, diags
|
||||
}
|
||||
|
||||
for _, depMark := range deprecationMarks {
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagWarning,
|
||||
Summary: "Deprecated value used",
|
||||
Detail: depMark.Message,
|
||||
Subject: rng,
|
||||
})
|
||||
}
|
||||
|
||||
return notDeprecatedValue, diags
|
||||
}
|
||||
|
||||
func (d *Deprecations) ValidateAsConfig(value cty.Value, module addrs.Module) tfdiags.Diagnostics {
|
||||
var diags tfdiags.Diagnostics
|
||||
_, pvms := value.UnmarkDeepWithPaths()
|
||||
|
||||
if len(pvms) == 0 || d.IsModuleCallDeprecationSuppressed(module) {
|
||||
return diags
|
||||
}
|
||||
|
||||
for _, pvm := range pvms {
|
||||
for m := range pvm.Marks {
|
||||
if depMark, ok := m.(marks.DeprecationMark); ok {
|
||||
diags = diags.Append(
|
||||
tfdiags.AttributeValue(
|
||||
tfdiags.Warning,
|
||||
"Deprecated value used",
|
||||
depMark.Message,
|
||||
pvm.Path,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return diags
|
||||
}
|
||||
|
||||
func (d *Deprecations) IsModuleCallDeprecationSuppressed(addr addrs.Module) bool {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
for _, mod := range d.suppressedModules {
|
||||
if mod.TargetContains(addr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/checks"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/deprecation"
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
"github.com/hashicorp/terraform/internal/moduletest/mocking"
|
||||
|
|
@ -201,5 +202,6 @@ func (c *Context) graphWalker(graph *Graph, operation walkOperation, opts *graph
|
|||
functionResults: opts.FunctionResults,
|
||||
Forget: opts.Forget,
|
||||
Actions: actions.NewActions(),
|
||||
Deprecations: deprecation.NewDeprecations(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/hashicorp/terraform/internal/checks"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/deprecation"
|
||||
"github.com/hashicorp/terraform/internal/experiments"
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
|
|
@ -222,6 +223,10 @@ type EvalContext interface {
|
|||
// declarations and their instances that are available in this
|
||||
// EvalContext.
|
||||
Actions() *actions.Actions
|
||||
|
||||
// Deprecations returns the deprecations object that tracks meta-information
|
||||
// about deprecation, e.g. which module calls suppress deprecation warnings.
|
||||
Deprecations() *deprecation.Deprecations
|
||||
}
|
||||
|
||||
func evalContextForModuleInstance(baseCtx EvalContext, addr addrs.ModuleInstance) EvalContext {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/hashicorp/terraform/internal/checks"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/deprecation"
|
||||
"github.com/hashicorp/terraform/internal/experiments"
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
|
|
@ -93,6 +94,7 @@ type BuiltinEvalContext struct {
|
|||
MoveResultsValue refactoring.MoveResults
|
||||
OverrideValues *mocking.Overrides
|
||||
ActionsValue *actions.Actions
|
||||
DeprecationsValue *deprecation.Deprecations
|
||||
}
|
||||
|
||||
// BuiltinEvalContext implements EvalContext
|
||||
|
|
@ -664,3 +666,7 @@ func (ctx *BuiltinEvalContext) ClientCapabilities() providers.ClientCapabilities
|
|||
func (ctx *BuiltinEvalContext) Actions() *actions.Actions {
|
||||
return ctx.ActionsValue
|
||||
}
|
||||
|
||||
func (ctx *BuiltinEvalContext) Deprecations() *deprecation.Deprecations {
|
||||
return ctx.DeprecationsValue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/hashicorp/terraform/internal/checks"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/deprecation"
|
||||
"github.com/hashicorp/terraform/internal/experiments"
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
|
|
@ -170,6 +171,9 @@ type MockEvalContext struct {
|
|||
|
||||
ActionsCalled bool
|
||||
ActionsState *actions.Actions
|
||||
|
||||
DeprecationCalled bool
|
||||
DeprecationState *deprecation.Deprecations
|
||||
}
|
||||
|
||||
// MockEvalContext implements EvalContext
|
||||
|
|
@ -451,3 +455,11 @@ func (c *MockEvalContext) Actions() *actions.Actions {
|
|||
c.ActionsCalled = true
|
||||
return c.ActionsState
|
||||
}
|
||||
|
||||
func (c *MockEvalContext) Deprecations() *deprecation.Deprecations {
|
||||
c.DeprecationCalled = true
|
||||
if c.DeprecationState != nil {
|
||||
return c.DeprecationState
|
||||
}
|
||||
return deprecation.NewDeprecations()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/hashicorp/terraform/internal/collections"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/deprecation"
|
||||
"github.com/hashicorp/terraform/internal/instances"
|
||||
"github.com/hashicorp/terraform/internal/lang"
|
||||
"github.com/hashicorp/terraform/internal/moduletest/mocking"
|
||||
|
|
@ -53,9 +54,11 @@ type ContextGraphWalker struct {
|
|||
PlanTimestamp time.Time
|
||||
Overrides *mocking.Overrides
|
||||
// Forget if set to true will cause the plan to forget all resources. This is
|
||||
// only allowd in the context of a destroy plan.
|
||||
Forget bool
|
||||
Actions *actions.Actions
|
||||
// only allowed in the context of a destroy plan.
|
||||
Forget bool
|
||||
|
||||
Actions *actions.Actions
|
||||
Deprecations *deprecation.Deprecations
|
||||
|
||||
// This is an output. Do not set this, nor read it while a graph walk
|
||||
// is in progress.
|
||||
|
|
@ -144,6 +147,7 @@ func (w *ContextGraphWalker) EvalContext() EvalContext {
|
|||
OverrideValues: w.Overrides,
|
||||
forget: w.Forget,
|
||||
ActionsValue: w.Actions,
|
||||
DeprecationsValue: w.Deprecations,
|
||||
}
|
||||
|
||||
return ctx
|
||||
|
|
|
|||
Loading…
Reference in a new issue