database

package
v0.0.0-...-2776c19 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: Apache-2.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrAmbiguousResult = errors.New("ambiguous result")

ErrAmbiguousResult occurs when a database query intended to yield a single item unexpectedly yields multiple items.

View Source
var ErrItemNotFound = errors.New("item not found")

ErrItemNotFound occurs when the requested item ID was not found, such as in a DBTransactionResult.

View Source
var ErrWrongPartition = errors.New("wrong partition key for transaction")

ErrWrongPartition occurs in a DBTransaction create step when the document has a partition key that differs from the transaction's partition key.

Functions

func CancelActiveOperations

func CancelActiveOperations(ctx context.Context, resourcesDBClient ResourcesDBClient, transaction DBTransaction, opts *ResourcesDBClientListActiveOperationDocsOptions) ([]string, error)

CancelActiveOperations queries for operation documents with a non-terminal status using the filters specified in opts. For every document returned in the query result, CancelActiveOperations adds patch operations to the given DBTransaction to mark the document as canceled.

func CosmosGenericToInternal

func CosmosGenericToInternal[InternalAPIType any](cosmosObj *GenericDocument[InternalAPIType]) (*InternalAPIType, error)

func CosmosToInternal

func CosmosToInternal[InternalAPIType, CosmosAPIType any](obj *CosmosAPIType) (*InternalAPIType, error)

func Delay

func Delay(ctx context.Context, delay time.Duration) error

Copied from azcore/internal/shared/shared.go

func DerivePartitionKey

func DerivePartitionKey[InternalAPIType any](internalObj *InternalAPIType) string

DerivePartitionKey computes the lowercased partition key for an internal object from its type. The CRUD layer is the canonical source of partition keys (the container knows its own rule), so this exists for two callers:

  • The read path's migration fallback, when a stored document predates the PartitionKey field on the envelope.
  • The in-memory mock CRUD, which is generic over every container type and would otherwise have to plumb a per-container PK through every helper.

Returns "" when no derivation is possible — the caller should treat that as a programming error.

func GetOrCreateServiceProviderCluster

func GetOrCreateServiceProviderCluster(
	ctx context.Context, dbClient ResourcesDBClient, clusterResourceID *azcorearm.ResourceID,
) (*api.ServiceProviderCluster, error)

GetOrCreateServiceProviderCluster gets the singleton ServiceProviderCluster instance named `default` for the given cluster resource ID. If it doesn't exist, it creates a new one.

func GetOrCreateServiceProviderNodePool

func GetOrCreateServiceProviderNodePool(
	ctx context.Context, dbClient ResourcesDBClient, nodePoolResourceID *azcorearm.ResourceID,
) (*api.ServiceProviderNodePool, error)

GetOrCreateServiceProviderNodePool gets the singleton ServiceProviderNodePool instance named `default` for the given node pool resource ID. If it doesn't exist, it creates a new one.

func InternalToCosmos

func InternalToCosmos[InternalAPIType, CosmosAPIType any](obj *InternalAPIType) (*CosmosAPIType, error)

func IsBadRequestError

func IsBadRequestError(err error) bool

func IsConflictError

func IsConflictError(err error) bool

IsConflictError returns true if err represents an HTTP 409 Conflict response.

func IsNotFoundError

func IsNotFoundError(err error) bool

IsNotFoundError returns true if err represents an HTTP 404 Not Found response.

func IsPreconditionFailedError

func IsPreconditionFailedError(err error) bool

IsPreconditionFailedError returns true if err represents an HTTP 412 Precondition Failed response.

func ListAll

func ListAll[InternalAPIType any](
	ctx context.Context,
	pageSize int32,
	listFn func(ctx context.Context, opts *DBClientListResourceDocsOptions) (DBClientIterator[InternalAPIType], error),
) ([]*InternalAPIType, error)

ListAll accumulates all pages from a DB GlobalLister into a slice. It calls listFn with a page size hint of pageSize and follows continuation tokens until all items have been collected. Any failure to list or iterate causes an early return because the caller needs the complete set of data to make correct decisions. listFn is expected to accept a opts *DBClientListResourceDocsOptions that supports paging via the PageSizeHint attribute. ListAll assists client code in breaking large list queries into multiple smaller chunks of pageSize or smaller. This helps reduce the load on the database at the cost of more round trips. pageSize determines the maximum number of items to be retrieved at once. A negative value will set a dynamic page size controlled by Cosmos.

func NewCosmosDatabaseClient

func NewCosmosDatabaseClient(url string, dbName string, clientOptions azcore.ClientOptions) (*azcosmos.DatabaseClient, error)

NewCosmosDatabaseClient instantiates a generic Cosmos database client.

func NewCosmosResourceCRUD

func NewCosmosResourceCRUD[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType], CosmosAPIType any](
	containerClient *azcosmos.ContainerClient, parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType) *nestedCosmosResourceCRUD[InternalAPIType, InternalAPITypePointer, CosmosAPIType]

NewCosmosResourceCRUD constructs a CRUD using the subscription-ID partition key policy and the standard ARM-style path builder. For containers that partition or build paths differently use NewCosmosResourceCRUDWithPartitionKey or NewCosmosResourceCRUDWithStrategies.

func NewCosmosResourceCRUDWithPartitionKey

func NewCosmosResourceCRUDWithPartitionKey[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType], CosmosAPIType any](
	containerClient *azcosmos.ContainerClient, parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType, partitionKeyDeriver PartitionKeyDeriver) *nestedCosmosResourceCRUD[InternalAPIType, InternalAPITypePointer, CosmosAPIType]

NewCosmosResourceCRUDWithPartitionKey constructs a CRUD with a caller-chosen partition key policy and the standard ARM-style path builder.

func NewCosmosResourceCRUDWithStrategies

func NewCosmosResourceCRUDWithStrategies[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType], CosmosAPIType any](
	containerClient *azcosmos.ContainerClient, parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType, partitionKeyDeriver PartitionKeyDeriver, resourceIDBuilder ResourceIDBuilder) *nestedCosmosResourceCRUD[InternalAPIType, InternalAPITypePointer, CosmosAPIType]

NewCosmosResourceCRUDWithStrategies constructs a CRUD with caller-chosen partition-key and resource-ID-path policies. Use this to back containers whose layout deviates from the standard ARO scheme (fleet, kube-applier).

func NewNotFoundError

func NewNotFoundError() *azcore.ResponseError

func NewOperation

func NewOperation(
	request OperationRequest,
	externalID *azcorearm.ResourceID,
	internalID ocm.InternalID,
	location, tenantID, clientID, notificationURI string,
	correlationData *arm.CorrelationData,
) *api.Operation

func NewPartitionKey

func NewPartitionKey(subscriptionID string) azcosmos.PartitionKey

NewPartitionKey creates a partition key from an Azure subscription ID.

func NewTransactionStepError

func NewTransactionStepError(step, totalSteps, httpStatusCode int) error

NewTransactionStepError returns an error that indicates that a step in a Cosmos DB transaction failed with the given HTTP status code.

func OldResourceIDToCosmosID

func OldResourceIDToCosmosID(resourceID *azcorearm.ResourceID) (string, error)

func PrepareForCreate

func PrepareForCreate[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType]](newObj InternalAPITypePointer) error

PrepareForCreate sets InstanceVersion to 1 on the CosmosMetadata of newObj. All Create paths (in this package and in databasetesting) must call this before serializing the document so that a fresh insert starts the version counter at 1. The value is unconditionally overwritten so callers can't accidentally carry over a value from a prior Get.

func PrepareForReplace

func PrepareForReplace[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType]](newObj InternalAPITypePointer) error

PrepareForReplace enforces the two invariants of an update: every Replace must carry a CosmosETag (we refuse unconditional updates) and the on-disk InstanceVersion auto-increments. All Replace paths (in this package and in databasetesting) must call this before serializing the document.

func SerializeItem

func SerializeItem[InternalAPIType, CosmosAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType]](newObj InternalAPITypePointer) (*arm.CosmosMetadata, []byte, error)

SerializeItem reads the partition key from newObj's CosmosMetadata and serializes the object to JSON. The caller is responsible for populating CosmosMetadata.PartitionKey ahead of time (via SetPartitionKey); SerializeItem refuses to write a document with an empty partition key because doing so silently corrupts the container.

func ToStatus

func ToStatus(doc *api.Operation) *arm.Operation

ToStatus converts an OperationDocument to the ARM operation status format.

Types

type BaseDocument

type BaseDocument struct {
	ID string `json:"id,omitempty"`

	// https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/time-to-live
	TimeToLive int `json:"ttl,omitempty"`

	// System-defined properties generated by Cosmos DB
	CosmosResourceID  string      `json:"_rid,omitempty"`
	CosmosSelf        string      `json:"_self,omitempty"`
	CosmosETag        azcore.ETag `json:"_etag,omitempty"`
	CosmosAttachments string      `json:"_attachments,omitempty"`
	CosmosTimestamp   int         `json:"_ts,omitempty"`
}

BaseDocument includes fields common to all container items.

type BillingDBClient

type BillingDBClient interface {
	BillingDocs(subscriptionID string) BillingDocCRUD
	BillingGlobalListers() BillingGlobalListers
}

BillingDBClient provides access to the Cosmos DB Billing container (separate from ARM resource documents).

func NewBillingDBClient

func NewBillingDBClient(database *azcosmos.DatabaseClient) (BillingDBClient, error)

NewBillingDBClient opens the Billing container on the given async database client.

type BillingDocCRUD

type BillingDocCRUD interface {
	// Create a new billing document
	Create(ctx context.Context, doc *BillingDocument) error

	// GetByID retrieves a billing document by its ID
	GetByID(ctx context.Context, billingDocID string) (*BillingDocument, error)

	// List returns an iterator for all billing documents in the given subscription partition.
	// This includes both active and deleted billing documents.
	List(ctx context.Context) (DBClientIterator[BillingDocument], error)

	// ListActive lists all active billing documents (without deletion time) for the subscription
	ListActive(ctx context.Context) ([]*BillingDocument, error)

	// ListActiveForCluster lists active billing documents for a specific cluster
	ListActiveForCluster(ctx context.Context, resourceID *azcorearm.ResourceID) ([]*BillingDocument, error)

	// PatchByID patches a billing document by its ID
	PatchByID(ctx context.Context, billingDocID string, ops BillingDocumentPatchOperations) error

	// PatchByClusterID patches all active billing documents for a cluster
	PatchByClusterID(ctx context.Context, resourceID *azcorearm.ResourceID, ops BillingDocumentPatchOperations) error
}

BillingDocCRUD provides a CRUD interface for managing billing documents within a subscription partition.

func NewBillingDocCRUD

func NewBillingDocCRUD(containerClient *azcosmos.ContainerClient, subscriptionID string) BillingDocCRUD

NewBillingDocCRUD creates a new BillingDocCRUD instance for a subscription

type BillingDocument

type BillingDocument struct {
	BaseDocument

	// The cluster creation time represents the time when the cluster was provisioned successfully
	CreationTime time.Time `json:"creationTime,omitempty"`
	// The cluster deletion time
	DeletionTime *time.Time `json:"deletionTime,omitempty"`

	// The location of the HCP cluster
	Location string `json:"location,omitempty"`
	// The tenant ID of the HCP cluster
	TenantID string `json:"tenantId,omitempty"`
	// The subscription ID of the HCP cluster (also the partition key)
	SubscriptionID string `json:"subscriptionId,omitempty"`
	// The HCP cluster ARM resource ID
	ResourceID *azcorearm.ResourceID `json:"resourceId,omitempty"`
	// The ARM resource ID of the managed resource group of the HCP cluster
	ManagedResourceGroup string `json:"managedResourceGroup,omitempty"`
}

BillingDocument records timestamps of Hosted Control Plane OpenShift cluster creation and deletion for the purpose of customer billing.

func NewBillingDocument

func NewBillingDocument(id string, resourceID *azcorearm.ResourceID) *BillingDocument

func (*BillingDocument) DeepCopy

func (in *BillingDocument) DeepCopy() *BillingDocument

DeepCopy creates a deep copy of the BillingDocument.

func (*BillingDocument) DeepCopyObject

func (in *BillingDocument) DeepCopyObject() runtime.Object

DeepCopyObject creates a deep copy of the BillingDocument as runtime.Object.

func (*BillingDocument) GetObjectKind

func (in *BillingDocument) GetObjectKind() schema.ObjectKind

GetObjectKind returns the object kind for BillingDocument.

func (*BillingDocument) GetObjectMeta

func (in *BillingDocument) GetObjectMeta() metav1.Object

GetObjectMeta returns metadata that allows Kubernetes informer machinery to key billing documents by their ID.

type BillingDocumentList

type BillingDocumentList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	ResourceVersion string
	Items           []BillingDocument `json:"items"`
}

BillingDocumentList is a list of billing documents for use with Kubernetes informers.

func (*BillingDocumentList) DeepCopy

func (in *BillingDocumentList) DeepCopy() *BillingDocumentList

DeepCopy creates a deep copy of the BillingDocumentList.

func (*BillingDocumentList) DeepCopyObject

func (in *BillingDocumentList) DeepCopyObject() runtime.Object

DeepCopyObject creates a deep copy of the BillingDocumentList as runtime.Object.

func (*BillingDocumentList) GetObjectKind

func (l *BillingDocumentList) GetObjectKind() schema.ObjectKind

GetObjectKind returns the object kind for BillingDocumentList.

type BillingDocumentPatchOperations

type BillingDocumentPatchOperations struct {
	azcosmos.PatchOperations
}

BillingDocumentPatchOperations represents a patch request for a BillingDocument.

func (*BillingDocumentPatchOperations) SetDeletionTime

func (p *BillingDocumentPatchOperations) SetDeletionTime(deletionTime time.Time)

SetDeletionTime appends a set operation for the DeletionTime field.

type BillingGlobalListers

type BillingGlobalListers interface {
	BillingDocs() GlobalLister[BillingDocument]
}

BillingGlobalListers exposes cross-partition listers for billing documents (for informers).

func NewCosmosBillingGlobalListers

func NewCosmosBillingGlobalListers(billing *azcosmos.ContainerClient) BillingGlobalListers

NewCosmosBillingGlobalListers builds BillingGlobalListers backed by the Billing container.

type ClusterNestedResourceIDBuilder

type ClusterNestedResourceIDBuilder struct{}

ClusterNestedResourceIDBuilder is the default ARO-resource path policy: a nil parent yields a /subscriptions/<name> path; a parent in the Microsoft.Resources namespace transitions via /providers/<namespace>; deeper parents (already in the provider namespace, like an HCP cluster or node pool) must include a resourceGroup. Use this for any container whose layout is rooted in the standard ARM subscriptions/resourceGroups scheme.

func (ClusterNestedResourceIDBuilder) BuildResourceID

func (ClusterNestedResourceIDBuilder) BuildResourceID(parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType, resourceName string) (*azcorearm.ResourceID, error)

type ControllerContainer

type ControllerContainer interface {
	// TODO controllers are a concept that is at this scope and at lower scopes and sometimes you want to query all like it
	// TODO they look a lot like operations, though we can model them as a one-off to start.
	Controllers(hcpClusterID string) ResourceCRUD[api.Controller, *api.Controller]
}

type CosmosDBTransactionDetails

type CosmosDBTransactionDetails struct {
	PartitionKey string                           `json:"partitionKey"`
	Steps        []CosmosDBTransactionStepDetails `json:"steps"`
}

type CosmosDBTransactionStep

type CosmosDBTransactionStep func(b *azcosmos.TransactionalBatch) (string, error)

type CosmosDBTransactionStepDetails

type CosmosDBTransactionStepDetails struct {
	ActionType string      `json:"actionType"`
	CosmosID   string      `json:"cosmosID"`
	ResourceID string      `json:"resourceID"`
	GoType     string      `json:"goType"`
	Etag       azcore.ETag `json:"etag"`
}

type DBClientIterator

type DBClientIterator[T any] interface {
	Items(ctx context.Context) DBClientIteratorItem[T]
	GetContinuationToken() string
	GetError() error
}

type DBClientIteratorItem

type DBClientIteratorItem[T any] iter.Seq2[string, *T]

type DBClientListResourceDocsOptions

type DBClientListResourceDocsOptions struct {
	// ResourceType matches (case-insensitively) the Azure resource type. If unspecified,
	// ResourcesDBClient.ListResourceDocs will match resource documents for any resource type.
	ResourceType *azcorearm.ResourceType

	// PageSizeHint can limit the number of items returned at once. A negative value will cause
	// the returned iterator to yield all matching documents (same as leaving the option nil).
	// A positive value will cause the returned iterator to include a continuation token if
	// additional items are available.
	PageSizeHint *int32

	// ContinuationToken can be supplied when limiting the number of items returned at once
	// through PageSizeHint.
	ContinuationToken *string
}

DBClientListResourceDocsOptions allows for limiting the results of ResourcesDBClient.ListResourceDocs.

type DBTransaction

type DBTransaction interface {
	// AddStep adds a transaction function to the list to perform
	AddStep(CosmosDBTransactionStepDetails, CosmosDBTransactionStep)

	// GetPartitionKey returns the transaction's partition key.
	GetPartitionKey() string

	// OnSuccess adds a function to call if the transaction executes successfully.
	OnSuccess(callback DBTransactionCallback)

	// Execute submits the prepared transaction.
	Execute(ctx context.Context, o *azcosmos.TransactionalBatchOptions) (DBTransactionResult, error)
}

type DBTransactionCallback

type DBTransactionCallback func(DBTransactionResult)

type DBTransactionResult

type DBTransactionResult interface {
	// GetItem returns the internal API representation for the cosmosUID.
	// That is consistent with other returns from our database layer.
	// The Item is only available if the transaction was
	// executed with the EnableContentResponseOnWrite option set, or
	// the document was requested with DBTransaction.ReadDoc.
	GetItem(cosmosUID string) (any, error)
}

type Defaulter

type Defaulter interface {
	EnsureDefaults()
}

type FleetDBClient

type FleetDBClient interface {
	Stamps() StampsCRUD
	GlobalListers() FleetGlobalListers
}

FleetDBClient is the database surface for the Fleet Cosmos container. It is intentionally separate from ResourcesDBClient because the Fleet container holds management cluster inventory data with its own access patterns and credential scoping.

func NewFleetDBClient

func NewFleetDBClient(database *azcosmos.DatabaseClient) (FleetDBClient, error)

NewFleetDBClient instantiates a FleetDBClient from a Cosmos DatabaseClient.

func NewFleetDBClientFromContainer

func NewFleetDBClientFromContainer(container *azcosmos.ContainerClient) FleetDBClient

NewFleetDBClientFromContainer wraps an already-opened container client.

type FleetGlobalListers

type FleetGlobalListers interface {
	Stamps() GlobalLister[fleet.Stamp]
	ManagementClusters() GlobalLister[fleet.ManagementCluster]
}

FleetGlobalListers provides cross-partition listers for fleet resource types.

type FleetPartitionKeyDeriver

type FleetPartitionKeyDeriver struct{}

FleetPartitionKeyDeriver partitions by the lowercased name of the root ancestor of the resource hierarchy — i.e. by stamp name. For top-level resources (nil parent) the resource name itself IS the partition key. List/GetByID with neither a parent nor a resource name to fall back on returns an error. This is the policy used by the fleet container.

func (FleetPartitionKeyDeriver) PartitionKey

func (FleetPartitionKeyDeriver) PartitionKey(parentResourceID *azcorearm.ResourceID, resourceName string) (string, error)

func (FleetPartitionKeyDeriver) PartitionKeyFromObject

func (FleetPartitionKeyDeriver) PartitionKeyFromObject(obj any) (string, error)

type FleetResourceIDBuilder

type FleetResourceIDBuilder struct{}

FleetResourceIDBuilder builds resource IDs for the fleet container, which lives outside the ARM subscriptions/resourceGroups hierarchy. A nil parent yields a top-level path "/providers/<full-type>/<name>" (e.g. a stamp); a non-nil parent extends with "/<leaf-type>/<name>". The whole path is lowercased.

func (FleetResourceIDBuilder) BuildResourceID

func (FleetResourceIDBuilder) BuildResourceID(parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType, resourceName string) (*azcorearm.ResourceID, error)

type GenericDocument

type GenericDocument[InternalAPIType any] struct {
	TypedDocument `json:",inline"`

	Content InternalAPIType `json:"properties"`
}

pointer of InternalAPIType needs to be arm.CosmosMetadataAccessor

func InternalToCosmosGeneric

func InternalToCosmosGeneric[InternalAPIType any](internalObj *InternalAPIType) (*GenericDocument[InternalAPIType], error)

type GlobalLister

type GlobalLister[T any] interface {
	List(ctx context.Context, options *DBClientListResourceDocsOptions) (DBClientIterator[T], error)
}

GlobalLister lists all resources of a particular type across all partitions.

type HCPClusterCRUD

type HCPClusterCRUD interface {
	ResourceCRUD[api.HCPOpenShiftCluster, *api.HCPOpenShiftCluster]
	ControllerContainer
	ManagementClusterContentContainer

	ExternalAuth(hcpClusterID string) ExternalAuthsCRUD
	NodePools(hcpClusterID string) NodePoolsCRUD
}

func NewHCPClusterCRUD

func NewHCPClusterCRUD(containerClient *azcosmos.ContainerClient, subscriptionID, resourceGroupName string) HCPClusterCRUD

type KubeApplierApplyDesireCRUD

type KubeApplierApplyDesireCRUD interface {
	ApplyDesiresForCluster(subscriptionID, resourceGroupName, clusterName string) (ResourceCRUD[kubeapplier.ApplyDesire, *kubeapplier.ApplyDesire], error)
	ApplyDesiresForNodePool(subscriptionID, resourceGroupName, clusterName, nodePoolName string) (ResourceCRUD[kubeapplier.ApplyDesire, *kubeapplier.ApplyDesire], error)
}

KubeApplierApplyDesireCRUD is the narrow per-type peer interface that the apply_desire controller takes as its database dependency. KubeApplierDBClient satisfies it; tests can also provide a one-method fake.

type KubeApplierDBClient

type KubeApplierDBClient interface {
	// ApplyDesiresForCluster returns a CRUD scoped to a cluster parent.
	ApplyDesiresForCluster(subscriptionID, resourceGroupName, clusterName string) (ResourceCRUD[kubeapplier.ApplyDesire, *kubeapplier.ApplyDesire], error)
	// ApplyDesiresForNodePool returns a CRUD scoped to a nodepool parent.
	ApplyDesiresForNodePool(subscriptionID, resourceGroupName, clusterName, nodePoolName string) (ResourceCRUD[kubeapplier.ApplyDesire, *kubeapplier.ApplyDesire], error)
	// ReadDesiresForCluster returns a CRUD scoped to a cluster parent.
	ReadDesiresForCluster(subscriptionID, resourceGroupName, clusterName string) (ResourceCRUD[kubeapplier.ReadDesire, *kubeapplier.ReadDesire], error)
	// ReadDesiresForNodePool returns a CRUD scoped to a nodepool parent.
	ReadDesiresForNodePool(subscriptionID, resourceGroupName, clusterName, nodePoolName string) (ResourceCRUD[kubeapplier.ReadDesire, *kubeapplier.ReadDesire], error)

	// Listers lists every *Desire of each kind in this container — i.e. across the
	// one management cluster's worth of data. Replaces the old GlobalListers /
	// PartitionListers split, which existed only because all management clusters
	// previously shared one container.
	Listers() KubeApplierListers

	// UntypedCRUD walks this container by resourceID prefix, returning
	// TypedDocument rows for cross-cutting cleanup. Deletion goes through
	// DeleteByCosmosID using the partitionKey from the listed row.
	UntypedCRUD(parentResourceID azcorearm.ResourceID) (UntypedResourceCRUD, error)
}

KubeApplierDBClient is the database surface for a single management cluster's kube-applier container. In the per-management-cluster container model, every container holds exactly one management cluster's *Desire documents, so callers never need to pass a management-cluster name into a method on this interface. Callers that span multiple management clusters (the backend) hold a KubeApplierDBClients (plural) and obtain a per-MC client via For().

func NewKubeApplierDBClient

func NewKubeApplierDBClient(container *azcosmos.ContainerClient, managementClusterResourceID *azcorearm.ResourceID) KubeApplierDBClient

NewKubeApplierDBClient wraps a pre-opened Cosmos container client for a single management cluster.

func NewKubeApplierDBClientFromDatabase

func NewKubeApplierDBClientFromDatabase(database *azcosmos.DatabaseClient, containerName string, managementClusterResourceID *azcorearm.ResourceID) (KubeApplierDBClient, error)

NewKubeApplierDBClientFromDatabase opens the named container under the given Cosmos database and wraps it for the named management cluster. Convenience for callers like the kube-applier sidecar that have a DatabaseClient in hand.

type KubeApplierDBClients

type KubeApplierDBClients interface {
	// For returns the client for the given management cluster, constructing it
	// on demand. It walks the configured ManagementClusterLister to find the
	// management cluster whose ResourceID matches; the container name comes
	// from the management cluster's Status.KubeApplierCosmosContainerName.
	// Returns nil if no management cluster matches, if the lister errors, or
	// if the matched management cluster has no container name configured.
	For(ctx context.Context, managementClusterResourceID *azcorearm.ResourceID) KubeApplierDBClient
}

KubeApplierDBClients is a thread-safe registry of KubeApplierDBClient keyed by management-cluster resourceID. Each entry corresponds to one Cosmos container, resolved at lookup time from the configured ManagementClusterLister. Per-MC clients are constructed lazily on first For() access and cached.

func NewKubeApplierDBClients

func NewKubeApplierDBClients(database *azcosmos.DatabaseClient, mcLister ManagementClusterLister) KubeApplierDBClients

NewKubeApplierDBClients constructs a thread-safe registry whose contents are resolved against the provided ManagementClusterLister. Each ManagementCluster's Status.KubeApplierCosmosContainerName names the Cosmos container; the management cluster's Status.MaestroConsumerName is used as the per-container partition key. Per-MC KubeApplierDBClient instances are built lazily and cached on first access via For().

type KubeApplierListers

type KubeApplierListers interface {
	ApplyDesires() GlobalLister[kubeapplier.ApplyDesire]
	ReadDesires() GlobalLister[kubeapplier.ReadDesire]
}

KubeApplierListers exposes per-container listers for each *Desire kind. The underlying container holds one management cluster's documents, so a List call returns every desire of that kind for that management cluster.

type KubeApplierPartitionKeyDeriver

type KubeApplierPartitionKeyDeriver struct {
	ManagementClusterResourceID *azcorearm.ResourceID
}

KubeApplierPartitionKeyDeriver derives the partition key used by the kube-applier container, which is partitioned by the lowercased management cluster resourceID. For CRUD-scope operations the per-container instance carries the management cluster's resourceID directly; for per-object derivation (read-path migration fallback, mock CRUD) we read the cluster off the *Desire's spec.managementCluster.

func (KubeApplierPartitionKeyDeriver) PartitionKey

func (KubeApplierPartitionKeyDeriver) PartitionKeyFromObject

func (KubeApplierPartitionKeyDeriver) PartitionKeyFromObject(obj any) (string, error)

type KubeApplierReadDesireCRUD

type KubeApplierReadDesireCRUD interface {
	ReadDesiresForCluster(subscriptionID, resourceGroupName, clusterName string) (ResourceCRUD[kubeapplier.ReadDesire, *kubeapplier.ReadDesire], error)
	ReadDesiresForNodePool(subscriptionID, resourceGroupName, clusterName, nodePoolName string) (ResourceCRUD[kubeapplier.ReadDesire, *kubeapplier.ReadDesire], error)
}

KubeApplierReadDesireCRUD is the ReadDesire peer of KubeApplierApplyDesireCRUD.

type LockClient

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

func NewLockClient

func NewLockClient(ctx context.Context, containerClient *azcosmos.ContainerClient) (*LockClient, error)

NewLockClient creates a LockClient around a ContainerClient. It attempts to read container properties to extract a default TTL. If this fails or if the container does not define a default TTL, the function returns an error.

func (*LockClient) AcquireLock

func (c *LockClient) AcquireLock(ctx context.Context, id string, timeout *time.Duration) (*azcosmos.ItemResponse, error)

AcquireLock persistently tries to acquire a lock for the given ID. If a timeout is provided, the function will cease after the timeout duration and return a context.DeadlineExceeded error.

func (*LockClient) GetDefaultTimeToLive

func (c *LockClient) GetDefaultTimeToLive() time.Duration

GetDefaultTimeToLive returns the default time-to-live value of the container as a time.Duration.

func (*LockClient) HoldLock

func (c *LockClient) HoldLock(ctx context.Context, item *azcosmos.ItemResponse) (cancelCtx context.Context, stop StopHoldLock)

HoldLock tries to hold an acquired lock by renewing it periodically from a goroutine until the returned stop function is called. The function also returns a new context which is cancelled if the lock is lost or some other error occurs. The stop function terminates the goroutine and returns the current lock, or nil if the lock was lost.

func (*LockClient) ReleaseLock

func (c *LockClient) ReleaseLock(ctx context.Context, item *azcosmos.ItemResponse) error

ReleaseLock attempts to release an acquired lock. Errors should be logged but not treated as fatal, since the container item's TTL value guarantees that it will be released eventually.

func (*LockClient) RenewLock

RenewLock attempts to renew an acquired lock. If successful it returns a new lock. If the lock was somehow lost, it returns a nil azcosmos.ItemResponse and no error.

func (*LockClient) SetName

func (c *LockClient) SetName(name string)

SetName overrides how a lock item identifies the owner. This is for informational purposes only. LockClient uses the hostname by default.

func (*LockClient) SetRetryAfterHeader

func (c *LockClient) SetRetryAfterHeader(header http.Header)

SetRetryAfterHeader sets a "Retry-After" header to the default TTL value.

func (*LockClient) TryAcquireLock

func (c *LockClient) TryAcquireLock(ctx context.Context, id string) (*azcosmos.ItemResponse, error)

TryAcquireLock tries once to acquire a lock for the given ID. If the lock is already taken, it returns a nil azcosmos.ItemResponse and no error.

type LockClientInterface

type LockClientInterface interface {
	GetDefaultTimeToLive() time.Duration
	SetRetryAfterHeader(header http.Header)
	AcquireLock(ctx context.Context, id string, timeout *time.Duration) (*azcosmos.ItemResponse, error)
	TryAcquireLock(ctx context.Context, id string) (*azcosmos.ItemResponse, error)
	HoldLock(ctx context.Context, item *azcosmos.ItemResponse) (context.Context, StopHoldLock)
	RenewLock(ctx context.Context, item *azcosmos.ItemResponse) (*azcosmos.ItemResponse, error)
	ReleaseLock(ctx context.Context, item *azcosmos.ItemResponse) error
}

type LocksDBClient

type LocksDBClient interface {
	LockClient() LockClientInterface
}

LocksDBClient provides access to the Cosmos DB Locks container used for subscription-scoped concurrency.

func NewLocksDBClient

func NewLocksDBClient(ctx context.Context, database *azcosmos.DatabaseClient) (LocksDBClient, error)

NewLocksDBClient opens the Locks container on the given async database client and builds the lock client.

type ManagementClusterContentContainer

type ManagementClusterContentContainer interface {
	ManagementClusterContents(resourceName string) ResourceCRUD[api.ManagementClusterContent, *api.ManagementClusterContent]
}

type ManagementClusterLister

type ManagementClusterLister interface {
	List(ctx context.Context) ([]*fleet.ManagementCluster, error)
}

ManagementClusterLister is the narrow lister shape KubeApplierDBClients depends on to resolve a management-cluster resourceID into its Cosmos container name and partition-key value. The listers package's full ManagementClusterLister satisfies it; declaring the slimmer interface here keeps the import direction clean (database can stay below database/listers in the import graph).

func NewDBBackedManagementClusterLister

func NewDBBackedManagementClusterLister(fleetClient FleetDBClient) ManagementClusterLister

NewDBBackedManagementClusterLister adapts a FleetDBClient's cross-partition ManagementClusters global lister into the slim ManagementClusterLister interface. Each List() call hits Cosmos directly — no informer caching — which is fine for low-cadence callers like the orphan-cleanup controller (60-minute jitter). Backend startup that doesn't yet have informers wired can use this without taking on the informer lifecycle.

type ManagementClustersCRUD

type ManagementClustersCRUD interface {
	ValidatingResourceCRUD[fleet.ManagementCluster, *fleet.ManagementCluster]
	Controllers() ResourceCRUD[api.Controller, *api.Controller]
}

ManagementClustersCRUD provides CRUD operations for management clusters and access to their nested controller status documents.

type OperationCRUD

type OperationCRUD interface {
	ResourceCRUD[api.Operation, *api.Operation]

	// ListActiveOperations returns an iterator that searches for asynchronous operation documents
	// with a non-terminal status in the "Resources" container under the given partition key. The
	// options argument can further limit the search to documents that match the provided values.
	//
	// Note that ListActiveOperations does not perform the search, but merely prepares an iterator
	// to do so. Hence the lack of a Context argument. The search is performed by calling Items() on
	// the iterator in a ranged for loop.
	ListActiveOperations(options *ResourcesDBClientListActiveOperationDocsOptions) DBClientIterator[api.Operation]
}

func NewOperationCRUD

func NewOperationCRUD(containerClient *azcosmos.ContainerClient, subscriptionID string) OperationCRUD

type OperationRequest

type OperationRequest = api.OperationRequest
const (
	OperationRequestCreate OperationRequest = "Create"
	OperationRequestUpdate OperationRequest = "Update"
	OperationRequestDelete OperationRequest = "Delete"

	// These are for POST actions on resources.
	OperationRequestRequestCredential OperationRequest = "RequestCredential"
	OperationRequestRevokeCredentials OperationRequest = "RevokeCredentials"
)

type PartitionKeyDeriver

type PartitionKeyDeriver interface {
	PartitionKey(parentResourceID *azcorearm.ResourceID, resourceName string) (string, error)
	PartitionKeyFromObject(obj any) (string, error)
}

PartitionKeyDeriver computes the Cosmos partition key for documents accessed through a CRUD scope. Implementations capture the partitioning policy of a container: ARO resource containers partition by subscription ID, the fleet container partitions by top-level resource name, the kube-applier container partitions by management cluster name. Injecting the deriver lets a single CRUD type serve all three schemes.

PartitionKey is the parent-scoped form used by CRUD operations: the two arguments cover both list/GetByID (resourceName is "") and per-item operations (resourceName is the leaf name). Implementations decide which arguments are load-bearing.

PartitionKeyFromObject derives the partition key directly from a fully-formed object. It is used by the read-path migration fallback and by the in-memory mock CRUD's generic helpers. Implementations return an error when the object's shape isn't appropriate for the deriver's policy (so a registry of derivers can be tried in order to find the one that applies).

type ResourceCRUD

type ResourceCRUD[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType]] interface {
	GetByID(ctx context.Context, cosmosID string) (*InternalAPIType, error)
	Get(ctx context.Context, resourceID string) (*InternalAPIType, error)
	List(ctx context.Context, opts *DBClientListResourceDocsOptions) (DBClientIterator[InternalAPIType], error)
	Create(ctx context.Context, newObj *InternalAPIType, options *azcosmos.ItemOptions) (*InternalAPIType, error)
	Replace(ctx context.Context, newObj *InternalAPIType, options *azcosmos.ItemOptions) (*InternalAPIType, error)
	Delete(ctx context.Context, resourceID string) error

	AddCreateToTransaction(ctx context.Context, transaction DBTransaction, newObj *InternalAPIType, opts *azcosmos.TransactionalBatchItemOptions) (string, error)
	AddReplaceToTransaction(ctx context.Context, transaction DBTransaction, newObj *InternalAPIType, opts *azcosmos.TransactionalBatchItemOptions) (string, error)
}

func NewControllerCRUD

func NewControllerCRUD(
	containerClient *azcosmos.ContainerClient, parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType) ResourceCRUD[api.Controller, *api.Controller]

type ResourceIDBuilder

type ResourceIDBuilder interface {
	BuildResourceID(parentResourceID *azcorearm.ResourceID, resourceType azcorearm.ResourceType, resourceName string) (*azcorearm.ResourceID, error)
}

ResourceIDBuilder constructs a full Azure resource ID from a parent scope, a resource type, and an optional leaf name. Implementations capture the path-construction policy of a container: ARO resource containers honor the Microsoft.Resources → provider-namespace transition; fleet and kube-applier containers use a simpler parent/type/name concatenation. resourceName is empty when the caller wants the *parent path* of all items (used by List).

type ResourcesDBClient

type ResourcesDBClient interface {
	// NewTransaction initiates a new transactional batch for the given partition key.
	NewTransaction(pk string) DBTransaction

	// UntypedCRUD provides access documents in the subscription
	UntypedCRUD(parentResourceID azcorearm.ResourceID) (UntypedResourceCRUD, error)

	// HCPClusters retrieves a CRUD interface for managing HCPCluster resources and their nested resources.
	HCPClusters(subscriptionID, resourceGroupName string) HCPClusterCRUD

	// Operations retrieves a CRUD interface for managing operations.  Remember that operations are not directly accessible
	// to end users via ARM.  They must also survive the thing they are deleting, so they live under a subscription directly.
	Operations(subscriptionID string) OperationCRUD

	Subscriptions() ResourceCRUD[arm.Subscription, *arm.Subscription]

	ServiceProviderClusters(subscriptionID, resourceGroupName, clusterName string) ResourceCRUD[api.ServiceProviderCluster, *api.ServiceProviderCluster]

	// ResourcesGlobalListers returns interfaces for listing ARM resource documents across all partitions
	// (Resources container only), intended for feeding SharedInformers.
	ResourcesGlobalListers() ResourcesGlobalListers

	ServiceProviderNodePools(subscriptionID, resourceGroupName, clusterName, nodePoolName string) ResourceCRUD[api.ServiceProviderNodePool, *api.ServiceProviderNodePool]
}

ResourcesDBClient provides a customized interface to the Cosmos DB containers used by the ARO-HCP resource provider.

func NewResourcesDBClient

func NewResourcesDBClient(database *azcosmos.DatabaseClient) (ResourcesDBClient, error)

NewResourcesDBClient instantiates a ResourcesDBClient from a Cosmos DatabaseClient instance targeting the Frontends async database (Resources container).

type ResourcesDBClientListActiveOperationDocsOptions

type ResourcesDBClientListActiveOperationDocsOptions struct {
	// Request matches the type of asynchronous operation requested
	Request *OperationRequest
	// ExternalID matches (case-insensitively) the Azure resource ID of the cluster or node pool
	ExternalID *azcorearm.ResourceID
	// IncludeNestedResources includes nested resources under ExternalID
	IncludeNestedResources bool
}

ResourcesDBClientListActiveOperationDocsOptions allows for limiting the results of ResourcesDBClient.ListActiveOperationDocs.

type ResourcesGlobalListers

type ResourcesGlobalListers interface {
	Subscriptions() GlobalLister[arm.Subscription]
	Clusters() GlobalLister[api.HCPOpenShiftCluster]
	NodePools() GlobalLister[api.HCPOpenShiftClusterNodePool]
	ExternalAuths() GlobalLister[api.HCPOpenShiftClusterExternalAuth]
	ServiceProviderClusters() GlobalLister[api.ServiceProviderCluster]
	ServiceProviderNodePools() GlobalLister[api.ServiceProviderNodePool]
	Controllers() GlobalLister[api.Controller]
	// ManagementClusterContents lists ManagementClusterContent documents across
	// partitions for every Cosmos resource type where managementClusterContents
	// is nested as a direct child resource. Those types are registered on the lister implementation.
	ManagementClusterContents() GlobalLister[api.ManagementClusterContent]
	Operations() GlobalLister[api.Operation]
	ActiveOperations() GlobalLister[api.Operation]
}

ResourcesGlobalListers provides access to global listers for each resource type. These are intended to feed SharedInformers via ListerWatchers.

func NewCosmosResourcesGlobalListers

func NewCosmosResourcesGlobalListers(resources *azcosmos.ContainerClient) ResourcesGlobalListers

type StampsCRUD

type StampsCRUD interface {
	ValidatingResourceCRUD[fleet.Stamp, *fleet.Stamp]
	ManagementClusters(stampIdentifier string) ManagementClustersCRUD
}

StampsCRUD provides CRUD operations for stamps and access to their nested management cluster sub-resources.

type StopHoldLock

type StopHoldLock func() *azcosmos.ItemResponse

type SubscriptionPartitionKeyDeriver

type SubscriptionPartitionKeyDeriver struct{}

SubscriptionPartitionKeyDeriver derives the partition key from the subscription ID embedded in the resource hierarchy. This is the policy used by every ARO resource container. For subscription-scoped resources the parent is nil and the resource name *is* the subscription ID.

func (SubscriptionPartitionKeyDeriver) PartitionKey

func (SubscriptionPartitionKeyDeriver) PartitionKey(parentResourceID *azcorearm.ResourceID, resourceName string) (string, error)

func (SubscriptionPartitionKeyDeriver) PartitionKeyFromObject

func (SubscriptionPartitionKeyDeriver) PartitionKeyFromObject(obj any) (string, error)

type TypedDocument

type TypedDocument struct {
	BaseDocument
	PartitionKey string                `json:"partitionKey"`
	ResourceID   *azcorearm.ResourceID `json:"resourceID"`
	ResourceType string                `json:"resourceType"`
	Properties   json.RawMessage       `json:"properties"`
}

TypedDocument is a BaseDocument with a ResourceType field to help distinguish heterogeneous items in a Cosmos DB container. The Properties field can be unmarshalled to any type that implements the DocumentProperties interface.

type UntypedResourceCRUD

type UntypedResourceCRUD interface {
	Get(ctx context.Context, resourceID *azcorearm.ResourceID) (*TypedDocument, error)
	// List returns back only direct descendents from the parent.
	List(ctx context.Context, opts *DBClientListResourceDocsOptions) (DBClientIterator[TypedDocument], error)
	// ListRecursive returns back every descendent from the parent.  For instance, if you ListRecursive on a cluster,
	// you will get the controllers for the cluster, the nodepools, the controllers for each nodepool, the external auths,
	// the controllers for the external auths, etc.
	ListRecursive(ctx context.Context, opts *DBClientListResourceDocsOptions) (DBClientIterator[TypedDocument], error)
	Delete(ctx context.Context, resourceID *azcorearm.ResourceID) error
	DeleteByCosmosID(ctx context.Context, partitionKey, cosmosID string) error

	Child(resourceType azcorearm.ResourceType, resourceName string) (UntypedResourceCRUD, error)
}

func NewUntypedCRUD

func NewUntypedCRUD(containerClient *azcosmos.ContainerClient, parentResourceID azcorearm.ResourceID) UntypedResourceCRUD

NewUntypedCRUD builds an UntypedResourceCRUD that scopes all operations to descendents of parentResourceID and derives partition keys from the subscription embedded in the resource hierarchy. For containers that partition differently use NewUntypedCRUDWithPartitionKey.

func NewUntypedCRUDWithPartitionKey

func NewUntypedCRUDWithPartitionKey(containerClient *azcosmos.ContainerClient, parentResourceID azcorearm.ResourceID, partitionKeyDeriver PartitionKeyDeriver) UntypedResourceCRUD

NewUntypedCRUDWithPartitionKey builds an UntypedResourceCRUD with a caller-supplied partition-key policy. Single-resource operations (GetByID, Get, Delete) call PartitionKey with a non-empty resourceName so a deriver that can't compute a key per resource can return an error; List / ListRecursive call PartitionKey with an empty resourceName so the same deriver can return "" to opt into a cross-partition query.

type ValidatingResourceCRUD

type ValidatingResourceCRUD[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType]] interface {
	GetByID(ctx context.Context, cosmosID string) (*InternalAPIType, error)
	Get(ctx context.Context, resourceID string) (*InternalAPIType, error)
	List(ctx context.Context, opts *DBClientListResourceDocsOptions) (DBClientIterator[InternalAPIType], error)
	Create(ctx context.Context, newObj *InternalAPIType, options *azcosmos.ItemOptions) (*InternalAPIType, error)
	Replace(ctx context.Context, newObj *InternalAPIType, oldObj *InternalAPIType, options *azcosmos.ItemOptions) (*InternalAPIType, error)
	Delete(ctx context.Context, resourceID string) error
}

func NewValidatingCRUD

func NewValidatingCRUD[InternalAPIType any, InternalAPITypePointer arm.CosmosMetadataAccessorPtr[InternalAPIType]](
	inner ResourceCRUD[InternalAPIType, InternalAPITypePointer],
	validateCreate func(context.Context, *InternalAPIType) field.ErrorList,
	validateReplace func(context.Context, *InternalAPIType, *InternalAPIType) field.ErrorList,
) ValidatingResourceCRUD[InternalAPIType, InternalAPITypePointer]

Directories

Path Synopsis
Package informers provides Cosmos-backed SharedIndexInformers for the kube-applier *Desire resource types.
Package informers provides Cosmos-backed SharedIndexInformers for the kube-applier *Desire resource types.
Package listers provides cache.Indexer-backed listers for the kube-applier *Desire resource types.
Package listers provides cache.Indexer-backed listers for the kube-applier *Desire resource types.
Package listertesting provides slice-backed and database-backed test implementations of the kube-applier listers.
Package listertesting provides slice-backed and database-backed test implementations of the kube-applier listers.
unioninformers
kubeapplier
Package kubeapplier contains union informers for the kube-applier *Desire types, peering the union listers in internal/database/unionlisters/kubeapplier.
Package kubeapplier contains union informers for the kube-applier *Desire types, peering the union listers in internal/database/unionlisters/kubeapplier.
unionlisters
kubeapplier
Package kubeapplier contains union listers for the kube-applier *Desire types.
Package kubeapplier contains union listers for the kube-applier *Desire types.

Jump to

Keyboard shortcuts

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