provisioning

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package provisioning provides an abstraction layer for infrastructure provisioning through multiple backends.

Index

Constants

View Source
const (
	// DefaultStatusPollInterval is the default interval for polling provider status.
	DefaultStatusPollInterval = 30 * time.Second

	// DefaultMaxJobHistory is the default number of jobs to keep in status.jobs array.
	DefaultMaxJobHistory = 10
)
View Source
const (
	BackoffBaseDelay = 2 * time.Minute
	BackoffMaxDelay  = 30 * time.Minute
)

Variables

This section is empty.

Functions

func AppendJob

func AppendJob(jobs []v1alpha1.JobStatus, newJob v1alpha1.JobStatus, maxHistory int) []v1alpha1.JobStatus

AppendJob adds a new job to the jobs array and trims to maxHistory.

func CheckAPIServerForNonTerminalProvisionJob

func CheckAPIServerForNonTerminalProvisionJob(ctx context.Context, apiReader client.Reader, key client.ObjectKey, fresh client.Object) bool

CheckAPIServerForNonTerminalProvisionJob reads the resource directly from the API server and returns true if a non-terminal provision job exists.

func ComputeBackoffFromJobs

func ComputeBackoffFromJobs(jobs []v1alpha1.JobStatus, configVersion string) time.Duration

ComputeBackoffFromJobs determines the next backoff duration based on the gap between the last two failed provision jobs with the same ConfigVersion.

func ComputeDeprovisionBackoff

func ComputeDeprovisionBackoff(jobs []v1alpha1.JobStatus) time.Duration

ComputeDeprovisionBackoff determines the next backoff duration for deprovision retries.

func ComputeDesiredConfigVersion

func ComputeDesiredConfigVersion(spec any) (string, error)

ComputeDesiredConfigVersion computes a hash of the spec and returns it. The caller must pass the resource's Spec field (not the entire resource).

func FindJobByID

func FindJobByID(jobs []v1alpha1.JobStatus, jobID string) *v1alpha1.JobStatus

FindJobByID finds a job by its ID in the jobs array. Returns a pointer to the job if found, nil otherwise.

func FindLatestJobByType

func FindLatestJobByType(jobs []v1alpha1.JobStatus, jobType v1alpha1.JobType) *v1alpha1.JobStatus

FindLatestJobByType finds the most recent job of the specified type by timestamp. Returns nil if no job of that type exists.

func GetJobsFromResource

func GetJobsFromResource(resource client.Object) []v1alpha1.JobStatus

GetJobsFromResource extracts the jobs array from a resource. Returns an empty slice for resource types that don't track jobs.

func HandleBackoff

func HandleBackoff(ctx context.Context, provState *State, latestJob *v1alpha1.JobStatus, triggerFn func() (ctrl.Result, error)) (ctrl.Result, error)

HandleBackoff checks if the backoff period has elapsed since the last failed job. If elapsed, it calls triggerFn to retry. Otherwise, it returns a RequeueAfter with the remaining delay.

func HasJobID

func HasJobID(job *v1alpha1.JobStatus) bool

HasJobID returns true if the job is non-nil and has a non-empty JobID.

func IsConfigApplied

func IsConfigApplied(jobs *[]v1alpha1.JobStatus, desiredConfigVersion string) bool

IsConfigApplied returns true if the current spec has been successfully applied. Only the latest provision job is considered to avoid false positives when a spec reverts to a previously applied value (A-B-A problem). Also returns true for legacy provision jobs (empty ConfigVersion) that succeeded, to avoid re-triggering provisioning for resources provisioned before ConfigVersion tracking was introduced.

func NeedsProvisionJob

func NeedsProvisionJob(latestJob *v1alpha1.JobStatus) bool

NeedsProvisionJob determines if a new provision job should be triggered. Returns true if no job exists, or if the previous job failed (allowing retry). Used by controllers without config-version-based provisioning (SecurityGroup, Subnet, VirtualNetwork). Controllers with ConfigVersion support should use EvaluateAction instead, which adds backoff and spec-change detection.

func PollDeprovisionJob

func PollDeprovisionJob(ctx context.Context, provider ProvisioningProvider, resource client.Object,
	jobs *[]v1alpha1.JobStatus, latestDeprovisionJob *v1alpha1.JobStatus, maxHistory int, pollInterval time.Duration) (ctrl.Result, bool, error)

PollDeprovisionJob polls the status of an existing deprovision job. Returns (result, done, error) where done=true means the job reached terminal state and the controller can proceed with finalizer removal. When a deprovision job fails with BlockDeletionOnFailure, the function retries after exponential backoff rather than blocking forever.

func PollJob

func PollJob(ctx context.Context, provider ProvisioningProvider, resource client.Object, provState *State, latestJob *v1alpha1.JobStatus, pollInterval time.Duration, callbacks *PollCallbacks) (ctrl.Result, error)

PollJob checks the status of an existing provision job and updates the jobs slice in place.

func RunDeprovisioningLifecycle

func RunDeprovisioningLifecycle(ctx context.Context, provider ProvisioningProvider, resource client.Object,
	jobs *[]v1alpha1.JobStatus, maxHistory int, pollInterval time.Duration) (ctrl.Result, bool, error)

RunDeprovisioningLifecycle encapsulates the full deprovisioning flow: trigger if no job exists, poll/retry if one does. Controllers call this instead of duplicating the trigger-or-poll logic. Returns (result, done, error) where done=true means the controller can proceed with finalizer removal.

func RunProvisioningLifecycle

func RunProvisioningLifecycle(
	ctx context.Context,
	provider ProvisioningProvider,
	resource client.Object,
	provState *State,
	maxHistory int,
	pollInterval time.Duration,
	callbacks *PollCallbacks,
	checkAPIServer func() bool,
	statusFlush func() error,
) (ctrl.Result, error)

RunProvisioningLifecycle encapsulates the full provisioning flow: evaluate action, trigger/poll/backoff as needed. Controllers call this instead of duplicating the switch statement. The callbacks customize behavior on success and failure.

statusFlush is called after a provision job is successfully triggered to persist the job status immediately, preventing duplicate jobs from concurrent reconciliations. Errors are logged but non-fatal — the end-of-reconcile status update serves as fallback.

func TenantStorageClassesFromContext

func TenantStorageClassesFromContext(ctx context.Context) []v1alpha1.ResolvedStorageClass

TenantStorageClassesFromContext retrieves the tenant storage classes from the context, or nil if not set.

func TriggerDeprovisionJob

func TriggerDeprovisionJob(ctx context.Context, provider ProvisioningProvider, resource client.Object,
	jobs *[]v1alpha1.JobStatus, maxHistory int, pollInterval time.Duration) (ctrl.Result, error)

TriggerDeprovisionJob triggers a deprovision job via the provider and handles the result. Updates the jobs slice in place. Returns the result for the controller to return.

func TriggerJob

func TriggerJob(ctx context.Context, provider ProvisioningProvider, resource client.Object, provState *State, maxHistory int, pollInterval time.Duration) (ctrl.Result, error)

TriggerJob triggers a new provision job and updates the jobs slice in place via State.

func UpdateJob

func UpdateJob(jobs []v1alpha1.JobStatus, updatedJob v1alpha1.JobStatus) bool

UpdateJob updates an existing job by ID with new values. Returns true if the job was found and updated, false otherwise.

func WithTenantStorageClasses

func WithTenantStorageClasses(ctx context.Context, scs []v1alpha1.ResolvedStorageClass) context.Context

WithTenantStorageClasses returns a context carrying the tenant's resolved storage classes. The AAP provider reads this when building extra_vars.

Types

type AAPClient

type AAPClient interface {
	GetTemplate(ctx context.Context, templateName string) (*aap.Template, error)
	LaunchJobTemplate(ctx context.Context, req aap.LaunchJobTemplateRequest) (*aap.LaunchJobTemplateResponse, error)
	LaunchWorkflowTemplate(ctx context.Context, req aap.LaunchWorkflowTemplateRequest) (*aap.LaunchWorkflowTemplateResponse, error)
	GetJob(ctx context.Context, jobID string) (*aap.Job, error)
	CancelJob(ctx context.Context, jobID string) error
}

AAPClient is the interface for AAP operations used by the provider.

type AAPProvider

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

AAPProvider implements ProvisioningProvider using direct AAP REST API integration.

Template resolution supports two modes:

  • Explicit: provisionTemplate and deprovisionTemplate are set directly
  • Prefix-based: templatePrefix is set, and template names are derived from the resource Kind (e.g., prefix "osac" + Kind "VirtualNetwork" → "osac-create-virtual-network")

func NewAAPProvider

func NewAAPProvider(client AAPClient, provisionTemplate, deprovisionTemplate string) *AAPProvider

NewAAPProvider creates a new AAP provider with explicit template names.

func NewAAPProviderWithPrefix

func NewAAPProviderWithPrefix(client AAPClient, templatePrefix string) *AAPProvider

NewAAPProviderWithPrefix creates a new AAP provider that derives template names from the resource Kind using the given prefix. For example, with prefix "osac" and a VirtualNetwork resource, it resolves to "osac-create-virtual-network" and "osac-delete-virtual-network".

func (*AAPProvider) GetDeprovisionStatus

func (p *AAPProvider) GetDeprovisionStatus(ctx context.Context, resource client.Object, jobID string) (ProvisionStatus, error)

GetDeprovisionStatus checks deprovisioning job status via AAP API.

func (*AAPProvider) GetProvisionStatus

func (p *AAPProvider) GetProvisionStatus(ctx context.Context, resource client.Object, jobID string) (ProvisionStatus, error)

GetProvisionStatus checks provisioning job status via AAP API.

func (*AAPProvider) Name

func (p *AAPProvider) Name() string

Name returns the provider name for logging.

func (*AAPProvider) TriggerDeprovision

func (p *AAPProvider) TriggerDeprovision(ctx context.Context, resource client.Object) (*DeprovisionResult, error)

TriggerDeprovision attempts to start deprovisioning for a resource. It checks whether a running provision job needs to be cancelled first.

func (*AAPProvider) TriggerProvision

func (p *AAPProvider) TriggerProvision(ctx context.Context, resource client.Object) (*ProvisionResult, error)

TriggerProvision triggers provisioning via AAP API. Autodetects whether the template is a job_template or workflow_job_template.

type Action

type Action int

Action represents the outcome of shouldTriggerProvision.

const (
	Skip    Action = iota // nothing to do
	Trigger               // trigger a new provision job
	Poll                  // poll an existing non-terminal job
	Requeue               // stale cache detected, requeue to refresh
	Backoff               // failed job with same config, retry after backoff
)

func EvaluateAction

func EvaluateAction(provState *State, checkAPIServer func() bool) (Action, *v1alpha1.JobStatus)

EvaluateAction determines the next provisioning action based on job history and config versions.

func (Action) String

func (a Action) String() string

type DeprovisionAction

type DeprovisionAction string

DeprovisionAction represents the action taken by a provider when attempting to deprovision.

const (
	// DeprovisionTriggered means deprovisioning was started and controller should poll status
	DeprovisionTriggered DeprovisionAction = "triggered"

	// DeprovisionWaiting means provider is not ready yet and controller should requeue
	DeprovisionWaiting DeprovisionAction = "waiting"

	// DeprovisionSkipped means provider determined deprovisioning is not needed
	DeprovisionSkipped DeprovisionAction = "skipped"
)

type DeprovisionResult

type DeprovisionResult struct {
	// Action indicates what the provider did
	Action DeprovisionAction

	// JobID is the tracking identifier when Action==DeprovisionTriggered
	// Used by controller to poll status via GetDeprovisionStatus()
	// Empty when Action==DeprovisionWaiting or Action==DeprovisionSkipped
	JobID string

	// BlockDeletionOnFailure indicates whether deletion should be blocked if deprovision fails
	// Stored in CR status for crash recovery (controller restart)
	// Providers set based on their cleanup guarantees
	BlockDeletionOnFailure bool

	// ProvisionJobStatus is the current status of the provision job (state and message)
	// Populated when provision job is checked before deprovisioning
	// This allows the controller to update the CR status to reflect job cancellation/termination
	// Empty when no provision job exists
	ProvisionJobStatus *ProvisionStatus
}

DeprovisionResult contains the result of attempting to trigger a deprovision operation.

type PollCallbacks

type PollCallbacks struct {
	// OnFailed is called when the job transitions to Failed state.
	OnFailed func(message string)
	// OnSuccess is called when the job succeeds.
	OnSuccess func(status ProvisionStatus)
}

PollCallbacks holds optional callbacks for provision job state transitions.

type ProviderConfig

type ProviderConfig struct {
	AAPClient           AAPClient
	ProvisionTemplate   string
	DeprovisionTemplate string

	// TemplatePrefix enables convention-based template name resolution for AAP.
	// When set, template names are derived from the resource Kind:
	//   {prefix}-create-{kind-kebab} and {prefix}-delete-{kind-kebab}
	// Explicit ProvisionTemplate/DeprovisionTemplate take precedence when set.
	TemplatePrefix string
}

ProviderConfig contains configuration for creating the AAP provisioning provider.

type ProvisionResult

type ProvisionResult struct {
	// JobID is the identifier for the triggered job
	JobID string

	// InitialState is the initial state of the job (typically Pending or Running)
	InitialState v1alpha1.JobState

	// Message is a human-readable status message
	Message string
}

ProvisionResult contains the result of triggering a provision operation.

type ProvisionStatus

type ProvisionStatus struct {
	// JobID is the unique identifier for this job.
	JobID string

	// State indicates the current state of the job.
	State v1alpha1.JobState

	// Message provides a human-readable status message.
	Message string

	// Progress indicates completion percentage (0-100).
	// Optional: providers that don't support progress tracking should leave this at 0.
	Progress int

	// StartTime is when the job started execution.
	StartTime time.Time

	// EndTime is when the job completed (succeeded or failed).
	// Zero value indicates job is still running.
	EndTime time.Time

	// ReconciledVersion is the configuration version that was successfully applied.
	// Only populated when State is JobStateSucceeded.
	ReconciledVersion string

	// ErrorDetails contains detailed error information when State is JobStateFailed.
	ErrorDetails string
}

ProvisionStatus represents the current state of a provisioning or deprovisioning job.

func (*ProvisionStatus) MessageWithDetails

func (s *ProvisionStatus) MessageWithDetails() string

MessageWithDetails returns the message with error details appended, if present.

type ProvisioningProvider

type ProvisioningProvider interface {
	// TriggerProvision starts provisioning for a resource.
	// Returns a ProvisionResult with job details and initial state.
	TriggerProvision(ctx context.Context, resource client.Object) (*ProvisionResult, error)

	// GetProvisionStatus checks the status of a provisioning job.
	// The resource parameter allows providers to check additional state if needed.
	GetProvisionStatus(ctx context.Context, resource client.Object, jobID string) (ProvisionStatus, error)

	// TriggerDeprovision attempts to deprovision a resource.
	// The provider performs any prerequisite checks and returns an action indicating
	// whether deprovisioning was triggered, needs to wait, or should be skipped.
	TriggerDeprovision(ctx context.Context, resource client.Object) (*DeprovisionResult, error)

	// GetDeprovisionStatus checks the status of a deprovisioning job.
	GetDeprovisionStatus(ctx context.Context, resource client.Object, jobID string) (ProvisionStatus, error)

	// Name returns the provider name for logging and identification.
	Name() string
}

ProvisioningProvider abstracts triggering infrastructure automation via AAP and retrieving job status.

func NewProvider

func NewProvider(config ProviderConfig) (ProvisioningProvider, error)

NewProvider creates an AAP provisioning provider from the configuration.

type RateLimitError

type RateLimitError struct {
	RetryAfter time.Duration
}

RateLimitError indicates a request was rate-limited and should be retried.

func AsRateLimitError

func AsRateLimitError(err error) (*RateLimitError, bool)

AsRateLimitError checks if err is a RateLimitError and returns it.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

type State

type State struct {
	Jobs                 *[]v1alpha1.JobStatus
	DesiredConfigVersion string
}

State points into the resource's status fields used by the provisioning lifecycle. Jobs is a pointer so shared functions can modify the slice in place. DesiredConfigVersion is a value snapshot captured at construction time — it is not updated if the instance status changes afterward.

Jump to

Keyboard shortcuts

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