diff --git a/.travis.yml b/.travis.yml
index c387cf7..bdc9c4a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,7 +16,7 @@
#
sudo: required
-group: deprecated-2017Q3
+dist: xenial
language: scala
scala:
- 2.12.7
@@ -41,7 +41,7 @@ deploy:
all_branches: true
repo: apache/openwhisk-runtime-dotnet
- provider: script
- script: "./tools/travis/publish.sh openwhisk 2.2 nightly"
+ script: "./tools/travis/publish.sh openwhisk 2.2 nightly && ./tools/travis/publish.sh openwhisk 3.0 nightly"
on:
branch: master
repo: apache/openwhisk-runtime-dotnet
diff --git a/README.md b/README.md
index 6e87b8a..a529e1f 100644
--- a/README.md
+++ b/README.md
@@ -23,157 +23,15 @@
[](https://travis-ci.org/apache/openwhisk-runtime-dotnet)
## Changelogs
-- [.NET Core 2.2 CHANGELOG.md](core/dotnet2.2/CHANGELOG.md)
-
-
-## Quick .NET Core Action
-A .NET Core action is a .NET Core class library with a method called `Main` that has the exact signature as follows:
-
-```csharp
-public Newtonsoft.Json.Linq.JObject Main(Newtonsoft.Json.Linq.JObject);
-```
-
-In order to compile, test and archive .NET Core projects, you must have the [.NET Core SDK](https://www.microsoft.com/net/download) installed locally and the environment variable `DOTNET_HOME` set to the location where the `dotnet` executable can be found.
-
-For example, 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.bin *
-```
-
-You need to specify the name of the function handler using `--main` argument.
-The value for `main` needs to be in the following format:
-`{Assembly}::{Class Full Name}::{Method}`, e.q.,
-`Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main`
-
-### Create the .NET Core Action
-To use on a deployment of OpenWhisk that contains the runtime as a kind:
-```bash
-wsk action update helloDotNet helloDotNet.bin --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:2.2
-```
-
-### Invoke the .NET Core Action
-Action invocation is the same for .NET Core actions as it is for Swift and JavaScript actions:
-
-```bash
-wsk action invoke --result helloDotNet --param name World
-```
-
-```json
- {
- "greeting": "Hello World!"
- }
-```
-
-## Local development
-```bash
-./gradlew core:dotnet2.2:distDocker
-```
-This will produce the image `whisk/action-dotnet-v2.2`
-
-Build and Push image
-```bash
-docker login
-./gradlew core:action-dotnet-v2.2:distDocker -PdockerImagePrefix=$prefix-user -PdockerRegistry=docker.io
-```
-
-Deploy OpenWhisk using ansible environment that contains the kind `dotnet:2.2`
-Assuming you have OpenWhisk already deploy localy and `OPENWHISK_HOME` pointing to root directory of OpenWhisk core repository.
-
-Set `ROOTDIR` to the root directory of this repository.
-
-Redeploy OpenWhisk
-```bash
-cd $OPENWHISK_HOME/ansible
-ANSIBLE_CMD="ansible-playbook -i ${ROOTDIR}/ansible/environments/local"
-$ANSIBLE_CMD setup.yml
-$ANSIBLE_CMD couchdb.yml
-$ANSIBLE_CMD initdb.yml
-$ANSIBLE_CMD wipe.yml
-$ANSIBLE_CMD openwhisk.yml
-```
-
-Or you can use `wskdev` and create a soft link to the target ansible environment, for example:
-```
-ln -s ${ROOTDIR}/ansible/environments/local ${OPENWHISK_HOME}/ansible/environments/local-dotnet
-wskdev fresh -t local-dotnet
-```
-
-### Testing
-Install dependencies from the root directory on $OPENWHISK_HOME repository
-```bash
-pushd $OPENWHISK_HOME
-./gradlew install
-podd $OPENWHISK_HOME
-```
+- [.NET Core 2.2 CHANGELOG.md](core/dotnet2.2/CHANGELOG.md)
+- [.NET Core 3.0 CHANGELOG.md](core/dotnet3.0/CHANGELOG.md)
-Using gradle to run all tests
-```bash
-./gradlew :tests:test
-```
-Using gradle to run some tests
-```bash
-./gradlew :tests:test --tests *ActionContainerTests*
-```
-Using IntelliJ:
-- Import project as gradle project.
-- Make sure working directory is root of the project/repo
+## Quick Start Guides
-#### Using container image to test
-To use as docker action push to your own dockerhub account
-```bash
-docker tag whisk/action-dotnet-v2.2 $user_prefix/action-dotnet-v2.2
-docker push $user_prefix/action-dotnet-v2.2
-```
-Then create the action using your the image from dockerhub
-```bash
-wsk action update helloDotNet helloDotNet.bin --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --docker $user_prefix/action-dotnet-v2.2
-```
-The `$user_prefix` is usually your dockerhub user id.
+- [.NET Core 2.2](core/dotnet2.2/QUICKSTART.md)
+- [.NET Core 3.0](core/dotnet3.0/QUICKSTART.md)
# License
+
[Apache 2.0](LICENSE.txt)
diff --git a/core/dotnet2.2/CHANGELOG.md b/core/dotnet2.2/CHANGELOG.md
index dc50cac..c530536 100644
--- a/core/dotnet2.2/CHANGELOG.md
+++ b/core/dotnet2.2/CHANGELOG.md
@@ -20,6 +20,6 @@
# .NET Core 2.2 OpenWhisk Runtime Container
-## 1.13 (next Apache release)
+## 1.13
Changes:
- Initial release
diff --git a/core/dotnet2.2/Dockerfile b/core/dotnet2.2/Dockerfile
index 21b9816..70f1067 100644
--- a/core/dotnet2.2/Dockerfile
+++ b/core/dotnet2.2/Dockerfile
@@ -15,7 +15,7 @@
# limitations under the License.
#
-FROM microsoft/dotnet:2.2-sdk-alpine AS build
+FROM mcr.microsoft.com/dotnet/core/sdk:2.2-alpine AS build
WORKDIR /app
COPY proxy/Apache.OpenWhisk.Runtime.Common/*.csproj ./Apache.OpenWhisk.Runtime.Common/
@@ -26,9 +26,9 @@ RUN dotnet restore
COPY proxy/Apache.OpenWhisk.Runtime.Common/. ./Apache.OpenWhisk.Runtime.Common/
COPY proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/. ./Apache.OpenWhisk.Runtime.Dotnet.Minimal/
WORKDIR /app/Apache.OpenWhisk.Runtime.Dotnet.Minimal
-RUN dotnet publish -c Release -r alpine.3.7-x64 -o out
+RUN dotnet publish -c Release -r alpine.3.9-x64 -o out
-FROM microsoft/dotnet:2.2-runtime-alpine AS runtime
+FROM mcr.microsoft.com/dotnet/core/runtime:2.2-alpine AS runtime
WORKDIR /app
COPY --from=build /app/Apache.OpenWhisk.Runtime.Dotnet.Minimal/out ./
ENV ASPNETCORE_URLS http://+:8080
diff --git a/core/dotnet2.2/QUICKSTART.md b/core/dotnet2.2/QUICKSTART.md
new file mode 100644
index 0000000..7b67b54
--- /dev/null
+++ b/core/dotnet2.2/QUICKSTART.md
@@ -0,0 +1,192 @@
+
+
+# Quick .NET Core 2.2 Action
+
+A .NET Core action is a .NET Core class library with a method called `Main` that has the exact signature as follows:
+
+```csharp
+public Newtonsoft.Json.Linq.JObject Main(Newtonsoft.Json.Linq.JObject);
+```
+
+In order to compile, test and archive .NET Core projects, you must have the [.NET Core SDK](https://www.microsoft.com/net/download) installed locally and the environment variable `DOTNET_HOME` set to the location where the `dotnet` executable can be found.
+
+For example, create a C# project called `Apache.OpenWhisk.Example.Dotnet`:
+
+```bash
+dotnet new classlib -n Apache.OpenWhisk.Example.Dotnet -lang C# -f netstandard2.0
+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.2
+```
+
+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 *
+```
+
+You need to specify the name of the function handler using `--main` argument.
+The value for `main` needs to be in the following format:
+`{Assembly}::{Class Full Name}::{Method}`, e.q.,
+`Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main`
+
+## Create the .NET Core Action
+
+To use on a deployment of OpenWhisk that contains the runtime as a kind:
+
+```bash
+wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:2.2
+```
+
+## Invoke the .NET Core Action
+
+Action invocation is the same for .NET Core actions as it is for Swift and JavaScript actions:
+
+```bash
+wsk action invoke --result helloDotNet --param name World
+```
+
+```json
+ {
+ "greeting": "Hello World!"
+ }
+```
+
+## Local Development
+
+```bash
+./gradlew core:dotnet2.2:distDocker
+```
+
+This will produce the image `whisk/action-dotnet-v2.2`
+
+Build and Push image
+
+```bash
+docker login
+./gradlew core:action-dotnet-v2.2:distDocker -PdockerImagePrefix=$prefix-user -PdockerRegistry=docker.io
+```
+
+Deploy OpenWhisk using ansible environment that contains the kind `dotnet:2.2`
+Assuming you have OpenWhisk already deploy localy and `OPENWHISK_HOME` pointing to root directory of OpenWhisk core repository.
+
+Set `ROOTDIR` to the root directory of this repository.
+
+Redeploy OpenWhisk
+
+```bash
+cd $OPENWHISK_HOME/ansible
+ANSIBLE_CMD="ansible-playbook -i ${ROOTDIR}/ansible/environments/local"
+$ANSIBLE_CMD setup.yml
+$ANSIBLE_CMD couchdb.yml
+$ANSIBLE_CMD initdb.yml
+$ANSIBLE_CMD wipe.yml
+$ANSIBLE_CMD openwhisk.yml
+```
+
+Or you can use `wskdev` and create a soft link to the target ansible environment, for example:
+
+```bash
+ln -s ${ROOTDIR}/ansible/environments/local ${OPENWHISK_HOME}/ansible/environments/local-dotnet
+wskdev fresh -t local-dotnet
+```
+
+### Testing
+
+Install dependencies from the root directory on $OPENWHISK_HOME repository
+
+```bash
+pushd $OPENWHISK_HOME
+./gradlew install
+podd $OPENWHISK_HOME
+```
+
+Using gradle to run all tests
+
+```bash
+./gradlew :tests:test
+```
+
+Using gradle to run some tests
+
+```bash
+./gradlew :tests:test --tests DotNet2_2ActionContainerTests
+```
+
+Using IntelliJ:
+
+- Import project as gradle project.
+- Make sure working directory is root of the project/repo
+
+#### Using Container Image To Test
+
+To use as docker action push to your own dockerhub account
+
+```bash
+docker tag whisk/action-dotnet-v2.2 $user_prefix/action-dotnet-v2.2
+docker push $user_prefix/action-dotnet-v2.2
+```
+
+Then create the action using your the image from dockerhub
+
+```bash
+wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --docker $user_prefix/action-dotnet-v2.2
+```
+
+The `$user_prefix` is usually your dockerhub user id.
+
+# License
+
+[Apache 2.0](../../LICENSE.txt)
diff --git a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj
index d667e84..ff84a8d 100644
--- a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj
+++ b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj
@@ -28,7 +28,7 @@
2.2.0
- 12.0.1
+ 12.0.2
diff --git a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj
index ce08efe..2d3a42a 100644
--- a/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj
+++ b/core/dotnet2.2/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj
@@ -21,20 +21,8 @@
netcoreapp2.2
-
-
- 2.2.0
-
-
- 2.2.0
-
-
- 12.0.1
-
-
-
-
+
diff --git a/core/dotnet3.0/CHANGELOG.md b/core/dotnet3.0/CHANGELOG.md
new file mode 100644
index 0000000..9339dd7
--- /dev/null
+++ b/core/dotnet3.0/CHANGELOG.md
@@ -0,0 +1,25 @@
+
+
+# .NET Core 3.0 OpenWhisk Runtime Container
+
+
+## 1.14 (next Apache release)
+Changes:
+- Initial release
diff --git a/core/dotnet3.0/Dockerfile b/core/dotnet3.0/Dockerfile
new file mode 100644
index 0000000..9e9576f
--- /dev/null
+++ b/core/dotnet3.0/Dockerfile
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.0-alpine AS build
+
+WORKDIR /app
+COPY proxy/Apache.OpenWhisk.Runtime.Common/*.csproj ./Apache.OpenWhisk.Runtime.Common/
+COPY proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/*.csproj ./Apache.OpenWhisk.Runtime.Dotnet.Minimal/
+COPY proxy/openwhisk-runtime-dotnet.sln ./openwhisk-runtime-dotnet.sln
+RUN dotnet restore
+
+COPY proxy/Apache.OpenWhisk.Runtime.Common/. ./Apache.OpenWhisk.Runtime.Common/
+COPY proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/. ./Apache.OpenWhisk.Runtime.Dotnet.Minimal/
+WORKDIR /app/Apache.OpenWhisk.Runtime.Dotnet.Minimal
+RUN dotnet publish -c Release -r alpine.3.9-x64 -o out
+
+FROM mcr.microsoft.com/dotnet/core/runtime:3.0-alpine AS runtime
+WORKDIR /app
+COPY --from=build /app/Apache.OpenWhisk.Runtime.Dotnet.Minimal/out ./
+ENV ASPNETCORE_URLS http://+:8080
+EXPOSE 8080/tcp
+ENTRYPOINT ["dotnet", "Apache.OpenWhisk.Runtime.Dotnet.Minimal.dll"]
diff --git a/core/dotnet3.0/QUICKSTART.md b/core/dotnet3.0/QUICKSTART.md
new file mode 100644
index 0000000..c8e720f
--- /dev/null
+++ b/core/dotnet3.0/QUICKSTART.md
@@ -0,0 +1,192 @@
+
+
+# Quick .NET Core 3.0 Action
+
+A .NET Core action is a .NET Core class library with a method called `Main` that has the exact signature as follows:
+
+```csharp
+public Newtonsoft.Json.Linq.JObject Main(Newtonsoft.Json.Linq.JObject);
+```
+
+In order to compile, test and archive .NET Core projects, you must have the [.NET Core SDK](https://www.microsoft.com/net/download) installed locally and the environment variable `DOTNET_HOME` set to the location where the `dotnet` executable can be found.
+
+For example, create a C# project called `Apache.OpenWhisk.Example.Dotnet`:
+
+```bash
+dotnet new classlib -n Apache.OpenWhisk.Example.Dotnet -lang C# -f netstandard2.1
+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.2
+```
+
+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 *
+```
+
+You need to specify the name of the function handler using `--main` argument.
+The value for `main` needs to be in the following format:
+`{Assembly}::{Class Full Name}::{Method}`, e.q.,
+`Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main`
+
+## Create the .NET Core Action
+
+To use on a deployment of OpenWhisk that contains the runtime as a kind:
+
+```bash
+wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --kind dotnet:3.0
+```
+
+## Invoke the .NET Core Action
+
+Action invocation is the same for .NET Core actions as it is for Swift and JavaScript actions:
+
+```bash
+wsk action invoke --result helloDotNet --param name World
+```
+
+```json
+ {
+ "greeting": "Hello World!"
+ }
+```
+
+## Local Development
+
+```bash
+./gradlew core:dotnet3.0:distDocker
+```
+
+This will produce the image `whisk/action-dotnet-v3.0`
+
+Build and Push image
+
+```bash
+docker login
+./gradlew core:action-dotnet-v3.0:distDocker -PdockerImagePrefix=$prefix-user -PdockerRegistry=docker.io
+```
+
+Deploy OpenWhisk using ansible environment that contains the kind `dotnet:3.0`
+Assuming you have OpenWhisk already deploy localy and `OPENWHISK_HOME` pointing to root directory of OpenWhisk core repository.
+
+Set `ROOTDIR` to the root directory of this repository.
+
+Redeploy OpenWhisk
+
+```bash
+cd $OPENWHISK_HOME/ansible
+ANSIBLE_CMD="ansible-playbook -i ${ROOTDIR}/ansible/environments/local"
+$ANSIBLE_CMD setup.yml
+$ANSIBLE_CMD couchdb.yml
+$ANSIBLE_CMD initdb.yml
+$ANSIBLE_CMD wipe.yml
+$ANSIBLE_CMD openwhisk.yml
+```
+
+Or you can use `wskdev` and create a soft link to the target ansible environment, for example:
+
+```bash
+ln -s ${ROOTDIR}/ansible/environments/local ${OPENWHISK_HOME}/ansible/environments/local-dotnet
+wskdev fresh -t local-dotnet
+```
+
+### Testing
+
+Install dependencies from the root directory on $OPENWHISK_HOME repository
+
+```bash
+pushd $OPENWHISK_HOME
+./gradlew install
+podd $OPENWHISK_HOME
+```
+
+Using gradle to run all tests
+
+```bash
+./gradlew :tests:test
+```
+
+Using gradle to run some tests
+
+```bash
+./gradlew :tests:test --tests DotNet3_0ActionContainerTests
+```
+
+Using IntelliJ:
+
+- Import project as gradle project.
+- Make sure working directory is root of the project/repo
+
+#### Using Container Image To Test
+
+To use as docker action push to your own dockerhub account
+
+```bash
+docker tag whisk/action-dotnet-v3.0 $user_prefix/action-dotnet-v3.0
+docker push $user_prefix/action-dotnet-v3.0
+```
+
+Then create the action using your the image from dockerhub
+
+```bash
+wsk action update helloDotNet helloDotNet.zip --main Apache.OpenWhisk.Example.Dotnet::Apache.OpenWhisk.Example.Dotnet.Hello::Main --docker $user_prefix/action-dotnet-v3.0
+```
+
+The `$user_prefix` is usually your dockerhub user id.
+
+# License
+
+[Apache 2.0](../../LICENSE.txt)
diff --git a/core/dotnet3.0/build.gradle b/core/dotnet3.0/build.gradle
new file mode 100644
index 0000000..3d62aac
--- /dev/null
+++ b/core/dotnet3.0/build.gradle
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+ext.dockerImageName = 'action-dotnet-v3.0'
+
+apply from: '../../gradle/docker.gradle'
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj
new file mode 100644
index 0000000..db2338b
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj
@@ -0,0 +1,35 @@
+
+
+
+
+ netcoreapp3.0
+
+
+
+
+ 2.2.0
+
+
+ 2.2.0
+
+
+ 12.0.2
+
+
+
+
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs
new file mode 100644
index 0000000..4f63bd0
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs
@@ -0,0 +1,43 @@
+/*
+ * 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.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Apache.OpenWhisk.Runtime.Common
+{
+ public static class HttpResponseExtension
+ {
+ public static async Task WriteResponse(this HttpResponse response, int code, string content)
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(content);
+ response.ContentLength = bytes.Length;
+ response.StatusCode = code;
+ await response.WriteAsync(content);
+ }
+
+ public static async Task WriteError(this HttpResponse response, string errorMessage)
+ {
+ JObject message = new JObject {{"error", new JValue(errorMessage)}};
+ await WriteResponse(response, 502, JsonConvert.SerializeObject(message));
+ }
+
+ }
+}
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs
new file mode 100644
index 0000000..f5d9489
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs
@@ -0,0 +1,178 @@
+/*
+ * 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 System.IO;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Newtonsoft.Json.Linq;
+
+namespace Apache.OpenWhisk.Runtime.Common
+{
+ public class Init
+ {
+ private readonly SemaphoreSlim _initSemaphoreSlim = new SemaphoreSlim(1, 1);
+
+ public bool Initialized { get; private set; }
+ private Type Type { get; set; }
+ private MethodInfo Method { get; set; }
+ private ConstructorInfo Constructor { get; set; }
+
+ public Init()
+ {
+ Initialized = false;
+ Type = null;
+ Method = null;
+ Constructor = null;
+ }
+
+ public async Task HandleRequest(HttpContext httpContext)
+ {
+ await _initSemaphoreSlim.WaitAsync();
+ try
+ {
+ if (Initialized)
+ {
+ await httpContext.Response.WriteError("Cannot initialize the action more than once.");
+ Console.Error.WriteLine("Cannot initialize the action more than once.");
+ return (new Run(Type, Method, Constructor));
+ }
+
+ string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
+ JObject inputObject = JObject.Parse(body);
+ if (!inputObject.ContainsKey("value"))
+ {
+ await httpContext.Response.WriteError("Missing main/no code to execute.");
+ return (null);
+ }
+
+ JToken message = inputObject["value"];
+
+ if (message["main"] == null || message["binary"] == null || message["code"] == null)
+ {
+ await httpContext.Response.WriteError("Missing main/no code to execute.");
+ return (null);
+ }
+
+ string main = message["main"].ToString();
+
+ bool binary = message["binary"].ToObject();
+
+ if (!binary)
+ {
+ await httpContext.Response.WriteError("code must be binary (zip file).");
+ return (null);
+ }
+
+ string[] mainParts = main.Split("::");
+ if (mainParts.Length != 3)
+ {
+ await httpContext.Response.WriteError("main required format is \"Assembly::Type::Function\".");
+ return (null);
+ }
+
+ string base64Zip = message["code"].ToString();
+ string tempPath = Path.Combine(Environment.CurrentDirectory, Guid.NewGuid().ToString());
+ string tempFile = Path.GetTempFileName();
+ await File.WriteAllBytesAsync(tempFile, Convert.FromBase64String(base64Zip));
+ try
+ {
+ System.IO.Compression.ZipFile.ExtractToDirectory(tempFile, tempPath);
+ }
+ catch (Exception)
+ {
+ await httpContext.Response.WriteError("Unable to decompress package.");
+ return (null);
+ }
+ finally
+ {
+ File.Delete(tempFile);
+ }
+
+ Environment.CurrentDirectory = tempPath;
+
+ string assemblyFile = $"{mainParts[0]}.dll";
+
+ string assemblyPath = Path.Combine(tempPath, assemblyFile);
+
+ if (!File.Exists(assemblyPath))
+ {
+ await httpContext.Response.WriteError($"Unable to locate requested assembly (\"{assemblyFile}\").");
+ return (null);
+ }
+
+ try
+ {
+ Assembly assembly = Assembly.LoadFrom(assemblyPath);
+ Type = assembly.GetType(mainParts[1]);
+ if (Type == null)
+ {
+ await httpContext.Response.WriteError($"Unable to locate requested type (\"{mainParts[1]}\").");
+ return (null);
+ }
+ Method = Type.GetMethod(mainParts[2]);
+ Constructor = Type.GetConstructor(Type.EmptyTypes);
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex.ToString());
+ await httpContext.Response.WriteError(ex.Message
+#if DEBUG
+ + ", " + ex.StackTrace
+#endif
+ );
+ return (null);
+ }
+
+ if (Method == null)
+ {
+ await httpContext.Response.WriteError($"Unable to locate requested method (\"{mainParts[2]}\").");
+ return (null);
+ }
+
+ if (Constructor == null)
+ {
+ await httpContext.Response.WriteError($"Unable to locate appropriate constructor for (\"{mainParts[1]}\").");
+ return (null);
+ }
+
+ Initialized = true;
+
+ await httpContext.Response.WriteResponse(200, "OK");
+
+ return (new Run(Type, Method, Constructor));
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex.StackTrace);
+ await httpContext.Response.WriteError(ex.Message
+#if DEBUG
+ + ", " + ex.StackTrace
+#endif
+ );
+ Startup.WriteLogMarkers();
+ return (null);
+ }
+ finally
+ {
+ _initSemaphoreSlim.Release();
+ }
+ }
+ }
+}
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs
new file mode 100644
index 0000000..1ee35bb
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs
@@ -0,0 +1,109 @@
+/*
+ * 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 System.IO;
+using System.Reflection;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+using Newtonsoft.Json.Linq;
+
+namespace Apache.OpenWhisk.Runtime.Common
+{
+ public class Run
+ {
+ private readonly Type _type;
+ private readonly MethodInfo _method;
+ private readonly ConstructorInfo _constructor;
+
+ public Run(Type type, MethodInfo method, ConstructorInfo constructor)
+ {
+ _type = type;
+ _method = method;
+ _constructor = constructor;
+ }
+
+ public async Task HandleRequest(HttpContext httpContext)
+ {
+ if (_type == null || _method == null || _constructor == null)
+ {
+ await httpContext.Response.WriteError("Cannot invoke an uninitialized action.");
+ return;
+ }
+
+ try
+ {
+ string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync();
+
+ JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body);
+
+ JObject valObject = null;
+
+ if (inputObject != null)
+ {
+ valObject = inputObject["value"] as JObject;
+ foreach (JToken token in inputObject.Children())
+ {
+ try
+ {
+ if (token.Path.Equals("value", StringComparison.InvariantCultureIgnoreCase))
+ continue;
+ string envKey = $"__OW_{token.Path.ToUpperInvariant()}";
+ string envVal = token.First.ToString();
+ Environment.SetEnvironmentVariable(envKey, envVal);
+ //Console.WriteLine($"Set environment variable \"{envKey}\" to \"{envVal}\".");
+ }
+ catch (Exception)
+ {
+ await Console.Error.WriteLineAsync(
+ $"Unable to set environment variable for the \"{token.Path}\" token.");
+ }
+ }
+ }
+
+ object owObject = _constructor.Invoke(new object[] { });
+
+ try
+ {
+ JObject output = (JObject) _method.Invoke(owObject, new object[] {valObject});
+
+ if (output == null)
+ {
+ await httpContext.Response.WriteError("The action returned null");
+ Console.Error.WriteLine("The action returned null");
+ return;
+ }
+
+ await httpContext.Response.WriteResponse(200, output.ToString());
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine(ex.StackTrace);
+ await httpContext.Response.WriteError(ex.Message
+#if DEBUG
+ + ", " + ex.StackTrace
+#endif
+ );
+ }
+ }
+ finally
+ {
+ Startup.WriteLogMarkers();
+ }
+ }
+ }
+}
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs
new file mode 100644
index 0000000..f11760c
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs
@@ -0,0 +1,69 @@
+/*
+ * 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 System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace Apache.OpenWhisk.Runtime.Common
+{
+ public class Startup
+ {
+ public static void WriteLogMarkers()
+ {
+ Console.WriteLine("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX");
+ Console.Error.WriteLine("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX");
+ }
+
+ public void Configure(IApplicationBuilder app)
+ {
+ PathString initPath = new PathString("/init");
+ PathString runPath = new PathString("/run");
+ Init init = new Init();
+ Run run = null;
+ app.Run(async (httpContext) =>
+ {
+ if (httpContext.Request.Path.Equals(initPath))
+ {
+ run = await init.HandleRequest(httpContext);
+ return;
+ }
+
+ if (httpContext.Request.Path.Equals(runPath))
+ {
+ if (!init.Initialized)
+ {
+ await httpContext.Response.WriteError("Cannot invoke an uninitialized action.");
+ return;
+ }
+
+ if (run == null)
+ {
+ await httpContext.Response.WriteError("Cannot invoke an uninitialized action.");
+ return;
+ }
+
+ await run.HandleRequest(httpContext);
+ }
+ }
+ );
+ }
+ }
+}
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj
new file mode 100644
index 0000000..452115d
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj
@@ -0,0 +1,28 @@
+
+
+
+
+ Exe
+ netcoreapp3.0
+
+
+
+
+
+
+
diff --git a/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Program.cs b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Program.cs
new file mode 100644
index 0000000..0eca9fa
--- /dev/null
+++ b/core/dotnet3.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Program.cs
@@ -0,0 +1,44 @@
+/*
+ * 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 Apache.OpenWhisk.Runtime.Common;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace Apache.OpenWhisk.Runtime.Dotnet.Minimal
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ CreateWebHostBuilder(args).Build().Run();
+ }
+
+ public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+ WebHost.CreateDefaultBuilder(args)
+ .ConfigureLogging((hostingContext, logging) =>
+ {
+ logging.ClearProviders();
+ })
+ .SuppressStatusMessages(true)
+ .UseStartup();
+
+ }
+}
+
diff --git a/core/dotnet3.0/proxy/build.gradle b/core/dotnet3.0/proxy/build.gradle
new file mode 100644
index 0000000..6a5d94e
--- /dev/null
+++ b/core/dotnet3.0/proxy/build.gradle
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+plugins {
+ id "net.karlmartens.dotnet" version "0.2.20"
+}
+
+repositories {
+ mavenCentral()
+}
+
+dotnet {
+ configuration 'Release'
+}
diff --git a/core/dotnet3.0/proxy/gradle/wrapper/gradle-wrapper.jar b/core/dotnet3.0/proxy/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/core/dotnet3.0/proxy/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/core/dotnet3.0/proxy/gradle/wrapper/gradle-wrapper.properties b/core/dotnet3.0/proxy/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..d475d27
--- /dev/null
+++ b/core/dotnet3.0/proxy/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
diff --git a/core/dotnet3.0/proxy/gradlew b/core/dotnet3.0/proxy/gradlew
new file mode 100644
index 0000000..d4ee78f
--- /dev/null
+++ b/core/dotnet3.0/proxy/gradlew
@@ -0,0 +1,188 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed 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.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/core/dotnet3.0/proxy/gradlew.bat b/core/dotnet3.0/proxy/gradlew.bat
new file mode 100644
index 0000000..ad0ff10
--- /dev/null
+++ b/core/dotnet3.0/proxy/gradlew.bat
@@ -0,0 +1,100 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/core/dotnet3.0/proxy/openwhisk-runtime-dotnet.sln b/core/dotnet3.0/proxy/openwhisk-runtime-dotnet.sln
new file mode 100644
index 0000000..25e60cc
--- /dev/null
+++ b/core/dotnet3.0/proxy/openwhisk-runtime-dotnet.sln
@@ -0,0 +1,39 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+
+#
+# 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.
+#
+
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.OpenWhisk.Runtime.Dotnet.Minimal", "Apache.OpenWhisk.Runtime.Dotnet.Minimal\Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj", "{F76F51C9-EB3B-4D4C-89C0-A71E0BEF88DC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.OpenWhisk.Runtime.Common", "Apache.OpenWhisk.Runtime.Common\Apache.OpenWhisk.Runtime.Common.csproj", "{26ADD70B-3101-4943-982C-16D380D4B044}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F76F51C9-EB3B-4D4C-89C0-A71E0BEF88DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F76F51C9-EB3B-4D4C-89C0-A71E0BEF88DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F76F51C9-EB3B-4D4C-89C0-A71E0BEF88DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F76F51C9-EB3B-4D4C-89C0-A71E0BEF88DC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {26ADD70B-3101-4943-982C-16D380D4B044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26ADD70B-3101-4943-982C-16D380D4B044}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26ADD70B-3101-4943-982C-16D380D4B044}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26ADD70B-3101-4943-982C-16D380D4B044}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/settings.gradle b/settings.gradle
index c7465fe..d787614 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -16,11 +16,15 @@
*/
include ':tests'
-include ':tests:dotnet'
+include ':tests:dotnet2.2'
+include ':tests:dotnet3.0'
include ':core:dotnet2.2'
include ':core:dotnet2.2:proxy'
+include ':core:dotnet3.0'
+include ':core:dotnet3.0:proxy'
+
rootProject.name = 'runtime-dotnet'
gradle.ext.openwhisk = [
diff --git a/tests/build.gradle b/tests/build.gradle
index 2b8c6ce..2cfb28f 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -43,5 +43,6 @@ tasks.withType(ScalaCompile) {
}
compileTestScala {
- dependsOn ':tests:dotnet:prepare'
+ dependsOn ':tests:dotnet2.2:prepare'
+ dependsOn ':tests:dotnet3.0:prepare'
}
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj b/tests/dotnet2.2/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
similarity index 91%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
rename to tests/dotnet2.2/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
index 2777248..05df906 100644
--- a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
+++ b/tests/dotnet2.2/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
@@ -24,4 +24,9 @@
+
+
+
+
+
diff --git a/tests/dotnet/build.gradle b/tests/dotnet2.2/build.gradle
similarity index 97%
rename from tests/dotnet/build.gradle
rename to tests/dotnet2.2/build.gradle
index 5efdad1..377f659 100644
--- a/tests/dotnet/build.gradle
+++ b/tests/dotnet2.2/build.gradle
@@ -42,7 +42,7 @@ task prepare_zip(type: Zip, dependsOn: prepare_distro) {
from file('build/dist/out')
include '*'
include '**/**'
- archiveName 'dotnettests.zip'
+ archiveName 'dotnettests2.2.zip'
destinationDir(file('../src/test/resources'))
}
diff --git a/tests/dotnet/openwhisk-tests-dotnet.sln b/tests/dotnet2.2/openwhisk-tests-dotnet.sln
similarity index 100%
rename from tests/dotnet/openwhisk-tests-dotnet.sln
rename to tests/dotnet2.2/openwhisk-tests-dotnet.sln
diff --git a/tests/dotnet3.0/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj b/tests/dotnet3.0/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
new file mode 100644
index 0000000..ddc5679
--- /dev/null
+++ b/tests/dotnet3.0/Apache.OpenWhisk.Tests.Dotnet/Apache.OpenWhisk.Tests.Dotnet.csproj
@@ -0,0 +1,32 @@
+
+
+
+
+ netstandard2.1
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/dotnet3.0/build.gradle b/tests/dotnet3.0/build.gradle
new file mode 100644
index 0000000..8c2e65e
--- /dev/null
+++ b/tests/dotnet3.0/build.gradle
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+plugins {
+ id "net.karlmartens.dotnet" version "0.2.20"
+}
+
+repositories {
+ mavenCentral()
+}
+
+dotnet {
+ configuration 'Release'
+}
+
+task prepare_distro(dependsOn: distribution) {
+ doLast {
+ copy {
+ from tarTree(resources.gzip(file('build/dist/netstandard2.1.tar.gz')))
+ into file('build/dist/out')
+ }
+ delete file('build/dist/netstandard2.1.tar.gz')
+ }
+}
+
+task prepare_zip(type: Zip, dependsOn: prepare_distro) {
+ from file('build/dist/out')
+ include '*'
+ include '**/**'
+ archiveName 'dotnettests3.0.zip'
+ destinationDir(file('../src/test/resources'))
+}
+
+task prepare(type: Delete, dependsOn: prepare_zip) {
+ delete getProject().getBuildDir().toPath().toFile()
+ followSymlinks = true
+}
diff --git a/tests/dotnet3.0/openwhisk-tests-dotnet.sln b/tests/dotnet3.0/openwhisk-tests-dotnet.sln
new file mode 100644
index 0000000..0f4ec0d
--- /dev/null
+++ b/tests/dotnet3.0/openwhisk-tests-dotnet.sln
@@ -0,0 +1,33 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+
+#
+# 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.
+#
+
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.OpenWhisk.Tests.Dotnet", "Apache.OpenWhisk.Tests.Dotnet\Apache.OpenWhisk.Tests.Dotnet.csproj", "{4DA37A8E-7505-4C51-8C75-B18BDA45392C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4DA37A8E-7505-4C51-8C75-B18BDA45392C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4DA37A8E-7505-4C51-8C75-B18BDA45392C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4DA37A8E-7505-4C51-8C75-B18BDA45392C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4DA37A8E-7505-4C51-8C75-B18BDA45392C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/AltEcho.cs b/tests/dotnetshared/AltEcho.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/AltEcho.cs
rename to tests/dotnetshared/AltEcho.cs
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Echo.cs b/tests/dotnetshared/Echo.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Echo.cs
rename to tests/dotnetshared/Echo.cs
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Environment.cs b/tests/dotnetshared/Environment.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Environment.cs
rename to tests/dotnetshared/Environment.cs
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Error.cs b/tests/dotnetshared/Error.cs
similarity index 78%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Error.cs
rename to tests/dotnetshared/Error.cs
index f98068f..7492475 100644
--- a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Error.cs
+++ b/tests/dotnetshared/Error.cs
@@ -16,6 +16,8 @@
*/
using Newtonsoft.Json.Linq;
+using System.Runtime.Versioning;
+using System.Reflection;
namespace Apache.OpenWhisk.Tests.Dotnet
{
@@ -24,7 +26,12 @@ public class Error
public JObject Main(JObject args)
{
JObject message = new JObject();
- message.Add("error", new JValue("This action is unhappy."));
+ var framework = Assembly
+ .GetEntryAssembly()?
+ .GetCustomAttribute()?
+ .FrameworkName;
+
+ message.Add("error", new JValue(framework));
return (message);
}
}
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Exception.cs b/tests/dotnetshared/Exception.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Exception.cs
rename to tests/dotnetshared/Exception.cs
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/NonEmptyConstructor.cs b/tests/dotnetshared/NonEmptyConstructor.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/NonEmptyConstructor.cs
rename to tests/dotnetshared/NonEmptyConstructor.cs
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Nuller.cs b/tests/dotnetshared/Nuller.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Nuller.cs
rename to tests/dotnetshared/Nuller.cs
diff --git a/tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Unicode.cs b/tests/dotnetshared/Unicode.cs
similarity index 100%
rename from tests/dotnet/Apache.OpenWhisk.Tests.Dotnet/Unicode.cs
rename to tests/dotnetshared/Unicode.cs
diff --git a/tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala b/tests/src/test/scala/actionContainers/DotNet2_2ActionContainerTests.scala
similarity index 96%
rename from tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala
rename to tests/src/test/scala/actionContainers/DotNet2_2ActionContainerTests.scala
index 6dfa575..6f84f75 100644
--- a/tests/src/test/scala/actionContainers/DotNetActionContainerTests.scala
+++ b/tests/src/test/scala/actionContainers/DotNet2_2ActionContainerTests.scala
@@ -25,8 +25,8 @@ import actionContainers.ActionContainer.withContainer
import java.nio.file.Paths
@RunWith(classOf[JUnitRunner])
-class DotNetActionContainerTests extends BasicActionRunnerTests with WskActorSystem {
- val functionb64 = ResourceHelpers.readAsBase64(Paths.get(getClass.getResource("/dotnettests.zip").getPath))
+class DotNet2_2ActionContainerTests extends BasicActionRunnerTests with WskActorSystem {
+ val functionb64 = ResourceHelpers.readAsBase64(Paths.get(getClass.getResource("/dotnettests2.2.zip").getPath))
// Helpers specific to java actions
override def withActionContainer(env: Map[String, String] = Map.empty)(
@@ -110,7 +110,10 @@ class DotNetActionContainerTests extends BasicActionRunnerTests with WskActorSys
runCode should be(200)
runRes shouldBe defined
- runRes.get.fields.get("error") shouldBe defined
+
+ runRes should {
+ be(Some(JsObject("error" -> JsString(".NETCoreApp,Version=v2.2"))))
+ }
}
checkStreams(out, err, {
diff --git a/tests/src/test/scala/actionContainers/DotNet3_0ActionContainerTests.scala b/tests/src/test/scala/actionContainers/DotNet3_0ActionContainerTests.scala
new file mode 100644
index 0000000..ec937ab
--- /dev/null
+++ b/tests/src/test/scala/actionContainers/DotNet3_0ActionContainerTests.scala
@@ -0,0 +1,225 @@
+/*
+ * 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.
+ */
+
+package actionContainers
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import common.WskActorSystem
+import spray.json._
+import actionContainers.ActionContainer.withContainer
+import java.nio.file.Paths
+
+@RunWith(classOf[JUnitRunner])
+class DotNet3_0ActionContainerTests extends BasicActionRunnerTests with WskActorSystem {
+ val functionb64 = ResourceHelpers.readAsBase64(Paths.get(getClass.getResource("/dotnettests3.0.zip").getPath))
+
+ // Helpers specific to java actions
+ override def withActionContainer(env: Map[String, String] = Map.empty)(
+ code: ActionContainer => Unit): (String, String) = withContainer("action-dotnet-v3.0", env)(code)
+
+ behavior of "dotnet action"
+
+ override val testNoSourceOrExec = {
+ TestConfig("")
+ }
+
+ override val testNotReturningJson = {
+ // skip this test since and add own below (see Nuller)
+ TestConfig("", skipTest = true)
+ }
+
+ override val testEnv = {
+ TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Environment::Main")
+ }
+
+ override val testEcho = {
+ TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.AltEcho::Main")
+ }
+
+ val testEchoNoWrite = {
+ TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::Main")
+ }
+
+ override val testUnicode = {
+ TestConfig(functionb64, main = "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Unicode::Main")
+ }
+
+ override val testInitCannotBeCalledMoreThanOnce = testEchoNoWrite
+
+ override val testEntryPointOtherThanMain = testEchoNoWrite
+
+ override val testLargeInput = testEchoNoWrite
+
+ it should "fail to initialize with bad archive" in {
+ val (out, err) = withActionContainer() { c =>
+ val brokenArchive = ("NOTAVALIDZIPFILE")
+
+ val (initCode, initRes) =
+ c.init(initPayload(brokenArchive, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Invalid::Main"))
+ initCode should not be (200)
+
+ initRes shouldBe defined
+
+ initRes should {
+ be(Some(JsObject("error" -> JsString("Unable to decompress package."))))
+ }
+ }
+ }
+
+ it should "return some error on action error" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, _) =
+ c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Exception::Main"))
+ initCode should be(200)
+
+ val (runCode, runRes) = c.run(runPayload(JsObject.empty))
+ runCode should not be (200)
+
+ runRes shouldBe defined
+ runRes.get.fields.get("error") shouldBe defined
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ (o + e).toLowerCase should include("exception")
+ })
+ }
+
+ it should "support application errors" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, _) =
+ c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Error::Main"))
+ initCode should be(200)
+
+ val (runCode, runRes) = c.run(runPayload(JsObject.empty))
+ runCode should be(200)
+
+ runRes shouldBe defined
+
+ runRes should {
+ be(Some(JsObject("error" -> JsString(".NETCoreApp,Version=v3.0"))))
+ }
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ o shouldBe empty
+ e shouldBe empty
+ })
+ }
+
+ it should "fails on invalid assembly reference" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(
+ initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet.DoesntExist::Apache.OpenWhisk.Tests.Dotnet.Echo::Main"))
+ initCode should be(502)
+
+ initRes shouldBe defined
+
+ initRes should {
+ be(
+ Some(JsObject("error" -> JsString(
+ "Unable to locate requested assembly (\"Apache.OpenWhisk.Tests.Dotnet.DoesntExist.dll\")."))))
+ }
+ }
+ }
+
+ it should "fails on invalid type reference" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) =
+ c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.FakeType::Main"))
+ initCode should be(502)
+
+ initRes should {
+ be(
+ Some(JsObject(
+ "error" -> JsString("Unable to locate requested type (\"Apache.OpenWhisk.Tests.Dotnet.FakeType\")."))))
+ }
+ }
+ }
+
+ it should "fails on invalid method reference" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(
+ initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo::FakeMethod"))
+ initCode should be(502)
+
+ initRes should {
+ be(Some(JsObject("error" -> JsString("Unable to locate requested method (\"FakeMethod\")."))))
+ }
+ }
+ }
+
+ it should "fails on type with no empty constructor" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(
+ initPayload(
+ functionb64,
+ "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.NonEmptyConstructor::Main"))
+ initCode should be(502)
+
+ initRes should {
+ be(
+ Some(JsObject("error" -> JsString(
+ "Unable to locate appropriate constructor for (\"Apache.OpenWhisk.Tests.Dotnet.NonEmptyConstructor\")."))))
+ }
+ }
+ }
+
+ it should "validate main string format 1" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) = c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet"))
+ initCode should not be (200)
+
+ initRes should {
+ be(Some(JsObject("error" -> JsString("main required format is \"Assembly::Type::Function\"."))))
+ }
+ }
+ }
+
+ it should "validate main string format 2" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, initRes) =
+ c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Echo"))
+ initCode should not be (200)
+
+ initRes should {
+ be(Some(JsObject("error" -> JsString("main required format is \"Assembly::Type::Function\"."))))
+ }
+ }
+ }
+
+ it should "enforce that the user returns an object" in {
+ val (out, err) = withActionContainer() { c =>
+ val (initCode, _) =
+ c.init(initPayload(functionb64, "Apache.OpenWhisk.Tests.Dotnet::Apache.OpenWhisk.Tests.Dotnet.Nuller::Main"))
+ initCode should be(200)
+
+ val (runCode, runRes) = c.run(runPayload(JsObject.empty))
+ runCode should not be (200)
+
+ runRes shouldBe defined
+ runRes.get.fields.get("error") shouldBe defined
+ }
+
+ checkStreams(out, err, {
+ case (o, e) =>
+ (o + e).toLowerCase should include("the action returned null")
+ })
+ }
+}
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index c75ab77..14db490 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -36,15 +36,15 @@ curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
docker version
-# Upgrade dpkg avoid problems installing dotnet 2.2
+# Upgrade dpkg avoid problems installing dotnet 3.0
# https://github.com/travis-ci/travis-ci/issues/9361#issuecomment-408431262
sudo apt-get install -y --force-yes -q -qq dpkg
# Install dotnet
-wget -q https://packages.microsoft.com/config/ubuntu/14.04/packages-microsoft-prod.deb
+wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get install -y apt-transport-https
sudo apt-get -y update -qq
-sudo apt-get install -y dotnet-sdk-2.2
+sudo apt-get install -y dotnet-sdk-3.0
# Build OpenWhisk deps before we run tests
cd $WHISKDIR