Skip to content

KeystoneProject CRD API Reference ​

Reference documentation for the KeystoneProject Custom Resource Definition. A KeystoneProject orders one Keystone project from a namespace that a ControlPlane assigns to a service owner through spec.namespaceAssignments. The c5c3-operator creates the project through K-ORC in the ControlPlane's admin domain, where every ordered KeystoneUser lives as well, and reports its id in status. No Secret is delivered: a KeystoneRoleAssignment gives an ordered user a role on the project, and the user's own Secret scopes a token to it.

The order lives in the assigned namespace, on the cluster that namespace is assigned on: the management cluster or a registered target cluster. Its K-ORC Project lives in the ControlPlane's namespace on the management cluster.

For the control loop, the watches and the teardown, see Keystone Orders Reconciler Architecture. The Order Resources from a ControlPlane guide walks the flow on the ControlPlane devstack.

API Group and Version ​

FieldValue
Groupc5c3.io
Versionv1alpha1
KindKeystoneProject
List KindKeystoneProjectList
ScopeNamespaced

Scheme registration: the init() function in keystoneproject_types.go registers both Kinds with the shared SchemeBuilder.

kubectl get keystoneproject prints four columns:

ColumnSource
Ready.status.conditions[?(@.type=='Ready')].status
ControlPlane.spec.controlPlaneRef.name
Project.status.projectName
Age.metadata.creationTimestamp

Example ​

A project ordered from the assigned namespace tenant-a against the ControlPlane cp in openstack. The project name defaults to metadata.name.

yaml
apiVersion: c5c3.io/v1alpha1
kind: KeystoneProject
metadata:
  name: workflow-project
  namespace: tenant-a
spec:
  controlPlaneRef:
    name: cp
    namespace: openstack

Spec ​

KeystoneProjectSpec ​

FieldTypeRequiredDefaultDescription
controlPlaneRefControlPlaneRefSpecYes—The ControlPlane whose identity plane the project is created in. Both halves are immutable, as on a KeystoneUser.
projectNamestringNometadata.nameThe Keystone project name (MinLength=1, MaxLength=255, no comma, mirroring K-ORC's KeystoneName). Immutable: a rule on the whole object compares the effective name. The admin project and the built-in service projects are reserved.

The reconciler resolves the projectName default itself. The kind has no defaulting webhook, so the stored object keeps the field empty.

The spec.namespaceAssignments entry for the order's namespace and cluster is the only consent, as for a KeystoneUser. The order requests no role, so the entry's allowedRoles is not consulted.

Without an entry ProjectReady reads False/NamespaceNotAssigned. The order is frozen: nothing is provisioned, repaired or swept, and the Keystone project it already has stays. Deleting the order still tears it down.

While a KeystoneRoleAssignment in the order's namespace names the order as its projectRef, deleting the order holds on ReferencedByRoleAssignments, and while a KeystoneApplicationCredential does, on ReferencedByApplicationCredentials. See Deletion Semantics.

Status ​

FieldTypeDescription
conditions[]metav1.ConditionProjectReady and the aggregate Ready. See Conditions.
observedGenerationint64The metadata.generation the controller last reconciled.
projectIDstringThe Keystone project id, once provisioned.
projectNamestringThe effective project name, once provisioned.
domainNamestringThe ControlPlane's admin domain, once provisioned. A consumer sets it as OS_PROJECT_DOMAIN_NAME.

Conditions ​

TypeStatusReasonMeaning
ProjectReadyTrueProjectProvisionedThe Keystone project exists in the admin domain.
ProjectReadyFalseProjectCollisionA project of this name exists in the admin domain that the order did not create, or the name is one the ControlPlane creates itself: its admin project, or a built-in service project (service-glance, service-placement, service-barbican, service-neutron, service-cinder, service-nova), whether or not that service is enabled. Names are compared as Keystone compares them, ignoring case and accents. The order never takes a project over.
ProjectReadyFalseProbingForCollisionThe probe that decides whether the project already exists has not resolved yet.
ProjectReadyFalseWaitingForProjectThe managed Project is not Available yet.
ProjectReadyFalseProjectFailedK-ORC reported a terminal error on the Project.
ProjectReadyFalseTransportErrorRetryFailedClearing a latched transport error from the Project failed.
ProjectReadyFalseProjectErrorA Kubernetes-level failure projecting the project.
ProjectReadyFalseReferencedByRoleAssignmentsThe order is being deleted while KeystoneRoleAssignments in its namespace still name it. The message lists them.
ProjectReadyFalseReferencedByApplicationCredentialsThe order is being deleted while KeystoneApplicationCredentials in its namespace still name it. The message lists them.
ProjectReadyFalseControlPlaneNotFoundspec.controlPlaneRef does not resolve, for an order on the management cluster.
ProjectReadyFalseNamespaceNotAssignedNo spec.namespaceAssignments entry assigns the order's namespace on its cluster, or, for an order on a target cluster, spec.controlPlaneRef does not resolve. The order is frozen.
ProjectReadyFalseClusterNameTooLongThe order lives on a target cluster whose name is longer than the 63 characters a label value carries.
ProjectReadyFalseWaitingForAdminCredentialThe ControlPlane's AdminCredentialReady is not True.
ReadyTrueAllReadyProjectReady is True.
ReadyFalseNotAllReadyProjectReady is not True.

Against an External-mode ControlPlane a wait on the Project is replaced by the classified K-ORC failure, as for a KeystoneUser. An order on a target cluster, and a reserved name, is reconciled again every 10 minutes.

Defaulting and Validation Summary ​

The kind has no webhook, because a target cluster runs none. Every rule is a CRD rule:

  • projectName: MinLength=1, MaxLength=255, pattern ^[^,]+$.
  • controlPlaneRef.name: required, MinLength=1, and a transition rule ("controlPlaneRef.name is immutable; delete and re-create the KeystoneProject to move it to another ControlPlane").
  • controlPlaneRef.namespace: RFC-1123 label, ≤ 63, and a transition rule ("controlPlaneRef.namespace is immutable; ..."), spelled __namespace__ in CEL.
  • On the object: metadata.name is at most 63 bytes ("metadata.name must be at most 63 bytes"), and the effective project name is frozen ("projectName is immutable; delete and re-create the KeystoneProject to rename its project").

The rejection corpus lives in tests/e2e/c5c3/invalid-keystoneproject-cr/, generated from its _generate.py and guarded by make verify-invalid-cr-fixtures.

Projected child names ​

The children live in the ControlPlane's namespace on the management cluster, named from a per-order prefix:

<metadata.name>-<8 hex>-project-<discriminator>

The hash covers <cluster>/<namespace>/<name>, as for a KeystoneUser. The discriminators are project (the managed K-ORC Project, which a KeystoneRoleAssignment names as its projectRef) and project-probe (the collision probe). Each child carries the labels c5c3.io/keystoneproject-name, c5c3.io/keystoneproject-namespace and c5c3.io/keystoneproject-cluster (empty for the management cluster) and no owner reference.

Deletion Semantics ​

The c5c3.io/keystoneproject-teardown finalizer is installed once the order's namespace is assigned. Deleting a KeystoneProject that carries it runs the teardown:

ResourceFate
Keystone projectDeleted with the managed K-ORC Project
Collision probeDeleted; an unmanaged import, so the project it found stays

The teardown first lists the KeystoneRoleAssignments in the order's namespace. While one names the order as its projectRef, the order reads ProjectReady=False/ReferencedByRoleAssignments, deletes nothing, and checks again every minute and whenever an assignment changes. K-ORC guards a Project with a finalizer while a RoleAssignment references it, and removing the project would take the assignment with it. Delete the assignments first.

The teardown holds the same way while a KeystoneApplicationCredential names the order as its projectRef, reading ProjectReady=False/ReferencedByApplicationCredentials: the credentials are scoped to the project. Delete the credential orders first.

Past the hold the teardown is the KeystoneUser one: patient while the ControlPlane exists, failing open once it is gone, and not consulting the assignment, so a frozen order tears down the same way.

Chainsaw E2E Tests ​

tests/e2e/c5c3/keystone-user/ runs on the e2e-controlplane job. It orders workflow-project beside the user, reads its id, assigns a role on it, scopes a token to it from a Job in the owner's namespace, freezes it with the assignment withdrawn, and deletes it down to its K-ORC Project. tests/e2e/c5c3/invalid-keystoneproject-cr/ is the admission rejection corpus, run on the e2e-operator (c5c3) job. The target-cluster path is proven in the two-API-server envtest TestIntegration_Multicluster_ControlPlanePlacement.

See ControlPlane E2E Test Suites.