runtime

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2024 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type EvalError

type EvalError struct {
	IsIncompleteData bool
	Err              error
}

func (*EvalError) Error

func (e *EvalError) Error() string

type Interface

type Interface interface {
	// Synchronize attempts to resolve as many resources as possible.
	// It returns true if the user should call Synchronize again, and false if all
	// resources are resolved. An error is returned if the synchronization process
	// encounters any issues.
	Synchronize() (bool, error)

	// TopologicalOrder returns the topological order of resources.
	TopologicalOrder() []string

	// ResourceDescriptor returns the descriptor for a given resource ID.
	// The descriptor provides metadata about the resource.
	ResourceDescriptor(resourceID string) ResourceDescriptor

	// GetResource retrieves a resource by its ID. It returns the resource object
	// and its current state. If the resource is not found or not yet resolved,
	// it returns nil and the appropriate ResourceState.
	GetResource(resourceID string) (*unstructured.Unstructured, ResourceState)

	// SetResource updates or sets a resource in the runtime. This is typically
	// called after a resource has been created or updated in the cluster.
	SetResource(resourceID string, obj *unstructured.Unstructured)

	// GetInstance returns the main instance object managed by this runtime.
	GetInstance() *unstructured.Unstructured

	// SetInstance updates the main instance object.
	// This is typically called after the instance has been updated in the cluster.
	SetInstance(obj *unstructured.Unstructured)

	// IsResourceReady returns true if the resource is ready, and false otherwise.
	IsResourceReady(resourceID string) (bool, string, error)

	// WantToCreateResource returns true if all the condition expressions return true
	// if not it will add itself to the ignored resources
	WantToCreateResource(resourceID string) (bool, error)

	// IgnoreResource ignores resource that has a condition expressison that evaluated
	// to false
	IgnoreResource(resourceID string)
}

Interface defines the main runtime interface for managing and synchronizing resources.

Note: The use of interfaces here is to allow for easy testing and mocking of the runtime the instance controller uses. e.g we can create a fake runtime that returns a specific set of resources for testing purposes.

The other reason for the interface is to allow for different implementations

type Resource

type Resource interface {
	ResourceDescriptor

	// Unstructured returns the resource data as an unstructured.Unstructured
	// object.
	Unstructured() *unstructured.Unstructured
}

Resource extends `ResourceDescriptor` to include the actual resource data.

type ResourceDescriptor

type ResourceDescriptor interface {
	// GetGroupVersionResource returns the k8s GVR for this resource. Note that
	// we don't use the GVK (GroupVersionKind) because the dynamic client needs
	// the GVR to interact with the API server. Yep, it's a bit unfortunate.
	GetGroupVersionResource() schema.GroupVersionResource

	// GetVariables returns the list of variables associated with this resource.
	GetVariables() []*variable.ResourceField

	// GetDependencies returns the list of resource IDs that this resource
	// depends on.
	GetDependencies() []string

	// GetReadyWhenExpressions returns the list of expressions that need to be
	// evaluated before the resource is considered ready.
	GetReadyWhenExpressions() []string

	// GetIncludeWhenExpressions returns the list of expressions that need to
	// be evaluated before deciding whether to create a resource
	GetIncludeWhenExpressions() []string

	// GetTopLevelFields returns the list of top-level fields in the resource.
	// e.g spec, status, metadata, etc.
	GetTopLevelFields() []string

	// IsNamespaced returns true if the resource is namespaced, and false if it's
	// cluster-scoped.
	IsNamespaced() bool
}

ResourceDescriptor provides metadata about a resource.

Note: the reason why we do not import resourcegroup/graph.Resource here is to avoid a circular dependency between the runtime and the graph packages. Had to scratch my head for a while to figure this out. But here is the quick overview:

  1. The runtime package depends on how resources are defined in the graph package.

  2. the graph package needs to instantiate the a runtime instance to during the reconciliation process.

  3. the graph package needs to classify the variables and dependencies of a resource to build the graph. The runtime package needs to know about these variables and dependencies to resolve the resources. This utility is moved to the types package. (Thinking about moving it to a new package called "internal/typesystem/variables")

type ResourceGroupRuntime

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

ResourceGroupRuntime implements the Interface for managing and synchronizing resources. Is is the responsibility of the consumer to call Synchronize appropriately, and decide whether to follow the TopologicalOrder or a BFS/DFS traversal of the resources.

func NewResourceGroupRuntime

func NewResourceGroupRuntime(
	instance Resource,
	resources map[string]Resource,
	topologicalOrder []string,
) (*ResourceGroupRuntime, error)

NewResourceGroupRuntime creates and initializes a new ResourceGroupRuntime instance.

It is also responsible of properly creating the ExpressionEvaluationState for each variable in the resources and the instance, and caching them for future use. This function will also call Synchronize to evaluate the static variables. This helps hide the complexity of the runtime from the caller (instance controller in this case).

The output of this function is NOT thread safe.

func (*ResourceGroupRuntime) GetInstance

func (rt *ResourceGroupRuntime) GetInstance() *unstructured.Unstructured

GetInstance returns the main instance object managed by this runtime.

func (*ResourceGroupRuntime) GetResource

GetResource returns a resource so that it's either created or updated in the cluster, it also returns the runtime state of the resource. Indicating whether the resource variables are resolved or not, and whether the resource readiness conditions are met or not.

func (*ResourceGroupRuntime) IgnoreResource

func (rt *ResourceGroupRuntime) IgnoreResource(resourceID string)

IgnoreResource ignores resource that has a conditions expressison that evaluated to false or whose dependencies are ignored

func (*ResourceGroupRuntime) IsResourceReady

func (rt *ResourceGroupRuntime) IsResourceReady(resourceID string) (bool, string, error)

IsResourceReady checks if a resource is ready based on the readyWhenExpressions defined in the resource. If no readyWhenExpressions are defined, the resource is considered ready.

func (*ResourceGroupRuntime) ResourceDescriptor

func (rt *ResourceGroupRuntime) ResourceDescriptor(id string) ResourceDescriptor

ResourceDescriptor returns the descriptor for a given resource id.

It is the responsibility of the caller to ensure that the resource id exists in the runtime. a.k.a the caller should use the TopologicalOrder to get the resource ids.

func (*ResourceGroupRuntime) SetInstance

func (rt *ResourceGroupRuntime) SetInstance(obj *unstructured.Unstructured)

SetInstance updates the main instance object. This is typically called after the instance has been updated in the cluster.

func (*ResourceGroupRuntime) SetResource

func (rt *ResourceGroupRuntime) SetResource(id string, resource *unstructured.Unstructured)

SetResource updates or sets a resource in the runtime. This is typically called after a resource has been created or updated in the cluster.

func (*ResourceGroupRuntime) Synchronize

func (rt *ResourceGroupRuntime) Synchronize() (bool, error)

Synchronize tries to resolve as many resources as possible. It returns true if the user should call Synchronize again, and false if something is still not resolved.

Every time Synchronize is called, it walks through the resources and tries to resolve as many as possible. If a resource is resolved, it's added to the resolved resources map.

func (*ResourceGroupRuntime) TopologicalOrder

func (rt *ResourceGroupRuntime) TopologicalOrder() []string

TopologicalOrder returns the topological order of resources.

func (*ResourceGroupRuntime) WantToCreateResource

func (rt *ResourceGroupRuntime) WantToCreateResource(resourceID string) (bool, error)

WantToCreateResource returns true if all the condition expressions return true if not it will add itself to the ignored resources

type ResourceState

type ResourceState string

ResourceState represents the current state of a resource in the runtime. It indicates the resource's readiness for processing or what it's waiting on.

The state here isn't directly tied to the dependencies in the graph, but rather the readiness of the resource itself. e.g Are the CEL expressions evaluated and replaced properly? are the readiness conditions met?

const (
	// ResourceStateResolved indicates that the resource is ready to be processed.
	// All its dependencies are resolved, and it can be safely created or updated.
	ResourceStateResolved ResourceState = "Resolved"

	// ResourceStateWaitingOnDependencies indicates that the resource is waiting
	// for its dependencies to be resolved. This includes waiting for other
	// resources it depends on to be created or updated, or for variables from
	// those dependencies to be available.
	ResourceStateWaitingOnDependencies ResourceState = "WaitingOnDependencies"

	// ResourceStateWaitingOnReadiness indicates that the resource is waiting
	// for its readiness conditions to be met. This typically occurs after the
	// resource has been created or updated, but is not yet in a stable state
	// according to its defined readiness criteria. e.g waiting for a Pod to
	// be running and ready, a PVC to be bound ...
	ResourceStateWaitingOnReadiness ResourceState = "WaitingOnReadiness"

	// ResourceStateIgnoredByConditions indicates that the resource is ignored
	// by a condition that evaluated to false. This typically occurs before
	// a resource is created or updated, and is decided by a variable defined
	// in the instance spec. Eg. Deciding whether to create a Deployment or
	// just a simple pod based on the defined replica.
	ResourceStateIgnoredByConditions ResourceState = "IgnoredByConditions"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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