Skip to content

Commit 89b76a7

Browse files
authored
Merge pull request #4 from ddevadat/dotnet-samples
Added get objects on dotnet function
2 parents a607258 + 854bf7f commit 89b76a7

File tree

13 files changed

+325
-2
lines changed

13 files changed

+325
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ This repository provides examples demonstrating how to use Oracle Functions.
2020
| Control OCI Compute instances (start/stop/status) |[sample](./samples/oci-compute-control-python)||[sample](./samples/oci-compute-control-dotnet)|
2121
| List OCI compartments |[sample](./samples/oci-list-compartments-python)||[sample](./samples/oci-list-compartments-dotnet)|
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)|
23-
| Read an object in OCI Object Storage |[sample](./samples/oci-objectstorage-get-object-python)|[sample](./samples/oci-objectstorage-get-object-java)|
23+
| 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)|
2525
| Create a PAR in OCI Object Storage |[sample](./samples/oci-objectstorage-create-par-python)||
2626
| Copy object from one OCI Object Storage bucket to another |[sample](./samples/oci-objectstorage-copy-objects-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 GetObjects
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: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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 GetObjects
17+
{
18+
public class GetObjectHelper
19+
{
20+
public static async Task<string> GetObject(ObjectStorageClient client, string bucketName, string namespaceName, string objectName)
21+
22+
{
23+
24+
try
25+
{
26+
27+
var getObjectRequest = new Oci.ObjectstorageService.Requests.GetObjectRequest
28+
{
29+
NamespaceName = namespaceName,
30+
BucketName = bucketName,
31+
ObjectName = objectName,
32+
};
33+
34+
var response = await client.GetObject(getObjectRequest);
35+
byte[] bytes;
36+
using (var memoryStream = new MemoryStream())
37+
{
38+
response.InputStream.CopyTo(memoryStream);
39+
bytes = memoryStream.ToArray();
40+
}
41+
42+
return Convert.ToBase64String(bytes);
43+
}
44+
45+
catch (OciException ex)
46+
{
47+
Console.WriteLine("Unable To Get Object : {0}", ex.Message);
48+
return "object not found!";
49+
}
50+
51+
}
52+
53+
54+
}
55+
}
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 GetObjects.csproj
5+
RUN dotnet build GetObjects.csproj -c Release
6+
RUN dotnet publish GetObjects.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", "GetObjects.dll"]
11+
CMD ["GetObjects: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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 GetObjects
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 bucketName = input.bucketName;
21+
string objectName = input.objectName;
22+
string namespaceName = input.namespaceName;
23+
ObjectStorageClient client = ObjectStorageClientHelper.GetObjectStorageClient();
24+
Task<string> object_str = GetObjectHelper.GetObject(client, bucketName, namespaceName, objectName);
25+
var object_detail = new ObjectDetails();
26+
if (object_str.Result != "object not found!")
27+
{
28+
byte[] data = Convert.FromBase64String(object_str.Result);
29+
string decodedString = Encoding.UTF8.GetString(data);
30+
object_detail.name = objectName;
31+
object_detail.content = decodedString;
32+
object_details_list.Add(object_detail);
33+
}
34+
35+
output.Add("results", object_details_list);
36+
return JsonSerializer.Serialize(output);
37+
38+
}
39+
40+
static void Main(string[] args) { Fdk.Handle(args[0]); }
41+
42+
}
43+
}
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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace GetObjects
4+
{
5+
6+
class InputMessage
7+
{
8+
public string objectName { get; set; }
9+
public string bucketName { get; set; }
10+
public string namespaceName { get; set; }
11+
12+
}
13+
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace GetObjects
4+
{
5+
6+
class ObjectDetails
7+
{
8+
public string name { get; set; }
9+
public string content { get; set; }
10+
11+
12+
}
13+
14+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Function that retrieves an object from a bucket in Object Storage using the OCI Dotnet SDK
2+
3+
This function uses Resource Principals to securely authorize a function to make
4+
API calls to OCI services using the [OCI Dotnet SDK](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/index.html).
5+
It returns the content of an object from a bucket in Object Storage.
6+
7+
The function calls the following OCI Dotnet SDK classes:
8+
* [Resource Principals](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.Common.Auth.ResourcePrincipalAuthenticationDetailsProvider.html) to authenticate
9+
* [Object Storage Client](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.ObjectstorageService.ObjectStorageClient.html) to interact with Object Storage
10+
11+
As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
12+
Whenever you see it, it's time for you to perform an action.
13+
14+
15+
## Prerequisites
16+
17+
1. Before you deploy this sample function, make sure you have run steps A, B
18+
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)
19+
* A - Set up your tenancy
20+
* B - Create application
21+
* C - Set up your Cloud Shell dev environment
22+
23+
2. Have your Oracle Object Storage Namespace available. This can be found by
24+
logging into your [cloud account](https://console.us-ashburn-1.oraclecloud.com/),
25+
under your user profile, click on your Tenancy. Your Object Storage Namespace
26+
is shown there.
27+
28+
29+
## List Applications
30+
31+
Assuming you have successfully completed the prerequisites, you should see your
32+
application in the list of applications.
33+
34+
```
35+
fn ls apps
36+
```
37+
38+
39+
## Create or Update your Dynamic Group
40+
41+
In order to use other OCI Services, your function must be part of a dynamic
42+
group. For information on how to create a dynamic group, refer to the
43+
[documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingdynamicgroups.htm#To).
44+
45+
When specifying the *Matching Rules*, we suggest matching all functions in a compartment with:
46+
47+
```
48+
ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'}
49+
```
50+
51+
52+
## Create or Update IAM Policies
53+
54+
Create a new policy that allows the dynamic group to `inspect objects` in
55+
the functions related compartment.
56+
57+
![user input icon](./images/userinput.png)
58+
59+
Your policy should look something like this:
60+
```
61+
Allow dynamic-group <dynamic-group-name> to inspect objects in compartment <compartment-name>
62+
```
63+
e.g.
64+
```
65+
Allow dynamic-group demo-func-dyn-group to inspect objects in compartment demo-func-compartment
66+
```
67+
For more information on how to create policies, go [here](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).
68+
69+
70+
## Review and customize the function
71+
72+
Review the following files in the current folder:
73+
74+
- [GetObjects.csproj](./GetObjects.csproj) specifies all the dependencies for your function
75+
- [func.yaml](./func.yaml) that contains metadata about your function and declares properties
76+
- [GetObjects.cs](./GetObjects.cs) which is your actual Dotnet function
77+
78+
The name of your function *oci-objectstorage-get-object-dotnet* is specified in [func.yaml](./func.yaml).
79+
80+
81+
## Deploy the function
82+
83+
In Cloud Shell, run the *fn deploy* command to build the function and its dependencies as a Docker image,
84+
push the image to the specified Docker registry, and deploy the function to Oracle Functions
85+
in the application created earlier:
86+
87+
![user input icon](./images/userinput.png)
88+
89+
```
90+
fn -v deploy --app <app-name>
91+
```
92+
e.g.
93+
```
94+
fn -v deploy --app myapp
95+
```
96+
97+
98+
## Test
99+
100+
![user input icon](./images/userinput.png)
101+
```
102+
echo -n <JSON-object> | fn invoke <app-name> <function-name>
103+
```
104+
e.g.
105+
```
106+
echo -n '{"objectName": "<object-name>","bucketName": "<bucket-name>","namespaceName":"<bucket-namespace>", }' | fn invoke myapp oci-objectstorage-get-object-dotnet
107+
```
108+
You should see the contents of the object appear in the terminal.
109+
110+
## Monitoring Functions
111+
112+
Learn how to configure basic observability for your function using metrics, alarms and email alerts:
113+
* [Basic Guidance for Monitoring your Functions](../basic-observability/functions.md)
114+
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-get-object-dotnet
3+
version: 0.0.67
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: GetObjects:Function:function_handler
8+
entrypoint: dotnet GetObjects.dll
Loading

samples/oci-objectstorage-list-objects-dotnet/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ It returns a list of objects from a given bucket in Object Storage.
66

77
The function calls the following OCI Dotnet SDK classes:
88
* [Resource Principals](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.Common.Auth.ResourcePrincipalAuthenticationDetailsProvider.html) to authenticate
9-
* [Identity Client](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.IdentityService.IdentityClient.html) to interact with Identity and Access Management
9+
* [Object Storage Client](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.ObjectstorageService.ObjectStorageClient.html) to interact with Object Storage
1010

1111
As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
1212
Whenever you see it, it's time for you to perform an action.

0 commit comments

Comments
 (0)