diff --git a/environments/nodejs/Dockerfile-12.16 b/environments/nodejs/Dockerfile-12.16 new file mode 100644 index 00000000..9b32e18e --- /dev/null +++ b/environments/nodejs/Dockerfile-12.16 @@ -0,0 +1,15 @@ +FROM node:12.16-alpine3.11 + +ARG NODE_ENV +ENV NODE_ENV $NODE_ENV + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY package.json /usr/src/app/ +RUN npm install && npm cache clean --force +COPY server.js /usr/src/app/server.js + +CMD [ "npm", "start" ] + +EXPOSE 8888 \ No newline at end of file diff --git a/environments/nodejs/builder/Dockerfile-12.16 b/environments/nodejs/builder/Dockerfile-12.16 new file mode 100644 index 00000000..26584814 --- /dev/null +++ b/environments/nodejs/builder/Dockerfile-12.16 @@ -0,0 +1,11 @@ +ARG BUILDER_IMAGE=fission/builder +FROM ${BUILDER_IMAGE} +# default variant is the official alpine node image (much smaller than the standard image) +FROM node:12.16-alpine3.11 + +ARG NODE_ENV +ENV NODE_ENV $NODE_ENV + +COPY --from=0 /builder /builder +ADD build.sh /usr/local/bin/build +RUN chmod +x /usr/local/bin/build diff --git a/hack/release-build.sh b/hack/release-build.sh index a7377b73..3ca96028 100755 --- a/hack/release-build.sh +++ b/hack/release-build.sh @@ -133,6 +133,7 @@ build_all_envs() { # call with version, env dir, image name base, image name variant build_env_image "$version" "nodejs" "node-env" "" build_env_image "$version" "nodejs" "node-env" "debian" + build_env_image "$version" "nodejs" "node-env" "12.16" build_env_image "$version" "binary" "binary-env" "" build_env_image "$version" "dotnet" "dotnet-env" "" build_env_image "$version" "dotnet20" "dotnet20-env" "" @@ -188,6 +189,7 @@ build_all_env_builders() { build_env_builder_image "$version" "go" "go-builder" "1.14" build_env_builder_image "$version" "jvm" "jvm-builder" "" build_env_builder_image "$version" "nodejs" "node-builder" "" + build_env_builder_image "$version" "nodejs" "node-builder" "12.16" build_env_builder_image "$version" "php7" "php-builder" "" build_env_builder_image "$version" "ruby" "ruby-builder" "" build_env_builder_image "$version" "dotnet20" "dotnet20-builder" "" diff --git a/test/build.sh b/test/build.sh index 39fbe684..15cc534a 100755 --- a/test/build.sh +++ b/test/build.sh @@ -30,10 +30,12 @@ build_and_push_builder $BUILDER_IMAGE:$TAG $REPO/go-mod-image-cache build_and_push_env_runtime python $REPO/python-env:$TAG "" build_and_push_env_runtime jvm $REPO/jvm-env:$TAG "" build_and_push_env_runtime go $REPO/go-env:$TAG "1.12" +build_and_push_env_runtime nodejs $REPO/node-env:$TAG "12.16" build_and_push_env_runtime tensorflow-serving $REPO/tensorflow-serving-env:$TAG "" build_and_push_env_builder python $REPO/python-env-builder:$TAG $BUILDER_IMAGE:$TAG "" build_and_push_env_builder jvm $REPO/jvm-env-builder:$TAG $BUILDER_IMAGE:$TAG "" build_and_push_env_builder go $REPO/go-env-builder:$TAG $BUILDER_IMAGE:$TAG "1.12" +build_and_push_env_builder nodejs $REPO/node-env-builder:$TAG $BUILDER_IMAGE:$TAG "12.16" build_fission_cli diff --git a/test/test_utils.sh b/test/test_utils.sh index d8aed4b8..3e17d74e 100755 --- a/test/test_utils.sh +++ b/test/test_utils.sh @@ -506,6 +506,8 @@ run_all_tests() { export GO_BUILDER_IMAGE=gcr.io/$GKE_PROJECT_NAME/go-env-builder:${imageTag} export JVM_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/jvm-env:${imageTag} export JVM_BUILDER_IMAGE=gcr.io/$GKE_PROJECT_NAME/jvm-env-builder:${imageTag} + export NODE_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/node-env:${imageTag} + export NODE_BUILDER_IMAGE=gcr.io/$GKE_PROJECT_NAME/node-env-builder:${imageTag} export TS_RUNTIME_IMAGE=gcr.io/$GKE_PROJECT_NAME/tensorflow-serving-env:${imageTag} set +e @@ -550,6 +552,7 @@ run_all_tests() { $ROOT/test/tests/test_backend_newdeploy.sh \ $ROOT/test/tests/test_environments/test_java_builder.sh \ $ROOT/test/tests/test_environments/test_java_env.sh \ + $ROOT/test/tests/test_environments/test_nodejs_env.sh \ $ROOT/test/tests/test_fn_update/test_configmap_update.sh \ $ROOT/test/tests/test_fn_update/test_env_update.sh \ $ROOT/test/tests/test_fn_update/test_nd_pkg_update.sh \ diff --git a/test/tests/test_environments/node_src/test-case-1/helloWorld.js b/test/tests/test_environments/node_src/test-case-1/helloWorld.js new file mode 100644 index 00000000..8f81c249 --- /dev/null +++ b/test/tests/test_environments/node_src/test-case-1/helloWorld.js @@ -0,0 +1,6 @@ +module.exports = async function (context) { + return { + status: 200, + body: "hello, world!\n", + }; +}; diff --git a/test/tests/test_environments/node_src/test-case-2/helloUser.js b/test/tests/test_environments/node_src/test-case-2/helloUser.js new file mode 100644 index 00000000..c129375a --- /dev/null +++ b/test/tests/test_environments/node_src/test-case-2/helloUser.js @@ -0,0 +1,15 @@ +var url = require("url"); + +module.exports = async function (context) { + console.log(context.request.url); + + var url_parts = url.parse(context.request.url, true); + var query = url_parts.query; + + console.log("query user : ", query.user); + + return { + status: 200, + body: "hello " + query.user + "!", + }; +}; diff --git a/test/tests/test_environments/node_src/test-case-3/wordCount.js b/test/tests/test_environments/node_src/test-case-3/wordCount.js new file mode 100644 index 00000000..98331057 --- /dev/null +++ b/test/tests/test_environments/node_src/test-case-3/wordCount.js @@ -0,0 +1,8 @@ +module.exports = async function (context) { + var splitStringArray = context.request.split(" "); + + return { + status: 200, + body: splitStringArray.length, + }; +}; diff --git a/test/tests/test_environments/node_src/test-case-4/momentExample.js b/test/tests/test_environments/node_src/test-case-4/momentExample.js new file mode 100644 index 00000000..f91abc78 --- /dev/null +++ b/test/tests/test_environments/node_src/test-case-4/momentExample.js @@ -0,0 +1,8 @@ +const momentpackage = require("moment"); + +module.exports = async function (context) { + return { + status: 200, + body: "Hello " + momentpackage().format(), + }; +}; diff --git a/test/tests/test_environments/node_src/test-case-4/package.json b/test/tests/test_environments/node_src/test-case-4/package.json new file mode 100644 index 00000000..7e0a449e --- /dev/null +++ b/test/tests/test_environments/node_src/test-case-4/package.json @@ -0,0 +1,9 @@ +{ + "name": "fission-nodejs-runtime", + "engines": { + "node": ">=7.6.0" + }, + "dependencies": { + "moment": "*" + } +} diff --git a/test/tests/test_environments/test_nodejs_env.sh b/test/tests/test_environments/test_nodejs_env.sh new file mode 100755 index 00000000..39c29715 --- /dev/null +++ b/test/tests/test_environments/test_nodejs_env.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +set -euo pipefail +source $(dirname $0)/../../utils.sh + +TEST_ID=$(generate_test_id) +echo "TEST_ID = $TEST_ID" + +tmp_dir="/tmp/test-$TEST_ID" +mkdir -p $tmp_dir + +ROOT=$(dirname $0)/../../.. + +cleanup() { + clean_resource_by_id $TEST_ID + rm -rf $tmp_dir +} + +if [ -z "${TEST_NOCLEANUP:-}" ]; then + trap cleanup EXIT +else + log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards." +fi + +env_v1api=nodejs-v1-$TEST_ID +env_v2api=nodejs-v2-$TEST_ID +fn1=test-nodejs-env-1-$TEST_ID +fn2=test-nodejs-env-2-$TEST_ID +fn3=test-nodejs-env-3-$TEST_ID +fn4=test-nodejs-env-4-$TEST_ID + +test_path=$ROOT/test/tests/test_environments/node_src + +log "Creating v1api environment ..." +log "NODE_RUNTIME_IMAGE = $NODE_RUNTIME_IMAGE" +fission env create \ + --name $env_v1api \ + --image $NODE_RUNTIME_IMAGE \ + +log "Creating v2api environment ..." +log "NODE_RUNTIME_IMAGE = $NODE_RUNTIME_IMAGE NODE_BUILDER_IMAGE = $NODE_BUILDER_IMAGE" +fission env create \ + --name $env_v2api \ + --image $NODE_RUNTIME_IMAGE \ + --builder $NODE_BUILDER_IMAGE +timeout 180s bash -c "wait_for_builder $env_v2api" + + +log "===== 1. test env with v1 api =====" +fission fn create --name $fn1 --env $env_v1api --code $test_path/test-case-1/helloWorld.js + +fission route create --function $fn1 --url /$fn1 --method GET +sleep 3 # Waiting for router to catch up +timeout 60 bash -c "test_fn $fn1 \"hello, world!\"" + +log "===== 2. test query string =====" +fission fn create --name $fn2 --env $env_v1api --code $test_path/test-case-2/helloUser.js + +fission route create --function $fn2 --url /$fn2 --method GET +sleep 3 # Waiting for router to catch up +timeout 60 bash -c "test_fn $fn2?user=foo \"hello foo!\"" + +log "===== 3. test POST =====" +fission fn create --name $fn3 --env $env_v1api --code $test_path/test-case-3/wordCount.js + +fission route create --function $fn3 --url /$fn3 --method POST +sleep 3 # Waiting for router to catch up +body='Its a beautiful day' +timeout 20 bash -c "test_post_route $fn3 $body 4" + +log "===== 4. test builder =====" +log "Creating package ..." +pushd $test_path/test-case-4 +zip -r $tmp_dir/src-pkg.zip momentExample.js package.json +popd +pkg=$(generate_test_id) +fission package create --name $pkg --src $tmp_dir/src-pkg.zip --env $env_v2api +timeout 60s bash -c "waitBuild $pkg" + +fission fn create --name $fn4 --pkg $pkg --env $env_v2api --entrypoint "momentExample" + +fission route create --function $fn4 --url /$fn4 --method GET +sleep 3 # Waiting for router to catch up +timeout 60 bash -c "test_fn $fn4 'Hello'" + +log "Test PASSED" diff --git a/test/utils.sh b/test/utils.sh index 828d4bff..d6ead6f8 100755 --- a/test/utils.sh +++ b/test/utils.sh @@ -97,7 +97,6 @@ test_post_route() { url="http://$FISSION_ROUTER/$1" body=$2 expect=$3 - set +e while true; do log "test_post_route: call curl" @@ -189,5 +188,6 @@ export GO_BUILDER_IMAGE=${GO_BUILDER_IMAGE:-fission/go-builder-1.12} export JVM_RUNTIME_IMAGE=${JVM_RUNTIME_IMAGE:-fission/jvm-env} export JVM_BUILDER_IMAGE=${JVM_BUILDER_IMAGE:-fission/jvm-builder} export NODE_RUNTIME_IMAGE=${NODE_RUNTIME_IMAGE:-fission/node-env} +export NODE_BUILDER_IMAGE=${NODE_BUILDER_IMAGE:-fission/node-env-builder} export TS_RUNTIME_IMAGE=${TS_RUNTIME_IMAGE:-fission/tensorflow-serving-env}