states: Two-level representation of check results

A significant goal of the design changes around checks in earlier commits
(with the introduction of package "checks") was to allow us to
differentiate between a configuration object that we didn't expand at all
due to an upstream error, which has _unknown_ check status, and a
configuration object that expanded to zero dynamic objects, which
therefore has a _passing_ check status.

However, our initial lowering of checks.State into states.CheckResults
stayed with the older model of just recording each leaf check in isolation,
without any tracking of the containers.

This commit therefore lightly reworks our representation of check results
in the state and plan with two main goals:
- The results are grouped by the static configuration object they came
  from, and we capture an aggregate status for each of those so that
  we can differentiate an unknown aggregate result from a passing
  aggregate result which has zero dynamic associated objects.
- The granularity of results is whole checkable objects rather than
  individual checks, because checkable objects have durable addresses
  between runs, but individual checks for an object are more of a
  syntactic convenience to make it easier for module authors to declare
  many independent conditions that each have their own error messages.

Since v1.2 exposed some details of our checks model into the JSON plan
output there are some unanswered questions here about how we can shift to
reporting in the two-level heirarchy described above. For now I've
preserved structural compatibility but not semantic compatibility: any
parser that was written against that format should still function but will
now see fewer results. We'll revisit this in a later commit and consider
other structures and what to do about our compatibility constraint on the
v1.2 structure.

Otherwise though, this is an internal-only change which preserves all of
the existing main behaviors of conditions as before, and just gets us
ready to build user-facing features in terms of this new structure.
This commit is contained in:
Martin Atkins 2022-06-16 11:09:19 -07:00
parent 3785619f93
commit 9e4861adbb
10 changed files with 770 additions and 648 deletions

View File

@ -2,6 +2,7 @@ package checks
import (
"fmt"
"sort"
"sync"
"github.com/hashicorp/terraform/internal/addrs"
@ -109,54 +110,26 @@ func (c *State) AllConfigAddrs() addrs.Set[addrs.ConfigCheckable] {
return c.statuses.Keys()
}
// AllObjectAddrs returns all of the addresses of individual checkable objects
// that were registered as part of the Terraform Core operation that this
// object is describing.
// ObjectAddrs returns the addresses of individual checkable objects belonging
// to the configuration object with the given address.
//
// If the corresponding Terraform Core operation returned an error or was
// using targeting to exclude some objects from the graph then this may not
// include declared objects for all of the expected configuration objects.
func (c *State) AllObjectAddrs() addrs.Set[addrs.Checkable] {
// This will panic if the given address isn't a known configuration object
// that has checks.
func (c *State) ObjectAddrs(configAddr addrs.ConfigCheckable) addrs.Set[addrs.Checkable] {
c.mu.Lock()
defer c.mu.Unlock()
st, ok := c.statuses.GetOk(configAddr)
if !ok {
panic(fmt.Sprintf("unknown configuration object %s", configAddr))
}
ret := addrs.MakeSet[addrs.Checkable]()
for _, st := range c.statuses.Elems {
for _, elem := range st.Value.objects.Elems {
ret.Add(elem.Key)
}
for _, elem := range st.objects.Elems {
ret.Add(elem.Key)
}
return ret
}
// OverallCheckStatus returns a summarization of all of the check results
// across the entire configuration as a single unified status.
//
// This is a reasonable approximation for deciding an overall result for an
// automated testing scenario.
func (c *State) OverallCheckStatus() Status {
c.mu.Lock()
defer c.mu.Unlock()
errorCount := 0
failCount := 0
unknownCount := 0
for _, elem := range c.statuses.Elems {
aggrStatus := c.aggregateCheckStatus(elem.Key)
switch aggrStatus {
case StatusPass:
// ok
case StatusFail:
failCount++
case StatusError:
errorCount++
default:
unknownCount++
}
}
return summarizeCheckStatuses(errorCount, failCount, unknownCount)
}
// AggregateCheckStatus returns a summarization of all of the check results
@ -168,13 +141,6 @@ func (c *State) AggregateCheckStatus(addr addrs.ConfigCheckable) Status {
c.mu.Lock()
defer c.mu.Unlock()
return c.aggregateCheckStatus(addr)
}
// aggregateCheckStatus is the main implementation of the public
// AggregateCheckStatus, which assumes that the caller has already acquired
// the mutex before calling.
func (c *State) aggregateCheckStatus(addr addrs.ConfigCheckable) Status {
st, ok := c.statuses.GetOk(addr)
if !ok {
panic(fmt.Sprintf("request for status of unknown configuration object %s", addr))
@ -183,6 +149,9 @@ func (c *State) aggregateCheckStatus(addr addrs.ConfigCheckable) Status {
if st.objects.Elems == nil {
// If we don't even know how many objects we have for this
// configuration construct then that summarizes as unknown.
// (Note: this is different than Elems being a non-nil empty map,
// which means that we know there are zero objects and therefore
// the aggregate result will be pass to pass below.)
return StatusUnknown
}
@ -255,45 +224,49 @@ func (c *State) ObjectCheckStatus(addr addrs.Checkable) Status {
return summarizeCheckStatuses(errorCount, failCount, unknownCount)
}
// AllCheckStatuses returns a flat map of all of the statuses of all of the
// checks associated with all of the objects know to the reciever.
// ObjectFailureMessages returns the zero or more failure messages reported
// for the object with the given address.
//
// If the corresponding Terraform Core operation returned an error or was
// using targeting to exclude some objects from the graph then this may not
// include declared objects for all of the expected configuration objects.
func (c *State) AllCheckStatuses() addrs.Map[addrs.Check, Status] {
c.mu.Lock()
defer c.mu.Unlock()
// Failure messages are recorded only for checks whose status is StatusFail,
// but since this aggregates together the results of all of the checks
// on the given object it's possible for there to be a mixture of failures
// and errors at the same time, which would aggregate as StatusError in
// ObjectCheckStatus's result because errors are defined as "stronger"
// than failures.
func (c *State) ObjectFailureMessages(addr addrs.Checkable) []string {
var ret []string
ret := addrs.MakeMap[addrs.Check, Status]()
configAddr := addr.ConfigCheckable()
for _, configElem := range c.statuses.Elems {
for _, objectElem := range configElem.Value.objects.Elems {
objectAddr := objectElem.Key
for checkType, checks := range objectElem.Value {
for idx, status := range checks {
checkAddr := addrs.Check{
Container: objectAddr,
Type: checkType,
Index: idx,
}
ret.Put(checkAddr, status)
st, ok := c.statuses.GetOk(configAddr)
if !ok {
panic(fmt.Sprintf("request for status of unknown object %s", addr))
}
if st.objects.Elems == nil {
panic(fmt.Sprintf("request for status of %s before establishing the checkable objects for %s", addr, configAddr))
}
checksByType, ok := st.objects.GetOk(addr)
if !ok {
panic(fmt.Sprintf("request for status of unknown object %s", addr))
}
for checkType, checks := range checksByType {
for i, status := range checks {
if status == StatusFail {
checkAddr := addrs.NewCheck(addr, checkType, i)
msg := c.failureMsgs.Get(checkAddr)
if msg != "" {
ret = append(ret, msg)
}
}
}
}
return ret
}
// We always return the messages in a lexical sort order just so that
// it'll be consistent between runs if we still have the same problems.
sort.Strings(ret)
// CheckFailureMessage gets the failure message associated with the given
// check, if any.
//
// Only failed checks (StatusFail) can have error messages. The result is the
// empty string if the given check either didn't fail or failed without an
// error message.
func (c *State) CheckFailureMessage(addr addrs.Check) string {
return c.failureMsgs.Get(addr)
return ret
}
func summarizeCheckStatuses(errorCount, failCount, unknownCount int) Status {

View File

@ -117,10 +117,6 @@ func TestChecksHappyPath(t *testing.T) {
// Everything should start with status unknown.
if got, want := checks.OverallCheckStatus(), StatusUnknown; got != want {
t.Errorf("incorrect initial overall check status %s; want %s", got, want)
}
{
wantConfigAddrs := addrs.MakeSet[addrs.ConfigCheckable](
resourceA,
@ -178,13 +174,8 @@ func TestChecksHappyPath(t *testing.T) {
/////////////////////////////////////////////////////////////////////////
// This "section" is simulating what a check reporting UI might do in
// order to analyze the checks after the Terraform operation completes.
// Since we reported that everything passed above, we should be able to
// see that when we query the object in various ways.
if got, want := checks.OverallCheckStatus(), StatusPass; got != want {
t.Errorf("incorrect final overall check status %s; want %s", got, want)
}
// This "section" is simulating what we might do to report the results
// of the checks after a run completes.
{
configCount := 0
@ -200,7 +191,7 @@ func TestChecksHappyPath(t *testing.T) {
}
{
wantObjAddrs := addrs.MakeSet[addrs.Checkable](
objAddrs := addrs.MakeSet[addrs.Checkable](
resourceInstA,
rootOutputInst,
resourceInstB,
@ -208,34 +199,10 @@ func TestChecksHappyPath(t *testing.T) {
resourceInstC1,
childOutputInst,
)
gotObjAddrs := checks.AllObjectAddrs()
if diff := cmp.Diff(wantObjAddrs, gotObjAddrs); diff != "" {
t.Errorf("wrong object addresses\n%s", diff)
}
for _, addr := range gotObjAddrs {
for _, addr := range objAddrs {
if got, want := checks.ObjectCheckStatus(addr), StatusPass; got != want {
t.Errorf("incorrect final check status for object %s: %s, but want %s", addr, got, want)
}
}
}
{
wantStatuses := addrs.MakeMap(
addrs.MakeMapElem(addrs.NewCheck(resourceInstA, addrs.ResourcePrecondition, 0), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(resourceInstA, addrs.ResourcePrecondition, 1), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(resourceInstA, addrs.ResourcePostcondition, 0), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(resourceInstB, addrs.ResourcePrecondition, 0), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(resourceInstC0, addrs.ResourcePostcondition, 0), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(resourceInstC1, addrs.ResourcePostcondition, 0), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(rootOutputInst, addrs.OutputPrecondition, 0), StatusPass),
addrs.MakeMapElem(addrs.NewCheck(childOutputInst, addrs.OutputPrecondition, 0), StatusPass),
)
gotStatuses := checks.AllCheckStatuses()
if diff := cmp.Diff(wantStatuses, gotStatuses); diff != "" {
t.Errorf("wrong check statuses\n%s", diff)
}
}
}

View File

@ -1,11 +1,14 @@
package jsonplan
// conditionResult is the representation of an evaluated condition block.
//
// This no longer really fits how Terraform is modelling checks -- we're now
// treating check status as a whole-object thing rather than an individual
// condition thing -- but we've preserved this for now to remain as compatible
// as possible with the interface we'd documented as part of the Terraform v1.2
// release, before we'd really solidified the use-cases for checks outside
// of just making a single plan and apply operation fail with an error.
type conditionResult struct {
// checkAddress is the globally-unique address of the condition block. This
// is intentionally unexported as it is an implementation detail.
checkAddress string
// Address is the absolute address of the condition's containing object.
Address string `json:"address,omitempty"`

View File

@ -506,28 +506,82 @@ func (p *plan) marshalCheckResults(results *states.CheckResults) error {
if results == nil {
return nil
}
for _, result := range results.Results {
cr := conditionResult{
checkAddress: result.CheckAddr.String(),
Address: result.CheckAddr.Container.String(),
Type: result.CheckAddr.Type.String(),
ErrorMessage: result.ErrorMessage,
// For the moment this is still producing the flat structure from
// the initial release of preconditions/postconditions in Terraform v1.2.
// This therefore discards the aggregate information about any configuration
// objects that might end up with zero instances declared.
// We'll need to think about what we want to do here in order to expose
// the full check details while hopefully also remaining compatible with
// what we previously documented.
for _, configElem := range results.ConfigResults.Elems {
for _, objectElem := range configElem.Value.ObjectResults.Elems {
objectAddr := objectElem.Key
result := objectElem.Value
var boolResult, unknown bool
switch result.Status {
case checks.StatusPass:
boolResult = true
case checks.StatusFail:
boolResult = false
case checks.StatusError:
boolResult = false
case checks.StatusUnknown:
unknown = true
}
// We need to export one of the previously-documented condition
// types here even though we're no longer actually representing
// individual checks, so we'll fib a bit and just report a
// fixed string depending on the object type. Note that this
// means we'll report that a resource postcondition failed even
// if it was actually a precondition, which is non-ideal but
// hopefully we replace this with an object-first data structure
// in the near future.
fakeCheckType := "Condition"
switch objectAddr.(type) {
case addrs.AbsResourceInstance:
fakeCheckType = "ResourcePostcondition"
case addrs.AbsOutputValue:
fakeCheckType = "OutputPrecondition"
}
// NOTE: Our original design for this data structure exposed
// each declared check individually, but checks don't really
// have durable addresses between runs so we've now simplified
// the model to say that it's entire objects that pass or fail,
// via the combination of all of their checks.
//
// The public data structure for this was built around the
// original design and so we approximate that here by
// generating only a single "condition" per object in most cases,
// but will generate one for each error message if we're
// reporting a failure and we have at least one message.
if result.Status == checks.StatusFail && len(result.FailureMessages) != 0 {
for _, msg := range result.FailureMessages {
p.Conditions = append(p.Conditions, conditionResult{
Address: objectAddr.String(),
Type: fakeCheckType,
Result: boolResult,
Unknown: unknown,
ErrorMessage: msg,
})
}
} else {
p.Conditions = append(p.Conditions, conditionResult{
Address: objectAddr.String(),
Type: fakeCheckType,
Result: boolResult,
Unknown: unknown,
})
}
}
switch result.Status {
case checks.StatusPass:
cr.Result = true
case checks.StatusFail:
cr.Result = false
case checks.StatusError:
cr.Result = false
case checks.StatusUnknown:
cr.Unknown = true
}
p.Conditions = append(p.Conditions, cr)
}
sort.Slice(p.Conditions, func(i, j int) bool {
return p.Conditions[i].checkAddress < p.Conditions[j].checkAddress
return p.Conditions[i].Address < p.Conditions[j].Address
})
return nil
}

View File

@ -213,78 +213,26 @@ func (ResourceInstanceActionReason) EnumDescriptor() ([]byte, []int) {
return file_planfile_proto_rawDescGZIP(), []int{2}
}
// CheckType defines the type of check block used to generate a check result.
type CheckType int32
// Status describes the status of a particular checkable object at the
// completion of the plan.
type CheckResults_Status int32
const (
CheckType_INVALID CheckType = 0
CheckType_RESOURCE_PRECONDITION CheckType = 1
CheckType_RESOURCE_POSTCONDITION CheckType = 2
CheckType_OUTPUT_PRECONDITION CheckType = 3
CheckResults_UNKNOWN CheckResults_Status = 0
CheckResults_PASS CheckResults_Status = 1
CheckResults_FAIL CheckResults_Status = 2
CheckResults_ERROR CheckResults_Status = 3
)
// Enum value maps for CheckType.
// Enum value maps for CheckResults_Status.
var (
CheckType_name = map[int32]string{
0: "INVALID",
1: "RESOURCE_PRECONDITION",
2: "RESOURCE_POSTCONDITION",
3: "OUTPUT_PRECONDITION",
}
CheckType_value = map[string]int32{
"INVALID": 0,
"RESOURCE_PRECONDITION": 1,
"RESOURCE_POSTCONDITION": 2,
"OUTPUT_PRECONDITION": 3,
}
)
func (x CheckType) Enum() *CheckType {
p := new(CheckType)
*p = x
return p
}
func (x CheckType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (CheckType) Descriptor() protoreflect.EnumDescriptor {
return file_planfile_proto_enumTypes[3].Descriptor()
}
func (CheckType) Type() protoreflect.EnumType {
return &file_planfile_proto_enumTypes[3]
}
func (x CheckType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use CheckType.Descriptor instead.
func (CheckType) EnumDescriptor() ([]byte, []int) {
return file_planfile_proto_rawDescGZIP(), []int{3}
}
// CheckStatus describes the status of a particular check at the completion of the plan.
type CheckStatus int32
const (
CheckStatus_UNKNOWN CheckStatus = 0
CheckStatus_PASS CheckStatus = 1
CheckStatus_FAIL CheckStatus = 2
CheckStatus_ERROR CheckStatus = 3
)
// Enum value maps for CheckStatus.
var (
CheckStatus_name = map[int32]string{
CheckResults_Status_name = map[int32]string{
0: "UNKNOWN",
1: "PASS",
2: "FAIL",
3: "ERROR",
}
CheckStatus_value = map[string]int32{
CheckResults_Status_value = map[string]int32{
"UNKNOWN": 0,
"PASS": 1,
"FAIL": 2,
@ -292,31 +240,31 @@ var (
}
)
func (x CheckStatus) Enum() *CheckStatus {
p := new(CheckStatus)
func (x CheckResults_Status) Enum() *CheckResults_Status {
p := new(CheckResults_Status)
*p = x
return p
}
func (x CheckStatus) String() string {
func (x CheckResults_Status) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (CheckStatus) Descriptor() protoreflect.EnumDescriptor {
return file_planfile_proto_enumTypes[4].Descriptor()
func (CheckResults_Status) Descriptor() protoreflect.EnumDescriptor {
return file_planfile_proto_enumTypes[3].Descriptor()
}
func (CheckStatus) Type() protoreflect.EnumType {
return &file_planfile_proto_enumTypes[4]
func (CheckResults_Status) Type() protoreflect.EnumType {
return &file_planfile_proto_enumTypes[3]
}
func (x CheckStatus) Number() protoreflect.EnumNumber {
func (x CheckResults_Status) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use CheckStatus.Descriptor instead.
func (CheckStatus) EnumDescriptor() ([]byte, []int) {
return file_planfile_proto_rawDescGZIP(), []int{4}
// Deprecated: Use CheckResults_Status.Descriptor instead.
func (CheckResults_Status) EnumDescriptor() ([]byte, []int) {
return file_planfile_proto_rawDescGZIP(), []int{5, 0}
}
// Plan is the root message type for the tfplan file
@ -358,10 +306,10 @@ type Plan struct {
OutputChanges []*OutputChange `protobuf:"bytes,4,rep,name=output_changes,json=outputChanges,proto3" json:"output_changes,omitempty"`
// An unordered set of check results for the entire configuration.
//
// This set should cover the full set of checks we expect to resolve but
// some of them may have unknown results if they cannot be decided until
// apply time.
CheckResults []*CheckResult `protobuf:"bytes,19,rep,name=check_results,json=checkResults,proto3" json:"check_results,omitempty"`
// Each element represents a single static configuration object that has
// checks, and each of those may have zero or more dynamic objects that
// the checks were applied to nested within.
CheckResults []*CheckResults `protobuf:"bytes,19,rep,name=check_results,json=checkResults,proto3" json:"check_results,omitempty"`
// An unordered set of target addresses to include when applying. If no
// target addresses are present, the plan applies to the whole
// configuration.
@ -455,7 +403,7 @@ func (x *Plan) GetOutputChanges() []*OutputChange {
return nil
}
func (x *Plan) GetCheckResults() []*CheckResult {
func (x *Plan) GetCheckResults() []*CheckResults {
if x != nil {
return x.CheckResults
}
@ -849,27 +797,23 @@ func (x *OutputChange) GetSensitive() bool {
return false
}
type CheckResult struct {
type CheckResults struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Address of the object containing the condition.
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
// Type of the condition block.
Type CheckType `protobuf:"varint,2,opt,name=type,proto3,enum=tfplan.CheckType" json:"type,omitempty"`
// Index of the condition block within the object and the CheckType.
// Indices are not consistent between runs if the configuration has
// changed, so indices are not correlatable between runs.
Index int64 `protobuf:"varint,3,opt,name=index,proto3" json:"index,omitempty"`
// The status of the check at the completion of the planning step.
Status CheckStatus `protobuf:"varint,4,opt,name=status,proto3,enum=tfplan.CheckStatus" json:"status,omitempty"`
// Optional custom error message for a failing condition.
ErrorMessage string `protobuf:"bytes,5,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"`
// Address of the configuration object that declared the checks.
ConfigAddr string `protobuf:"bytes,1,opt,name=config_addr,json=configAddr,proto3" json:"config_addr,omitempty"`
// The aggregate status of the entire configuration object, based on
// the statuses of its zero or more checkable objects.
Status CheckResults_Status `protobuf:"varint,2,opt,name=status,proto3,enum=tfplan.CheckResults_Status" json:"status,omitempty"`
// The results for individual objects that were declared by the
// configuration object named in config_addr.
Objects []*CheckResults_ObjectResult `protobuf:"bytes,3,rep,name=objects,proto3" json:"objects,omitempty"`
}
func (x *CheckResult) Reset() {
*x = CheckResult{}
func (x *CheckResults) Reset() {
*x = CheckResults{}
if protoimpl.UnsafeEnabled {
mi := &file_planfile_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -877,13 +821,13 @@ func (x *CheckResult) Reset() {
}
}
func (x *CheckResult) String() string {
func (x *CheckResults) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CheckResult) ProtoMessage() {}
func (*CheckResults) ProtoMessage() {}
func (x *CheckResult) ProtoReflect() protoreflect.Message {
func (x *CheckResults) ProtoReflect() protoreflect.Message {
mi := &file_planfile_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@ -895,44 +839,30 @@ func (x *CheckResult) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
// Deprecated: Use CheckResult.ProtoReflect.Descriptor instead.
func (*CheckResult) Descriptor() ([]byte, []int) {
// Deprecated: Use CheckResults.ProtoReflect.Descriptor instead.
func (*CheckResults) Descriptor() ([]byte, []int) {
return file_planfile_proto_rawDescGZIP(), []int{5}
}
func (x *CheckResult) GetAddr() string {
func (x *CheckResults) GetConfigAddr() string {
if x != nil {
return x.Addr
return x.ConfigAddr
}
return ""
}
func (x *CheckResult) GetType() CheckType {
if x != nil {
return x.Type
}
return CheckType_INVALID
}
func (x *CheckResult) GetIndex() int64 {
if x != nil {
return x.Index
}
return 0
}
func (x *CheckResult) GetStatus() CheckStatus {
func (x *CheckResults) GetStatus() CheckResults_Status {
if x != nil {
return x.Status
}
return CheckStatus_UNKNOWN
return CheckResults_UNKNOWN
}
func (x *CheckResult) GetErrorMessage() string {
func (x *CheckResults) GetObjects() []*CheckResults_ObjectResult {
if x != nil {
return x.ErrorMessage
return x.Objects
}
return ""
return nil
}
// DynamicValue represents a value whose type is not decided until runtime,
@ -1099,6 +1029,69 @@ func (x *PlanResourceAttr) GetAttr() *Path {
return nil
}
type CheckResults_ObjectResult struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ObjectAddr string `protobuf:"bytes,1,opt,name=object_addr,json=objectAddr,proto3" json:"object_addr,omitempty"`
Status CheckResults_Status `protobuf:"varint,2,opt,name=status,proto3,enum=tfplan.CheckResults_Status" json:"status,omitempty"`
FailureMessages []string `protobuf:"bytes,3,rep,name=failure_messages,json=failureMessages,proto3" json:"failure_messages,omitempty"`
}
func (x *CheckResults_ObjectResult) Reset() {
*x = CheckResults_ObjectResult{}
if protoimpl.UnsafeEnabled {
mi := &file_planfile_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CheckResults_ObjectResult) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CheckResults_ObjectResult) ProtoMessage() {}
func (x *CheckResults_ObjectResult) ProtoReflect() protoreflect.Message {
mi := &file_planfile_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CheckResults_ObjectResult.ProtoReflect.Descriptor instead.
func (*CheckResults_ObjectResult) Descriptor() ([]byte, []int) {
return file_planfile_proto_rawDescGZIP(), []int{5, 0}
}
func (x *CheckResults_ObjectResult) GetObjectAddr() string {
if x != nil {
return x.ObjectAddr
}
return ""
}
func (x *CheckResults_ObjectResult) GetStatus() CheckResults_Status {
if x != nil {
return x.Status
}
return CheckResults_UNKNOWN
}
func (x *CheckResults_ObjectResult) GetFailureMessages() []string {
if x != nil {
return x.FailureMessages
}
return nil
}
type Path_Step struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -1114,7 +1107,7 @@ type Path_Step struct {
func (x *Path_Step) Reset() {
*x = Path_Step{}
if protoimpl.UnsafeEnabled {
mi := &file_planfile_proto_msgTypes[10]
mi := &file_planfile_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1127,7 +1120,7 @@ func (x *Path_Step) String() string {
func (*Path_Step) ProtoMessage() {}
func (x *Path_Step) ProtoReflect() protoreflect.Message {
mi := &file_planfile_proto_msgTypes[10]
mi := &file_planfile_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1188,7 +1181,7 @@ var File_planfile_proto protoreflect.FileDescriptor
var file_planfile_proto_rawDesc = []byte{
0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x6e, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x06, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0xa6, 0x06, 0x0a, 0x04, 0x50, 0x6c, 0x61,
0x12, 0x06, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x22, 0xa7, 0x06, 0x0a, 0x04, 0x50, 0x6c, 0x61,
0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x07, 0x75,
0x69, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x74,
@ -1209,160 +1202,161 @@ var file_planfile_proto_rawDesc = []byte{
0x3b, 0x0a, 0x0e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e,
0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x6f,
0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x0d,
0x75, 0x74, 0x70, 0x75, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0d,
0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x13, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65,
0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x66, 0x6f, 0x72,
0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73,
0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65, 0x70,
0x6c, 0x61, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, 0x72,
0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0e,
0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x56,
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e,
0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e,
0x64, 0x12, 0x4b, 0x0a, 0x13, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x5f, 0x61, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x72, 0x65, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x65,
0x76, 0x61, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a, 0x52,
0x0a, 0x0e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65,
0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x0c, 0x63, 0x68, 0x65, 0x63, 0x6b,
0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65,
0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x74,
0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x66, 0x6f,
0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72,
0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x65,
0x70, 0x6c, 0x61, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65,
0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18,
0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65,
0x6e, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61,
0x6e, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x65,
0x6e, 0x64, 0x12, 0x4b, 0x0a, 0x13, 0x72, 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x5f, 0x61,
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x2e, 0x72, 0x65,
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x52, 0x12, 0x72, 0x65, 0x6c,
0x65, 0x76, 0x61, 0x6e, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x1a,
0x52, 0x0a, 0x0e, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61,
0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x02, 0x38, 0x01, 0x1a, 0x4d, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
0x61, 0x74, 0x74, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x12, 0x20, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c,
0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x61, 0x74,
0x74, 0x72, 0x22, 0x69, 0x0a, 0x07, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
0x65, 0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d,
0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
0x38, 0x01, 0x1a, 0x4d, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61,
0x74, 0x74, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12,
0x20, 0x0a, 0x04, 0x61, 0x74, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x61, 0x74, 0x74,
0x72, 0x22, 0x69, 0x0a, 0x07, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04,
0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
0x12, 0x2c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
0x1c, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xe4, 0x01,
0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61,
0x6e, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0x2c, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69,
0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c,
0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0xe4, 0x01, 0x0a,
0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x2c, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63,
0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x42, 0x0a,
0x16, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76,
0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x14, 0x62, 0x65, 0x66,
0x6f, 0x72, 0x65, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68,
0x73, 0x12, 0x40, 0x0a, 0x15, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x69,
0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x13,
0x61, 0x66, 0x74, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61,
0x74, 0x68, 0x73, 0x22, 0xd3, 0x02, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12,
0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x64,
0x64, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x61,
0x64, 0x64, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x52,
0x75, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x65,
0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
0x6f, 0x73, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69,
0x64, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x61,
0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70,
0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72,
0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0f, 0x72,
0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12, 0x49,
0x0a, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18,
0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x52,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x68, 0x0a, 0x0c, 0x4f, 0x75, 0x74,
0x70, 0x75, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a,
0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69,
0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74,
0x69, 0x76, 0x65, 0x22, 0xb0, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x25, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43,
0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14,
0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69,
0x6e, 0x64, 0x65, 0x78, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68,
0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x28, 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69,
0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63,
0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63, 0x6b,
0x22, 0xa5, 0x01, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x65,
0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61,
0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x2e, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65,
0x70, 0x73, 0x1a, 0x74, 0x0a, 0x04, 0x53, 0x74, 0x65, 0x70, 0x12, 0x27, 0x0a, 0x0e, 0x61, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e,
0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b,
0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61,
0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00,
0x52, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x0a, 0x0a, 0x08,
0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2a, 0x31, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65,
0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07,
0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, 0x46,
0x52, 0x45, 0x53, 0x48, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x2a, 0x70, 0x0a, 0x06, 0x41,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12,
0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52,
0x45, 0x41, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10,
0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x05, 0x12, 0x16, 0x0a,
0x12, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45,
0x41, 0x54, 0x45, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f,
0x54, 0x48, 0x45, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x07, 0x2a, 0x86, 0x03,
0x0a, 0x1c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e,
0x63, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x08,
0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x50, 0x4c,
0x41, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x54, 0x41, 0x49, 0x4e,
0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45,
0x5f, 0x42, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x21, 0x0a,
0x1d, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45,
0x5f, 0x43, 0x41, 0x4e, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03,
0x12, 0x25, 0x0a, 0x21, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55,
0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43,
0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x04, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x45, 0x4c, 0x45, 0x54,
0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x57, 0x52, 0x4f, 0x4e, 0x47, 0x5f,
0x52, 0x45, 0x50, 0x45, 0x54, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a,
0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43,
0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x06, 0x12, 0x1b, 0x0a, 0x17,
0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x45,
0x41, 0x43, 0x48, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x07, 0x12, 0x1c, 0x0a, 0x18, 0x44, 0x45, 0x4c,
0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d,
0x4f, 0x44, 0x55, 0x4c, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x50, 0x4c, 0x41,
0x43, 0x45, 0x5f, 0x42, 0x59, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x53, 0x10, 0x09,
0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45,
0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
0x0a, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53,
0x45, 0x5f, 0x44, 0x45, 0x50, 0x45, 0x4e, 0x44, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x50, 0x45, 0x4e,
0x44, 0x49, 0x4e, 0x47, 0x10, 0x0b, 0x2a, 0x68, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54,
0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00,
0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x50, 0x52, 0x45,
0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x52,
0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x43, 0x4f, 0x4e, 0x44,
0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x55, 0x54, 0x50, 0x55,
0x54, 0x5f, 0x50, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03,
0x2a, 0x39, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04,
0x50, 0x41, 0x53, 0x53, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x02,
0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x42, 0x42, 0x5a, 0x40, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
0x6f, 0x72, 0x70, 0x2f, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x73, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x42,
0x0a, 0x16, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69,
0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c,
0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x14, 0x62, 0x65,
0x66, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50, 0x61, 0x74,
0x68, 0x73, 0x12, 0x40, 0x0a, 0x15, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x6e, 0x73,
0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52,
0x13, 0x61, 0x66, 0x74, 0x65, 0x72, 0x53, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x50,
0x61, 0x74, 0x68, 0x73, 0x22, 0xd3, 0x02, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12,
0x12, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61,
0x64, 0x64, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x72, 0x65, 0x76, 0x5f, 0x72, 0x75, 0x6e, 0x5f,
0x61, 0x64, 0x64, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x65, 0x76,
0x52, 0x75, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x73,
0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65,
0x70, 0x6f, 0x73, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76,
0x69, 0x64, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68,
0x61, 0x6e, 0x67, 0x65, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07,
0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70,
0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
0x65, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x0c, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0f,
0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x12,
0x49, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e,
0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e,
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x0c, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x68, 0x0a, 0x0c, 0x4f, 0x75,
0x74, 0x70, 0x75, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x26,
0x0a, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e,
0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x06,
0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74,
0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x65, 0x6e, 0x73, 0x69,
0x74, 0x69, 0x76, 0x65, 0x22, 0xe9, 0x02, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f,
0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x41, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e,
0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b, 0x0a, 0x07, 0x6f,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74,
0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x1a, 0x8f, 0x01, 0x0a, 0x0c, 0x4f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x33, 0x0a, 0x06, 0x73, 0x74,
0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x74, 0x66, 0x70,
0x6c, 0x61, 0x6e, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73,
0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
0x29, 0x0a, 0x10, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x75,
0x72, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x34, 0x0a, 0x06, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10,
0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x41, 0x53, 0x53, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46,
0x41, 0x49, 0x4c, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03,
0x22, 0x28, 0x0a, 0x0c, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x07, 0x6d, 0x73, 0x67, 0x70, 0x61, 0x63, 0x6b, 0x22, 0xa5, 0x01, 0x0a, 0x04, 0x50,
0x61, 0x74, 0x68, 0x12, 0x27, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x50, 0x61, 0x74, 0x68,
0x2e, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x1a, 0x74, 0x0a, 0x04,
0x53, 0x74, 0x65, 0x70, 0x12, 0x27, 0x0a, 0x0e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0d,
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
0x0b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x66, 0x70, 0x6c, 0x61, 0x6e, 0x2e, 0x44, 0x79, 0x6e, 0x61,
0x6d, 0x69, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x65, 0x6c, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x0a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
0x6f, 0x72, 0x2a, 0x31, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f,
0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f,
0x59, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x52, 0x45, 0x46, 0x52, 0x45, 0x53, 0x48, 0x5f, 0x4f,
0x4e, 0x4c, 0x59, 0x10, 0x02, 0x2a, 0x70, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45,
0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x12,
0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x44,
0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x4c, 0x45, 0x54,
0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x06, 0x12,
0x16, 0x0a, 0x12, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x5f, 0x44,
0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x07, 0x2a, 0x86, 0x03, 0x0a, 0x1c, 0x52, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45,
0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x45,
0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x54, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12,
0x16, 0x0a, 0x12, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x59, 0x5f, 0x52, 0x45,
0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x50, 0x4c, 0x41,
0x43, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x41, 0x4e, 0x4e, 0x4f,
0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x45,
0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f,
0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10,
0x04, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45, 0x43, 0x41,
0x55, 0x53, 0x45, 0x5f, 0x57, 0x52, 0x4f, 0x4e, 0x47, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x54, 0x49,
0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45,
0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x49,
0x4e, 0x44, 0x45, 0x58, 0x10, 0x06, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45,
0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x45, 0x41, 0x43, 0x48, 0x5f, 0x4b, 0x45,
0x59, 0x10, 0x07, 0x12, 0x1c, 0x0a, 0x18, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x42, 0x45,
0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x10,
0x08, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x50, 0x4c, 0x41, 0x43, 0x45, 0x5f, 0x42, 0x59, 0x5f,
0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x53, 0x10, 0x09, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45,
0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49,
0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x0a, 0x12, 0x23, 0x0a, 0x1f, 0x52,
0x45, 0x41, 0x44, 0x5f, 0x42, 0x45, 0x43, 0x41, 0x55, 0x53, 0x45, 0x5f, 0x44, 0x45, 0x50, 0x45,
0x4e, 0x44, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x0b,
0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x74, 0x65, 0x72, 0x72, 0x61, 0x66, 0x6f,
0x72, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e,
0x73, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x61, 0x6e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -1377,55 +1371,56 @@ func file_planfile_proto_rawDescGZIP() []byte {
return file_planfile_proto_rawDescData
}
var file_planfile_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
var file_planfile_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_planfile_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
var file_planfile_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_planfile_proto_goTypes = []interface{}{
(Mode)(0), // 0: tfplan.Mode
(Action)(0), // 1: tfplan.Action
(ResourceInstanceActionReason)(0), // 2: tfplan.ResourceInstanceActionReason
(CheckType)(0), // 3: tfplan.CheckType
(CheckStatus)(0), // 4: tfplan.CheckStatus
(*Plan)(nil), // 5: tfplan.Plan
(*Backend)(nil), // 6: tfplan.Backend
(*Change)(nil), // 7: tfplan.Change
(*ResourceInstanceChange)(nil), // 8: tfplan.ResourceInstanceChange
(*OutputChange)(nil), // 9: tfplan.OutputChange
(*CheckResult)(nil), // 10: tfplan.CheckResult
(*DynamicValue)(nil), // 11: tfplan.DynamicValue
(*Path)(nil), // 12: tfplan.Path
nil, // 13: tfplan.Plan.VariablesEntry
(*PlanResourceAttr)(nil), // 14: tfplan.Plan.resource_attr
(CheckResults_Status)(0), // 3: tfplan.CheckResults.Status
(*Plan)(nil), // 4: tfplan.Plan
(*Backend)(nil), // 5: tfplan.Backend
(*Change)(nil), // 6: tfplan.Change
(*ResourceInstanceChange)(nil), // 7: tfplan.ResourceInstanceChange
(*OutputChange)(nil), // 8: tfplan.OutputChange
(*CheckResults)(nil), // 9: tfplan.CheckResults
(*DynamicValue)(nil), // 10: tfplan.DynamicValue
(*Path)(nil), // 11: tfplan.Path
nil, // 12: tfplan.Plan.VariablesEntry
(*PlanResourceAttr)(nil), // 13: tfplan.Plan.resource_attr
(*CheckResults_ObjectResult)(nil), // 14: tfplan.CheckResults.ObjectResult
(*Path_Step)(nil), // 15: tfplan.Path.Step
}
var file_planfile_proto_depIdxs = []int32{
0, // 0: tfplan.Plan.ui_mode:type_name -> tfplan.Mode
13, // 1: tfplan.Plan.variables:type_name -> tfplan.Plan.VariablesEntry
8, // 2: tfplan.Plan.resource_changes:type_name -> tfplan.ResourceInstanceChange
8, // 3: tfplan.Plan.resource_drift:type_name -> tfplan.ResourceInstanceChange
9, // 4: tfplan.Plan.output_changes:type_name -> tfplan.OutputChange
10, // 5: tfplan.Plan.check_results:type_name -> tfplan.CheckResult
6, // 6: tfplan.Plan.backend:type_name -> tfplan.Backend
14, // 7: tfplan.Plan.relevant_attributes:type_name -> tfplan.Plan.resource_attr
11, // 8: tfplan.Backend.config:type_name -> tfplan.DynamicValue
12, // 1: tfplan.Plan.variables:type_name -> tfplan.Plan.VariablesEntry
7, // 2: tfplan.Plan.resource_changes:type_name -> tfplan.ResourceInstanceChange
7, // 3: tfplan.Plan.resource_drift:type_name -> tfplan.ResourceInstanceChange
8, // 4: tfplan.Plan.output_changes:type_name -> tfplan.OutputChange
9, // 5: tfplan.Plan.check_results:type_name -> tfplan.CheckResults
5, // 6: tfplan.Plan.backend:type_name -> tfplan.Backend
13, // 7: tfplan.Plan.relevant_attributes:type_name -> tfplan.Plan.resource_attr
10, // 8: tfplan.Backend.config:type_name -> tfplan.DynamicValue
1, // 9: tfplan.Change.action:type_name -> tfplan.Action
11, // 10: tfplan.Change.values:type_name -> tfplan.DynamicValue
12, // 11: tfplan.Change.before_sensitive_paths:type_name -> tfplan.Path
12, // 12: tfplan.Change.after_sensitive_paths:type_name -> tfplan.Path
7, // 13: tfplan.ResourceInstanceChange.change:type_name -> tfplan.Change
12, // 14: tfplan.ResourceInstanceChange.required_replace:type_name -> tfplan.Path
10, // 10: tfplan.Change.values:type_name -> tfplan.DynamicValue
11, // 11: tfplan.Change.before_sensitive_paths:type_name -> tfplan.Path
11, // 12: tfplan.Change.after_sensitive_paths:type_name -> tfplan.Path
6, // 13: tfplan.ResourceInstanceChange.change:type_name -> tfplan.Change
11, // 14: tfplan.ResourceInstanceChange.required_replace:type_name -> tfplan.Path
2, // 15: tfplan.ResourceInstanceChange.action_reason:type_name -> tfplan.ResourceInstanceActionReason
7, // 16: tfplan.OutputChange.change:type_name -> tfplan.Change
3, // 17: tfplan.CheckResult.type:type_name -> tfplan.CheckType
4, // 18: tfplan.CheckResult.status:type_name -> tfplan.CheckStatus
6, // 16: tfplan.OutputChange.change:type_name -> tfplan.Change
3, // 17: tfplan.CheckResults.status:type_name -> tfplan.CheckResults.Status
14, // 18: tfplan.CheckResults.objects:type_name -> tfplan.CheckResults.ObjectResult
15, // 19: tfplan.Path.steps:type_name -> tfplan.Path.Step
11, // 20: tfplan.Plan.VariablesEntry.value:type_name -> tfplan.DynamicValue
12, // 21: tfplan.Plan.resource_attr.attr:type_name -> tfplan.Path
11, // 22: tfplan.Path.Step.element_key:type_name -> tfplan.DynamicValue
23, // [23:23] is the sub-list for method output_type
23, // [23:23] is the sub-list for method input_type
23, // [23:23] is the sub-list for extension type_name
23, // [23:23] is the sub-list for extension extendee
0, // [0:23] is the sub-list for field type_name
10, // 20: tfplan.Plan.VariablesEntry.value:type_name -> tfplan.DynamicValue
11, // 21: tfplan.Plan.resource_attr.attr:type_name -> tfplan.Path
3, // 22: tfplan.CheckResults.ObjectResult.status:type_name -> tfplan.CheckResults.Status
10, // 23: tfplan.Path.Step.element_key:type_name -> tfplan.DynamicValue
24, // [24:24] is the sub-list for method output_type
24, // [24:24] is the sub-list for method input_type
24, // [24:24] is the sub-list for extension type_name
24, // [24:24] is the sub-list for extension extendee
0, // [0:24] is the sub-list for field type_name
}
func init() { file_planfile_proto_init() }
@ -1495,7 +1490,7 @@ func file_planfile_proto_init() {
}
}
file_planfile_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CheckResult); i {
switch v := v.(*CheckResults); i {
case 0:
return &v.state
case 1:
@ -1543,6 +1538,18 @@ func file_planfile_proto_init() {
}
}
file_planfile_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CheckResults_ObjectResult); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_planfile_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Path_Step); i {
case 0:
return &v.state
@ -1555,7 +1562,7 @@ func file_planfile_proto_init() {
}
}
}
file_planfile_proto_msgTypes[10].OneofWrappers = []interface{}{
file_planfile_proto_msgTypes[11].OneofWrappers = []interface{}{
(*Path_Step_AttributeName)(nil),
(*Path_Step_ElementKey)(nil),
}
@ -1564,8 +1571,8 @@ func file_planfile_proto_init() {
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_planfile_proto_rawDesc,
NumEnums: 5,
NumMessages: 11,
NumEnums: 4,
NumMessages: 12,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -46,10 +46,10 @@ message Plan {
// An unordered set of check results for the entire configuration.
//
// This set should cover the full set of checks we expect to resolve but
// some of them may have unknown results if they cannot be decided until
// apply time.
repeated CheckResult check_results = 19;
// Each element represents a single static configuration object that has
// checks, and each of those may have zero or more dynamic objects that
// the checks were applied to nested within.
repeated CheckResults check_results = 19;
// An unordered set of target addresses to include when applying. If no
// target addresses are present, the plan applies to the whole
@ -217,39 +217,32 @@ message OutputChange {
bool sensitive = 3;
}
// CheckType defines the type of check block used to generate a check result.
enum CheckType {
INVALID = 0;
RESOURCE_PRECONDITION = 1;
RESOURCE_POSTCONDITION = 2;
OUTPUT_PRECONDITION = 3;
}
message CheckResults {
// Status describes the status of a particular checkable object at the
// completion of the plan.
enum Status {
UNKNOWN = 0;
PASS = 1;
FAIL = 2;
ERROR = 3;
}
// CheckStatus describes the status of a particular check at the completion of the plan.
enum CheckStatus {
UNKNOWN = 0;
PASS = 1;
FAIL = 2;
ERROR = 3;
}
message ObjectResult {
string object_addr = 1;
Status status = 2;
repeated string failure_messages = 3;
}
message CheckResult {
// Address of the object containing the condition.
string addr = 1;
// Address of the configuration object that declared the checks.
string config_addr = 1;
// Type of the condition block.
CheckType type = 2;
// The aggregate status of the entire configuration object, based on
// the statuses of its zero or more checkable objects.
Status status = 2;
// Index of the condition block within the object and the CheckType.
// Indices are not consistent between runs if the configuration has
// changed, so indices are not correlatable between runs.
int64 index = 3;
// The status of the check at the completion of the planning step.
CheckStatus status = 4;
// Optional custom error message for a failing condition.
string error_message = 5;
// The results for individual objects that were declared by the
// configuration object named in config_addr.
repeated ObjectResult objects = 3;
}
// DynamicValue represents a value whose type is not decided until runtime,

View File

@ -14,7 +14,6 @@ import (
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/plans/internal/planproto"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/tfdiags"
"github.com/hashicorp/terraform/version"
"github.com/zclconf/go-cty/cty"
)
@ -91,48 +90,80 @@ func readTfplan(r io.Reader) (*plans.Plan, error) {
})
}
for _, rawCR := range rawPlan.CheckResults {
cr := &states.CheckResult{}
switch rawCR.Status {
case planproto.CheckStatus_UNKNOWN:
cr.Status = checks.StatusUnknown
case planproto.CheckStatus_PASS:
cr.Status = checks.StatusPass
case planproto.CheckStatus_FAIL:
cr.Status = checks.StatusFail
case planproto.CheckStatus_ERROR:
cr.Status = checks.StatusError
plan.Checks.ConfigResults = addrs.MakeMap[addrs.ConfigCheckable, *states.CheckResultAggregate]()
for _, rawCRs := range rawPlan.CheckResults {
aggr := &states.CheckResultAggregate{}
switch rawCRs.Status {
case planproto.CheckResults_UNKNOWN:
aggr.Status = checks.StatusUnknown
case planproto.CheckResults_PASS:
aggr.Status = checks.StatusPass
case planproto.CheckResults_FAIL:
aggr.Status = checks.StatusFail
case planproto.CheckResults_ERROR:
aggr.Status = checks.StatusError
default:
return nil, fmt.Errorf("check for %s as unsupported status %#v", rawCR.Addr, rawCR.Status)
return nil, fmt.Errorf("aggregate check results for %s have unsupported status %#v", rawCRs.ConfigAddr, rawCRs.Status)
}
var diags tfdiags.Diagnostics
var checkType addrs.CheckType
var objectAddr addrs.Checkable
switch rawCR.Type {
case planproto.CheckType_OUTPUT_PRECONDITION:
checkType = addrs.OutputPrecondition
objectAddr, diags = addrs.ParseAbsOutputValueStr(rawCR.Addr)
if diags.HasErrors() {
return nil, diags.Err()
}
case planproto.CheckType_RESOURCE_PRECONDITION:
checkType = addrs.ResourcePrecondition
objectAddr, diags = addrs.ParseAbsResourceInstanceStr(rawCR.Addr)
if diags.HasErrors() {
return nil, diags.Err()
}
case planproto.CheckType_RESOURCE_POSTCONDITION:
checkType = addrs.ResourcePostcondition
objectAddr, diags = addrs.ParseAbsResourceInstanceStr(rawCR.Addr)
if diags.HasErrors() {
return nil, diags.Err()
}
default:
return nil, fmt.Errorf("check for %s has unsupported type %s", rawCR.Addr, rawCR.Type)
// Some trickiness here: we only have an address parser for
// addrs.Checkable and not for addrs.ConfigCheckable, but that's okay
// because once we have an addrs.Checkable we can always derive an
// addrs.ConfigCheckable from it, and a ConfigCheckable should always
// be the same syntax as a Checkable with no index information and
// thus we can reuse the same parser for both here.
configAddrProxy, diags := addrs.ParseCheckableStr(rawCRs.ConfigAddr)
if diags.HasErrors() {
return nil, diags.Err()
}
cr.CheckAddr = addrs.NewCheck(objectAddr, checkType, int(rawCR.Index))
cr.ErrorMessage = rawCR.ErrorMessage
plan.Checks.Results = append(plan.Checks.Results, cr)
configAddr := configAddrProxy.ConfigCheckable()
if configAddr.String() != configAddrProxy.String() {
// This is how we catch if the config address included index
// information that would be allowed in a Checkable but not
// in a ConfigCheckable.
return nil, fmt.Errorf("invalid checkable config address %s", rawCRs.ConfigAddr)
}
aggr.ObjectResults = addrs.MakeMap[addrs.Checkable, *states.CheckResultObject]()
for _, rawCR := range rawCRs.Objects {
objectAddr, diags := addrs.ParseCheckableStr(rawCR.ObjectAddr)
if diags.HasErrors() {
return nil, diags.Err()
}
if !addrs.Equivalent(objectAddr.ConfigCheckable(), configAddr) {
return nil, fmt.Errorf("checkable object %s should not be grouped under %s", objectAddr, configAddr)
}
obj := &states.CheckResultObject{
FailureMessages: rawCR.FailureMessages,
}
switch rawCR.Status {
case planproto.CheckResults_UNKNOWN:
obj.Status = checks.StatusUnknown
case planproto.CheckResults_PASS:
obj.Status = checks.StatusPass
case planproto.CheckResults_FAIL:
obj.Status = checks.StatusFail
case planproto.CheckResults_ERROR:
obj.Status = checks.StatusError
default:
return nil, fmt.Errorf("object check results for %s has unsupported status %#v", rawCR.ObjectAddr, rawCR.Status)
}
aggr.ObjectResults.Put(objectAddr, obj)
}
// If we ended up with no elements in the map then we'll just nil it,
// primarily just to make life easier for our round-trip tests.
if aggr.ObjectResults.Len() == 0 {
aggr.ObjectResults.Elems = nil
}
plan.Checks.ConfigResults.Put(configAddr, aggr)
}
// If we ended up with no elements in the map then we'll just nil it,
// primarily just to make life easier for our round-trip tests.
if plan.Checks.ConfigResults.Len() == 0 {
plan.Checks.ConfigResults.Elems = nil
}
for _, rawRC := range rawPlan.ResourceChanges {
@ -413,7 +444,7 @@ func writeTfplan(plan *plans.Plan, w io.Writer) error {
Variables: map[string]*planproto.DynamicValue{},
OutputChanges: []*planproto.OutputChange{},
CheckResults: []*planproto.CheckResult{},
CheckResults: []*planproto.CheckResults{},
ResourceChanges: []*planproto.ResourceInstanceChange{},
ResourceDrift: []*planproto.ResourceInstanceChange{},
}
@ -455,36 +486,46 @@ func writeTfplan(plan *plans.Plan, w io.Writer) error {
}
if plan.Checks != nil {
for _, cr := range plan.Checks.Results {
pcr := &planproto.CheckResult{
Addr: cr.CheckAddr.Container.String(),
Index: int64(cr.CheckAddr.Index),
ErrorMessage: cr.ErrorMessage,
for _, configElem := range plan.Checks.ConfigResults.Elems {
crs := configElem.Value
pcrs := &planproto.CheckResults{
ConfigAddr: configElem.Key.String(),
}
switch cr.Status {
switch crs.Status {
case checks.StatusUnknown:
pcr.Status = planproto.CheckStatus_UNKNOWN
pcrs.Status = planproto.CheckResults_UNKNOWN
case checks.StatusPass:
pcr.Status = planproto.CheckStatus_PASS
pcrs.Status = planproto.CheckResults_PASS
case checks.StatusFail:
pcr.Status = planproto.CheckStatus_FAIL
pcrs.Status = planproto.CheckResults_FAIL
case checks.StatusError:
pcr.Status = planproto.CheckStatus_ERROR
pcrs.Status = planproto.CheckResults_ERROR
default:
return fmt.Errorf("condition result %s has unsupported status %s", cr.CheckAddr, cr.Status)
}
switch cr.CheckAddr.Type {
case addrs.OutputPrecondition:
pcr.Type = planproto.CheckType_OUTPUT_PRECONDITION
case addrs.ResourcePrecondition:
pcr.Type = planproto.CheckType_RESOURCE_PRECONDITION
case addrs.ResourcePostcondition:
pcr.Type = planproto.CheckType_RESOURCE_POSTCONDITION
default:
return fmt.Errorf("condition result %s has unsupported type %s", cr.CheckAddr, cr.CheckAddr.Type)
return fmt.Errorf("checkable configuration %s has unsupported aggregate status %s", configElem.Key, crs.Status)
}
rawPlan.CheckResults = append(rawPlan.CheckResults, pcr)
for _, objectElem := range configElem.Value.ObjectResults.Elems {
cr := objectElem.Value
pcr := &planproto.CheckResults_ObjectResult{
ObjectAddr: objectElem.Key.String(),
FailureMessages: objectElem.Value.FailureMessages,
}
switch cr.Status {
case checks.StatusUnknown:
pcr.Status = planproto.CheckResults_UNKNOWN
case checks.StatusPass:
pcr.Status = planproto.CheckResults_PASS
case checks.StatusFail:
pcr.Status = planproto.CheckResults_FAIL
case checks.StatusError:
pcr.Status = planproto.CheckResults_ERROR
default:
return fmt.Errorf("checkable object %s has unsupported status %s", objectElem.Key, crs.Status)
}
pcrs.Objects = append(pcrs.Objects, pcr)
}
rawPlan.CheckResults = append(rawPlan.CheckResults, pcrs)
}
}

View File

@ -8,6 +8,7 @@ import (
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/checks"
"github.com/hashicorp/terraform/internal/lang/globalref"
"github.com/hashicorp/terraform/internal/lang/marks"
"github.com/hashicorp/terraform/internal/plans"
@ -171,19 +172,31 @@ func TestTFPlanRoundTrip(t *testing.T) {
},
},
Checks: &states.CheckResults{
Results: []*states.CheckResult{
{
CheckAddr: addrs.NewCheck(
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_thing",
Name: "woot",
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
addrs.ResourcePostcondition,
0,
),
},
},
ConfigResults: addrs.MakeMap(
addrs.MakeMapElem[addrs.ConfigCheckable](
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_thing",
Name: "woot",
}.InModule(addrs.RootModule),
&states.CheckResultAggregate{
Status: checks.StatusFail,
ObjectResults: addrs.MakeMap(
addrs.MakeMapElem[addrs.Checkable](
addrs.Resource{
Mode: addrs.ManagedResourceMode,
Type: "test_thing",
Name: "woot",
}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance),
&states.CheckResultObject{
Status: checks.StatusFail,
FailureMessages: []string{"Oh no!"},
},
),
),
},
),
),
},
TargetAddrs: []addrs.Targetable{
addrs.Resource{

View File

@ -5,28 +5,73 @@ import (
"github.com/hashicorp/terraform/internal/checks"
)
// CheckResults represents a snapshot of the status of a set of checks declared
// in configuration, updated after each Terraform Core run that changes the state
// or remote system in a way that might impact the check results.
// CheckResults represents a summary snapshot of the status of a set of checks
// declared in configuration, updated after each Terraform Core run that
// changes the state or remote system in a way that might impact the check
// results.
//
// Unlike a checks.State, this type only tracks the leaf check results and
// doesn't retain any information about how the checks were declared in
// configuration. That's because this subset of the data is intended to survive
// from one run to the next, and the next run will probably have a changed
// configuration anyway and so it's only meaningful to consider changes
// to the presence of checks and their statuses between runs.
// Unlike a checks.State, this type only tracks the overall results for
// each checkable object and doesn't aim to preserve the identity of individual
// checks in the configuration. For our UI reporting purposes, it is entire
// objects that pass or fail based on their declared checks; the individual
// checks have no durable identity between runs, and so are only a language
// design convenience to help authors describe various independent conditions
// with different failure messages each.
//
// CheckResults should typically be considered immutable once constructed:
// instead of updating it in-place,instead construct an entirely new
// CheckResults object based on a fresh checks.State.
type CheckResults struct {
Results []*CheckResult
// ConfigResults has all of the individual check results grouped by the
// configuration object they relate to.
//
// The top-level map here will always have a key for every configuration
// object that includes checks at the time of evaluating the results,
// even if there turned out to be no instances of that object and
// therefore no individual check results.
ConfigResults addrs.Map[addrs.ConfigCheckable, *CheckResultAggregate]
}
// Check is the state of a single check, inside the Checks struct.
type CheckResult struct {
CheckAddr addrs.Check
Status checks.Status
// CheckResultAggregate represents both the overall result for a particular
// configured object that has checks and the individual checkable objects
// it declared, if any.
type CheckResultAggregate struct {
// Status is the aggregate status across all objects.
//
// Sometimes an error or check failure during planning will prevent
// Terraform Core from even determining the individual checkable objects
// associated with a downstream configuration object, and that situation is
// described here by this Status being checks.StatusUnknown and there being
// no elements in the ObjectResults field.
//
// That's different than Terraform Core explicitly reporting that there are
// no instances of the config object (e.g. a resource with count = 0),
// which leads to the aggregate status being checks.StatusPass while
// ObjectResults is still empty.
Status checks.Status
// If Status is checks.StatusError then there might also be an error
// message describing what problem the check detected.
ErrorMessage string
ObjectResults addrs.Map[addrs.Checkable, *CheckResultObject]
}
// CheckResultObject is the check status for a single checkable object.
//
// This aggregates together all of the checks associated with a particular
// object into a single pass/fail/error/unknown result, because checkable
// objects have durable addresses that can survive between runs, but their
// individual checks do not. (Module authors are free to reorder their checks
// for a particular object in the configuration with no change in meaning.)
type CheckResultObject struct {
// Status is the check status of the checkable object, derived from the
// results of all of its individual checks.
Status checks.Status
// FailureMessages is an optional set of module-author-defined messages
// describing the problems that the checks detected, for objects whose
// status is checks.StatusFail.
//
// (checks.StatusError problems get reported as normal diagnostics during
// evaluation instead, and so will not appear here.)
FailureMessages []string
}
// NewCheckResults constructs a new states.CheckResults object that is a
@ -35,65 +80,103 @@ type CheckResult struct {
// This should be called only after a Terraform Core run has completed and
// recorded any results from running the checks in the given object.
func NewCheckResults(source *checks.State) *CheckResults {
statuses := source.AllCheckStatuses()
if statuses.Len() == 0 {
return &CheckResults{}
ret := &CheckResults{
ConfigResults: addrs.MakeMap[addrs.ConfigCheckable, *CheckResultAggregate](),
}
results := make([]*CheckResult, 0, statuses.Len())
for _, elem := range statuses.Elems {
errMsg := source.CheckFailureMessage(elem.Key)
results = append(results, &CheckResult{
CheckAddr: elem.Key,
Status: elem.Value,
ErrorMessage: errMsg,
})
for _, configAddr := range source.AllConfigAddrs() {
aggr := &CheckResultAggregate{
Status: source.AggregateCheckStatus(configAddr),
ObjectResults: addrs.MakeMap[addrs.Checkable, *CheckResultObject](),
}
for _, objectAddr := range source.ObjectAddrs(configAddr) {
obj := &CheckResultObject{
Status: source.ObjectCheckStatus(objectAddr),
FailureMessages: source.ObjectFailureMessages(objectAddr),
}
aggr.ObjectResults.Put(objectAddr, obj)
}
ret.ConfigResults.Put(configAddr, aggr)
}
return &CheckResults{results}
// If there aren't actually any configuration objects then we'll just
// leave the map as a whole nil, because having it be zero-value makes
// life easier for deep comparisons in unit tests elsewhere.
if ret.ConfigResults.Len() == 0 {
ret.ConfigResults.Elems = nil
}
return ret
}
// AllCheckedObjects returns a set of all of the objects that have at least
// one check in the set of results.
func (r *CheckResults) AllCheckedObjects() addrs.Set[addrs.Checkable] {
if r == nil || len(r.Results) == 0 {
if r == nil || len(r.ConfigResults.Elems) == 0 {
return nil
}
ret := addrs.MakeSet[addrs.Checkable]()
for _, result := range r.Results {
ret.Add(result.CheckAddr.Container)
for _, configElem := range r.ConfigResults.Elems {
for _, objElem := range configElem.Value.ObjectResults.Elems {
ret.Add(objElem.Key)
}
}
return ret
}
// GetCheckResults scans over the checks and returns the first one that
// has the given address, or nil if there is no such check.
// GetObjectResult looks up the result for a single object, or nil if there
// is no such object.
//
// In main code we shouldn't typically need to look up individual checks
// In main code we shouldn't typically need to look up individual objects
// like this, since we'll usually be reporting check results in an aggregate
// form, but determining the result of a particular check is useful in our
// form, but determining the result of a particular object is useful in our
// internal unit tests, and so this is here primarily for that purpose.
func (r *CheckResults) GetCheckResult(addr addrs.Check) *CheckResult {
for _, result := range r.Results {
if addrs.Equivalent(result.CheckAddr, addr) {
return result
}
func (r *CheckResults) GetObjectResult(objectAddr addrs.Checkable) *CheckResultObject {
configAddr := objectAddr.ConfigCheckable()
aggr := r.ConfigResults.Get(configAddr)
if aggr == nil {
return nil
}
return nil
return aggr.ObjectResults.Get(objectAddr)
}
func (r *CheckResults) DeepCopy() *CheckResults {
if r == nil {
return nil
}
if len(r.Results) == 0 {
return &CheckResults{}
ret := &CheckResults{}
if r.ConfigResults.Elems == nil {
return ret
}
// Everything inside CheckResult is either a value type or is
// treated as immutable by convention, so we don't need to
// copy any deeper.
results := make([]*CheckResult, len(r.Results))
copy(results, r.Results)
return &CheckResults{results}
ret.ConfigResults = addrs.MakeMap[addrs.ConfigCheckable, *CheckResultAggregate]()
for _, configElem := range r.ConfigResults.Elems {
aggr := &CheckResultAggregate{
Status: configElem.Value.Status,
}
if configElem.Value.ObjectResults.Elems != nil {
aggr.ObjectResults = addrs.MakeMap[addrs.Checkable, *CheckResultObject]()
for _, objectElem := range configElem.Value.ObjectResults.Elems {
result := &CheckResultObject{
Status: objectElem.Value.Status,
// NOTE: We don't deep-copy this slice because it's
// immutable once constructed by convention.
FailureMessages: objectElem.Value.FailureMessages,
}
aggr.ObjectResults.Put(objectElem.Key, result)
}
}
ret.ConfigResults.Put(configElem.Key, aggr)
}
return ret
}

View File

@ -2912,22 +2912,14 @@ resource "test_resource" "a" {
}
addr := mustResourceInstanceAddr("data.test_data_source.a")
wantCheckTypes := []addrs.CheckType{
addrs.ResourcePrecondition,
addrs.ResourcePostcondition,
}
for _, ty := range wantCheckTypes {
checkAddr := addr.Check(ty, 0)
if gotResult := plan.Checks.GetCheckResult(checkAddr); gotResult == nil {
t.Errorf("no condition result for %s", checkAddr)
} else {
wantResult := &states.CheckResult{
CheckAddr: checkAddr,
Status: checks.StatusPass,
}
if diff := cmp.Diff(wantResult, gotResult, valueComparer); diff != "" {
t.Errorf("wrong condition result for %s\n%s", checkAddr, diff)
}
if gotResult := plan.Checks.GetObjectResult(addr); gotResult == nil {
t.Errorf("no check result for %s", addr)
} else {
wantResult := &states.CheckResultObject{
Status: checks.StatusPass,
}
if diff := cmp.Diff(wantResult, gotResult, valueComparer); diff != "" {
t.Errorf("wrong check result for %s\n%s", addr, diff)
}
}
})
@ -3034,17 +3026,17 @@ resource "test_resource" "a" {
t.Fatalf("wrong error:\ngot: %s\nwant: %q", got, want)
}
addr := mustResourceInstanceAddr("data.test_data_source.a")
checkAddr := addr.Check(addrs.ResourcePostcondition, 0)
if gotResult := plan.Checks.GetCheckResult(checkAddr); gotResult == nil {
t.Errorf("no condition result for %s", checkAddr)
if gotResult := plan.Checks.GetObjectResult(addr); gotResult == nil {
t.Errorf("no check result for %s", addr)
} else {
wantResult := &states.CheckResult{
CheckAddr: checkAddr,
Status: checks.StatusFail,
ErrorMessage: "Results cannot be empty.",
wantResult := &states.CheckResultObject{
Status: checks.StatusFail,
FailureMessages: []string{
"Results cannot be empty.",
},
}
if diff := cmp.Diff(wantResult, gotResult, valueComparer); diff != "" {
t.Errorf("wrong condition result\n%s", diff)
t.Errorf("wrong check result\n%s", diff)
}
}
})
@ -3129,16 +3121,14 @@ output "a" {
if got, want := outputPlan.Action, plans.Create; got != want {
t.Errorf("wrong planned action\ngot: %s\nwant: %s", got, want)
}
checkAddr := addr.Check(addrs.OutputPrecondition, 0)
if gotResult := plan.Checks.GetCheckResult(checkAddr); gotResult == nil {
t.Errorf("no condition result for %s", checkAddr)
if gotResult := plan.Checks.GetObjectResult(addr); gotResult == nil {
t.Errorf("no check result for %s", addr)
} else {
wantResult := &states.CheckResult{
CheckAddr: checkAddr,
Status: checks.StatusPass,
wantResult := &states.CheckResultObject{
Status: checks.StatusPass,
}
if diff := cmp.Diff(wantResult, gotResult, valueComparer); diff != "" {
t.Errorf("wrong condition result\n%s", diff)
t.Errorf("wrong check result\n%s", diff)
}
}
})
@ -3189,14 +3179,12 @@ output "a" {
if got, want := outputPlan.Action, plans.Create; got != want {
t.Errorf("wrong planned action\ngot: %s\nwant: %s", got, want)
}
checkAddr := addr.Check(addrs.OutputPrecondition, 0)
if gotResult := plan.Checks.GetCheckResult(checkAddr); gotResult == nil {
t.Errorf("no condition result for %s", checkAddr)
if gotResult := plan.Checks.GetObjectResult(addr); gotResult == nil {
t.Errorf("no condition result for %s", addr)
} else {
wantResult := &states.CheckResult{
CheckAddr: checkAddr,
Status: checks.StatusFail,
ErrorMessage: "Wrong boop.",
wantResult := &states.CheckResultObject{
Status: checks.StatusFail,
FailureMessages: []string{"Wrong boop."},
}
if diff := cmp.Diff(wantResult, gotResult, valueComparer); diff != "" {
t.Errorf("wrong condition result\n%s", diff)