@@ -24,6 +24,22 @@ def compose(req: fnv1.RunFunctionRequest, rsp: fnv1.RunFunctionResponse):
2424 })
2525"""
2626
27+ composition_script_with_exception = """
28+ from crossplane.function.proto.v1 import run_function_pb2 as fnv1
29+
30+ def compose(req: fnv1.RunFunctionRequest, rsp: fnv1.RunFunctionResponse):
31+ rsp.desired.resources["bucket"].resource.update({
32+ "apiVersion": "s3.aws.upbound.io/v1beta2",
33+ "kind": "Bucket",
34+ "spec": {
35+ "forProvider": {
36+ "region": "us-east-1"
37+ }
38+ },
39+ })
40+ raise AttributeError
41+ """
42+
2743async_composition_script = """
2844from crossplane.function.proto.v1 import run_function_pb2 as fnv1
2945
@@ -39,6 +55,22 @@ async def compose(req: fnv1.RunFunctionRequest, rsp: fnv1.RunFunctionResponse):
3955 })
4056"""
4157
58+ async_composition_script_with_exception = """
59+ from crossplane.function.proto.v1 import run_function_pb2 as fnv1
60+
61+ async def compose(req: fnv1.RunFunctionRequest, rsp: fnv1.RunFunctionResponse):
62+ rsp.desired.resources["bucket"].resource.update({
63+ "apiVersion": "s3.aws.upbound.io/v1beta2",
64+ "kind": "Bucket",
65+ "spec": {
66+ "forProvider": {
67+ "region": "us-east-1"
68+ }
69+ },
70+ })
71+ raise AttributeError
72+ """
73+
4274operation_script = """
4375from crossplane.function.proto.v1 import run_function_pb2 as fnv1
4476
@@ -140,6 +172,106 @@ class TestCase:
140172 context = structpb .Struct (),
141173 ),
142174 ),
175+ TestCase (
176+ reason = "Function should fail gracefully when script is missing." ,
177+ req = fnv1 .RunFunctionRequest (
178+ input = resource .dict_to_struct ({}),
179+ ),
180+ want = fnv1 .RunFunctionResponse (
181+ meta = fnv1 .ResponseMeta (ttl = durationpb .Duration (seconds = 60 )),
182+ results = [
183+ {
184+ "message" : "missing script in function input" ,
185+ "severity" : "SEVERITY_FATAL" ,
186+ }
187+ ],
188+ desired = fnv1 .State (),
189+ context = structpb .Struct (),
190+ ),
191+ ),
192+ TestCase (
193+ reason = "Function should fail gracefully when script is empty." ,
194+ req = fnv1 .RunFunctionRequest (
195+ input = resource .dict_to_struct ({"script" : "" }),
196+ ),
197+ want = fnv1 .RunFunctionResponse (
198+ meta = fnv1 .ResponseMeta (ttl = durationpb .Duration (seconds = 60 )),
199+ results = [
200+ {
201+ "message" : "missing script in function input" ,
202+ "severity" : "SEVERITY_FATAL" ,
203+ }
204+ ],
205+ desired = fnv1 .State (),
206+ context = structpb .Struct (),
207+ ),
208+ ),
209+ TestCase (
210+ reason = "Function should fail gracefully when compose script raises an exception." ,
211+ req = fnv1 .RunFunctionRequest (
212+ input = resource .dict_to_struct (
213+ {"script" : composition_script_with_exception }
214+ ),
215+ ),
216+ want = fnv1 .RunFunctionResponse (
217+ meta = fnv1 .ResponseMeta (ttl = durationpb .Duration (seconds = 60 )),
218+ results = [
219+ {
220+ "message" : "Exception: <class 'AttributeError'>, traceback: [' File \" <string>\" , line 14, in compose\\ n']" ,
221+ "severity" : "SEVERITY_FATAL" ,
222+ }
223+ ],
224+ desired = fnv1 .State (
225+ resources = {
226+ "bucket" : fnv1 .Resource (
227+ resource = resource .dict_to_struct (
228+ {
229+ "apiVersion" : "s3.aws.upbound.io/v1beta2" ,
230+ "kind" : "Bucket" ,
231+ "spec" : {
232+ "forProvider" : {"region" : "us-east-1" }
233+ },
234+ }
235+ )
236+ )
237+ }
238+ ),
239+ context = structpb .Struct (),
240+ ),
241+ ),
242+ TestCase (
243+ reason = "Function should fail gracefully when async compose script raises an exception." ,
244+ req = fnv1 .RunFunctionRequest (
245+ input = resource .dict_to_struct (
246+ {"script" : async_composition_script_with_exception }
247+ ),
248+ ),
249+ want = fnv1 .RunFunctionResponse (
250+ meta = fnv1 .ResponseMeta (ttl = durationpb .Duration (seconds = 60 )),
251+ results = [
252+ {
253+ "message" : "Exception: <class 'AttributeError'>, traceback: [' File \" <string>\" , line 14, in compose\\ n']" ,
254+ "severity" : "SEVERITY_FATAL" ,
255+ }
256+ ],
257+ desired = fnv1 .State (
258+ resources = {
259+ "bucket" : fnv1 .Resource (
260+ resource = resource .dict_to_struct (
261+ {
262+ "apiVersion" : "s3.aws.upbound.io/v1beta2" ,
263+ "kind" : "Bucket" ,
264+ "spec" : {
265+ "forProvider" : {"region" : "us-east-1" }
266+ },
267+ }
268+ )
269+ )
270+ }
271+ ),
272+ context = structpb .Struct (),
273+ ),
274+ ),
143275 ]
144276
145277 runner = fn .FunctionRunner ()
0 commit comments