Skip to content

Commit 38435fb

Browse files
author
Paddy Carver
committed
Document tftypes package.
1 parent b5c2c6b commit 38435fb

File tree

11 files changed

+232
-13
lines changed

11 files changed

+232
-13
lines changed

tfprotov5/tftypes/attribute_path.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,81 @@ import (
66
)
77

88
var (
9+
// ErrNotAttributePathStepper is returned when a type that doesn't full
10+
// the AttributePathStepper interface is passed to WalkAttributePath.
911
ErrNotAttributePathStepper = errors.New("doesn't fill tftypes.AttributePathStepper interface")
10-
ErrInvalidStep = errors.New("step cannot be applied to this value")
12+
13+
// ErrInvalidStep is returned when an AttributePath has the wrong kind
14+
// of AttributePathStep for the type that WalkAttributePath is
15+
// operating on.
16+
ErrInvalidStep = errors.New("step cannot be applied to this value")
1117
)
1218

19+
// AttributePath is a type that can point to a specific value within an
20+
// aggregate Terraform value. It consists of steps, each identifying one
21+
// element or attribute of the current value, and making that the current
22+
// value. This allows referring to arbitrarily precise values.
1323
type AttributePath struct {
24+
// Steps are the steps that must be followed from the root of the value
25+
// to obtain the value being indicated.
1426
Steps []AttributePathStep
1527
}
1628

29+
// NewErrorf returns an error associated with the value indicated by `a`. This
30+
// is equivalent to calling a.NewError(fmt.Errorf(f, args...)).
1731
func (a AttributePath) NewErrorf(f string, args ...interface{}) error {
1832
return attributePathError{
1933
error: fmt.Errorf(f, args...),
2034
path: a,
2135
}
2236
}
2337

38+
// NewError returns an error that associates `err` with the value indicated by
39+
// `a`.
2440
func (a AttributePath) NewError(err error) error {
2541
return attributePathError{
2642
error: err,
2743
path: a,
2844
}
2945
}
3046

47+
// WithAttributeName adds an AttributeName step to `a`, using `name` as the
48+
// attribute's name.
3149
func (a *AttributePath) WithAttributeName(name string) {
3250
a.Steps = append(a.Steps, AttributeName(name))
3351
}
3452

53+
// WithElementKeyString adds an ElementKeyString step to `a`, using `key` as
54+
// the element's key.
3555
func (a *AttributePath) WithElementKeyString(key string) {
3656
a.Steps = append(a.Steps, ElementKeyString(key))
3757
}
3858

59+
// WithElementKeyInt adds an ElementKeyInt step to `a`, using `key` as the
60+
// element's key.
3961
func (a *AttributePath) WithElementKeyInt(key int64) {
4062
a.Steps = append(a.Steps, ElementKeyInt(key))
4163
}
4264

65+
// WithElementKeyValue adds an ElementKeyValue to `a`, using `key` as the
66+
// element's key.
4367
func (a *AttributePath) WithElementKeyValue(key Value) {
4468
a.Steps = append(a.Steps, ElementKeyValue(key))
4569
}
4670

71+
// WithoutLastStep removes the last step, whatever kind of step it was, from
72+
// `a`.
4773
func (a *AttributePath) WithoutLastStep() {
4874
a.Steps = a.Steps[:len(a.Steps)-1]
4975
}
5076

77+
// AttributePathStep is an intentionally unimplementable interface that
78+
// functions as an enum, allowing us to use different strongly-typed step types
79+
// as a generic "step" type.
80+
//
81+
// An AttributePathStep is meant to indicate a single step in an AttributePath,
82+
// indicating a specific attribute or element that is the next value in the
83+
// path.
5184
type AttributePathStep interface {
5285
unfulfillable() // make this interface fillable only by this package
5386
}
@@ -58,29 +91,53 @@ var (
5891
_ AttributePathStep = ElementKeyInt(0)
5992
)
6093

94+
// AttributeName is an AttributePathStep implementation that indicates the next
95+
// step in the AttributePath is to select an attribute. The value of the
96+
// AttributeName is the name of the attribute to be selected.
6197
type AttributeName string
6298

6399
func (a AttributeName) unfulfillable() {}
64100

101+
// ElementKeyString is an AttributePathStep implementation that indicates the
102+
// next step in the AttributePath is to select an element using a string key.
103+
// The value of the ElementKeyString is the key of the element to select.
65104
type ElementKeyString string
66105

67106
func (e ElementKeyString) unfulfillable() {}
68107

108+
// ElementKeyInt is an AttributePathStep implementation that indicates the next
109+
// step in the AttributePath is to select an element using an int64 key. The
110+
// value of the ElementKeyInt is the key of the element to select.
69111
type ElementKeyInt int64
70112

71113
func (e ElementKeyInt) unfulfillable() {}
72114

115+
// ElementKeyValue is an AttributePathStep implementation that indicates the
116+
// next step in the AttributePath is to select an element using the element
117+
// itself as a key. The value of the ElementKeyValue is the key of the element
118+
// to select.
73119
type ElementKeyValue Value
74120

75121
func (e ElementKeyValue) unfulfillable() {}
76122

123+
// AttributePathStepper is an interface that types can implement to make them
124+
// traversable by WalkAttributePath, allowing providers to retrieve the
125+
// specific value an AttributePath is pointing to.
77126
type AttributePathStepper interface {
78127
// Return the attribute or element the AttributePathStep is referring
79128
// to, or an error if the AttributePathStep is referring to an
80129
// attribute or element that doesn't exist.
81130
ApplyTerraform5AttributePathStep(AttributePathStep) (interface{}, error)
82131
}
83132

133+
// WalkAttributePath will return the value that `path` is pointing to, using
134+
// `in` as the root. If an error is returned, the AttributePath returned will
135+
// indicate the steps that remained to be applied when the error was
136+
// encountered.
137+
//
138+
// map[string]interface{} and []interface{} types have built-in support. Other
139+
// types need to use the AttributePathStepper interface to tell
140+
// WalkAttributePath how to traverse themselves.
84141
func WalkAttributePath(in interface{}, path AttributePath) (interface{}, AttributePath, error) {
85142
if len(path.Steps) < 1 {
86143
return in, path, nil

tfprotov5/tftypes/doc.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@
3030
// support using them as destinations for converted data:
3131
//
3232
// * String values can be converted into strings
33+
//
3334
// * Number values can be converted into *big.Floats
35+
//
3436
// * Boolean values can be converted into bools
37+
//
3538
// * List, Set, and Tuple values can be converted into a slice of Values
39+
//
3640
// * Map and Object values can be converted into a map with string keys and
37-
// Value values.
41+
// Value values.
3842
//
3943
// These defaults were chosen because they're capable of losslessly
4044
// representing all possible values for their Terraform type, with the

tfprotov5/tftypes/list.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ package tftypes
22

33
import "fmt"
44

5+
// List is a Terraform type representing an ordered collection of elements, all
6+
// of the same type.
57
type List struct {
68
ElementType Type
79
}
810

11+
// Is returns whether `t` is a List type or not. If `t` is an instance of the
12+
// List type and its ElementType property is nil, it will return true. If `t`'s
13+
// ElementType property is not nil, it will only return true if its ElementType
14+
// is considered the same type as `l`'s ElementType.
915
func (l List) Is(t Type) bool {
1016
v, ok := t.(List)
1117
if !ok {
@@ -23,6 +29,8 @@ func (l List) String() string {
2329

2430
func (l List) private() {}
2531

32+
// MarshalJSON returns a JSON representation of the full type signature of `l`,
33+
// including its ElementType.
2634
func (l List) MarshalJSON() ([]byte, error) {
2735
elementType, err := l.ElementType.MarshalJSON()
2836
if err != nil {

tfprotov5/tftypes/map.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@ package tftypes
22

33
import "fmt"
44

5+
// Map is a Terraform type representing an unordered collection of elements,
6+
// all of the same type, each identifiable with a unique string key.
57
type Map struct {
68
AttributeType Type
79
}
810

11+
// Is returns whether `t` is a Map type or not. If `t` is an instance of the
12+
// Map type and its AttributeType property is not nil, it will only return true
13+
// if its AttributeType is considered the same type as `m`'s AttributeType.
914
func (m Map) Is(t Type) bool {
1015
v, ok := t.(Map)
1116
if !ok {
@@ -23,6 +28,8 @@ func (m Map) String() string {
2328

2429
func (m Map) private() {}
2530

31+
// MarshalJSON returns a JSON representation of the full type signature of `m`,
32+
// including its AttributeType.
2633
func (m Map) MarshalJSON() ([]byte, error) {
2734
attributeType, err := m.AttributeType.MarshalJSON()
2835
if err != nil {

tfprotov5/tftypes/object.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@ package tftypes
22

33
import "encoding/json"
44

5+
// Object is a Terraform type representing an unordered collection of
6+
// attributes, potentially of differing types, each identifiable with a unique
7+
// string name. The number of attributes, their names, and their types are part
8+
// of the type signature for the Object, and so two Objects with different
9+
// attribute names or types are considered to be distinct types.
510
type Object struct {
611
AttributeTypes map[string]Type
712
}
813

14+
// Is returns whether `t` is an Object type or not. If `t` is an instance of
15+
// the Object type and its AttributeTypes property is not nil, it will only
16+
// return true the AttributeTypes are considered the same. To be considered
17+
// equal, the same set of keys must be present in each, and each key's value
18+
// needs to be considered the same type between the two Objects.
919
func (o Object) Is(t Type) bool {
1020
v, ok := t.(Object)
1121
if !ok {
@@ -33,6 +43,8 @@ func (o Object) String() string {
3343

3444
func (o Object) private() {}
3545

46+
// MarshalJSON returns a JSON representation of the full type signature of `o`,
47+
// including the AttributeTypes.
3648
func (o Object) MarshalJSON() ([]byte, error) {
3749
attrs, err := json.Marshal(o.AttributeTypes)
3850
if err != nil {

tfprotov5/tftypes/primitive.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,22 @@ package tftypes
33
import "fmt"
44

55
const (
6-
UnknownType = primitive("Unknown")
6+
// DynamicPseudoType is a pseudo-type in Terraform's type system that
7+
// is used as a wildcard type. It indicates that any Terraform type can
8+
// be used.
79
DynamicPseudoType = primitive("DynamicPseudoType")
8-
String = primitive("String")
9-
Number = primitive("Number")
10-
Bool = primitive("Bool")
10+
11+
// String is a primitive type in Terraform that represents a UTF-8
12+
// string of bytes.
13+
String = primitive("String")
14+
15+
// Number is a primitive type in Terraform that represents a real
16+
// number.
17+
Number = primitive("Number")
18+
19+
// Bool is a primitive type in Terraform that represents a true or
20+
// false boolean value.
21+
Bool = primitive("Bool")
1122
)
1223

1324
var (

tfprotov5/tftypes/set.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ package tftypes
22

33
import "fmt"
44

5+
// Set is a Terraform type representing an unordered collection of unique
6+
// elements, all of the same type.
57
type Set struct {
68
ElementType Type
79
}
810

11+
// Is returns whether `t` is a Set type or not. If `t` is an instance of the
12+
// Set type and its ElementType property is nil, it will return true. If `t`'s
13+
// ElementType property is not nil, it will only return true if its ElementType
14+
// is considered the same type as `s`'s ElementType.
915
func (s Set) Is(t Type) bool {
1016
v, ok := t.(Set)
1117
if !ok {
@@ -23,6 +29,8 @@ func (s Set) String() string {
2329

2430
func (s Set) private() {}
2531

32+
// MarshalJSON returns a JSON representation of the full type signature of `s`,
33+
// including its ElementType.
2634
func (s Set) MarshalJSON() ([]byte, error) {
2735
elementType, err := s.ElementType.MarshalJSON()
2836
if err != nil {

tfprotov5/tftypes/tuple.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@ package tftypes
22

33
import "encoding/json"
44

5+
// Tuple is a Terraform type representing an ordered collection of elements,
6+
// potentially of differing types. The number of elements and their types are
7+
// part of the type signature for the Tuple, and so two Tuples with different
8+
// numbers or types of elements are considered to be distinct types.
59
type Tuple struct {
610
ElementTypes []Type
711
}
812

13+
// Is returns whether `t` is a Tuple type or not. If `t` is an instance of the
14+
// Tuple type and its ElementTypes property is not nil, it will only return
15+
// true if the ElementTypes are considered the same. To be considered the same,
16+
// there must be the same number of ElementTypes, arranged in the same order,
17+
// and the types in each position must be considered the same as the type in
18+
// the same position in the other Tuple.
919
func (tu Tuple) Is(t Type) bool {
1020
v, ok := t.(Tuple)
1121
if !ok {
@@ -30,6 +40,8 @@ func (tu Tuple) String() string {
3040

3141
func (tu Tuple) private() {}
3242

43+
// MarshalJSON returns a JSON representation of the full type signature of
44+
// `tu`, including the ElementTypes.
3345
func (tu Tuple) MarshalJSON() ([]byte, error) {
3446
elements, err := json.Marshal(tu.ElementTypes)
3547
if err != nil {

tfprotov5/tftypes/type.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,36 @@ import (
66
"fmt"
77
)
88

9+
// Type is an interface representing a Terraform type. It is only meant to be
10+
// implemented by the tftypes package. Types define the shape and
11+
// characteristics of data coming from or being sent to Terraform.
912
type Type interface {
13+
// Is is used to determine what type a Type implementation is. It is
14+
// the recommended method for determining whether two types are
15+
// equivalent or not.
1016
Is(Type) bool
17+
18+
// String returns a string representation of the Type's name.
1119
String() string
20+
21+
// MarshalJSON returns a JSON representation of the Type's signature.
22+
// It is modeled based on Terraform's requirements for type signature
23+
// JSON representations, and may change over time to match Terraform's
24+
// formatting.
1225
MarshalJSON() ([]byte, error)
26+
27+
// private is meant to keep this interface from being implemented by
28+
// types from other packages.
1329
private()
1430
}
1531

1632
type jsonType struct {
1733
t Type
1834
}
1935

36+
// ParseJSONType returns a Type from its JSON representation. The JSON
37+
// representation should come from Terraform or from MarshalJSON as the format
38+
// is not part of this package's API guarantees.
2039
func ParseJSONType(buf []byte) (Type, error) {
2140
var t jsonType
2241
err := json.Unmarshal(buf, &t)

tfprotov5/tftypes/unknown_value.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package tftypes
22

33
const (
4+
// UnknownValue represents a value that is not yet known. It can be the
5+
// value of any type.
46
UnknownValue = unknown(0)
57
)
68

0 commit comments

Comments
 (0)