structured

package
v1.5.0 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2023 License: MPL-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package structured contains the structured representation of the JSON changes returned by the jsonplan package.

Placing these in a dedicated package allows for greater reuse across the various type of renderers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Change

type Change struct {

	// BeforeExplicit matches AfterExplicit except references the Before value.
	BeforeExplicit bool

	// AfterExplicit refers to whether the After value is explicit or
	// implicit. It is explicit if it has been specified by the user, and
	// implicit if it has been set as a consequence of other changes.
	//
	// For example, explicitly setting a value to null in a list should result
	// in After being null and AfterExplicit being true. In comparison,
	// removing an element from a list should also result in After being null
	// and AfterExplicit being false. Without the explicit information our
	// functions would not be able to tell the difference between these two
	// cases.
	AfterExplicit bool

	// Before contains the value before the proposed change.
	//
	// The type of the value should be informed by the schema and cast
	// appropriately when needed.
	Before interface{}

	// After contains the value after the proposed change.
	//
	// The type of the value should be informed by the schema and cast
	// appropriately when needed.
	After interface{}

	// Unknown describes whether the After value is known or unknown at the time
	// of the plan. In practice, this means the after value should be rendered
	// simply as `(known after apply)`.
	//
	// The concrete value could be a boolean describing whether the entirety of
	// the After value is unknown, or it could be a list or a map depending on
	// the schema describing whether specific elements or attributes within the
	// value are unknown.
	Unknown interface{}

	// BeforeSensitive matches Unknown, but references whether the Before value
	// is sensitive.
	BeforeSensitive interface{}

	// AfterSensitive matches Unknown, but references whether the After value is
	// sensitive.
	AfterSensitive interface{}

	// ReplacePaths contains a set of paths that point to attributes/elements
	// that are causing the overall resource to be replaced rather than simply
	// updated.
	ReplacePaths attribute_path.Matcher

	// RelevantAttributes contains a set of paths that point attributes/elements
	// that we should display. Any element/attribute not matched by this Matcher
	// should be skipped.
	RelevantAttributes attribute_path.Matcher
}

Change contains the unmarshalled generic interface{} types that are output by the JSON functions in the various json packages (such as jsonplan and jsonprovider).

A Change can be converted into a computed.Diff, ready for rendering, with the ComputeDiffForAttribute, ComputeDiffForOutput, and ComputeDiffForBlock functions.

The Before and After fields are actually go-cty values, but we cannot convert them directly because of the Terraform Cloud redacted endpoint. The redacted endpoint turns sensitive values into strings regardless of their types. Because of this, we cannot just do a direct conversion using the ctyjson package. We would have to iterate through the schema first, find the sensitive values and their mapped types, update the types inside the schema to strings, and then go back and do the overall conversion. This isn't including any of the more complicated parts around what happens if something was sensitive before and isn't sensitive after or vice versa. This would mean the type would need to change between the before and after value. It is in fact just easier to iterate through the values as generic JSON interfaces.

func FromJsonChange

func FromJsonChange(change jsonplan.Change, relevantAttributes attribute_path.Matcher) Change

FromJsonChange unmarshals the raw []byte values in the jsonplan.Change structs into generic interface{} types that can be reasoned about.

func FromJsonOutput

func FromJsonOutput(output jsonstate.Output) Change

FromJsonOutput unmarshals the raw values in the jsonstate.Output structs into generic interface{} types that can be reasoned about.

func FromJsonResource

func FromJsonResource(resource jsonstate.Resource) Change

FromJsonResource unmarshals the raw values in the jsonstate.Resource structs into generic interface{} types that can be reasoned about.

func FromJsonViewsOutput

func FromJsonViewsOutput(output viewsjson.Output) Change

FromJsonViewsOutput unmarshals the raw values in the viewsjson.Output structs into generic interface{} types that can be reasoned about.

func (Change) AsCreate

func (change Change) AsCreate() Change

AsCreate returns the current change as if it is a Create operation.

Basically it replaces all the before values with nil or false.

func (Change) AsDelete

func (change Change) AsDelete() Change

AsDelete returns the current change as if it is a Delete operation.

Basically it replaces all the after values with nil or false.

func (Change) AsMap

func (change Change) AsMap() ChangeMap

AsMap converts the Change into an object or map representation by converting the internal Before, After, Unknown, BeforeSensitive, and AfterSensitive data structures into generic maps.

func (Change) AsNoOp

func (change Change) AsNoOp() Change

AsNoOp returns the current change as if it is a NoOp operation.

Basically it replaces all the after values with the before values.

func (Change) AsSlice

func (change Change) AsSlice() ChangeSlice

AsSlice converts the Change into a slice representation by converting the internal Before, After, Unknown, BeforeSensitive, and AfterSensitive data structures into generic slices.

func (Change) CalculateAction

func (change Change) CalculateAction() plans.Action

CalculateAction does a very simple analysis to make the best guess at the action this change describes. For complex types such as objects, maps, lists, or sets it is likely more efficient to work out the action directly instead of relying on this function.

func (Change) CheckForSensitive

func (change Change) CheckForSensitive(processInner ProcessSensitiveInner, createDiff CreateSensitiveDiff) (computed.Diff, bool)

CheckForSensitive is a helper function that handles all common functionality for processing a sensitive value.

It returns the computed sensitive diff and true if this value was sensitive and needs to be rendered as such, otherwise it returns the second return value as false and the first value can be discarded.

The actual processing of sensitive values happens within the ProcessSensitiveInner and CreateSensitiveDiff functions. Callers should implement these functions as appropriate when using this function.

The ProcessSensitiveInner function should simply return a computed.Diff for the provided Change. The provided Change will be the same as the original change but with the sensitive metadata removed. The new inner diff is then passed into the actual CreateSensitiveDiff function which should return the actual sensitive diff.

We include the inner change into the sensitive diff as a way to let the sensitive renderer have as much information as possible, while still letting it do the actual rendering.

func (Change) CheckForUnknown

func (change Change) CheckForUnknown(childUnknown interface{}, process ProcessUnknown, processBefore ProcessUnknownWithBefore) (computed.Diff, bool)

CheckForUnknown is a helper function that handles all common functionality for processing an unknown value.

It returns the computed unknown diff and true if this value was unknown and needs to be rendered as such, otherwise it returns the second return value as false and the first return value should be discarded.

The actual processing of unknown values happens in the ProcessUnknown and ProcessUnknownWithBefore functions. If a value is unknown and is being created, the ProcessUnknown function is called and the caller should decide how to create the unknown value. If a value is being updated the ProcessUnknownWithBefore function is called and the function provides the before value as if it is being deleted for the caller to handle. Note that values being deleted will never be marked as unknown so this case isn't handled.

The childUnknown argument is meant to allow callers with extra information about the type being processed to provide a list of known children that might not be present in the before or after values. These values will be propagated as the unknown values in the before value should it be needed.

func (Change) GetDefaultActionForIteration

func (change Change) GetDefaultActionForIteration() plans.Action

GetDefaultActionForIteration is used to guess what the change could be for complex attributes (collections and objects) and blocks.

You can't really tell the difference between a NoOp and an Update just by looking at the attribute itself as you need to inspect the children.

This function returns a Delete or a Create action if the before or after values were null, and returns a NoOp for all other cases. It should be used in conjunction with compareActions to calculate the actual action based on the actions of the children.

func (Change) IsAfterSensitive

func (change Change) IsAfterSensitive() bool

func (Change) IsBeforeSensitive

func (change Change) IsBeforeSensitive() bool

func (Change) IsUnknown

func (change Change) IsUnknown() bool

type ChangeMap

type ChangeMap struct {
	// Before contains the value before the proposed change.
	Before map[string]interface{}

	// After contains the value after the proposed change.
	After map[string]interface{}

	// Unknown contains the unknown status of any elements/attributes of this
	// map/object.
	Unknown map[string]interface{}

	// BeforeSensitive contains the before sensitive status of any
	// elements/attributes of this map/object.
	BeforeSensitive map[string]interface{}

	// AfterSensitive contains the after sensitive status of any
	// elements/attributes of this map/object.
	AfterSensitive map[string]interface{}

	// ReplacePaths matches the same attributes in Change exactly.
	ReplacePaths attribute_path.Matcher

	// RelevantAttributes matches the same attributes in Change exactly.
	RelevantAttributes attribute_path.Matcher
}

ChangeMap is a Change that represents a Map or an Object type, and has converted the relevant interfaces into maps for easier access.

func (ChangeMap) AllKeys

func (m ChangeMap) AllKeys() []string

AllKeys returns all the possible keys for this map. The keys for the map are potentially hidden and spread across multiple internal data structures and so this function conveniently packages them up.

func (ChangeMap) ExplicitKeys

func (m ChangeMap) ExplicitKeys() []string

ExplicitKeys returns the keys in the Before and After, as opposed to AllKeys which also includes keys from the additional meta structures (like the sensitive and unknown values).

This function is useful for processing nested attributes and repeated blocks where the unknown and sensitive structs contain information about the actual attributes, while the before and after structs hold the actual nested values.

func (ChangeMap) GetChild

func (m ChangeMap) GetChild(key string) Change

GetChild safely packages up a Change object for the given child, handling all the cases where the data might be null or a static boolean.

type ChangeSlice

type ChangeSlice struct {
	// Before contains the value before the proposed change.
	Before []interface{}

	// After contains the value after the proposed change.
	After []interface{}

	// Unknown contains the unknown status of any elements of this list/set.
	Unknown []interface{}

	// BeforeSensitive contains the before sensitive status of any elements of
	//this list/set.
	BeforeSensitive []interface{}

	// AfterSensitive contains the after sensitive status of any elements of
	//this list/set.
	AfterSensitive []interface{}

	// ReplacePaths matches the same attributes in Change exactly.
	ReplacePaths attribute_path.Matcher

	// RelevantAttributes matches the same attributes in Change exactly.
	RelevantAttributes attribute_path.Matcher
}

ChangeSlice is a Change that represents a Tuple, Set, or List type, and has converted the relevant interfaces into slices for easier access.

func (ChangeSlice) GetChild

func (s ChangeSlice) GetChild(beforeIx, afterIx int) Change

GetChild safely packages up a Change object for the given child, handling all the cases where the data might be null or a static boolean.

type CreateSensitiveDiff

type CreateSensitiveDiff func(inner computed.Diff, beforeSensitive, afterSensitive bool, action plans.Action) computed.Diff

type ProcessSensitiveInner

type ProcessSensitiveInner func(change Change) computed.Diff

type ProcessUnknown

type ProcessUnknown func(current Change) computed.Diff

type ProcessUnknownWithBefore

type ProcessUnknownWithBefore func(current Change, before Change) computed.Diff

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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