github.com/opentofu/opentofu@v1.7.1/internal/checks/status.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package checks
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"github.com/zclconf/go-cty/cty"
    12  )
    13  
    14  // Status represents the status of an individual check associated with a
    15  // checkable object.
    16  type Status rune
    17  
    18  //go:generate go run golang.org/x/tools/cmd/stringer -type=Status
    19  
    20  const (
    21  	// StatusUnknown represents that there is not yet a conclusive result
    22  	// for the check, either because we haven't yet visited its associated
    23  	// object or because the check condition itself depends on a value not
    24  	// yet known during planning.
    25  	StatusUnknown Status = 0
    26  	// NOTE: Our implementation relies on StatusUnknown being the zero value
    27  	// of Status.
    28  
    29  	// StatusPass represents that OpenTofu Core has evaluated the check's
    30  	// condition and it returned true, indicating success.
    31  	StatusPass Status = 'P'
    32  
    33  	// StatusFail represents that OpenTofu Core has evaluated the check's
    34  	// condition and it returned false, indicating failure.
    35  	StatusFail Status = 'F'
    36  
    37  	// StatusError represents that OpenTofu Core tried to evaluate the check's
    38  	// condition but encountered an error while evaluating the check expression.
    39  	//
    40  	// This is different than StatusFail because StatusFail indiciates that
    41  	// the condition was valid and returned false, whereas StatusError
    42  	// indicates that the condition was not valid at all.
    43  	StatusError Status = 'E'
    44  )
    45  
    46  // StatusForCtyValue returns the Status value corresponding to the given
    47  // cty Value, which must be one of either cty.True, cty.False, or
    48  // cty.UnknownVal(cty.Bool) or else this function will panic.
    49  //
    50  // The current behavior of this function is:
    51  //
    52  //	cty.True                  StatusPass
    53  //	cty.False                 StatusFail
    54  //	cty.UnknownVal(cty.Bool)  StatusUnknown
    55  //
    56  // Any other input will panic. Note that there's no value that can produce
    57  // StatusError, because in case of a condition error there will not typically
    58  // be a result value at all.
    59  func StatusForCtyValue(v cty.Value) Status {
    60  	if !v.Type().Equals(cty.Bool) {
    61  		panic(fmt.Sprintf("cannot use %s as check status", v.Type().FriendlyName()))
    62  	}
    63  	if v.IsNull() {
    64  		panic("cannot use null as check status")
    65  	}
    66  
    67  	switch {
    68  	case v == cty.True:
    69  		return StatusPass
    70  	case v == cty.False:
    71  		return StatusFail
    72  	case !v.IsKnown():
    73  		return StatusUnknown
    74  	default:
    75  		// Should be impossible to get here unless something particularly
    76  		// weird is going on, like a marked condition result.
    77  		panic(fmt.Sprintf("cannot use %#v as check status", v))
    78  	}
    79  }