Documentation
¶
Index ¶
- Variables
- func CompareOptionalString(a, b OptionalString) int
- func CompareResourceCoordinate(a, b ResourceCoordinate) int
- func IterPlaceholders(data interface{}, finalErr *error) iter.Seq2[string, PlaceholderSub]
- func Version() string
- type ContextPlaceholder
- type DepthFirstIterateOrder
- type DistanceMatrix
- func (d DistanceMatrix) FillDistanceMatrix() DistanceMatrix
- func (d DistanceMatrix) FindAncestorsOf(c ResourceCoordinate) iter.Seq2[ResourceCoordinate, int]
- func (d DistanceMatrix) FindDescendentsOf(c ResourceCoordinate) iter.Seq2[ResourceCoordinate, int]
- func (d DistanceMatrix) ResolveSelectorPlaceholder(context ResourceCoordinate, sp *SelectorPlaceholder) error
- type DriftResolution
- type DriftType
- type ErrCycle
- type ErrGraph
- type ErrInvalidPlaceholder
- type ErrNoRuleMatch
- type ErrParamsMismatch
- type Graph
- func (g *Graph[D]) AddAnonymousDependency(from ResourceCoordinate, to ResourceCoordinate) error
- func (g *Graph[D]) BuildAdjacencyMatrix() DistanceMatrix
- func (g *Graph[D]) DepthFirstIterate(o DepthFirstIterateOrder) iter.Seq[ResourceCoordinate]
- func (g *Graph[D]) DepthFirstIterateFrom(c ResourceCoordinate, o DepthFirstIterateOrder) iter.Seq[ResourceCoordinate]
- func (g *Graph[D]) Expand(ctx context.Context, definitions ModuleDefinitionIndex[D], ...)
- func (g *Graph[D]) HasErrors() bool
- func (g *Graph[D]) IsExpanded() bool
- func (g *Graph[D]) LabelCycle() map[ResourceCoordinate]bool
- func (g *Graph[D]) ResolveResourcePlaceholder(aliasContext ResourceCoordinate, rt *ResourcePlaceholder) error
- type Manifest
- type ManifestCoProvision
- type ManifestResource
- type ManifestWorkload
- type ModuleConfiguration
- type ModuleDefinition
- type ModuleDefinitionIndex
- type OptionalString
- func (o OptionalString) IsSet() bool
- func (o OptionalString) Map(f func(s string) string) OptionalString
- func (o OptionalString) MustValue() string
- func (o OptionalString) Ref() *string
- func (o OptionalString) String() string
- func (o OptionalString) ValueOr(defaultValue string) string
- func (o OptionalString) ValueOrFunc(defaultValue func() string) string
- type PlaceholderSub
- type PlaceholderType
- type ResourceCoordinate
- type ResourceNode
- type ResourcePlaceholder
- type Rule
- type SelectorFilter
- type SelectorFunction
- type SelectorPlaceholder
- type TfVarPlaceholder
Constants ¶
This section is empty.
Variables ¶
var DefaultAnonymousEdgeAliasFunc = func(from, to ResourceCoordinate) string { h := sha256.New() _, _ = h.Write([]byte(to.Type)) _, _ = h.Write([]byte{0}) _, _ = h.Write([]byte(to.Class)) _, _ = h.Write([]byte{0}) _, _ = h.Write([]byte(to.Id)) return base64.RawStdEncoding.EncodeToString(h.Sum(nil)) }
DefaultAnonymousEdgeAliasFunc is the function used to determine an alias for an anonymous edge added due to placeholder resolution or coprovisioning rules.
var DefaultClass = "default"
DefaultClass is the default class to assign resources that haven't requested a class specifically
return fmt.Sprintf("shared.%s", alias) }
DefaultSharedResourceIdFunc is the function that allocates ids to the shared resources anchored by the manifest. The function uses the resource alias by default.
var DefaultWorkloadResourceIdFunc = func(ctx context.Context, workload string, alias string, manifest ManifestResource) string { return fmt.Sprintf("workloads.%s.%s", workload, alias) }
DefaultWorkloadResourceIdFunc is the function that allocates ids to the resources anchored by the workloads. The function by default uses the workload id and alias, but you can choose to override this.
var DefaultWorkloadResourceType = "workload"
DefaultWorkloadResourceType is the type of the workload resource node that we inject for each workload.
var InheritClassOrIdSymbol = "@"
InheritClassOrIdSymbol is the symbol that can be used in place of the class or id to inherit the value from the resource that declares the dependency or co-provisions the resource.
var RePlaceholder = regexp.MustCompile(`\${[^{}]+}`)
Functions ¶
func CompareOptionalString ¶
func CompareOptionalString(a, b OptionalString) int
func CompareResourceCoordinate ¶
func CompareResourceCoordinate(a, b ResourceCoordinate) int
func IterPlaceholders ¶
func IterPlaceholders(data interface{}, finalErr *error) iter.Seq2[string, PlaceholderSub]
IterPlaceholders streams over the data type and returns any observed placeholders and a parsed object for them. It will automatically deduplicate placeholders so they only need to be evaluated once.
Types ¶
type ContextPlaceholder ¶
type ContextPlaceholder struct {
// Key is the context key from the context map
Key string
}
func (ContextPlaceholder) Type ¶
func (c ContextPlaceholder) Type() PlaceholderType
type DepthFirstIterateOrder ¶
type DepthFirstIterateOrder int
const ( DepthFirstIteratePreOrder DepthFirstIterateOrder = iota DepthFirstIteratePostOrder )
type DistanceMatrix ¶
type DistanceMatrix map[ResourceCoordinate]map[ResourceCoordinate]int
func (DistanceMatrix) FillDistanceMatrix ¶
func (d DistanceMatrix) FillDistanceMatrix() DistanceMatrix
FillDistanceMatrix builds a full distance matrix. Looking up any node should produce all the nodes that are dependencies in some way by their minimum depth. Nodes that don't have any dependencies are excluded. This uses the Floyd-Warshall (https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) algorithm.
func (DistanceMatrix) FindAncestorsOf ¶
func (d DistanceMatrix) FindAncestorsOf(c ResourceCoordinate) iter.Seq2[ResourceCoordinate, int]
FindAncestorsOf returns an iteration over all the resources that depend on c, directly and transitively through. The integer value is the depth.
func (DistanceMatrix) FindDescendentsOf ¶
func (d DistanceMatrix) FindDescendentsOf(c ResourceCoordinate) iter.Seq2[ResourceCoordinate, int]
FindDescendentsOf returns an iteration over all the resources that the given resource c depends on, directly and transitively through other dependencies. The integer value is the depth. This is more efficient than the DepthFirstIterate function but doesn't return in any particular order.
func (DistanceMatrix) ResolveSelectorPlaceholder ¶
func (d DistanceMatrix) ResolveSelectorPlaceholder(context ResourceCoordinate, sp *SelectorPlaceholder) error
ResolveSelectorPlaceholder fills the MatchedCoordinates field on the selector placeholder with the correct matched nodes based on the distance matrix.
type DriftResolution ¶
type DriftResolution string
const ( // DriftResolutionAcceptModuleChange allows the node to accept module and configuration changes DriftResolutionAcceptModuleChange DriftResolution = "accept_module_change" // DriftResolutionAcceptConfigChange allows the node to accept configuration changes DriftResolutionAcceptConfigChange DriftResolution = "accept_config_change" )
type DriftType ¶
type DriftType string
const ( // DriftNone means the nodes are using exactly the same module configuration DriftNone DriftType = "" // DriftConfigurationChange means the nodes are using the same module, but they differ in version, params, // or configuration. An upgrade is likely to succeed. DriftConfigurationChange DriftType = "config_change" // DriftModuleChange means the nodes are using different modules entirely and a replacement will likely be needed. DriftModuleChange DriftType = "module_change" // DriftConfigurationChangeSkipped occurs when a configuration change is skipped due to a drift resolution strategy. DriftConfigurationChangeSkipped DriftType = "config_change_skipped" // DriftModuleChangeSkipped occurs when a module change is skipped due to a drift resolution strategy. DriftModuleChangeSkipped DriftType = "module_change_skipped" )
func ApplyDriftResolution ¶
func ApplyDriftResolution(current DriftType, resolution DriftResolution) (DriftType, bool)
type ErrGraph ¶
type ErrGraph struct {
ByNode map[ResourceCoordinate]error
}
type ErrInvalidPlaceholder ¶
type ErrInvalidPlaceholder struct {
// contains filtered or unexported fields
}
func NewErrInvalidPlaceholder ¶
func NewErrInvalidPlaceholder(message string) *ErrInvalidPlaceholder
func (*ErrInvalidPlaceholder) Error ¶
func (e *ErrInvalidPlaceholder) Error() string
type ErrNoRuleMatch ¶
type ErrNoRuleMatch struct{}
func (*ErrNoRuleMatch) Error ¶
func (e *ErrNoRuleMatch) Error() string
type ErrParamsMismatch ¶
type ErrParamsMismatch struct{}
func (*ErrParamsMismatch) Error ¶
func (e *ErrParamsMismatch) Error() string
type Graph ¶
type Graph[D ModuleConfiguration] struct { // Nodes is the map of node coordinate to node details. Nodes map[ResourceCoordinate]ResourceNode[D] `json:"nodes"` // Edges is the map of node, to node via a labeled edge. The label is the 'alias' in the dependent resources. Edges map[ResourceCoordinate]map[string]ResourceCoordinate `json:"edges"` // Workloads are the set of named workloads that have been added from the manifest. Workloads map[string]ResourceCoordinate `json:"workloads"` SharedResources map[string]ResourceCoordinate `json:"shared_resources"` // LeafResources are leaf resources in the graph that may be workload resources, shared resources, or dependent // resources. The common concept is that no nodes depend on them. LeafResources map[ResourceCoordinate]bool `json:"leaf_resources"` // contains filtered or unexported fields }
A Graph is the graph state resulted from applying a set of module definitions and rules to a manifest. This is done through the SeedAndExpandAll api OR through a combination of a single call to Seed and 'N' calls to Expand until IsExpanded returns true. The graph holds a set of nodes and edges along with the workloads, shared resources. The generic parameter D is the implementation of the ModuleConfiguration which includes things like the module, version, and dependency declarations. None of which particularly matter for the graph resolution itself. On each node, we also store an error found during expansion or a drift when we have compared the result to a previous graph from a previous deployment.
func Seed ¶
func Seed[D ModuleConfiguration](ctx context.Context, manifest Manifest) Graph[D]
The Seed function is a constructor that creates the initial graph with leaf nodes and prepares for Expand.
func SeedAndExpandAll ¶
func SeedAndExpandAll[D ModuleConfiguration](ctx context.Context, manifest Manifest, definitions ModuleDefinitionIndex[D], previousGraph *Graph[D]) (Graph[D], error)
SeedAndExpandAll is the constructor that seeds the graph and expands all iteratively until the end of the graph is reached. It then labels any cycles and identifies if errors were found. THIS IS THE CONSTRUCTOR YOU SHOULD USE.
func (*Graph[D]) AddAnonymousDependency ¶
func (g *Graph[D]) AddAnonymousDependency(from ResourceCoordinate, to ResourceCoordinate) error
AddAnonymousDependency can be used after the graph is expanded to add additional dependency edges to the graph. You should call LabelCycle after this to check if there is now a dependency cycle. The node is added with an alias that is a base64 encoded hash. The hash algorithm is DefaultAnonymousEdgeHash.
func (*Graph[D]) BuildAdjacencyMatrix ¶
func (g *Graph[D]) BuildAdjacencyMatrix() DistanceMatrix
BuildAdjacencyMatrix returns a DistanceMatrix which contains only the immediate neighbours set to distance 1.
func (*Graph[D]) DepthFirstIterate ¶
func (g *Graph[D]) DepthFirstIterate(o DepthFirstIterateOrder) iter.Seq[ResourceCoordinate]
DepthFirstIterate iterates through the entire graph in a depth first way. This is useful to make sure that all dependencies are processed or visited first.
func (*Graph[D]) DepthFirstIterateFrom ¶
func (g *Graph[D]) DepthFirstIterateFrom(c ResourceCoordinate, o DepthFirstIterateOrder) iter.Seq[ResourceCoordinate]
DepthFirstIterateFrom iterates through the subgraph rooted at the given resource coordinate.
func (*Graph[D]) Expand ¶
func (g *Graph[D]) Expand(ctx context.Context, definitions ModuleDefinitionIndex[D], previousGraph *Graph[D])
Expand attempts to expand the next unexpanded node. This is only needed if you are using Seed and IsExpanded manually.
func (*Graph[D]) IsExpanded ¶
IsExpanded returns whether the graph is fully expanded. This is only useful if you are using Seed and Expand manually.
func (*Graph[D]) LabelCycle ¶
func (g *Graph[D]) LabelCycle() map[ResourceCoordinate]bool
LabelCycle will attempt to find a cycle in the graph. This does not find _all_ cycles. This is called automatically within SeedAndExpandAll but can be called again if you have added additional edges to the graph through AddAnonymousDependency.
func (*Graph[D]) ResolveResourcePlaceholder ¶
func (g *Graph[D]) ResolveResourcePlaceholder(aliasContext ResourceCoordinate, rt *ResourcePlaceholder) error
ResolveResourcePlaceholder fills the Coordinate field on the resource placeholder with the correct node.
type Manifest ¶
type Manifest struct {
Workloads map[string]ManifestWorkload
}
type ManifestCoProvision ¶
type ManifestCoProvision struct {
ManifestResource
// If IsDependentOnCurrent is true, then we create an edge from the co provisioned resource to the current resource
// so that this co provisioned resource "depends" on the current resource and is only provisioned after the
// current resource is completely provisioned. This may be needed if the co provisioned resource uses selectors
// to pull values out of the current resource or relies on side effects from it.
IsDependentOnCurrent bool
// If CopyDependentsOnCurrent is true, then we also add edges from all resources that depend on the current resource
// to the co provisioned resource. So that we enforce a sibling relationships between the current resource and the
// co provisioned one. This ensures that the co provisioned resource is co provisioned before the parents.
CopyDependentsOnCurrent bool
}
type ManifestResource ¶
type ManifestResource struct {
Type string
Class OptionalString
Id OptionalString
Params map[string]interface{}
}
type ManifestWorkload ¶
type ManifestWorkload struct {
Resources map[string]ManifestResource
Outputs map[string]string
}
type ModuleConfiguration ¶
type ModuleConfiguration interface {
CalculateDrift(mc ModuleConfiguration) DriftType
GetDependencies() map[string]ManifestResource
GetCoProvisioned() []ManifestCoProvision
}
type ModuleDefinition ¶
type ModuleDefinition[E ModuleConfiguration] struct { // The resource matching bits ResourceType string Rules []Rule // The actual configuration of the module Configuration E }
type ModuleDefinitionIndex ¶
type ModuleDefinitionIndex[D ModuleConfiguration] struct { // contains filtered or unexported fields }
func NewModuleDefinitionIndex ¶
func NewModuleDefinitionIndex[D ModuleConfiguration](defs []ModuleDefinition[D]) *ModuleDefinitionIndex[D]
func (*ModuleDefinitionIndex[D]) FindBest ¶
func (d *ModuleDefinitionIndex[D]) FindBest(_ context.Context, coordinate ResourceCoordinate) (ModuleDefinition[D], bool)
type OptionalString ¶
type OptionalString struct {
// contains filtered or unexported fields
}
OptionalString is a static non-pointer implementation of a nullable string. Use IsSet to check the value, and MustValue to retrieve tha value. Various utility constructors and methods exist for making things easy
func OptionalStringOf ¶
func OptionalStringOf(s string) OptionalString
OptionalStringOf returns an OptionalString with the value set.
func OptionalStringOfNonEmpty ¶
func OptionalStringOfNonEmpty(s string) OptionalString
OptionalStringOfNonEmpty is similar to OptionalStringOf but treats an empty string as not set.
func OptionalStringOfRef ¶
func OptionalStringOfRef(s *string) OptionalString
OptionalStringOfRef returns an OptionalString with the value set if it is not nil.
func (OptionalString) IsSet ¶
func (o OptionalString) IsSet() bool
func (OptionalString) Map ¶
func (o OptionalString) Map(f func(s string) string) OptionalString
func (OptionalString) MustValue ¶
func (o OptionalString) MustValue() string
func (OptionalString) Ref ¶
func (o OptionalString) Ref() *string
func (OptionalString) String ¶
func (o OptionalString) String() string
func (OptionalString) ValueOr ¶
func (o OptionalString) ValueOr(defaultValue string) string
func (OptionalString) ValueOrFunc ¶
func (o OptionalString) ValueOrFunc(defaultValue func() string) string
type PlaceholderSub ¶
type PlaceholderSub interface {
Type() PlaceholderType
}
func ParsePlaceholder ¶
func ParsePlaceholder(placeholder string) (PlaceholderSub, error)
type PlaceholderType ¶
type PlaceholderType string
const ( PlaceholderTypeResource PlaceholderType = "resource" PlaceholderTypeContext PlaceholderType = "context" PlaceholderTypeTfVar PlaceholderType = "var" PlaceholderTypeSelector PlaceholderType = "select" PlaceholderTypeSelf PlaceholderType = "self" )
type ResourceCoordinate ¶
func (ResourceCoordinate) MarshalText ¶
func (rc ResourceCoordinate) MarshalText() ([]byte, error)
func (ResourceCoordinate) String ¶
func (rc ResourceCoordinate) String() string
func (*ResourceCoordinate) UnmarshalText ¶
func (rc *ResourceCoordinate) UnmarshalText(data []byte) error
type ResourceNode ¶
type ResourceNode[D ModuleConfiguration] struct { // The ModuleConfiguration of this node. This is the _next_ configuration to use, not necessarily what was // previously used. This has already had any NextDriftResolution strategy applied. ModuleConfiguration D `json:"config"` // The Params (parameters) captured from the Manifest or the dependent node. Params map[string]interface{} `json:"params"` // ParamsDefinedBy is coordinates of the node that defined the Params, which has a direct dependency on this resource and should be used for placeholder context in the params. // Empty string, if there's no direct dependency. ParamsDefinedBy *ResourceCoordinate `json:"params_defined_by"` // CurrentDrift DEPRECATED use DetectedDrift, keeping it for backward compatibility CurrentDrift int `json:"current_drift,omitzero"` // DetectedDrift is the drift found in the current Expand cycle, caused by the module rules or module configuration // changing since the previous graph. DetectedDrift DriftType `json:"detected_drift,omitzero"` // EffectiveDrift is the final drift after applying the NextDriftResolution strategy to the DetectedDrift. EffectiveDrift DriftType `json:"effective_drift,omitzero"` // Error is an error encountered during Expand, we don't serialize this since we should not store error'ed graphs. Error error `json:"-"` // NextDriftResolution is the drift resolution to use in the _next_ graph expansion. This is usually set by the module // definition or by an operator/admin. We don't serialize this, since this is only used when expanding a new graph. NextDriftResolution DriftResolution `json:"-"` }
ResourceNode is the state of a node in the graph.
type ResourcePlaceholder ¶
type ResourcePlaceholder struct {
// Coordinate is the matched coordinate once we've resolved the placeholder
Coordinate *ResourceCoordinate
// Alias is the local alias within the context of the current node
Alias string
IsShared bool
// IsSelf holds whether this is the self placeholder
IsSelf bool
// Output captures the output key traversal they want to pull out of the target resource
Output []string
}
func (ResourcePlaceholder) Type ¶
func (r ResourcePlaceholder) Type() PlaceholderType
type Rule ¶
type Rule struct {
ResourceClass OptionalString
ResourceId OptionalString
}
type SelectorFilter ¶
type SelectorFilter struct {
Type string
Class OptionalString
Id OptionalString
}
func ParseSelectorFilter ¶
func ParseSelectorFilter(raw string) SelectorFilter
func (SelectorFilter) Matches ¶
func (f SelectorFilter) Matches(rc ResourceCoordinate, context ResourceCoordinate) bool
type SelectorFunction ¶
type SelectorFunction struct {
Func string
Args []interface{}
}
type SelectorPlaceholder ¶
type SelectorPlaceholder struct {
// MatchedCoordinates is the set of matches nodes once we've resolved the placeholder
MatchedCoordinates []ResourceCoordinate
// Functions is the list of dependency / consumer function calls
Functions []string
// Args is the 1:1 map of args to each function call
Args []string
// Output is the output key traversal to pull out of the target resources
Output []string
}
func (SelectorPlaceholder) Type ¶
func (e SelectorPlaceholder) Type() PlaceholderType
type TfVarPlaceholder ¶
type TfVarPlaceholder struct {
Key string
}
func (TfVarPlaceholder) Type ¶
func (e TfVarPlaceholder) Type() PlaceholderType