@@ -1660,6 +1660,11 @@ func TestRunFunction(t *testing.T) {
16601660 "queryType": "UserValidation",
16611661 "users": ["user@example.com"]
16621662 }` ),
1663+ Observed : & fnv1.State {
1664+ Composite : & fnv1.Resource {
1665+ Resource : resource .MustStructJSON (xr ),
1666+ },
1667+ },
16631668 },
16641669 },
16651670 want : want {
@@ -1675,8 +1680,14 @@ func TestRunFunction(t *testing.T) {
16751680 Desired : & fnv1.State {
16761681 Composite : & fnv1.Resource {
16771682 Resource : resource .MustStructJSON (`{
1678- "apiVersion": "",
1679- "kind": ""
1683+ "apiVersion": "example.org/v1",
1684+ "kind": "XR",
1685+ "metadata": {
1686+ "name": "cool-xr"
1687+ },
1688+ "spec": {
1689+ "count": 2
1690+ }
16801691 }` ),
16811692 },
16821693 },
@@ -1694,6 +1705,11 @@ func TestRunFunction(t *testing.T) {
16941705 "queryType": "UserValidation",
16951706 "users": ["user@example.com"]
16961707 }` ),
1708+ Observed : & fnv1.State {
1709+ Composite : & fnv1.Resource {
1710+ Resource : resource .MustStructJSON (xr ),
1711+ },
1712+ },
16971713 Credentials : map [string ]* fnv1.Credentials {
16981714 "azure-creds" : {
16991715 Source : & fnv1.Credentials_CredentialData {CredentialData : creds },
@@ -1714,8 +1730,14 @@ func TestRunFunction(t *testing.T) {
17141730 Desired : & fnv1.State {
17151731 Composite : & fnv1.Resource {
17161732 Resource : resource .MustStructJSON (`{
1717- "apiVersion": "",
1718- "kind": ""
1733+ "apiVersion": "example.org/v1",
1734+ "kind": "XR",
1735+ "metadata": {
1736+ "name": "cool-xr"
1737+ },
1738+ "spec": {
1739+ "count": 2
1740+ }
17191741 }` ),
17201742 },
17211743 },
@@ -2413,6 +2435,237 @@ func TestRunFunction(t *testing.T) {
24132435 },
24142436 },
24152437 },
2438+ "OperationWithoutWatchedResource" : {
2439+ reason : "The Function should return fatal if it runs as operation without a watched resource" ,
2440+ args : args {
2441+ ctx : context .Background (),
2442+ req : & fnv1.RunFunctionRequest {
2443+ Meta : & fnv1.RequestMeta {Tag : "hello" },
2444+ Input : resource .MustStructJSON (`{
2445+ "apiVersion": "msgraph.fn.crossplane.io/v1alpha1",
2446+ "kind": "Input",
2447+ "queryType": "UserValidation",
2448+ "users": ["user@example.com"],
2449+ "target": "context.validatedUsers"
2450+ }` ),
2451+ Credentials : map [string ]* fnv1.Credentials {
2452+ "azure-creds" : {
2453+ Source : & fnv1.Credentials_CredentialData {CredentialData : creds },
2454+ },
2455+ },
2456+ RequiredResources : map [string ]* fnv1.Resources {},
2457+ },
2458+ },
2459+ want : want {
2460+ rsp : & fnv1.RunFunctionResponse {
2461+ Meta : & fnv1.ResponseMeta {Tag : "hello" , Ttl : durationpb .New (response .DefaultTTL )},
2462+ Results : []* fnv1.Result {
2463+ {
2464+ Severity : fnv1 .Severity_SEVERITY_FATAL ,
2465+ Message : `operation: no resource to process with name ops.crossplane.io/watched-resource` ,
2466+ Target : fnv1 .Target_TARGET_COMPOSITE .Enum (),
2467+ },
2468+ },
2469+ },
2470+ },
2471+ },
2472+ "OperationWithLessThanOneWatchedResource" : {
2473+ reason : "The Function should return fatal if it runs as operation with less than one watched resource" ,
2474+ args : args {
2475+ ctx : context .Background (),
2476+ req : & fnv1.RunFunctionRequest {
2477+ Meta : & fnv1.RequestMeta {Tag : "hello" },
2478+ Input : resource .MustStructJSON (`{
2479+ "apiVersion": "msgraph.fn.crossplane.io/v1alpha1",
2480+ "kind": "Input",
2481+ "queryType": "UserValidation",
2482+ "users": ["user@example.com"],
2483+ "target": "context.validatedUsers"
2484+ }` ),
2485+ Credentials : map [string ]* fnv1.Credentials {
2486+ "azure-creds" : {
2487+ Source : & fnv1.Credentials_CredentialData {CredentialData : creds },
2488+ },
2489+ },
2490+ RequiredResources : map [string ]* fnv1.Resources {
2491+ "ops.crossplane.io/watched-resource" : {
2492+ Items : nil ,
2493+ },
2494+ },
2495+ },
2496+ },
2497+ want : want {
2498+ rsp : & fnv1.RunFunctionResponse {
2499+ Meta : & fnv1.ResponseMeta {Tag : "hello" , Ttl : durationpb .New (response .DefaultTTL )},
2500+ Results : []* fnv1.Result {
2501+ {
2502+ Severity : fnv1 .Severity_SEVERITY_FATAL ,
2503+ Message : `operation: incorrect number of resources sent to the function. expected 1, got 0` ,
2504+ Target : fnv1 .Target_TARGET_COMPOSITE .Enum (),
2505+ },
2506+ },
2507+ },
2508+ },
2509+ },
2510+ "OperationWithMoreThanOneWatchedResource" : {
2511+ reason : "The Function should return fatal if it runs as operation with more than one watched resource" ,
2512+ args : args {
2513+ ctx : context .Background (),
2514+ req : & fnv1.RunFunctionRequest {
2515+ Meta : & fnv1.RequestMeta {Tag : "hello" },
2516+ Input : resource .MustStructJSON (`{
2517+ "apiVersion": "msgraph.fn.crossplane.io/v1alpha1",
2518+ "kind": "Input",
2519+ "queryType": "UserValidation",
2520+ "users": ["user@example.com"],
2521+ "target": "context.validatedUsers"
2522+ }` ),
2523+ Credentials : map [string ]* fnv1.Credentials {
2524+ "azure-creds" : {
2525+ Source : & fnv1.Credentials_CredentialData {CredentialData : creds },
2526+ },
2527+ },
2528+ RequiredResources : map [string ]* fnv1.Resources {
2529+ "ops.crossplane.io/watched-resource" : {
2530+ Items : []* fnv1.Resource {
2531+ {
2532+ Resource : resource .MustStructJSON (xr ),
2533+ },
2534+ {
2535+ Resource : resource .MustStructJSON (xr ),
2536+ },
2537+ },
2538+ },
2539+ },
2540+ },
2541+ },
2542+ want : want {
2543+ rsp : & fnv1.RunFunctionResponse {
2544+ Meta : & fnv1.ResponseMeta {Tag : "hello" , Ttl : durationpb .New (response .DefaultTTL )},
2545+ Results : []* fnv1.Result {
2546+ {
2547+ Severity : fnv1 .Severity_SEVERITY_FATAL ,
2548+ Message : `operation: incorrect number of resources sent to the function. expected 1, got 2` ,
2549+ Target : fnv1 .Target_TARGET_COMPOSITE .Enum (),
2550+ },
2551+ },
2552+ },
2553+ },
2554+ },
2555+ "OperationWithNilObjectInWatchedResource" : {
2556+ reason : "The Function should return fatal if it runs as operation watched resource with zero length Resource.Object" ,
2557+ args : args {
2558+ ctx : context .Background (),
2559+ req : & fnv1.RunFunctionRequest {
2560+ Meta : & fnv1.RequestMeta {Tag : "hello" },
2561+ Input : resource .MustStructJSON (`{
2562+ "apiVersion": "msgraph.fn.crossplane.io/v1alpha1",
2563+ "kind": "Input",
2564+ "queryType": "UserValidation",
2565+ "users": ["user@example.com"],
2566+ "target": "context.validatedUsers"
2567+ }` ),
2568+ Credentials : map [string ]* fnv1.Credentials {
2569+ "azure-creds" : {
2570+ Source : & fnv1.Credentials_CredentialData {CredentialData : creds },
2571+ },
2572+ },
2573+ RequiredResources : map [string ]* fnv1.Resources {
2574+ "ops.crossplane.io/watched-resource" : {
2575+ Items : []* fnv1.Resource {
2576+ {},
2577+ },
2578+ },
2579+ },
2580+ },
2581+ },
2582+ want : want {
2583+ rsp : & fnv1.RunFunctionResponse {
2584+ Meta : & fnv1.ResponseMeta {Tag : "hello" , Ttl : durationpb .New (response .DefaultTTL )},
2585+ Results : []* fnv1.Result {
2586+ {
2587+ Severity : fnv1 .Severity_SEVERITY_FATAL ,
2588+ Message : `operation: Resource.Object property in operation resource can not be empty` ,
2589+ Target : fnv1 .Target_TARGET_COMPOSITE .Enum (),
2590+ },
2591+ },
2592+ },
2593+ },
2594+ },
2595+ "OperationWithWatchedResource" : {
2596+ reason : "The Function should return fatal if it runs as operation watched resource with nil Resource" ,
2597+ args : args {
2598+ ctx : context .Background (),
2599+ req : & fnv1.RunFunctionRequest {
2600+ Meta : & fnv1.RequestMeta {Tag : "hello" },
2601+ Input : resource .MustStructJSON (`{
2602+ "apiVersion": "msgraph.fn.crossplane.io/v1alpha1",
2603+ "kind": "Input",
2604+ "queryType": "UserValidation",
2605+ "users": ["user@example.com"],
2606+ "target": "status.validatedUsers"
2607+ }` ),
2608+ Credentials : map [string ]* fnv1.Credentials {
2609+ "azure-creds" : {
2610+ Source : & fnv1.Credentials_CredentialData {CredentialData : creds },
2611+ },
2612+ },
2613+ RequiredResources : map [string ]* fnv1.Resources {
2614+ "ops.crossplane.io/watched-resource" : {
2615+ Items : []* fnv1.Resource {
2616+ {
2617+ Resource : resource .MustStructJSON (xr ),
2618+ },
2619+ },
2620+ },
2621+ },
2622+ },
2623+ },
2624+ want : want {
2625+ rsp : & fnv1.RunFunctionResponse {
2626+ Meta : & fnv1.ResponseMeta {Tag : "hello" , Ttl : durationpb .New (response .DefaultTTL )},
2627+ Conditions : []* fnv1.Condition {
2628+ {
2629+ Type : "FunctionSuccess" ,
2630+ Status : fnv1 .Status_STATUS_CONDITION_TRUE ,
2631+ Reason : "Success" ,
2632+ Target : fnv1 .Target_TARGET_COMPOSITE_AND_CLAIM .Enum (),
2633+ },
2634+ },
2635+ Results : []* fnv1.Result {
2636+ {
2637+ Severity : fnv1 .Severity_SEVERITY_NORMAL ,
2638+ Message : `QueryType: "UserValidation"` ,
2639+ Target : fnv1 .Target_TARGET_COMPOSITE .Enum (),
2640+ },
2641+ },
2642+ Desired : & fnv1.State {
2643+ Composite : & fnv1.Resource {
2644+ Resource : resource .MustStructJSON (`{
2645+ "apiVersion": "example.org/v1",
2646+ "kind": "XR",
2647+ "metadata": {
2648+ "name": "cool-xr"
2649+ },
2650+ "spec": {
2651+ "count": 2
2652+ },
2653+ "status": {
2654+ "validatedUsers": [
2655+ {
2656+ "id": "test-user-id",
2657+ "displayName": "Test User",
2658+ "userPrincipalName": "user@example.com",
2659+ "mail": "user@example.com"
2660+ }
2661+ ]
2662+ }
2663+ }` ),
2664+ },
2665+ },
2666+ },
2667+ },
2668+ },
24162669 }
24172670
24182671 for name , tc := range cases {
0 commit comments