Files
opentf/internal/addrs/check_rule.go
Martin Atkins e74bf2d0a1 go.mod: Use the new "tool" directive
Previously the Go toolchain had no explicit support for "tools" and so we
used the typical Go community workaround of adding "tools.go" files (two,
for some reason) that existed only to trick the Go toolchain into
considering the tools as dependencies we could track in go.mod.

Go 1.24 introduced explicit support for tracking tools as part of go.mod,
and the ability to run those using "go tool" instead of "go run", and so
this commit switches us over to using that strategy for everything we were
previously managing in tools.go.

There are some intentional exceptions here:

- The protobuf-compile script can't use "go tool" or "go run" because the
  tools in question are run only indirectly through protoc. However, we
  do still use the "tool" directive in go.mod to tell the Go toolchain that
  we depend on those tools, so that it'll track which versions we are
  currently using as part of go.mod.
- Our golangci-lint Makefile target uses "go run" to run a specific
  version of golangci-lint. We _intentionally_ don't consider that tool
  to be a direct dependency of OpenTofu because it has a lot of indirect
  dependencies that would pollute our go.mod file. Therefore that continues
  to use "go run" after this commit.
- Both of our tools.go files previously referred to
  github.com/nishanths/exhaustive , but nothing actually appears to be
  using that tool in the current OpenTofu tree, so it's no longer a
  dependency after this commit.

All of the dependencies we have _only_ for tools are now classified as
"indirect" in the go.mod file. This is the default behavior of the Go
toolchain and appears to be motivated by making it clearer that these
modules do not contribute anything to the runtime behavior of OpenTofu.
This also corrected a historical oddity in our go.mod where for some reason
the "indirect" dependencies had been split across two different "require"
directives; they are now all grouped together in a single directive.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
2025-10-10 07:06:56 -03:00

120 lines
3.6 KiB
Go

// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package addrs
import (
"fmt"
)
// CheckRule is the address of a check rule within a checkable object.
//
// This represents the check rule globally within a configuration, and is used
// during graph evaluation to identify a condition result object to update with
// the result of check rule evaluation.
//
// The check address is not distinct from resource traversals, and check rule
// values are not intended to be available to the language, so the address is
// not Referenceable.
//
// Note also that the check address is only relevant within the scope of a run,
// as reordering check blocks between runs will result in their addresses
// changing. CheckRule is therefore for internal use only and should not be
// exposed in durable artifacts such as state snapshots.
type CheckRule struct {
Container Checkable
Type CheckRuleType
Index int
}
func NewCheckRule(container Checkable, typ CheckRuleType, index int) CheckRule {
return CheckRule{
Container: container,
Type: typ,
Index: index,
}
}
func (c CheckRule) String() string {
container := c.Container.String()
switch c.Type {
case ResourcePrecondition:
return fmt.Sprintf("%s.precondition[%d]", container, c.Index)
case ResourcePostcondition:
return fmt.Sprintf("%s.postcondition[%d]", container, c.Index)
case OutputPrecondition:
return fmt.Sprintf("%s.precondition[%d]", container, c.Index)
case CheckDataResource:
return fmt.Sprintf("%s.data[%d]", container, c.Index)
case CheckAssertion:
return fmt.Sprintf("%s.assert[%d]", container, c.Index)
case InputValidation:
return fmt.Sprintf("%s.validation[%d]", container, c.Index)
default:
// This should not happen
return fmt.Sprintf("%s.condition[%d]", container, c.Index)
}
}
func (c CheckRule) UniqueKey() UniqueKey {
return checkRuleKey{
ContainerKey: c.Container.UniqueKey(),
Type: c.Type,
Index: c.Index,
}
}
type checkRuleKey struct {
ContainerKey UniqueKey
Type CheckRuleType
Index int
}
func (k checkRuleKey) uniqueKeySigil() {}
// CheckRuleType describes a category of check. We use this only to establish
// uniqueness for Check values, and do not expose this concept of "check types"
// (which is subject to change in future) in any durable artifacts such as
// state snapshots.
//
// (See [CheckableKind] for an enumeration that we _do_ use externally, to
// describe the type of object being checked rather than the type of the check
// itself.)
type CheckRuleType int
//go:generate go tool golang.org/x/tools/cmd/stringer -type=CheckRuleType check_rule.go
const (
InvalidCondition CheckRuleType = 0
ResourcePrecondition CheckRuleType = 1
ResourcePostcondition CheckRuleType = 2
OutputPrecondition CheckRuleType = 3
CheckDataResource CheckRuleType = 4
CheckAssertion CheckRuleType = 5
InputValidation CheckRuleType = 6
)
// Description returns a human-readable description of the check type. This is
// presented in the user interface through a diagnostic summary.
func (c CheckRuleType) Description() string {
switch c {
case ResourcePrecondition:
return "Resource precondition"
case ResourcePostcondition:
return "Resource postcondition"
case OutputPrecondition:
return "Module output value precondition"
case CheckDataResource:
return "Check block data resource"
case CheckAssertion:
return "Check block assertion"
case InputValidation:
return "Input variable validation"
default:
// This should not happen
return "Condition"
}
}