composite.py defines the primary authoring model for function-pythonic. It provides:
BaseComposite: the base class your composition classes subclass.- Resource wrappers for composed and required resources.
- Condition and result helpers.
- Connection secret and connection-detail handling.
- Convenience descriptors for TTL and ready state.
At runtime, function-pythonic instantiates your BaseComposite subclass with a
RunFunctionRequest, then your compose() implementation mutates desired state via
wrapper objects.
Key object graph:
self.request: wrapped incoming request (read-oriented).self.response: wrapped outgoing response (write-oriented).self.resources: composed resource collection (desired.resources).self.requireds: required/extra resource selectors and resolved items.self.conditions: composite condition helpers.self.results: function result helpers.
Exposed as BaseComposite.ttl.
- Getter reads
response.meta.ttland returnsintor fractionalfloat. - Setter accepts
intorfloatand maps intoseconds/nanos. - Invalid type raises
ValueError.
Exposed as BaseComposite.ready.
- Getter maps protobuf ready enum to
True,False, orNone. - Setter writes protobuf ready enum:
True->READY_TRUEFalse->READY_FALSENone->READY_UNSPECIFIED
Exposed as BaseComposite.connectionSecret.
- Crossplane v1:
- Reads from
spec.writeConnectionSecretToRef. - Setting to a different value raises
NotImplementedError.
- Reads from
- Crossplane v2:
- Reads/writes
input.writeConnectionSecretToRefas a protobufMapwrapper.
- Reads/writes
Exposed as BaseComposite.connection; returns _Connection.
- Manages
desired.composite.connection_details. - In Crossplane v2, mirrors connection details into a composed
v1/Secret. - Ignores non-string/unknown/
Nonevalues when appropriate.
Subclass this class and implement:
class MyComposite(BaseComposite):
def compose(self):
...or async:
class MyComposite(BaseComposite):
async def compose(self):
...Initialization behavior:
- Creates
self.request(protobuf.Message) from input request. - Creates
self.responsewith:- copied
meta.tag - default TTL of 60s
- cloned
desiredandcontextfrom request
- copied
- Selects
self.parametersfrom:observed.composite.resource.spec.parametersfor single-use composites- otherwise
input.parameters
- Initializes:
self.credentialsself.contextself.environment(apiextensions.crossplane.io/environment)self.requiredsself.resources- defaults:
autoReady=True,usages=False,unknownsFatal=False
- Binds composite-focused shortcuts:
self.observed,self.desired,self.apiVersion,self.kind,self.metadata,self.spec,self.statusself.conditions,self.results,self.events(eventsis deprecated alias)
compose() in BaseComposite is abstract and raises NotImplementedError.
Collection wrapper around request.credentials.
- Access:
self.credentials['name']orself.credentials.name - Supports
bool,len,contains, and iteration of(name, Credential)
Wrapper around a single credential’s credential_data.data.
- Access:
credential['key']orcredential.key - Supports
bool,len,contains, and iteration of(key, value)
Collection wrapper for response.desired.resources.
- Access/create by name:
self.resources.vpcorself.resources['vpc'] - Assign raw resource object:
self.resources['x'] = resource - Delete by name.
- Iteration yields
(name, Resource)
Instances are cached by composition resource name.
Represents one composed resource entry.
Construction binds:
observed=request.observed.resources[name].resourcedesired=response.desired.resources[name].resourceconditions,connection- toggles:
autoReady,usages,unknownsFatal(defaultNone, inherit from composite)
resource(kind?, apiVersion?, namespace?, name?):
- Clears desired resource (
self.desired()). - Supports swapped first two args when first arg looks like
apiVersion. - Optionally sets
metadata.namespaceandmetadata.name. - Returns
self.
apiVersion,kind,metadata,spec,type,datamap to desired resource.statusis read from observed resource status.externalNamereads desired annotation, falls back to observed annotation, and writes back into desired.
readygetter:- returns cached explicit value if set
- otherwise maps desired ready enum
- if unspecified and auto-ready is enabled, computes via
auto_ready.resource_ready()and sets desired ready true when determined.
readysetter writes ready enum similarly to composite-level setter.
setReadyCondition(type='Ready'):- reads
conditions[type] - if condition true ->
readyset to observed name - else sets
readyto astatus.not<type>Condition...path
- reads
addDependency(resource, field=_notset):- Adds explicit dependency annotation:
metadata.annotations["pythonic.dependency/<resource.name>"] = <field> - If field omitted, derives from dependent resource readiness.
- Converts non-wrapper truthy/falsey values into observed-name or status-based tokens.
- Adds explicit dependency annotation:
Collection wrapper for required resources.
- Crossplane v1 uses
extra_resources. - Crossplane v2 uses
required_resources. - Supports
bool,len,contains, iteration of(name, RequiredResources).
Selector + resolved-items wrapper for a named required resource request.
- Callable reset/update:
required(kind?, apiVersion?, namespace?, name?, labels?)
- Selector properties:
apiVersion,kind,namespace,matchName,matchLabels
- Resolved results:
- index access
required[ix] -> RequiredResource bool,len, iteration
- index access
matchLabels setter accepts mapping-like iteration or (key, value) pairs.
Read-only wrapper for one returned required resource item.
Fields:
name,ixobserved,apiVersion,kind,metadata,spec,type,data,statusconditions,connection
Truthiness reflects existence of observed.
Wrapper for condition access on composite/resource/required resource.
- Access by type:
conditions['Ready']orconditions.Ready - Supports
bool,len, iteration - Merges condition types from observed and response (when response exists)
Represents one condition type. Subclasses protobuf.ProtobufValue.
_protobuf_value serialization includes:
type,status,reason,message, optional RFC3339lastTransitionTime.
Mutation:
condition(reason=?, message=?, status=?, claim=?)updates in one call.statusmaps between bool/unknown and protobuf status enums.reason,messageread/write strings.lastTransitionTimereads from observed condition timestamp (read-only).claimtoggles target:- composite only
- composite + claim
- unspecified
Creation rules:
- If response exists, setting fields creates condition entry when missing.
- Without response, creation is disallowed (
ValueError: Condition is read only).
Wrapper for response.results.
Factory methods:
info(reason?, message?, claim?)warning(reason?, message?, claim?)fatal(reason?, message?, claim?)
Also supports bool, len, index, and iteration.
Wrapper around one result entry.
Properties:
- severity flags:
info,warning,fatal reasonmessageclaimtarget (composite vs composite+claim vs unspecified)
A Result() without backing entry is falsey and ignores setters.
Internal helper returned by BaseComposite.connection.
Behavior:
- Reads/writes composite connection details map.
observedexposes observed connection details.__call__(**kwargs)clears and resets connection details.- On v2, keeps a composed secret resource synchronized:
- secret name defaults to
connection-secretorconnectionSecret.resourceName - sets type
connection.crossplane.io/v1alpha1 - base64-encodes values into
secret.data - removes secret when last key removed
- secret name defaults to
- For cluster-scoped XR without secret namespace, emits fatal result:
- reason:
ConnectionNoNamespace - message:
Cluster scoped XR must specify connection secret namespace
- reason:
from crossplane.pythonic import BaseComposite
class ExampleComposite(BaseComposite):
def compose(self):
bucket = self.resources.bucket("Bucket", "s3.aws.crossplane.io/v1beta1")
bucket.spec.forProvider.region = self.spec.region
# propagate observed id when available
self.status.bucketId = bucket.status.atProvider.id
# optional condition/result
self.conditions.BucketReady("Available", "Bucket is ready", True)
self.results.info("Composed", "Bucket desired state generated")- Required resources:
- v1:
extra_resources - v2:
required_resources
- v1:
- Connection secret handling:
- v1: relies on XR
writeConnectionSecretToRef, no write-through override - v2: allows
connectionSecretoverrides and manages composed secret mirror
- v1: relies on XR