Skip to content

Commit f91254e

Browse files
committed
Add advertises_capabilities and has_capability helpers
Functions need to know whether Crossplane will honor particular request or response fields, like schema requirements. Crossplane v2.2 and later advertise their capabilities in the request metadata, but older versions don't advertise capabilities at all. This commit adds two helpers. advertises_capabilities checks whether the calling Crossplane advertises its capabilities. has_capability checks whether a specific capability is present. Functions should check advertises_capabilities first, since has_capability returns False both when a capability is absent and when Crossplane predates capability advertisement. Signed-off-by: Nic Cope <[email protected]>
1 parent d726cca commit f91254e

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

crossplane/function/request.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,29 @@ def get_credentials(req: fnv1.RunFunctionRequest, name: str) -> Credentials:
133133
return empty
134134

135135

136+
def advertises_capabilities(req: fnv1.RunFunctionRequest) -> bool:
137+
"""Check whether Crossplane advertises its capabilities.
138+
139+
Args:
140+
req: The RunFunctionRequest to check.
141+
142+
Returns:
143+
True if Crossplane advertises its capabilities.
144+
145+
Crossplane v2.2 and later advertise their capabilities in the request
146+
metadata. If this returns False, the calling Crossplane predates capability
147+
advertisement and has_capability will always return False, even for features
148+
the older Crossplane does support.
149+
150+
if not request.advertises_capabilities(req):
151+
# Pre-v2.2 Crossplane, capabilities are unknown.
152+
...
153+
elif request.has_capability(req, fnv1.CAPABILITY_REQUIRED_SCHEMAS):
154+
response.require_schema(rsp, "xr", xr_api_version, xr_kind)
155+
"""
156+
return fnv1.CAPABILITY_CAPABILITIES in req.meta.capabilities
157+
158+
136159
def has_capability(
137160
req: fnv1.RunFunctionRequest,
138161
cap: fnv1.Capability.ValueType,
@@ -150,9 +173,9 @@ def has_capability(
150173
this to determine whether Crossplane will honor certain fields in their
151174
response, or populate certain fields in their request.
152175
153-
If CAPABILITY_CAPABILITIES is absent, the calling Crossplane predates
154-
capability advertisement (pre-v2.2). In this case has_capability always
155-
returns False, even for features the older Crossplane does support.
176+
Use advertises_capabilities to check whether Crossplane advertises its
177+
capabilities at all. If it doesn't, has_capability always returns False even
178+
for features the older Crossplane does support.
156179
157180
if request.has_capability(req, fnv1.CAPABILITY_REQUIRED_SCHEMAS):
158181
response.require_schema(rsp, "xr", xr_api_version, xr_kind)

tests/test_request.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,37 @@ class TestCase:
264264
dataclasses.asdict(case.want), dataclasses.asdict(got), case.reason
265265
)
266266

267+
def test_advertises_capabilities(self) -> None:
268+
@dataclasses.dataclass
269+
class TestCase:
270+
reason: str
271+
req: fnv1.RunFunctionRequest
272+
want: bool
273+
274+
cases = [
275+
TestCase(
276+
reason="Should return False when no capabilities are advertised.",
277+
req=fnv1.RunFunctionRequest(),
278+
want=False,
279+
),
280+
TestCase(
281+
reason="Should return True when CAPABILITY_CAPABILITIES is present.",
282+
req=fnv1.RunFunctionRequest(
283+
meta=fnv1.RequestMeta(
284+
capabilities=[
285+
fnv1.CAPABILITY_CAPABILITIES,
286+
fnv1.CAPABILITY_REQUIRED_SCHEMAS,
287+
],
288+
),
289+
),
290+
want=True,
291+
),
292+
]
293+
294+
for case in cases:
295+
got = request.advertises_capabilities(case.req)
296+
self.assertEqual(case.want, got, case.reason)
297+
267298
def test_has_capability(self) -> None:
268299
@dataclasses.dataclass
269300
class TestCase:

0 commit comments

Comments
 (0)