diff --git a/README.md b/README.md index 7cf29d3..78ecfe4 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,8 @@ This repository provides examples demonstrating how to use Oracle Functions. | Display an OCI Cloud Event |[sample](./samples/oci-event-display-python)||[sample](./samples/oci-event-display-dotnet)| | Invoke another Function using the OCI SDK |[sample](./samples/oci-invoke-function-python)||[sample](./samples/oci-invoke-function-dotnet)| | Run a SQL statement against Autonomous DB using ORDS | [sample](./samples/oci-adb-ords-runsql-python) ||[sample](./samples/oci-adb-ords-runsql-dotnet)| -| Run a SQL statement against Autonomous DB using DB Client |[sample](./samples/oci-adb-client-runsql-python)|| [sample](./samples/oci-adb-client-runsql-dotnet) -| Publish a notification using ONS |[sample](./samples/oci-ons-publish-python)| +| Run a SQL statement against Autonomous DB using DB Client |[sample](./samples/oci-adb-client-runsql-python)|| [sample](./samples/oci-adb-client-runsql-dotnet)| +| Publish a notification using ONS |[sample](./samples/oci-ons-publish-python)||[sample](./samples/oci-ons-publish-dotnet)| | Send an email using Email Delivery Service |[sample](./samples/oci-email-send-python)| | Decrypt cipher using Vault keys |[sample](./samples/oci-vault-decrypt-python)||[sample](./samples/oci-vault-decrypt-dotnet)| | Get a secret from Vault |[sample](./samples/oci-vault-get-secret-python)||[sample](./samples/oci-vault-get-secret-dotnet)| diff --git a/samples/oci-ons-publish-dotnet/Common/ONSClientHelper.cs b/samples/oci-ons-publish-dotnet/Common/ONSClientHelper.cs new file mode 100644 index 0000000..3f03057 --- /dev/null +++ b/samples/oci-ons-publish-dotnet/Common/ONSClientHelper.cs @@ -0,0 +1,30 @@ + +using System; +using System.Threading.Tasks; +using System.Text; + +using Oci.Common; +using Oci.Common.Auth; +using Oci.OnsService; + + +namespace PublishONS +{ + public class ONSClientHelper + { + public static NotificationDataPlaneClient GetONSClient() + { + try + { + return new NotificationDataPlaneClient(ResourcePrincipalAuthenticationDetailsProvider.GetProvider(), new ClientConfiguration()); + } + catch (Exception ex) + { + Console.WriteLine("Unable To Create Resource Principal Provider: {0}", ex.Message); + Console.WriteLine("Defaulting to Instance Provider"); + return new NotificationDataPlaneClient(new InstancePrincipalsAuthenticationDetailsProvider(), new ClientConfiguration()); + } + } + + } +} diff --git a/samples/oci-ons-publish-dotnet/Controller/InvokeONSHelper.cs b/samples/oci-ons-publish-dotnet/Controller/InvokeONSHelper.cs new file mode 100644 index 0000000..bc7a599 --- /dev/null +++ b/samples/oci-ons-publish-dotnet/Controller/InvokeONSHelper.cs @@ -0,0 +1,56 @@ + +using System; +using System.Threading.Tasks; +using System.Text; +using System.Collections.Generic; +using System.IO; +using Oci.Common.Model; +using Oci.Common; +using Oci.Common.Auth; +using Oci.OnsService; +using Oci.OnsService.Models; +using Oci.OnsService.Requests; +using Oci.OnsService.Responses; + + +namespace PublishONS +{ + public class InvokeONSHelper + { + public static async Task SendMessage(NotificationDataPlaneClient client, string topic_id, string msg_title, string msg_body) + + { + + try + { + + // Create a request and dependent object(s). + var messageDetails = new Oci.OnsService.Models.MessageDetails + { + Title = msg_title, + Body = msg_body + }; + var publishMessageRequest = new Oci.OnsService.Requests.PublishMessageRequest + { + TopicId = topic_id, + MessageDetails = messageDetails, + MessageType = Oci.OnsService.Requests.PublishMessageRequest.MessageTypeEnum.RawText + }; + + var response = await client.PublishMessage(publishMessageRequest); + var messageIdValue = response.PublishResult.MessageId; + return messageIdValue; + + } + + catch (OciException ex) + { + Console.WriteLine("Unable To Send Message to ONS : {0}", ex.Message); + return "Failed " + ex.Message; + } + + } + + + } +} diff --git a/samples/oci-ons-publish-dotnet/Dockerfile b/samples/oci-ons-publish-dotnet/Dockerfile new file mode 100644 index 0000000..984e8f8 --- /dev/null +++ b/samples/oci-ons-publish-dotnet/Dockerfile @@ -0,0 +1,11 @@ +FROM fnproject/dotnet:3.1-1.0.4-dev as build-stage +WORKDIR /function +COPY . . +RUN dotnet sln add PublishONS.csproj +RUN dotnet build PublishONS.csproj -c Release +RUN dotnet publish PublishONS.csproj -c Release -o out +FROM fnproject/dotnet:3.1-1.0.4 +WORKDIR /function +COPY --from=build-stage /function/out/ /function/ +ENTRYPOINT ["dotnet", "PublishONS.dll"] +CMD ["PublishONS:Function:function_handler"] \ No newline at end of file diff --git a/samples/oci-ons-publish-dotnet/Function.sln b/samples/oci-ons-publish-dotnet/Function.sln new file mode 100644 index 0000000..f87916a --- /dev/null +++ b/samples/oci-ons-publish-dotnet/Function.sln @@ -0,0 +1,17 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/samples/oci-ons-publish-dotnet/Models/InputMessage.cs b/samples/oci-ons-publish-dotnet/Models/InputMessage.cs new file mode 100644 index 0000000..9cc7fcb --- /dev/null +++ b/samples/oci-ons-publish-dotnet/Models/InputMessage.cs @@ -0,0 +1,15 @@ +using System; + +namespace PublishONS +{ + + class InputMessage + { + public string topic_id { get; set; } + public string msg_title { get; set; } + public string msg_body { get; set; } + + + } + +} diff --git a/samples/oci-ons-publish-dotnet/Models/ObjectDetails.cs b/samples/oci-ons-publish-dotnet/Models/ObjectDetails.cs new file mode 100644 index 0000000..d5d4a73 --- /dev/null +++ b/samples/oci-ons-publish-dotnet/Models/ObjectDetails.cs @@ -0,0 +1,14 @@ +using System; + +namespace PublishONS +{ + + class ObjectDetails + { + + public string result { get; set; } + + + } + +} diff --git a/samples/oci-ons-publish-dotnet/PublishONS.cs b/samples/oci-ons-publish-dotnet/PublishONS.cs new file mode 100644 index 0000000..b4de871 --- /dev/null +++ b/samples/oci-ons-publish-dotnet/PublishONS.cs @@ -0,0 +1,39 @@ +using Fnproject.Fn.Fdk; +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Oci.OnsService; +using Oci.OnsService.Models; + +namespace PublishONS +{ + class Function + { + public string function_handler(InputMessage input) + { + + Dictionary> output = new Dictionary>(); + var object_details_list = new List(); + string topic_id = input.topic_id; + string msg_title = input.msg_title; + string msg_body = input.msg_body; + + NotificationDataPlaneClient client = ONSClientHelper.GetONSClient(); + Task messageIdValue = InvokeONSHelper.SendMessage(client, topic_id, msg_title, msg_body); + + var object_detail = new ObjectDetails(); + object_detail.result = messageIdValue.Result; + object_details_list.Add(object_detail); + + output.Add("results", object_details_list); + return System.Text.Json.JsonSerializer.Serialize(output); + + } + + static void Main(string[] args) { Fdk.Handle(args[0]); } + + } +} diff --git a/samples/oci-ons-publish-dotnet/PublishONS.csproj b/samples/oci-ons-publish-dotnet/PublishONS.csproj new file mode 100644 index 0000000..bac1f04 --- /dev/null +++ b/samples/oci-ons-publish-dotnet/PublishONS.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + diff --git a/samples/oci-ons-publish-dotnet/README.md b/samples/oci-ons-publish-dotnet/README.md new file mode 100644 index 0000000..fc5901c --- /dev/null +++ b/samples/oci-ons-publish-dotnet/README.md @@ -0,0 +1,99 @@ +# Function that publishes a notification +This function publishes a notification. + +As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png). +Whenever you see it, it's time for you to perform an action. + + +## Prerequisites +Before you deploy this sample function, make sure you have run step A, B and C of the [Oracle Functions Quick Start Guide for Cloud Shell](https://www.oracle.com/webfolder/technetwork/tutorials/infographics/oci_functions_cloudshell_quickview/functions_quickview_top/functions_quickview/index.html) +* A - Set up your tenancy +* B - Create application +* C - Set up your Cloud Shell dev environment + + +## List Applications +Assuming your have successfully completed the prerequisites, you should see your +application in the list of applications. +``` +fn ls apps +``` + + +## Create or Update your Dynamic Group +In order to use other OCI Services, your function must be part of a dynamic group. For information on how to create a dynamic group, refer to the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingdynamicgroups.htm#To). + +When specifying the *Matching Rules*, we suggest matching all functions in a compartment with: +``` +ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'} +``` +Please check the [Accessing Other Oracle Cloud Infrastructure Resources from Running Functions](https://docs.cloud.oracle.com/en-us/iaas/Content/Functions/Tasks/functionsaccessingociresources.htm) for other *Matching Rules* options. + + +## Create or Update IAM Policies +Create a new policy that allows the dynamic group to use the Notificaton Service. We will grant `use` access to `ons-topics` in the compartment. + +![user input icon](./images/userinput.png) + +Your policy should look something like this: +``` +Allow dynamic-group to use ons-topics in compartment +``` + +For more information on how to create policies, check the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm). + + +## Review and customize the function +Review the following files in the current folder: +* the code of the function, [PublishONS.cs](./PublishONS.cs) +* its dependencies, [PublishONS.csproj](./PublishONS.csproj) +* the function metadata, [func.yaml](./func.yaml) + + +## Deploy the function +In Cloud Shell, run the *fn deploy* command to build the function and its dependencies as a Docker image, +push the image to OCIR, and deploy the function to Oracle Functions in your application. + +![user input icon](./images/userinput.png) +``` +fn -v deploy --app +``` + + +## Create the Notification topic +Create a Notification topic with an email subscription. + +![user input icon](./images/userinput.png) + +Go to the OCI console, navigate to Application Integration > Notifications. Click *Create Topic*. + +![create topic](./images/ons-create-topic.png) + +Click on your topic and create a email subscription to this topic by clicking *Create Subscription* and entering your email address. You will receive an email to confirm your subscription. + +![create subscription](./images/ons-create-email-subscription.png) + +Note the OCID of your topic. + + +## Invoke the function +Run the following command to test your function. + +![user input icon](./images/userinput.png) + +``` +echo '{"topic_id": "", "msg_title": "message-title", "msg_body": "message-body"}' | fn invoke oci-ons-publish-dotnet +``` +e.g.: +``` +echo '{"topic_id": "ocid1.onstopic.xxxx", "msg_title": "a message from Functions", "msg_body": "This email was sent by Oracle Functions!"}' | fn invoke myapp oci-ons-publish-dotnet +``` + +Upon success, you should receive an email from the Notification Service. + + +## Monitoring Functions and Notifications Topics + +Learn how to configure basic observability for your function and topic using metrics, alarms and email alerts: +* [Basic Guidance for Monitoring your Functions](../basic-observability/functions.md) +* [Basic Guidance for Monitoring your Notifications Topics](../basic-observability/notifications.md) diff --git a/samples/oci-ons-publish-dotnet/func.yaml b/samples/oci-ons-publish-dotnet/func.yaml new file mode 100644 index 0000000..44ddcfc --- /dev/null +++ b/samples/oci-ons-publish-dotnet/func.yaml @@ -0,0 +1,8 @@ +schema_version: 20180708 +name: oci-ons-publish-dotnet +version: 0.0.99 +runtime: dotnet3.1 +build_image: fnproject/dotnet:3.1-1.0.4-dev +run_image: fnproject/dotnet:3.1-1.0.4 +cmd: PublishONS:Function:function_handler +entrypoint: dotnet PublishONS.dll diff --git a/samples/oci-ons-publish-dotnet/images/ons-create-email-subscription.png b/samples/oci-ons-publish-dotnet/images/ons-create-email-subscription.png new file mode 100644 index 0000000..8793f4a Binary files /dev/null and b/samples/oci-ons-publish-dotnet/images/ons-create-email-subscription.png differ diff --git a/samples/oci-ons-publish-dotnet/images/ons-create-topic.png b/samples/oci-ons-publish-dotnet/images/ons-create-topic.png new file mode 100644 index 0000000..01b1ca1 Binary files /dev/null and b/samples/oci-ons-publish-dotnet/images/ons-create-topic.png differ diff --git a/samples/oci-ons-publish-dotnet/images/ons-topic.png b/samples/oci-ons-publish-dotnet/images/ons-topic.png new file mode 100644 index 0000000..d6aab20 Binary files /dev/null and b/samples/oci-ons-publish-dotnet/images/ons-topic.png differ diff --git a/samples/oci-ons-publish-dotnet/images/userinput.png b/samples/oci-ons-publish-dotnet/images/userinput.png new file mode 100644 index 0000000..ce6a202 Binary files /dev/null and b/samples/oci-ons-publish-dotnet/images/userinput.png differ