Skip to content

Commit

Permalink
Support array result include sequence action (#65)
Browse files Browse the repository at this point in the history
* Support array result

* Add test case

* Add another test case

* Add document for support array result
  • Loading branch information
ningyougang authored Aug 16, 2022
1 parent fdfe9c8 commit 24995db
Show file tree
Hide file tree
Showing 8 changed files with 276 additions and 6 deletions.
99 changes: 99 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,105 @@

[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)
[![Build Status](https://travis-ci.com/apache/openwhisk-runtime-dotnet.svg?branch=master)](https://travis-ci.com/github/apache/openwhisk-runtime-dotnet)
## Give it a try today

Create a C# project called Apache.OpenWhisk.Example.Dotnet:

```bash
dotnet new classlib -n Apache.OpenWhisk.Example.Dotnet -lang "C#"
cd Apache.OpenWhisk.Example.Dotnet
```

Install the [Newtonsoft.Json](https://www.newtonsoft.com/json) NuGet package as follows:

```bash
dotnet add package Newtonsoft.Json -v 12.0.1
```

Now create a file called `Hello.cs` with the following content:

```csharp
using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Example.Dotnet
{
public class Hello
{
public JObject Main(JObject args)
{
string name = "stranger";
if (args.ContainsKey("name")) {
name = args["name"].ToString();
}
JObject message = new JObject();
message.Add("greeting", new JValue($"Hello, {name}!"));
return (message);
}
}
}
```
Publish the project as follows:

```bash
dotnet publish -c Release -o out
```

Zip the published files as follows:

```bash
cd out
zip -r -0 helloDotNet.zip *
```

Create the action

```bash
wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:2.2
```

For the return result, not only support `dictionary` but also support `array`

So a very simple `hello array` function would be:

```csharp
using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloArray
{
public JArray Main(JObject args)
{
JArray jarray = new JArray();
jarray.Add("a");
jarray.Add("b");
return (jarray);
}
}
}
```

And support array result for sequence action as well, the first action's array result can be used as next action's input parameter.

So the function can be:

```csharp
using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloPassArrayParam
{
public JArray Main(JArray args)
{
return (args);
}
}
}
```

## Changelogs

Expand Down
18 changes: 15 additions & 3 deletions core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public async Task HandleRequest(HttpContext httpContext)
JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body);

JObject valObject = null;
JArray valArray = null;

if (inputObject != null)
{
Expand All @@ -76,18 +77,29 @@ await Console.Error.WriteLineAsync(
}
}
}
if (valObject == null) {
valArray = inputObject["value"] as JArray;
}

object owObject = _constructor.Invoke(new object[] { });

try
{
JObject output;
JContainer output;

if(_awaitableMethod) {
output = (JObject) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valArray});
}
}
else {
output = (JObject) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) _method.Invoke(owObject, new object[] {valArray});
}
}

if (output == null)
Expand Down
18 changes: 15 additions & 3 deletions core/dotnet3.1/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public async Task HandleRequest(HttpContext httpContext)
JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body);

JObject valObject = null;
JArray valArray = null;

if (inputObject != null)
{
Expand All @@ -75,19 +76,30 @@ await Console.Error.WriteLineAsync(
$"Unable to set environment variable for the \"{token.Path}\" token.");
}
}
if (valObject == null) {
valArray = inputObject["value"] as JArray;
}
}

object owObject = _constructor.Invoke(new object[] { });

try
{
JObject output;
JContainer output;

if(_awaitableMethod) {
output = (JObject) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valArray});
}
}
else {
output = (JObject) _method.Invoke(owObject, new object[] {valObject});
if (valObject != null) {
output = (JContainer) _method.Invoke(owObject, new object[] {valObject});
} else {
output = (JContainer) _method.Invoke(owObject, new object[] {valArray});
}
}

if (output == null)
Expand Down
33 changes: 33 additions & 0 deletions tests/dotnetshared/HelloArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloArray
{
public JArray Main(JObject args)
{
JArray jarray = new JArray();
jarray.Add("a");
jarray.Add("b");
return (jarray);
}
}
}
30 changes: 30 additions & 0 deletions tests/dotnetshared/HelloPassArrayParam.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

using System;
using Newtonsoft.Json.Linq;

namespace Apache.OpenWhisk.Tests.Dotnet
{
public class HelloPassArrayParam
{
public JArray Main(JArray args)
{
return (args);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,32 @@ class DotNet2_2ActionContainerTests extends BasicActionRunnerTests with WskActor
(o + e).toLowerCase should include("the action returned null")
})
}

it should "support return array result" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloArray::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsObject()))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}

it should "support array as input param" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(
functionb64,
"Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloPassArrayParam::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsArray(JsString("a"), JsString("b"))))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,32 @@ class DotNet3_1ActionContainerTests extends BasicActionRunnerTests with WskActor
(o + e).toLowerCase should include("the action returned null")
})
}

it should "support return array result" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloArray::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsObject()))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}

it should "support array as input param" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(
functionb64,
"Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloPassArrayParam::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsArray(JsString("a"), JsString("b"))))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,32 @@ class DotNet3_1ActionContainerTests_2_2 extends BasicActionRunnerTests with WskA
(o + e).toLowerCase should include("the action returned null")
})
}

it should "support return array result" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloArray::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsObject()))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}

it should "support array as input param" in {
val (out, err) = withActionContainer() { c =>
val (initCode, _) =
c.init(
initPayload(
functionb64,
"Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.HelloPassArrayParam::Main"))
initCode should be(200)

val (runCode, runRes) = c.runForJsArray(runPayload(JsArray(JsString("a"), JsString("b"))))
runCode should be(200)
runRes shouldBe Some(JsArray(JsString("a"), JsString("b")))
}
}
}

0 comments on commit 24995db

Please sign in to comment.