fn: support for dotnet (#326)

* Add initial support for dotnet

* Initial work on dotnet example

* fn: fix docker incantation

* fn: .gitignore

* Add README.md for dotnet example

* Update docs
This commit is contained in:
Seif Lotfy سيف لطفي
2016-12-05 23:13:52 +01:00
committed by C Cirello
parent 52d0dc941c
commit 717d8455e9
8 changed files with 186 additions and 0 deletions

3
examples/hash/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
dotnet.*
func.yaml
project.lock.json

53
examples/hash/README.md Normal file
View File

@@ -0,0 +1,53 @@
# Using dotnet with functions
Make sure you downloaded and installed [dotnet](https://www.microsoft.com/net/core). Now create an empty dotnet project in the directory of your function:
```bash
dotnet new
```
By default dotnet creates a ```Program.cs``` file with a main method. To make it work with IronFunction's `fn` tool please rename it to ```func.cs```.
Now change the code as you desire to do whatever magic you need it to do. Once done you can now create an iron function out of it.
## Creating an IronFunction
Simply run
```bash
fn init <username>/<funcname>
```
This will create the ```func.yaml``` file required by functions, which can be built by running:
## Push to docker
```bash
fn push
```
This will create a docker image and push the image to docker.
## Publishing to IronFunctions
```bash
fn routes create <app_name>
```
This creates a full path in the form of `http://<host>:<port>/r/<app_name>/<function>`
## Testing
```bash
fn run
```
## Calling
```bash
fn call <app_name> <funcname>
```
or
```bash
curl http://<host>:<port>/r/<app_name>/<function>
```

65
examples/hash/func.cs Executable file
View File

@@ -0,0 +1,65 @@
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
// if nothing is being piped in, then exit
if (!IsPipedInput())
return;
var input = Console.In.ReadToEnd();
var stream = DownloadRemoteImageFile(input);
var hash = CreateChecksum(stream);
Console.WriteLine(hash);
}
private static bool IsPipedInput()
{
try
{
bool isKey = Console.KeyAvailable;
return false;
}
catch
{
return true;
}
}
private static byte[] DownloadRemoteImageFile(string uri)
{
var request = System.Net.WebRequest.CreateHttp(uri);
var response = request.GetResponseAsync().Result;
var stream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
stream.CopyTo(ms);
return ms.ToArray();
}
}
private static string CreateChecksum(byte[] stream)
{
using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(stream);
var sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < hash.Length; i++)
{
sBuilder.Append(hash[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
}
}
}

19
examples/hash/project.json Executable file
View File

@@ -0,0 +1,19 @@
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.1": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.1.0"
}
},
"imports": "dnxcore50"
}
}
}

View File

@@ -132,6 +132,7 @@ var acceptableFnRuntimes = map[string]string{
"ruby": "iron/ruby", "ruby": "iron/ruby",
"scala": "iron/scala", "scala": "iron/scala",
"rust": "corey/rust-alpine", "rust": "corey/rust-alpine",
"dotnet": "microsoft/dotnet:runtime",
} }
const tplDockerfile = `FROM {{ .BaseImage }} const tplDockerfile = `FROM {{ .BaseImage }}

View File

@@ -28,6 +28,7 @@ var (
".rb": "ruby", ".rb": "ruby",
".py": "python", ".py": "python",
".rs": "rust", ".rs": "rust",
".cs": "dotnet",
} }
fnInitRuntimes []string fnInitRuntimes []string

View File

@@ -15,6 +15,8 @@ func GetLangHelper(lang string) (LangHelper, error) {
return &PythonHelper{}, nil return &PythonHelper{}, nil
case "rust": case "rust":
return &RustLangHelper{}, nil return &RustLangHelper{}, nil
case "dotnet":
return &DotNetLangHelper{}, nil
} }
return nil, fmt.Errorf("No language helper found for %v", lang) return nil, fmt.Errorf("No language helper found for %v", lang)
} }

42
fn/langs/dotnet.go Normal file
View File

@@ -0,0 +1,42 @@
package langs
import (
"fmt"
"os"
"os/exec"
)
type DotNetLangHelper struct{}
func (lh *DotNetLangHelper) Entrypoint() string {
return "dotnet dotnet.dll"
}
func (lh *DotNetLangHelper) HasPreBuild() bool {
return true
}
// PreBuild for Go builds the binary so the final image can be as small as possible
func (lh *DotNetLangHelper) PreBuild() error {
wd, err := os.Getwd()
if err != nil {
return err
}
cmd := exec.Command(
"docker", "run",
"--rm", "-v",
wd+":/dotnet", "-w", "/dotnet", "microsoft/dotnet",
"/bin/sh", "-c", "dotnet restore && dotnet publish -c release -b /tmp -o .",
)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return fmt.Errorf("error running docker build: %v", err)
}
return nil
}
func (lh *DotNetLangHelper) AfterBuild() error {
return nil
}