Skip to content

Commit 6d68d86

Browse files
authored
Merge pull request #6 from ddevadat/dotnet-samples
added create par dotnet function
2 parents c0547f3 + dd36258 commit 6d68d86

File tree

12 files changed

+316
-1
lines changed

12 files changed

+316
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This repository provides examples demonstrating how to use Oracle Functions.
2222
| List objects in OCI Object Storage |[sample](./samples/oci-objectstorage-list-objects-python)|[sample](./samples/oci-objectstorage-list-objects-java)|[sample](./samples/oci-objectstorage-list-objects-dotnet)|
2323
| Read an object in OCI Object Storage |[sample](./samples/oci-objectstorage-get-object-python)|[sample](./samples/oci-objectstorage-get-object-java)|[sample](./samples/oci-objectstorage-get-object-dotnet)|
2424
| Create an object in OCI Object Storage |[sample](./samples/oci-objectstorage-put-object-python)|[sample](./samples/oci-objectstorage-put-object-java)|[sample](./samples/oci-objectstorage-put-object-dotnet)|
25-
| Create a PAR in OCI Object Storage |[sample](./samples/oci-objectstorage-create-par-python)||
25+
| Create a PAR in OCI Object Storage |[sample](./samples/oci-objectstorage-create-par-python)||[sample](./samples/oci-objectstorage-create-par-dotnet)|
2626
| Copy object from one OCI Object Storage bucket to another |[sample](./samples/oci-objectstorage-copy-objects-python)||
2727
| Display an OCI Cloud Event |[sample](./samples/oci-event-display-python)|
2828
| Invoke another Function using the OCI SDK |[sample](./samples/oci-invoke-function-python)|||
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
using System;
3+
using System.Threading.Tasks;
4+
using System.Text;
5+
6+
using Oci.Common;
7+
using Oci.Common.Auth;
8+
using Oci.ObjectstorageService;
9+
10+
11+
namespace CreatePAR
12+
{
13+
public class ObjectStorageClientHelper
14+
{
15+
public static ObjectStorageClient GetObjectStorageClient()
16+
{
17+
try
18+
{
19+
return new ObjectStorageClient(ResourcePrincipalAuthenticationDetailsProvider.GetProvider(), new ClientConfiguration());
20+
}
21+
catch (Exception ex)
22+
{
23+
Console.WriteLine("Unable To Create Resource Principal Provider: {0}", ex.Message);
24+
Console.WriteLine("Defaulting to Instance Provider");
25+
return new ObjectStorageClient(new InstancePrincipalsAuthenticationDetailsProvider(), new ClientConfiguration());
26+
}
27+
}
28+
29+
}
30+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
using System;
3+
using System.Threading.Tasks;
4+
using System.Text;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using Oci.Common.Model;
8+
using Oci.Common;
9+
using Oci.Common.Auth;
10+
using Oci.ObjectstorageService;
11+
using Oci.ObjectstorageService.Models;
12+
using Oci.ObjectstorageService.Requests;
13+
using Oci.ObjectstorageService.Responses;
14+
15+
16+
namespace CreatePAR
17+
{
18+
public class CreatePARHelper
19+
{
20+
21+
public static async Task<string> CreatePAR(ObjectStorageClient client, string bucketName, string namespaceName, string parName, int lifetime, string region)
22+
23+
{
24+
25+
try
26+
{
27+
DateTime currentTime = DateTime.Now;
28+
DateTime parexpiry = currentTime.AddMinutes(lifetime);
29+
string object_storage_endpoint = "https://objectstorage." + region + ".oraclecloud.com";
30+
var createPreauthenticatedRequestDetails = new Oci.ObjectstorageService.Models.CreatePreauthenticatedRequestDetails
31+
{
32+
Name = parName,
33+
BucketListingAction = Oci.ObjectstorageService.Models.PreauthenticatedRequest.BucketListingActionEnum.ListObjects,
34+
AccessType = Oci.ObjectstorageService.Models.CreatePreauthenticatedRequestDetails.AccessTypeEnum.AnyObjectWrite,
35+
TimeExpires = parexpiry
36+
};
37+
var createPreauthenticatedRequestRequest = new Oci.ObjectstorageService.Requests.CreatePreauthenticatedRequestRequest
38+
{
39+
NamespaceName = namespaceName,
40+
BucketName = bucketName,
41+
CreatePreauthenticatedRequestDetails = createPreauthenticatedRequestDetails,
42+
};
43+
44+
var response = await client.CreatePreauthenticatedRequest(createPreauthenticatedRequestRequest);
45+
return object_storage_endpoint + response.PreauthenticatedRequest.AccessUri;
46+
47+
48+
}
49+
50+
catch (OciException ex)
51+
{
52+
Console.WriteLine("Unable To Put Object : {0}", ex.Message);
53+
return "Failed " + ex.Message;
54+
}
55+
56+
}
57+
58+
59+
}
60+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Fnproject.Fn.Fdk;
2+
using System.Runtime.CompilerServices;
3+
using System.Collections.Generic;
4+
using System;
5+
using System.Text;
6+
using System.Text.Json;
7+
using System.Threading.Tasks;
8+
using Oci.ObjectstorageService;
9+
using Oci.ObjectstorageService.Models;
10+
11+
namespace CreatePAR
12+
{
13+
class Function
14+
{
15+
public string function_handler(InputMessage input)
16+
{
17+
18+
Dictionary<string, List<ObjectDetails>> output = new Dictionary<string, List<ObjectDetails>>();
19+
var object_details_list = new List<ObjectDetails>();
20+
string parName = input.PARName;
21+
string bucketName = Environment.GetEnvironmentVariable("BUCKET_NAME");
22+
string namespaceName = Environment.GetEnvironmentVariable("NAMESPACE");
23+
int lifetime = Int32.Parse(Environment.GetEnvironmentVariable("LIFETIME"));
24+
string region = Environment.GetEnvironmentVariable("REGION");
25+
ObjectStorageClient client = ObjectStorageClientHelper.GetObjectStorageClient();
26+
Task<string> object_str = CreatePARHelper.CreatePAR(client, bucketName, namespaceName, parName, lifetime, region);
27+
var object_detail = new ObjectDetails();
28+
object_detail.parname = parName;
29+
object_detail.bucketname = bucketName;
30+
object_detail.parurl = object_str.Result;
31+
object_details_list.Add(object_detail);
32+
33+
output.Add("results", object_details_list);
34+
return JsonSerializer.Serialize(output);
35+
36+
}
37+
38+
static void Main(string[] args) { Fdk.Handle(args[0]); }
39+
40+
}
41+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>netcoreapp3.1</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Fnproject.Fn.Fdk" Version="1.0.4" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="OCI.DotNetSDK.Common" Version="42.1.0" />
14+
<PackageReference Include="OCI.DotNetSDK.Objectstorage" Version="42.1.0" />
15+
</ItemGroup>
16+
17+
</Project>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM fnproject/dotnet:3.1-1.0.4-dev as build-stage
2+
WORKDIR /function
3+
COPY . .
4+
RUN dotnet sln add CreatePAR.csproj
5+
RUN dotnet build CreatePAR.csproj -c Release
6+
RUN dotnet publish CreatePAR.csproj -c Release -o out
7+
FROM fnproject/dotnet:3.1-1.0.4
8+
WORKDIR /function
9+
COPY --from=build-stage /function/out/ /function/
10+
ENTRYPOINT ["dotnet", "CreatePAR.dll"]
11+
CMD ["CreatePAR:Function:function_handler"]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio 15
3+
VisualStudioVersion = 15.0.26124.0
4+
MinimumVisualStudioVersion = 15.0.26124.0
5+
Global
6+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7+
Debug|Any CPU = Debug|Any CPU
8+
Debug|x64 = Debug|x64
9+
Debug|x86 = Debug|x86
10+
Release|Any CPU = Release|Any CPU
11+
Release|x64 = Release|x64
12+
Release|x86 = Release|x86
13+
EndGlobalSection
14+
GlobalSection(SolutionProperties) = preSolution
15+
HideSolutionNode = FALSE
16+
EndGlobalSection
17+
EndGlobal
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
3+
namespace CreatePAR
4+
{
5+
6+
class InputMessage
7+
{
8+
public string PARName { get; set; }
9+
10+
}
11+
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace CreatePAR
4+
{
5+
6+
class ObjectDetails
7+
{
8+
public string parname { get; set; }
9+
10+
public string bucketname { get; set; }
11+
public string parurl { get; set; }
12+
13+
14+
}
15+
16+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Function that creates a PAR
2+
This function creates a PAR (Pre-Authenticated Request) for a bucket in Object Storage.
3+
4+
As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
5+
Whenever you see it, it's time for you to perform an action.
6+
7+
8+
## Prerequisites
9+
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)
10+
* A - Set up your tenancy
11+
* B - Create application
12+
* C - Set up your Cloud Shell dev environment
13+
14+
15+
## List Applications
16+
Assuming your have successfully completed the prerequisites, you should see your
17+
application in the list of applications.
18+
```
19+
fn ls apps
20+
```
21+
22+
23+
## Create or Update your Dynamic Group
24+
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).
25+
26+
When specifying the *Matching Rules*, we suggest matching all functions in a compartment with:
27+
```
28+
ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'}
29+
```
30+
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.
31+
32+
33+
## Create or Update IAM Policies
34+
Create a new policy that allows the dynamic group to manage compute instances. We will grant `manage` access to a specific `bucket` and `objects` in that bucket for a given compartment.
35+
36+
![user input icon](./images/userinput.png)
37+
38+
Your policy should look something like this:
39+
```
40+
Allow dynamic-group <dynamic-group-name> to manage buckets in compartment <compartment-name> where target.bucket.name=<bucket-name>
41+
Allow dynamic-group <dynamic-group-name> to manage objects in compartment <compartment-name> where target.bucket.name=<bucket-name>
42+
```
43+
For more information on how to create policies, go [here](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).
44+
45+
46+
## Review and customize your function
47+
Review the following files in the current folder:
48+
* the code of the function, [CreatePAR.cs](./CreatePAR.cs)
49+
* its dependencies, [CreatePAR.proj](./CreatePAR.proj)
50+
* the function metadata, [func.yaml](./func.yaml)
51+
52+
53+
## Deploy the function
54+
In Cloud Shell, run the *fn deploy* command to build the function and its dependencies as a Docker image,
55+
push the image to OCIR, and deploy the function to Oracle Functions in your application.
56+
57+
![user input icon](./images/userinput.png)
58+
```
59+
fn -v deploy --app <app-name>
60+
```
61+
62+
63+
## Set the function configuration values
64+
The function requires the config value *bucket-name* and *lifetime* to be set.
65+
66+
![user input icon](./images/userinput.png)
67+
68+
Use the *fn* CLI to set the config value:
69+
```
70+
fn config function <app-name> <function-name> BUCKET_NAME <bucket-name>
71+
fn config function <app-name> <function-name> NAMESPACE <bucket-namespace>
72+
fn config function <app-name> <function-name> LIFETIME <PAR-lifetime-in-minutes>
73+
fn config function <app-name> <function-name> REGION <region>
74+
```
75+
e.g.
76+
```
77+
fn config function myapp oci-objectstorage-create-par-dotnet BUCKET_NAME 'my-bucket'
78+
fn config function myapp oci-objectstorage-create-par-dotnet NAMESPACE 'samplenamespace'
79+
fn config function myapp oci-objectstorage-create-par-dotnet LIFETIME '30'
80+
fn config function myapp oci-objectstorage-create-par-dotnet REGION 'ap-osaka-1'
81+
```
82+
83+
## Invoke the function
84+
The function requires the name of the PAR in the payload to be invoked.
85+
86+
![user input icon](./images/userinput.png)
87+
```
88+
89+
echo '{"PAR name": <PAR name> }' | fn invoke <app-name> oci-objectstorage-create-par-dotnet
90+
```
91+
e.g.:
92+
```
93+
echo '{"PAR name": "myPAR" }' | fn invoke myapp oci-objectstorage-create-par-dotnet
94+
```
95+
96+
Upon success, the function returns the PAR URL.
97+
98+
99+
## Monitoring Functions
100+
101+
Learn how to configure basic observability for your function using metrics, alarms and email alerts:
102+
* [Basic Guidance for Monitoring your Functions](../basic-observability/functions.md)
103+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
schema_version: 20180708
2+
name: oci-objectstorage-create-par-dotnet
3+
version: 0.0.79
4+
runtime: dotnet3.1
5+
build_image: fnproject/dotnet:3.1-1.0.4-dev
6+
run_image: fnproject/dotnet:3.1-1.0.4
7+
cmd: CreatePAR:Function:function_handler
8+
entrypoint: dotnet CreatePAR.dll
Loading

0 commit comments

Comments
 (0)