Skip to content

added copy object dotnet function #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ This repository provides examples demonstrating how to use Oracle Functions.
| 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)|
| 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)|
| Create a PAR in OCI Object Storage |[sample](./samples/oci-objectstorage-create-par-python)||[sample](./samples/oci-objectstorage-create-par-dotnet)|
| Copy object from one OCI Object Storage bucket to another |[sample](./samples/oci-objectstorage-copy-objects-python)||
| Copy object from one OCI Object Storage bucket to another |[sample](./samples/oci-objectstorage-copy-objects-python)||[sample](./samples/oci-objectstorage-copy-objects-dotnet)|
| Display an OCI Cloud Event |[sample](./samples/oci-event-display-python)|
| Invoke another Function using the OCI SDK |[sample](./samples/oci-invoke-function-python)|||
| Run a SQL statement against Autonomous DB using ORDS | [sample](./samples/oci-adb-ords-runsql-python) |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

using System;
using System.Threading.Tasks;
using System.Text;

using Oci.Common;
using Oci.Common.Auth;
using Oci.ObjectstorageService;


namespace CopyObjects
{
public class ObjectStorageClientHelper
{
public static ObjectStorageClient GetObjectStorageClient()
{
try
{
return new ObjectStorageClient(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 ObjectStorageClient(new InstancePrincipalsAuthenticationDetailsProvider(), new ClientConfiguration());
}
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

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.ObjectstorageService;
using Oci.ObjectstorageService.Models;
using Oci.ObjectstorageService.Requests;
using Oci.ObjectstorageService.Responses;


namespace CopyObjects
{
public class CopyObjectsHelper
{
public static async Task<string> CopyObject(ObjectStorageClient client, string src_bucketName, string dest_bucketName, string namespaceName, string objectName)

{

try
{

var copyObjectDetails = new Oci.ObjectstorageService.Models.CopyObjectDetails
{
DestinationBucket = dest_bucketName,
DestinationNamespace = namespaceName,
SourceObjectName = objectName,
DestinationObjectName = objectName,
DestinationRegion = Environment.GetEnvironmentVariable("REGION"),
};

var copyObjectRequest = new Oci.ObjectstorageService.Requests.CopyObjectRequest
{
NamespaceName = namespaceName,
BucketName = src_bucketName,
CopyObjectDetails = copyObjectDetails,
};

var response = await client.CopyObject(copyObjectRequest);
var opcWorkRequestIdValue = response.OpcWorkRequestId;

return opcWorkRequestIdValue;

}

catch (OciException ex)
{
Console.WriteLine("Unable To Put Object : {0}", ex.Message);
return "Failed " + ex.Message;
}

}


}
}
43 changes: 43 additions & 0 deletions samples/oci-objectstorage-copy-objects-dotnet/CopyObjects.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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 Newtonsoft.Json;
using Oci.ObjectstorageService;
using Oci.ObjectstorageService.Models;

namespace CopyObjects
{
class Function
{
public string function_handler(String input)
{

Dictionary<string, List<ObjectDetails>> output = new Dictionary<string, List<ObjectDetails>>();
var object_details_list = new List<ObjectDetails>();

dynamic event_json = JsonConvert.DeserializeObject(input);

string src_bucketName = event_json.data.additionalDetails["bucketName"];
string dest_bucketName = event_json.data.additionalDetails["bucketName"] + "_IMMUTABLE";
string namespaceName = event_json.data.additionalDetails["namespace"];
string objectName = event_json.data.resourceName;

ObjectStorageClient client = ObjectStorageClientHelper.GetObjectStorageClient();
Task<string> object_str = CopyObjectsHelper.CopyObject(client, src_bucketName, dest_bucketName, namespaceName, objectName);
var object_detail = new ObjectDetails();
object_detail.result = object_str.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]); }

}
}
18 changes: 18 additions & 0 deletions samples/oci-objectstorage-copy-objects-dotnet/CopyObjects.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Fnproject.Fn.Fdk" Version="1.0.4" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="OCI.DotNetSDK.Common" Version="42.1.0" />
<PackageReference Include="OCI.DotNetSDK.Objectstorage" Version="42.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta1" />
</ItemGroup>

</Project>
11 changes: 11 additions & 0 deletions samples/oci-objectstorage-copy-objects-dotnet/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM fnproject/dotnet:3.1-1.0.4-dev as build-stage
WORKDIR /function
COPY . .
RUN dotnet sln add CopyObjects.csproj
RUN dotnet build CopyObjects.csproj -c Release
RUN dotnet publish CopyObjects.csproj -c Release -o out
FROM fnproject/dotnet:3.1-1.0.4
WORKDIR /function
COPY --from=build-stage /function/out/ /function/
ENTRYPOINT ["dotnet", "CopyObjects.dll"]
CMD ["CopyObjects:Function:function_handler"]
17 changes: 17 additions & 0 deletions samples/oci-objectstorage-copy-objects-dotnet/Function.sln
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;

namespace CopyObjects
{

class InputMessage
{
public string objectName { get; set; }
public string bucketName { get; set; }
public string namespaceName { get; set; }

public string content { get; set; }

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace CopyObjects
{

class ObjectDetails
{

public string result { get; set; }


}

}
157 changes: 157 additions & 0 deletions samples/oci-objectstorage-copy-objects-dotnet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Function that copies an object in an OCI Object Storage bucket to another bucket using the OCI Dotnet SDK
This function can be used to create *"Immutable Copies"* of objects in an OCI bucket by copying them, during creation/update, to another bucket with defined retention policies. This is especially useful when using the [Oracle Backup Cloud Service](https://docs.oracle.com/en/cloud/paas/db-backup-cloud/csdbb/oracle-database-backup-cloud-service.html) to ensure backups are maintained for a specified amount of time.


This function uses Resource Principals to securely authorize a function to make
API calls to OCI services using the [OCI Dotnet SDK](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/index.html).
It creates an object in a bucket in Object Storage and returns a message with a status.


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

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

1. Before you deploy this sample function, make sure you have run steps 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

2. Have your Oracle Object Storage Namespace available. This can be found by
logging into your [cloud account](https://console.us-ashburn-1.oraclecloud.com/),
under your user profile, click on your Tenancy. Your Object Storage Namespace
is shown there.


## List Applications

Assuming you 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'}
```


## Create or Update IAM Policies

Create a new policy that allows the dynamic group to `manage objects` and `manage buckets` in the functions related compartment.

![user input icon](./images/userinput.png)

Your policy should look something like this:
```
Allow service objectstorage-<region> to manage object-family in compartment <compartment-name>
Allow dynamic-group <dynamic-group-name> to manage objects in compartment <compartment-name>
Allow dynamic-group <dynamic-group-name> to manage buckets in compartment <compartment-name>
```
e.g.
```
Allow service objectstorage-eu-frankfurt-1 to manage object-family in compartment demo-func-compartment
Allow dynamic-group demo-func-dyn-group to manage objects in compartment demo-func-compartment
Allow dynamic-group demo-func-dyn-group to manage buckets in compartment demo-func-compartment
```
For more information on how to create policies, go [here](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).


## Review and customize the function

Review the following files in the current folder:

- [CopyObjects.csproj](./CopyObjects.csproj) specifies all the dependencies for your function
- [func.yaml](./func.yaml) that contains metadata about your function and declares properties
- [CopyObjects.cs](./CopyObjects.cs) which is your actual Python function

The name of your function *oci-objectstorage-copy-objects-dotnet* is specified in [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 the specified Docker registry, and deploy the function to Oracle Functions
in the application created earlier:

![user input icon](./images/userinput.png)

```
fn -v deploy --app <app-name>
```
e.g.
```
fn -v deploy --app myapp
```

## Set the function configuration values
The function requires the config value *REGION* to be set.

![user input icon](./images/userinput.png)

Use the *fn* CLI to set the config value:
```
fn config function <app-name> <function-name> REGION <region>
```
e.g.
```
fn config function myapp oci-objectstorage-create-par-dotnet REGION 'eu-frankfurt-1'
```

## Create Object Store Buckets

![user input icon](./images/userinput.png)

From the OCI Console > Storage > Object Storage > Create Bucket with bucket name = "TEST" and enable "Emit Object Events"

From the OCI Console > Storage > Object Storage > Create Bucket with bucket name = "TEST_IMMUTABLE" and apply a retention policy

## Create an Event Rule on Bucket

![user input icon](./images/userinput.png)

From the OCI Console > Observability & Management > Event Service > Create Rule:

Display Name: IMMUTABLE-OBJECT_STORE
Rule Conditions:
Event Type: Object Storage: Object - Create; Object - Update
Attribute: bucketName: TEST
Actions (<app-name> as per the `fn -v deploy --app <app-name>`) :
Function: (root): <app-name>

![event](./images/create_rule.png)

## Test

![user input icon](./images/userinput.png)

From the OCI Console > Storage > Object Storage > TEST

Objects -> Upload; Drop file to upload

From the OCI Console > Storage > Object Storage > TEST_IMMUTABLE

__The file uploaded to the TEST bucket should now be present in the TEST_IMMUTABLE bucket.__


## Monitoring Functions

Learn how to configure basic observability for your function using metrics, alarms and email alerts:
* [Basic Guidance for Monitoring your Functions](../basic-observability/functions.md)

8 changes: 8 additions & 0 deletions samples/oci-objectstorage-copy-objects-dotnet/func.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
schema_version: 20180708
name: oci-objectstorage-copy-objects-dotnet
version: 0.0.84
runtime: dotnet3.1
build_image: fnproject/dotnet:3.1-1.0.4-dev
run_image: fnproject/dotnet:3.1-1.0.4
cmd: CopyObjects:Function:function_handler
entrypoint: dotnet CopyObjects.dll
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.