tftypes

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 20, 2020 License: MPL-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package tftypes provides a type system for Terraform configuration and state values.

Terraform's configuration and state values are stored using a collection of types. There are primitive types, such as strings, numbers, and booleans, but there are also aggregate types such as lists, sets, tuples, maps, and objects, which consist of multiple values of primitive types aggregated into a single value. There is also a dynamic pseudo-type that represents an unknown type. It is useful for indicating that any type of data is acceptable.

Terraform's values map neatly onto either primitives built into Go or types in the Go standard library, with one exception. Terraform has the concept of unknown values, values that may or may not be set at a future date. These are distinct from null values, which indicate a value that is known to not be set, and are mostly encountered when a user has interpolated a computed field into another field; the field that is interpolated into has an unknown value, because the field being interpolated won't have its value known until apply time.

To address this, the tftypes package wraps all values in a special Value type. This Value type is capable of holding known and unknown values, interrogating whether the value is known or not, and accessing the concrete value that Terraform sent in the cases where the value is known. A common pattern is to use the Value.IsKnown() method to confirm that a value is known, then to use the Value.As() method to retrieve the underlying data for use.

When using the Value.As() method, certain types have built-in behavior to support using them as destinations for converted data:

* String values can be converted into strings

* Number values can be converted into *big.Floats

* Boolean values can be converted into bools

* List, Set, and Tuple values can be converted into a slice of Values

* Map and Object values can be converted into a map with string keys and Value values.

These defaults were chosen because they're capable of losslessly representing all possible values for their Terraform type, with the exception of null values. Converting into pointer versions of any of these types will correctly surface null values as well.

Custom, provider-defined types can define their own conversion logic that will be respected by Value.As(), as well, by implementing the FromTerraform5Value method for that type. The FromTerraform5Value method accepts a Value as an argument and returns an error. The Value passed in will be the same Value that Value.As() was called on. The recommended implementation of the FromTerraform5Value method is to call Value.As() on the passed Value, converting it into one of the built-in types above, and then performing whatever type casting or conversion logic is required to assign the data to the provider-supplied type.

Index

Examples

Constants

View Source
const (
	// DynamicPseudoType is a pseudo-type in Terraform's type system that
	// is used as a wildcard type. It indicates that any Terraform type can
	// be used.
	DynamicPseudoType = primitive("DynamicPseudoType")

	// String is a primitive type in Terraform that represents a UTF-8
	// string of bytes.
	String = primitive("String")

	// Number is a primitive type in Terraform that represents a real
	// number.
	Number = primitive("Number")

	// Bool is a primitive type in Terraform that represents a true or
	// false boolean value.
	Bool = primitive("Bool")
)
View Source
const (
	// UnknownValue represents a value that is not yet known. It can be the
	// value of any type.
	UnknownValue = unknown(0)
)

Variables

View Source
var (
	// ErrNotAttributePathStepper is returned when a type that doesn't full
	// the AttributePathStepper interface is passed to WalkAttributePath.
	ErrNotAttributePathStepper = errors.New("doesn't fill tftypes.AttributePathStepper interface")

	// ErrInvalidStep is returned when an AttributePath has the wrong kind
	// of AttributePathStep for the type that WalkAttributePath is
	// operating on.
	ErrInvalidStep = errors.New("step cannot be applied to this value")
)

Functions

func ValueComparer

func ValueComparer() cmp.Option

ValueComparer returns a github.com/google/go-cmp/cmp#Option that can be used to tell go-cmp how to compare Values.

Types

type AttributeName

type AttributeName string

AttributeName is an AttributePathStep implementation that indicates the next step in the AttributePath is to select an attribute. The value of the AttributeName is the name of the attribute to be selected.

type AttributePath

type AttributePath struct {
	// Steps are the steps that must be followed from the root of the value
	// to obtain the value being indicated.
	Steps []AttributePathStep
}

AttributePath is a type that can point to a specific value within an aggregate Terraform value. It consists of steps, each identifying one element or attribute of the current value, and making that the current value. This allows referring to arbitrarily precise values.

func WalkAttributePath

func WalkAttributePath(in interface{}, path AttributePath) (interface{}, AttributePath, error)

WalkAttributePath will return the value that `path` is pointing to, using `in` as the root. If an error is returned, the AttributePath returned will indicate the steps that remained to be applied when the error was encountered.

map[string]interface{} and []interface{} types have built-in support. Other types need to use the AttributePathStepper interface to tell WalkAttributePath how to traverse themselves.

func (AttributePath) NewError

func (a AttributePath) NewError(err error) error

NewError returns an error that associates `err` with the value indicated by `a`.

func (AttributePath) NewErrorf

func (a AttributePath) NewErrorf(f string, args ...interface{}) error

NewErrorf returns an error associated with the value indicated by `a`. This is equivalent to calling a.NewError(fmt.Errorf(f, args...)).

func (*AttributePath) WithAttributeName

func (a *AttributePath) WithAttributeName(name string)

WithAttributeName adds an AttributeName step to `a`, using `name` as the attribute's name.

func (*AttributePath) WithElementKeyInt

func (a *AttributePath) WithElementKeyInt(key int64)

WithElementKeyInt adds an ElementKeyInt step to `a`, using `key` as the element's key.

func (*AttributePath) WithElementKeyString

func (a *AttributePath) WithElementKeyString(key string)

WithElementKeyString adds an ElementKeyString step to `a`, using `key` as the element's key.

func (*AttributePath) WithElementKeyValue

func (a *AttributePath) WithElementKeyValue(key Value)

WithElementKeyValue adds an ElementKeyValue to `a`, using `key` as the element's key.

func (*AttributePath) WithoutLastStep

func (a *AttributePath) WithoutLastStep()

WithoutLastStep removes the last step, whatever kind of step it was, from `a`.

type AttributePathStep

type AttributePathStep interface {
	// contains filtered or unexported methods
}

AttributePathStep is an intentionally unimplementable interface that functions as an enum, allowing us to use different strongly-typed step types as a generic "step" type.

An AttributePathStep is meant to indicate a single step in an AttributePath, indicating a specific attribute or element that is the next value in the path.

type AttributePathStepper

type AttributePathStepper interface {
	// Return the attribute or element the AttributePathStep is referring
	// to, or an error if the AttributePathStep is referring to an
	// attribute or element that doesn't exist.
	ApplyTerraform5AttributePathStep(AttributePathStep) (interface{}, error)
}

AttributePathStepper is an interface that types can implement to make them traversable by WalkAttributePath, allowing providers to retrieve the specific value an AttributePath is pointing to.

type ElementKeyInt

type ElementKeyInt int64

ElementKeyInt is an AttributePathStep implementation that indicates the next step in the AttributePath is to select an element using an int64 key. The value of the ElementKeyInt is the key of the element to select.

type ElementKeyString

type ElementKeyString string

ElementKeyString is an AttributePathStep implementation that indicates the next step in the AttributePath is to select an element using a string key. The value of the ElementKeyString is the key of the element to select.

type ElementKeyValue

type ElementKeyValue Value

ElementKeyValue is an AttributePathStep implementation that indicates the next step in the AttributePath is to select an element using the element itself as a key. The value of the ElementKeyValue is the key of the element to select.

type List

type List struct {
	ElementType Type
}

List is a Terraform type representing an ordered collection of elements, all of the same type.

func (List) Is

func (l List) Is(t Type) bool

Is returns whether `t` is a List type or not. If `t` is an instance of the List type and its ElementType property is nil, it will return true. If `t`'s ElementType property is not nil, it will only return true if its ElementType is considered the same type as `l`'s ElementType.

func (List) MarshalJSON deprecated

func (l List) MarshalJSON() ([]byte, error)

MarshalJSON returns a JSON representation of the full type signature of `l`, including its ElementType.

Deprecated: this is not meant to be called by third-party code.

func (List) String

func (l List) String() string

type Map

type Map struct {
	AttributeType Type
}

Map is a Terraform type representing an unordered collection of elements, all of the same type, each identifiable with a unique string key.

func (Map) Is

func (m Map) Is(t Type) bool

Is returns whether `t` is a Map type or not. If `t` is an instance of the Map type and its AttributeType property is not nil, it will only return true if its AttributeType is considered the same type as `m`'s AttributeType.

func (Map) MarshalJSON deprecated

func (m Map) MarshalJSON() ([]byte, error)

MarshalJSON returns a JSON representation of the full type signature of `m`, including its AttributeType.

Deprecated: this is not meant to be called by third-party code.

func (Map) String

func (m Map) String() string

type Object

type Object struct {
	AttributeTypes map[string]Type
}

Object is a Terraform type representing an unordered collection of attributes, potentially of differing types, each identifiable with a unique string name. The number of attributes, their names, and their types are part of the type signature for the Object, and so two Objects with different attribute names or types are considered to be distinct types.

func (Object) Is

func (o Object) Is(t Type) bool

Is returns whether `t` is an Object type or not. If `t` is an instance of the Object type and its AttributeTypes property is not nil, it will only return true the AttributeTypes are considered the same. To be considered equal, the same set of keys must be present in each, and each key's value needs to be considered the same type between the two Objects.

func (Object) MarshalJSON deprecated

func (o Object) MarshalJSON() ([]byte, error)

MarshalJSON returns a JSON representation of the full type signature of `o`, including the AttributeTypes.

Deprecated: this is not meant to be called by third-party code.

func (Object) String

func (o Object) String() string

type Set

type Set struct {
	ElementType Type
}

Set is a Terraform type representing an unordered collection of unique elements, all of the same type.

func (Set) Is

func (s Set) Is(t Type) bool

Is returns whether `t` is a Set type or not. If `t` is an instance of the Set type and its ElementType property is nil, it will return true. If `t`'s ElementType property is not nil, it will only return true if its ElementType is considered the same type as `s`'s ElementType.

func (Set) MarshalJSON deprecated

func (s Set) MarshalJSON() ([]byte, error)

MarshalJSON returns a JSON representation of the full type signature of `s`, including its ElementType.

Deprecated: this is not meant to be called by third-party code.

func (Set) String

func (s Set) String() string

type Tuple

type Tuple struct {
	ElementTypes []Type
}

Tuple is a Terraform type representing an ordered collection of elements, potentially of differing types. The number of elements and their types are part of the type signature for the Tuple, and so two Tuples with different numbers or types of elements are considered to be distinct types.

func (Tuple) Is

func (tu Tuple) Is(t Type) bool

Is returns whether `t` is a Tuple type or not. If `t` is an instance of the Tuple type and its ElementTypes property is not nil, it will only return true if the ElementTypes are considered the same. To be considered the same, there must be the same number of ElementTypes, arranged in the same order, and the types in each position must be considered the same as the type in the same position in the other Tuple.

func (Tuple) MarshalJSON deprecated

func (tu Tuple) MarshalJSON() ([]byte, error)

MarshalJSON returns a JSON representation of the full type signature of `tu`, including the ElementTypes.

Deprecated: this is not meant to be called by third-party code.

func (Tuple) String

func (tu Tuple) String() string

type Type

type Type interface {
	// Is is used to determine what type a Type implementation is. It is
	// the recommended method for determining whether two types are
	// equivalent or not.
	Is(Type) bool

	// String returns a string representation of the Type's name.
	String() string

	// MarshalJSON returns a JSON representation of the Type's signature.
	// It is modeled based on Terraform's requirements for type signature
	// JSON representations, and may change over time to match Terraform's
	// formatting.
	//
	// Deprecated: this is not meant to be called by third-party code.
	MarshalJSON() ([]byte, error)
	// contains filtered or unexported methods
}

Type is an interface representing a Terraform type. It is only meant to be implemented by the tftypes package. Types define the shape and characteristics of data coming from or being sent to Terraform.

func ParseJSONType deprecated

func ParseJSONType(buf []byte) (Type, error)

ParseJSONType returns a Type from its JSON representation. The JSON representation should come from Terraform or from MarshalJSON as the format is not part of this package's API guarantees.

Deprecated: this is not meant to be called by third-party code.

func TypeFromElements

func TypeFromElements(elements []Value) (Type, error)

TypeFromElements returns the common type that the passed elements all have in common. An error will be returned if the passed elements are not of the same type.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value is a piece of data from Terraform or being returned to Terraform. It has a Type associated with it, defining its shape and characteristics, and a Go representation of that Type containing the data itself. Values are a special type and are not represented as pure Go values beause they can contain UnknownValues, which cannot be losslessly represented in Go's type system.

The recommended usage of a Value is to check that it is known, using Value.IsKnown, then to convert it to a Go type, using Value.As. The Go type can then be manipulated.

func NewValue

func NewValue(t Type, val interface{}) Value

NewValue returns a Value constructed using the specified Type and stores the passed value in it.

The passed value should be in one of the builtin Value representations or implement the ValueCreator interface.

The builtin Value representations are:

* String: string, *string

  • Number: *big.Float, int64, *int64, int32, *int32, int16, *int16, int8, *int8, int, *int, uint64, *uint64, uint32, *uint32, uint16, *uint16, uint8, *uint8, byte, *byte, uint, *uint, float64, *float64, float32, *float32

* Bool: bool, *bool

* Map and Object: map[string]Value

* Tuple, List, and Set: []Value

func (Value) As

func (val Value) As(dst interface{}) error

As converts a Value into a Go value. `dst` must be set to a pointer to a value of a supported type for the Value's type or an implementation of the ValueConverter interface.

For Strings, `dst` must be a pointer to a string or a pointer to a pointer to a string. If it's a pointer to a pointer to a string, if the Value is null, the pointer to the string will be set to nil. If it's a pointer to a string, if the Value is null, the string will be set to the empty value.

For Numbers, `dst` must be a poitner to a big.Float or a pointer to a pointer to a big.Float. If it's a pointer to a pointer to a big.Float, if the Value is null, the pointer to the big.Float will be set to nil. If it's a pointer to a big.Float, if the Value is null, the big.Float will be set to 0.

For Bools, `dst` must be a pointer to a bool or a pointer to a pointer to a bool. If it's a pointer to a pointer to a bool, if the Value is null, the pointer to the bool will be set to nil. If it's a pointer to a bool, if the Value is null, the bool will be set to false.

For Maps and Objects, `dst` must be a pointer to a map[string]Value or a pointer to a pointer to a map[string]Value. If it's a pointer to a pointer to a map[string]Value, if the Value is null, the pointer to the map[string]Value will be set to nil. If it's a pointer to a map[string]Value, if the Value is null, the map[string]Value will be set to an empty map.

For Lists, Sets, and Tuples, `dst` must be a pointer to a []Value or a pointer to a pointer to a []Value. If it's a pointer to a pointer to a []Value, if the Value is null, the poitner to []Value will be set to nil. If it's a pointer to a []Value, if the Value is null, the []Value will be set to an empty slice.

Future builtin conversions may be added over time.

If `val` is unknown, an error will be returned, as unknown values can't be represented in Go's type system. Providers should check Value.IsKnown before calling Value.As.

Example (Interface)
package main

import (
	"fmt"

	"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
)

type exampleResource struct {
	name         string
	suppliedName *bool
}

// fill the tftypes.ValueConverter interface to control how As works
// we want a pointer to exampleResource so we can change the properties
func (e *exampleResource) FromTerraform5Value(val tftypes.Value) error {

	v := map[string]tftypes.Value{}
	err := val.As(&v)
	if err != nil {
		return err
	}

	err = v["name"].As(&e.name)
	if err != nil {
		return err
	}

	err = v["supplied_name"].As(&e.suppliedName)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	// our tftypes.Value would usually come over the wire as a
	// DynamicValue, but for simplicity, let's just declare one inline here
	val := tftypes.NewValue(tftypes.Object{
		AttributeTypes: map[string]tftypes.Type{
			"name":          tftypes.String,
			"supplied_name": tftypes.Bool,
		},
	}, map[string]tftypes.Value{
		"name":          tftypes.NewValue(tftypes.String, "ozymandias"),
		"supplied_name": tftypes.NewValue(tftypes.Bool, nil),
	})

	// exampleResource has FromTerraform5Value method defined on it, see
	// value_example_test.go for implementation details. We'd put the
	// function and type inline here, but apparently Go can't have methods
	// defined on types defined inside a function
	var res exampleResource

	// call As as usual
	err := val.As(&res)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.name)
	fmt.Println(res.suppliedName)
}
Output:

ozymandias
<nil>
Example (String)
package main

import (
	"fmt"

	"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
)

func main() {
	// Values come over the wire, usually from a DynamicValue for this
	// example, we're just building one inline
	val := tftypes.NewValue(tftypes.String, "hello, world")

	var salutation string

	// we need to use a pointer so we can modify the value, just like
	// json.Unmarshal
	err := val.As(&salutation)
	if err != nil {
		panic(err)
	}

	fmt.Println(salutation)
}
Output:

hello, world
Example (StringNull)
package main

import (
	"fmt"

	"github.com/hashicorp/terraform-plugin-go/tfprotov5/tftypes"
)

func main() {
	type exampleResource struct {
		salutation         string
		nullableSalutation *string
	}

	// let's see what happens when we have a null value
	val := tftypes.NewValue(tftypes.String, nil)

	var res exampleResource

	// we can use a pointer to a variable, but the variable can't hold nil,
	// so we'll get the empty value. You can use this if you don't care
	// about null, and consider it equivalent to the empty value.
	err := val.As(&res.salutation)
	if err != nil {
		panic(err)
	}

	// we can use a pointer to a pointer to a variable, which can hold nil,
	// so we'll be able to distinguish between a null and an empty string
	err = val.As(&res.nullableSalutation)
	if err != nil {
		panic(err)
	}

	fmt.Println(res.salutation)
	fmt.Println(res.nullableSalutation)
}
Output:


<nil>

func (Value) Is

func (val Value) Is(t Type) bool

Is calls Type.Is using the Type of the Value.

func (Value) IsFullyKnown

func (val Value) IsFullyKnown() bool

IsFullyKnown returns true if `val` is known. If `val` is an aggregate type, IsFullyKnown only returns true if all elements and attributes are known, as well.

func (Value) IsKnown

func (val Value) IsKnown() bool

IsKnown returns true if `val` is known. If `val` is an aggregate type, only the top level of the aggregate type is checked; elements and attributes are not checked.

func (Value) IsNull

func (val Value) IsNull() bool

IsNull returns true if the Value is null.

func (Value) MarshalMsgPack deprecated

func (val Value) MarshalMsgPack(t Type) ([]byte, error)

MarshalMsgPack returns a msgpack representation of the Value. This is used for constructing tfprotov5.DynamicValues.

Deprecated: this is not meant to be called by third parties. Don't use it.

type ValueConverter

type ValueConverter interface {
	FromTerraform5Value(Value) error
}

ValueConverter is an interface that provider-defined types can implement to control how Value.As will convert a Value into that type. The passed Value is the Value that Value.As is being called on. The intended usage is to call Value.As on the passed Value, converting it into a builtin type, and then converting or casting that builtin type to the provider-defined type.

type ValueCreator

type ValueCreator interface {
	ToTerraform5Value() (interface{}, error)
}

ValueCreator is an interface that provider-defined types can implement to control how NewValue will convert that type into a Value. The returned interface should return one of the builtin Value representations that should be used for that Value.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL