Skip to content

Added List compartment dotnet function #2

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 6 commits into from
Sep 28, 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ This repository provides examples demonstrating how to use Oracle Functions.
|------------------------------------------------------|:------:|:----:|:----:|
| Hello World |[sample](./samples/helloworld)|[sample](./samples/helloworld)|[sample](./samples/helloworld)|
| List OCI Compute instances |[sample](./samples/oci-list-instances-python)|[sample](./samples/oci-list-instances-java)|[sample](./samples/oci-list-instances-dotnet)|
| Control OCI Compute instances (start/stop/status) |[sample](./samples/oci-compute-control-python)|
| List OCI compartments |[sample](./samples/oci-list-compartments-python)|
| Control OCI Compute instances (start/stop/status) |[sample](./samples/oci-compute-control-python)||[sample](./samples/oci-compute-control-dotnet)|
| List OCI compartments |[sample](./samples/oci-list-compartments-python)||[sample](./samples/oci-list-compartments-dotnet)|
| List objects in OCI Object Storage |[sample](./samples/oci-objectstorage-list-objects-python)|[sample](./samples/oci-objectstorage-list-objects-java)|
| Read an object in OCI Object Storage |[sample](./samples/oci-objectstorage-get-object-python)|[sample](./samples/oci-objectstorage-get-object-java)|
| Create an object in OCI Object Storage |[sample](./samples/oci-objectstorage-put-object-python)|[sample](./samples/oci-objectstorage-put-object-java)|
Expand Down
29 changes: 29 additions & 0 deletions samples/oci-compute-control-dotnet/Common/ComputeClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

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

using Oci.Common;
using Oci.Common.Auth;
using Oci.CoreService;


namespace ControlInstance
{
public class ComputeClientHelper
{
public static ComputeClient GetComputeClient()
{
try{

return new ComputeClient(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 ComputeClient(new InstancePrincipalsAuthenticationDetailsProvider(), new ClientConfiguration());
}
}

}
}
56 changes: 56 additions & 0 deletions samples/oci-compute-control-dotnet/ControlInstance.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
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.CoreService;

namespace ControlInstance
{
class Function
{
public string function_handler(InputMessage input)
{
string command;
string instance_ocid;
Dictionary<string, string> output = new Dictionary<string, string>();
try{
command=input.command.ToLower();
instance_ocid=input.instance_ocid;
ComputeClient client = ComputeClientHelper.GetComputeClient();
if (command=="status")
{
Task<string> instance_state = ComputeController.GetComputeStatus(client,instance_ocid);
output.Add("result", instance_state.Result);
}
else if (command=="start")
{
Task<string> instance_state = ComputeController.StartCompute(client,instance_ocid);
output.Add("result", instance_state.Result);
}
else if (command=="stop")
{
Task<string> instance_state = ComputeController.StopCompute(client,instance_ocid);
output.Add("result", instance_state.Result);
}
else
{
output.Add("result", "Invalid Command");
}

return JsonSerializer.Serialize(output);

}
catch(Exception ex){
Console.WriteLine($"Invalid Payload: {ex.Message}");
output.Add("result", "Invalid Payload");
return JsonSerializer.Serialize(output);
}
}

static void Main(string[] args) { Fdk.Handle(args[0]); }

}
}
18 changes: 18 additions & 0 deletions samples/oci-compute-control-dotnet/ControlInstance.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.Core" Version="42.1.0" />
<PackageReference Include="OCI.DotNetSDK.Identity" Version="42.1.0" />
</ItemGroup>

</Project>
94 changes: 94 additions & 0 deletions samples/oci-compute-control-dotnet/Controller/ComputeController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

using System;
using System.Threading.Tasks;
using System.Text;
using Oci.Common.Model;
using Oci.Common;
using Oci.Common.Auth;
using Oci.CoreService;
using Oci.CoreService.Models;
using Oci.CoreService.Requests;
using Oci.CoreService.Responses;

namespace ControlInstance
{
public class ComputeController
{
public static async Task<string> GetComputeStatus(ComputeClient client,string instance_ocid)
{
try
{
var getInstanceRequest = new Oci.CoreService.Requests.GetInstanceRequest
{
InstanceId = instance_ocid
};

var getInstancesResponse = await client.GetInstance(getInstanceRequest);
return getInstancesResponse.Instance.LifecycleState.ToString();
}
catch (OciException ex)
{
return ex.ServiceCode;
}
}

public static async Task<string> StartCompute(ComputeClient client,string instance_ocid)
{
Console.WriteLine($"Starting Instance Id: {instance_ocid}");
try
{
if (GetComputeStatus(client,instance_ocid).Result == "Stopped" )
{
var instanceActionRequest = new Oci.CoreService.Requests.InstanceActionRequest
{
InstanceId = instance_ocid,
Action = "START",
};

var getInstancesResponse = await client.InstanceAction(instanceActionRequest);
Console.WriteLine($"Start Response Code : {getInstancesResponse.Instance.LifecycleState.ToString()}");
return GetComputeStatus(client,instance_ocid).Result;
}
else
{
Console.WriteLine($"Instance Is Already Running");
return "Instance Is Already Running";
}
}
catch (OciException ex)
{
return ex.Message;
}
}

public static async Task<string> StopCompute(ComputeClient client,string instance_ocid)
{
Console.WriteLine($"Stopping Instance Id: {instance_ocid}");
try
{
if (GetComputeStatus(client,instance_ocid).Result == "Running" )
{
var instanceActionRequest = new Oci.CoreService.Requests.InstanceActionRequest
{
InstanceId = instance_ocid,
Action = "STOP",
};

var getInstancesResponse = await client.InstanceAction(instanceActionRequest);
Console.WriteLine($"Stop Response Code : {getInstancesResponse.Instance.LifecycleState.ToString()}");
return GetComputeStatus(client,instance_ocid).Result;
}
else
{
Console.WriteLine($"Instance Is Already Stopped");
return "Instance Is Already Stopped";
}
}
catch (OciException ex)
{
return ex.Message;
}
}

}
}
11 changes: 11 additions & 0 deletions samples/oci-compute-control-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 ControlInstance.csproj
RUN dotnet build ControlInstance.csproj -c Release
RUN dotnet publish ControlInstance.csproj -c Release -o out
FROM fnproject/dotnet:3.1-1.0.4
WORKDIR /function
COPY --from=build-stage /function/out/ /function/
ENTRYPOINT ["dotnet", "ControlInstance.dll"]
CMD ["ControlInstance:Function:function_handler"]
17 changes: 17 additions & 0 deletions samples/oci-compute-control-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
14 changes: 14 additions & 0 deletions samples/oci-compute-control-dotnet/Models/InputMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace ControlInstance
{

class InputMessage
{
public string command { get; set; }

public string instance_ocid { get; set; }

}

}
111 changes: 111 additions & 0 deletions samples/oci-compute-control-dotnet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Function that controls a Compute instance

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/iaas/tools/dotnet/latest/api/index.html).
It returns a list of all instances within the compartment that calls the function.

The function calls the following OCI Dotnet SDK classes:
* [ResourcePrincipalAuthenticationDetailsProvider](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.Common.Auth.ResourcePrincipalAuthenticationDetailsProvider.html) to authenticate
* [ComputeClient](https://docs.oracle.com/en-us/iaas/tools/dotnet/latest/api/Oci.CoreService.ComputeClient.html) to interact with Compute

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 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


## 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 `inspect instances` in
the functions related compartment.

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

Your policy should look something like this:
```
Allow dynamic-group <dynamic-group-name> to inspect instances in compartment <compartment-name>
```
e.g.
```
Allow dynamic-group demo-func-dyn-group to inspect instances 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 your function

Review the following files in the current folder:
- [ControlInstance.csproj](./ControlInstance.csproj) specifies all the dependencies for your function
- [func.yaml](./func.yaml) that contains metadata about your function and declares properties
- [ControlInstance.cs](./ControlInstance.cs) which contains the Dotnet code

The name of your function *oci-compute-control-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
```


## Test

Use the *fn* CLI to invoke your function with your app name and the compartment OCID:

![user input icon](./images/userinput.png)
```
echo '{"command":"<command>", "instance_ocid":"<instance-ocid>"}' | fn invoke <app-name> <function-name>
```
e.g.
```
echo '{"command":"stop", "instance_ocid":"ocid1.fnfunc.oc1.iad.aaaaaxxxxx"}' | fn invoke myapp oci-compute-control-dotnet
```
The supported values for command are "status", "start" and "stop".


## 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-compute-control-dotnet/func.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
schema_version: 20180708
name: oci-compute-control-dotnet
version: 0.0.2
runtime: dotnet3.1
build_image: fnproject/dotnet:3.1-1.0.4-dev
run_image: fnproject/dotnet:3.1-1.0.4
cmd: ControlInstance:Function:function_handler
entrypoint: dotnet ControlInstance.dll
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading