- Requirements
- Usage
- Basic Usage
- Using Regular Expressions to Capture Message Data
- Using Regular Expressions to Match Multiple Resources
- Condition Matching Wildcards
- MatchConditions are ANDed
- Overriding Conditions
- Matching the Composite Resource
- Matching Missing Conditions
- Setting Default Conditions
- Creating Events
- Customizing Matching Behavior
- Determining the Status of the Function Itself
This function requires Crossplane v1.17 or newer.
Function Status Transformer allows you to create hooks that will trigger by matching the status conditions of managed resources. Each hook can be configured to set one or more status conditions on the composite resource and the claim.
Here is a basic usage example. The function will look for the
cloudsql-instance
resource within the observed resource map. If that resource
matches the specified condition criteria, the condition in setConditions
will
get set on both the composite resource and the claim.
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
compositeTypeRef:
apiVersion: your.api.group/v1alpha1
kind: XYourCompositeKind
mode: Pipeline
pipeline:
# Insert your pipeline steps here.
- step: status-handler
functionRef:
name: function-status-transformer
input:
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resources:
# Note that "name" refers to the resource's identifier within the
# Composition and not the object's metadata.name.
# Related documentation:
# https://docs.crossplane.io/latest/guides/function-patch-and-transform/#resource-templates
- name: "cloudsql-instance"
conditions:
- type: Synced
status: "False"
reason: ReconcileError
message: "failed to create the database: some internal error."
setConditions:
- target: CompositeAndClaim
condition:
type: DatabaseReady
status: "False"
reason: FailedToCreate
message: "failed to create the database"
You can use regular expressions to capture data from the status condition message on the managed resource. The captured groups can then be inserted into status condition and event messages on the composite resource and claim.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resources:
- name: "cloudsql-instance"
conditions:
- type: Synced
status: "False"
reason: ReconcileError
message: "failed to create the database: (?P<Error>.+)"
setConditions:
- target: CompositeAndClaim
condition:
type: DatabaseReady
status: "False"
reason: FailedToCreate
message: "Encountered an error creating the database: {{ .Error }}"
createEvents:
- target: CompositeAndClaim
event:
type: Warning
reason: FailedToCreate
message: "Encountered an error creating the database: {{ .Error }}"
You can use regular expressions in the resourceKey
. This will allow you to
match multiple resources of a similar type. For instance, say you spin up
multiple instances of the same type and name them like cloudsql-1
,
cloudsql-2
, etc. You could write a single hook to handle all of these by using
a resource key of cloudsql-\\d+
.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resources:
- name: "cloudsql-\\d+"
conditions:
- type: Synced
status: "False"
reason: ReconcileError
If you do not care about the particular value of a status condition that you are
matching against, you can leave it empty and it will act as a wildcard. The only
value that cannot be left empty is the type
.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resources:
- name: "cloudsql-\\d+"
conditions:
# The "reason" and "message" fields will be treated as wildcards.
- type: Synced
status: "False"
When using multiple matchers
, they must all match before setConditions
will
be triggered.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
# Both matchers must be true before the corresponding setConditions will
# be set
- matchers:
- resources:
- name: "cloudsql"
conditions:
- type: Synced
status: "True"
- resources:
- name: "cloudsql"
conditions:
- type: Ready
status: "True"
setConditions: {...}
Hooks will be executed in order. By default a setCondition
will not set a
condition that was previously set by function-status-transformer (Note: This
does not apply to conditions set by previous functions in the pipeline).
Condition uniqueness is determined by the type
. To override a condition that
was already set, you can use force
.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- setConditions:
# This condition will be set as it is the first time the type is set.
- target: CompositeAndClaim
condition:
type: DatabaseReady
status: "True"
reason: Example
- setConditions:
# This condition will not be set as it has been set before and is not
# forceful.
- target: CompositeAndClaim
condition:
type: DatabaseReady
status: "False"
reason: FailedToCreate
message: "Encountered an error creating the database: {{ .Error }}"
- setConditions:
# This condition will be set as it is forceful.
- target: CompositeAndClaim
force: true
condition:
type: DatabaseReady
status: "False"
reason: FailedToCreate
message: "Encountered an error creating the database: {{ .Error }}"
You can match against the composite resource. To do this, use
includeCompositeAsResource
as seen below.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- includeCompositeAsResource: true
conditions:
- type: Synced
status: "False"
reason: "SomeError"
You can match against missing conditions. To do this, use the default unknown condition values.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resources:
- name: "cloudsql"
conditions:
# These are the values seen when a condition does not exist.
- type: Synced
status: "Unknown"
reason: ""
message: ""
If you want to set one or more conditions when no other hook has matched, you
can do this by placing a hook at the end and make sure the setCondition
force
values are omitted or set to false. For matching, you can either use all
wildcard fields (see Condition Matching
Wildcards) or you can specify a type that will
never exist. The only requirement is that the resourceKey
must match one or
more resources.
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resourceKey: "cloudsql"
condition:
# This is a type that does not exist on the resource.
type: ThisTypeDoesNotExist
# These are the values seen when a condition does not exist.
status: "Unknown"
reason: ""
message: ""
- setConditions:
- target: CompositeAndClaim
force: false
condition:
type: DatabaseReady
status: "Unknown"
reason: Unknown
In addition to setting conditions, you can also create events for both the composite resource and the claim. You should note that events should be created sparingly, and will be limited by the behavior documented in 5802
To create events, use createEvents
as seen below.
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
compositeTypeRef:
apiVersion: your.api.group/v1alpha1
kind: XYourCompositeKind
mode: Pipeline
pipeline:
# Insert your pipeline steps here.
- step: status-handler
functionRef:
name: function-status-transformer
input:
apiVersion: function-status-transformer.fn.crossplane.io/v1beta1
kind: StatusTransformation
statusConditionHooks:
- matchers:
- resources:
- name: "cloudsql-instance"
conditions:
- type: Synced
status: "False"
reason: ReconcileError
message: "failed to create the database: some internal error."
createEvents:
- target: CompositeAndClaim
event:
type: Warning
reason: FailedToCreate
message: "failed to create the database"
Any given matcher will first find all resources selected by matcher.resources
.
It will then compare the status conditions of the resources against the status
conditions found in matcher.conditions
. You can customize the comparison
behavior by setting matcher.type
. The different match types and their
behaviors can be seen below.
AnyResourceMatchesAnyCondition
- Considered a match if any resource matches any condition. An example use case would be if you want to transform any error condition from one of your managed resources into an error condition on your composite and claim.AnyResourceMatchesAllConditions
- Considered a match if any resources matches all conditions. An example use case would be if you want to check if any resource is synced but not ready. You could then communicate to the user that everything is valid and they just need to wait for resources to become ready.AllResourcesMatchAnyCondition
- Considered a match if all resources match any condition. An example use case would be if you want to check that some resources match one of the many possible good states.AllResourcesMatchAllConditions
(default) - Considered a match if all resources match all conditions. An example use case would be checking that all resources are both synced and ready. You could then let the user know that everything is ready to go.
The status of this function can be found by viewing the
StatusTransformationSuccess
status condition on the composite resource. The
function will use this status condition to communicate its own state and will
not emit fatal results. This means that the overall state of the claim and
composite resource will not be affected by this functions failure. See the
following sections on some common conditions you may encounter and what they
mean.
Notes:
- Any error encountered within a
statusConditionHook
will be logged, but only the last error will be present on theStatusTransformationSuccess
condition.
If no failures are encountered, the StatusTransformationSuccess
condition will be
set to True
with a reason of Available
.
- lastTransitionTime: "2024-08-02T15:57:20Z"
reason: Available
status: "True"
type: StatusTransformationSuccess
If an invalid input is provided, the StatusTransformationSuccess
condition will be
set to False
with a reason of InputFailure
. Note that no matchCondition
or
setCondition
will be evaluated.
- lastTransitionTime: "2024-08-02T15:11:35Z"
message: 'cannot get Function input from *v1beta1.RunFunctionRequest: cannot get
function input *v1beta1.StatusTransformation from *v1beta1.RunFunctionRequest:
cannot unmarshal JSON from *structpb.Struct into *v1beta1.StatusTransformation:
json: cannot unmarshal Go value of type v1beta1.StatusTransformation: unknown
name "statusConditionHookss"'
reason: InputFailure
status: "False"
type: StatusTransformationSuccess
If an invalid regular expression is provided in a matchCondition
message
or
resourceKey
, the StatusTransformationSuccess
condition will be set to
False
with a reason of MatchFailure
. Note that no further matchCondition
will be evaluated for corresponding statusConditionHook
and the overall result
of matching for the hook will be a failure. All other statusConditionHooks
will attempt to be evaluated as normal.
- lastTransitionTime: "2024-08-02T15:29:51Z"
message: 'error when matching, statusConditionHookIndex: 0, matchConditionIndex:
0: [failed to compile message regex, error parsing regexp: invalid or unsupported
Perl syntax: `(?!`]'
reason: MatchFailure
status: "False"
type: StatusTransformationSuccess
If an invalid template is provided in a setCondition
message, the
StatusTransformationSuccess
condition will be set to False
with a reason of
SetConditionFailure
.
- lastTransitionTime: "2024-08-02T15:46:45Z"
message: 'failed to set condition, statusConditionHookIndex: 0, setConditionIndex:
0: [failed to parse template, template: :1: unexpected "}" in operand]'
reason: SetConditionFailure
status: "False"
type: StatusTransformationSuccess