function.request

Utilities for working with RunFunctionRequests.

  1# Copyright 2025 The Crossplane Authors.
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#     http://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14
 15"""Utilities for working with RunFunctionRequests."""
 16
 17import dataclasses
 18
 19import crossplane.function.proto.v1.run_function_pb2 as fnv1
 20from crossplane.function import resource
 21
 22
 23@dataclasses.dataclass
 24class Credentials:
 25    """Credentials."""
 26
 27    type: str
 28    data: dict
 29
 30
 31def get_required_resources(req: fnv1.RunFunctionRequest, name: str) -> list[dict]:
 32    """Get required resources by name from the request.
 33
 34    Args:
 35        req: The RunFunctionRequest containing required resources.
 36        name: The name of the required resource set to get.
 37
 38    Returns:
 39        A list of resources as dictionaries. Empty list if not found.
 40
 41    Required resources are previously called "extra resources" in composition
 42    functions. For operation functions, there are no observed resources, so
 43    all resources are "required" resources that the function requested.
 44    """
 45    if name not in req.required_resources:
 46        return []
 47
 48    return [
 49        resource.struct_to_dict(item.resource)
 50        for item in req.required_resources[name].items
 51    ]
 52
 53
 54def get_watched_resource(req: fnv1.RunFunctionRequest) -> dict | None:
 55    """Get the watched resource that triggered this operation.
 56
 57    Args:
 58        req: The RunFunctionRequest to check for a watched resource.
 59
 60    Returns:
 61        The watched resource as a dictionary, or None if not found.
 62
 63    When a WatchOperation creates an Operation, it injects the resource that
 64    changed using the special requirement name 'ops.crossplane.io/watched-resource'.
 65    This helper makes it easy to access that resource.
 66    """
 67    watched = get_required_resources(req, "ops.crossplane.io/watched-resource")
 68    return watched[0] if watched else None
 69
 70
 71def get_required_resource(req: fnv1.RunFunctionRequest, name: str) -> dict | None:
 72    """Get a single required resource by name from the request.
 73
 74    Args:
 75        req: The RunFunctionRequest containing required resources.
 76        name: The name of the required resource to get.
 77
 78    Returns:
 79        The first resource as a dictionary, or None if not found.
 80
 81    This is a convenience function for when you know there should be exactly
 82    one resource with the given requirement name.
 83    """
 84    resources = get_required_resources(req, name)
 85    return resources[0] if resources else None
 86
 87
 88def get_credentials(req: fnv1.RunFunctionRequest, name: str) -> Credentials:
 89    """Get the supplied credentials from the request.
 90
 91    Args:
 92        req: The RunFunctionRequest containing credentials.
 93        name: The name of the credentials to get.
 94
 95    Returns:
 96        The requested credentials with type and data.
 97
 98    If the credentials don't exist, returns empty credentials with type "data"
 99    and empty data dictionary.
100    """
101    empty = Credentials(type="data", data={})
102
103    if not req or name not in req.credentials:
104        return empty
105
106    cred = req.credentials[name]
107
108    # Use WhichOneof to determine which field in the oneof is set
109    source_type = cred.WhichOneof("source")
110    if source_type == "credential_data":
111        # Convert bytes data to string data for backward compatibility
112        data = {}
113        for key, value in cred.credential_data.data.items():
114            data[key] = value.decode("utf-8")
115        return Credentials(type="credential_data", data=data)
116
117    # If no recognized source type is set, return empty
118    return empty
@dataclasses.dataclass
class Credentials:
24@dataclasses.dataclass
25class Credentials:
26    """Credentials."""
27
28    type: str
29    data: dict

Credentials.

Credentials(type: str, data: dict)
type: str
data: dict
def get_required_resources( req: crossplane.function.proto.v1.run_function_pb2.RunFunctionRequest, name: str) -> list[dict]:
32def get_required_resources(req: fnv1.RunFunctionRequest, name: str) -> list[dict]:
33    """Get required resources by name from the request.
34
35    Args:
36        req: The RunFunctionRequest containing required resources.
37        name: The name of the required resource set to get.
38
39    Returns:
40        A list of resources as dictionaries. Empty list if not found.
41
42    Required resources are previously called "extra resources" in composition
43    functions. For operation functions, there are no observed resources, so
44    all resources are "required" resources that the function requested.
45    """
46    if name not in req.required_resources:
47        return []
48
49    return [
50        resource.struct_to_dict(item.resource)
51        for item in req.required_resources[name].items
52    ]

Get required resources by name from the request.

Arguments:
  • req: The RunFunctionRequest containing required resources.
  • name: The name of the required resource set to get.
Returns:

A list of resources as dictionaries. Empty list if not found.

Required resources are previously called "extra resources" in composition functions. For operation functions, there are no observed resources, so all resources are "required" resources that the function requested.

def get_watched_resource( req: crossplane.function.proto.v1.run_function_pb2.RunFunctionRequest) -> dict | None:
55def get_watched_resource(req: fnv1.RunFunctionRequest) -> dict | None:
56    """Get the watched resource that triggered this operation.
57
58    Args:
59        req: The RunFunctionRequest to check for a watched resource.
60
61    Returns:
62        The watched resource as a dictionary, or None if not found.
63
64    When a WatchOperation creates an Operation, it injects the resource that
65    changed using the special requirement name 'ops.crossplane.io/watched-resource'.
66    This helper makes it easy to access that resource.
67    """
68    watched = get_required_resources(req, "ops.crossplane.io/watched-resource")
69    return watched[0] if watched else None

Get the watched resource that triggered this operation.

Arguments:
  • req: The RunFunctionRequest to check for a watched resource.
Returns:

The watched resource as a dictionary, or None if not found.

When a WatchOperation creates an Operation, it injects the resource that changed using the special requirement name 'ops.crossplane.io/watched-resource'. This helper makes it easy to access that resource.

def get_required_resource( req: crossplane.function.proto.v1.run_function_pb2.RunFunctionRequest, name: str) -> dict | None:
72def get_required_resource(req: fnv1.RunFunctionRequest, name: str) -> dict | None:
73    """Get a single required resource by name from the request.
74
75    Args:
76        req: The RunFunctionRequest containing required resources.
77        name: The name of the required resource to get.
78
79    Returns:
80        The first resource as a dictionary, or None if not found.
81
82    This is a convenience function for when you know there should be exactly
83    one resource with the given requirement name.
84    """
85    resources = get_required_resources(req, name)
86    return resources[0] if resources else None

Get a single required resource by name from the request.

Arguments:
  • req: The RunFunctionRequest containing required resources.
  • name: The name of the required resource to get.
Returns:

The first resource as a dictionary, or None if not found.

This is a convenience function for when you know there should be exactly one resource with the given requirement name.

def get_credentials( req: crossplane.function.proto.v1.run_function_pb2.RunFunctionRequest, name: str) -> Credentials:
 89def get_credentials(req: fnv1.RunFunctionRequest, name: str) -> Credentials:
 90    """Get the supplied credentials from the request.
 91
 92    Args:
 93        req: The RunFunctionRequest containing credentials.
 94        name: The name of the credentials to get.
 95
 96    Returns:
 97        The requested credentials with type and data.
 98
 99    If the credentials don't exist, returns empty credentials with type "data"
100    and empty data dictionary.
101    """
102    empty = Credentials(type="data", data={})
103
104    if not req or name not in req.credentials:
105        return empty
106
107    cred = req.credentials[name]
108
109    # Use WhichOneof to determine which field in the oneof is set
110    source_type = cred.WhichOneof("source")
111    if source_type == "credential_data":
112        # Convert bytes data to string data for backward compatibility
113        data = {}
114        for key, value in cred.credential_data.data.items():
115            data[key] = value.decode("utf-8")
116        return Credentials(type="credential_data", data=data)
117
118    # If no recognized source type is set, return empty
119    return empty

Get the supplied credentials from the request.

Arguments:
  • req: The RunFunctionRequest containing credentials.
  • name: The name of the credentials to get.
Returns:

The requested credentials with type and data.

If the credentials don't exist, returns empty credentials with type "data" and empty data dictionary.