From 6999935b990d741dc7fa1185c4c64fee8b13fff9 Mon Sep 17 00:00:00 2001 From: Rodric Rabbah Date: Tue, 20 Jul 2021 13:26:08 -0400 Subject: [PATCH 01/19] Restore python 2.7 runtime. --- core/python2ActionLoop/Dockerfile | 90 +++++++++++++++++++ core/python2ActionLoop/Makefile | 31 +++++++ core/python2ActionLoop/bin/compile | 115 +++++++++++++++++++++++++ core/python2ActionLoop/build.gradle | 19 ++++ core/python2ActionLoop/lib/launcher.py | 73 ++++++++++++++++ settings.gradle | 1 + 6 files changed, 329 insertions(+) create mode 100644 core/python2ActionLoop/Dockerfile create mode 100644 core/python2ActionLoop/Makefile create mode 100755 core/python2ActionLoop/bin/compile create mode 100644 core/python2ActionLoop/build.gradle create mode 100755 core/python2ActionLoop/lib/launcher.py diff --git a/core/python2ActionLoop/Dockerfile b/core/python2ActionLoop/Dockerfile new file mode 100644 index 00000000..266fa385 --- /dev/null +++ b/core/python2ActionLoop/Dockerfile @@ -0,0 +1,90 @@ +# +# 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. +# + +# build go proxy from source +FROM golang:1.15 AS builder_source +ARG GO_PROXY_GITHUB_USER=nimbella-corp +ARG GO_PROXY_GITHUB_BRANCH=dev +RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \ + https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\ + cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \ + mv proxy /bin/proxy + +# or build it from a release +FROM golang:1.15 AS builder_release +ARG GO_PROXY_RELEASE_VERSION=1.15@1.17.0 +RUN curl -sL \ + https://github.com/apache/openwhisk-runtime-go/archive/{$GO_PROXY_RELEASE_VERSION}.tar.gz\ + | tar xzf -\ + && cd openwhisk-runtime-go-*/main\ + && GO111MODULE=on go build -o /bin/proxy + +FROM python:2.7-alpine + +# select the builder to use +ARG GO_PROXY_BUILD_FROM=source + +# Upgrade and install basic Python dependencies +RUN apk add --no-cache \ + bash \ + build-base \ + bzip2-dev \ + curl \ + gcc \ + libc-dev \ + libxslt-dev \ + libxml2-dev \ + libffi-dev \ + linux-headers \ + openssl-dev \ + python-dev + +# Install common modules for python +RUN pip install --no-cache-dir --upgrade pip setuptools six \ + && pip install --no-cache-dir \ + gevent==1.3.6 \ + flask==1.0.2 \ + beautifulsoup4==4.6.3 \ + httplib2==0.11.3 \ + kafka_python==1.4.3 \ + lxml==4.2.5 \ + python-dateutil==2.7.3 \ + requests==2.19.1 \ + scrapy==1.5.1 \ + simplejson==3.16.0 \ + virtualenv==16.0.0 \ + twisted==18.7.0 \ + signalfx_lambda==0.2.1 + +# install nim +RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | sed -e 's/--directory/-d/g'| bash + +RUN mkdir -p /action +WORKDIR / +COPY --from=builder_source /bin/proxy /bin/proxy_source +COPY --from=builder_release /bin/proxy /bin/proxy_release +RUN mv /bin/proxy_${GO_PROXY_BUILD_FROM} /bin/proxy + +ADD bin/compile /bin/compile +ADD lib/launcher.py /lib/launcher.py +# the compiler script +ENV OW_COMPILER=/bin/compile +# log initialization errors +ENV OW_LOG_INIT_ERROR=1 +# the launcher must wait for an ack +ENV OW_WAIT_FOR_ACK=1 +ENTRYPOINT ["/bin/proxy"] diff --git a/core/python2ActionLoop/Makefile b/core/python2ActionLoop/Makefile new file mode 100644 index 00000000..4bae7ae3 --- /dev/null +++ b/core/python2ActionLoop/Makefile @@ -0,0 +1,31 @@ +# +# 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. +# +IMG=whisk/actionloop-python-v2.7:latest + +build: + docker build -t $(IMG) -f Dockerfile . + +clean: + docker rmi -f $(IMG) + +debug: + docker run -p 8080:8080 \ + -ti --entrypoint=/bin/bash -v $(PWD):/mnt \ + -e OW_COMPILER=/mnt/bin/compile \ + $(IMG) + +.PHONY: build clean debug diff --git a/core/python2ActionLoop/bin/compile b/core/python2ActionLoop/bin/compile new file mode 100755 index 00000000..2b0ea6af --- /dev/null +++ b/core/python2ActionLoop/bin/compile @@ -0,0 +1,115 @@ +#!/usr/bin/env python +"""Python Action Builder +# +# 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 __future__ import print_function +import os, os.path, sys, imp, ast, shutil, subprocess, traceback +from os.path import abspath, exists, dirname + +# write a file creating intermediate directories +def write_file(file, body, executable=False): + try: os.makedirs(dirname(file), mode=0o755) + except: pass + with open(file, mode="wb") as f: + f.write(body) + if executable: + os.chmod(file, 0o755) + +# copy a file eventually replacing a substring +def copy_replace(src, dst, match=None, replacement=""): + with open(src, 'rb') as s: + body = s.read() + if match: + body = body.replace(match, replacement) + write_file(dst, body) + +# assemble sources +def sources(launcher, main, src_dir): + # move exec in the right place if exists + src_file = "%s/exec" % src_dir + if exists(src_file): + os.rename(src_file, "%s/__main__.py" % src_dir) + if exists("%s/__main__.py" % src_dir): + os.rename("%s/__main__.py" % src_dir, "%s/main__.py" % src_dir) + + # write the boilerplate in a temp dir + copy_replace(launcher, "%s/exec__.py" % src_dir, + "from main__ import main as main", + "from main__ import %s as main" % main ) + +# compile sources +def build(src_dir, tgt_dir): + # in general, compile your program into an executable format + # for scripting languages, move sources and create a launcher + # move away the action dir and replace with the new + shutil.rmtree(tgt_dir) + shutil.move(src_dir, tgt_dir) + tgt_file = "%s/exec" % tgt_dir + write_file(tgt_file, """#!/bin/bash +if [[ "$__OW_EXECUTION_ENV" == "" || "$(cat $0.env)" == "$__OW_EXECUTION_ENV" ]] +then cd "$(dirname $0)" + exec /usr/local/bin/python exec__.py "$@" +else echo "Execution Environment Mismatch" + echo "Expected: $(cat $0.env)" + echo "Actual: $__OW_EXECUTION_ENV" + exit 1 +fi +""", True) + if os.environ.get("__OW_EXECUTION_ENV"): + write_file("%s.env"%tgt_file, os.environ['__OW_EXECUTION_ENV']) + return tgt_file + +#check if a module exists +def check(tgt_dir, module_name): + try: + + # find module + mod = imp.find_module(module_name, [tgt_dir]) + # parse module + ast.parse(mod[0].read()) + # check virtualenv + path_to_virtualenv = abspath('%s/virtualenv' % tgt_dir) + if os.path.isdir(path_to_virtualenv): + activate_this_file = path_to_virtualenv + '/bin/activate_this.py' + if not os.path.exists(activate_this_file): + # check if this was packaged for windows + activate_this_file = path_to_virtualenv + '/Scripts/activate_this.py' + if not os.path.exists(activate_this_file): + sys.stderr.write("Invalid virtualenv. Zip file does not include 'activate_this.py'.\n") + except ImportError: + sys.stderr.write("Zip file does not include %s\n" % module_name) + except SyntaxError as er: + sys.stderr.write(er.msg) + except Exception as ex: + sys.stderr.write(ex.message) + sys.stderr.flush() + +if __name__ == '__main__': + if len(sys.argv) < 4: + sys.stdout.write("usage: \n") + sys.stdout.flush() + sys.exit(1) + launcher = "%s/lib/launcher.py" % dirname(dirname(sys.argv[0])) + src_dir = abspath(sys.argv[2]) + tgt_dir = abspath(sys.argv[3]) + sources(launcher, sys.argv[1], src_dir) + tgt = build(abspath(sys.argv[2]), tgt_dir) + check(tgt_dir, "main__") + sys.stdout.flush() + sys.stderr.flush() diff --git a/core/python2ActionLoop/build.gradle b/core/python2ActionLoop/build.gradle new file mode 100644 index 00000000..66ecc3aa --- /dev/null +++ b/core/python2ActionLoop/build.gradle @@ -0,0 +1,19 @@ +/* + * 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 = 'actionloop-python-v2.7' +apply from: '../../gradle/docker.gradle' diff --git a/core/python2ActionLoop/lib/launcher.py b/core/python2ActionLoop/lib/launcher.py new file mode 100755 index 00000000..3aa3272b --- /dev/null +++ b/core/python2ActionLoop/lib/launcher.py @@ -0,0 +1,73 @@ +# +# 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 __future__ import print_function +from os import fdopen +import sys, os, codecs, json, traceback, warnings + +sys.stdout = codecs.getwriter('utf8')(sys.stdout) +sys.stderr = codecs.getwriter('utf8')(sys.stderr) + +try: + # if the directory 'virtualenv' is extracted out of a zip file + path_to_virtualenv = os.path.abspath('./virtualenv') + if os.path.isdir(path_to_virtualenv): + # activate the virtualenv using activate_this.py contained in the virtualenv + activate_this_file = path_to_virtualenv + '/bin/activate_this.py' + if not os.path.exists(activate_this_file): # try windows path + activate_this_file = path_to_virtualenv + '/Scripts/activate_this.py' + if os.path.exists(activate_this_file): + with open(activate_this_file) as f: + code = compile(f.read(), activate_this_file, 'exec') + exec(code, dict(__file__=activate_this_file)) + else: + sys.stderr.write("Invalid virtualenv. Zip file does not include 'activate_this.py'.\n") + sys.exit(1) +except Exception: + traceback.print_exc(file=sys.stderr, limit=0) + sys.exit(1) + +# now import the action as process input/output +from main__ import main as main + +env = os.environ +out = fdopen(3, "wb") +if os.getenv("__OW_WAIT_FOR_ACK", "") != "": + out.write(json.dumps({"ok": True}, ensure_ascii=False).encode('utf-8')) + out.write(b'\n') + out.flush() +while True: + line = sys.stdin.readline().decode('utf-8') + if not line: break + args = json.loads(line) + payload = {} + for key in args: + akey = key.encode("ascii", "ignore") + if akey == "value": + payload = args["value"] + else: + env["__OW_%s" % akey.upper()] = args[key].encode("ascii", "ignore") + res = {} + try: + res = main(payload) + except Exception as ex: + print(traceback.format_exc(), file=sys.stderr) + res = {"error": str(ex)} + out.write(json.dumps(res, ensure_ascii=False).encode('utf-8')) + out.write(b'\n') + sys.stdout.flush() + sys.stderr.flush() + out.flush() diff --git a/settings.gradle b/settings.gradle index 82b9a9ae..b649190a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,6 +17,7 @@ include 'tests' +include 'core:python2ActionLoop' include 'core:python3Action' include 'core:python36AiAction' include 'core:python39Action' From e27ee5f9b65b6bc1bdd1cee5de75f5c199921ea0 Mon Sep 17 00:00:00 2001 From: Rodric Rabbah Date: Tue, 20 Jul 2021 13:26:45 -0400 Subject: [PATCH 02/19] Update requirements.txt and docker files for Nimbella remote builds. --- .travis.yml | 26 +++---------- README.md | 2 +- core/python36AiAction/Dockerfile | 13 +++++-- core/python36AiAction/requirements.txt | 5 +++ .../signalfx-lambda-python/.gitkeep | 0 core/python39Action/Dockerfile | 12 ++++-- core/python39Action/requirements.txt | 16 ++++++++ .../signalfx-lambda-python/.gitkeep | 0 core/python3Action/Dockerfile | 14 +++++-- core/python3Action/bin/compile | 9 +++++ core/python3Action/requirements.txt | 37 ++++++++++++++----- .../signalfx-lambda-python/.gitkeep | 0 12 files changed, 91 insertions(+), 43 deletions(-) create mode 100644 core/python36AiAction/signalfx-lambda-python/.gitkeep create mode 100644 core/python39Action/signalfx-lambda-python/.gitkeep create mode 100644 core/python3Action/signalfx-lambda-python/.gitkeep diff --git a/.travis.yml b/.travis.yml index d2508dff..18ec909e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,29 +39,13 @@ script: - "./tools/travis/build.sh && ./tools/travis/test.sh" deploy: - provider: script - script: "./tools/travis/publish.sh openwhisk ${TRAVIS_TAG%@*} ${TRAVIS_TAG##*@}" + script: "./tools/travis/publish.sh nimbella 3 ${TRAVIS_TAG} && ./tools/travis/publish.sh nimbella 3-ai ${TRAVIS_TAG} && ./tools/travis/publish.sh nimbella 39 ${TRAVIS_TAG}" on: tags: true all_branches: true - repo: apache/openwhisk-runtime-python + repo: nimbella-corp/openwhisk-runtime-python - provider: script - script: "./tools/travis/publish.sh openwhisk 3 nightly && ./tools/travis/publish.sh openwhisk 3-ai nightly" + script: "./tools/travis/publish.sh nimbella 3 nightly && ./tools/travis/publish.sh nimbella 3-ai nightly && ./tools/travis/publish.sh nimbella 39 nightly" on: - branch: master - repo: apache/openwhisk-runtime-python -env: - global: - - secure: Ac7MlWUpsLwmbcjCigDf+vftiXAEJbf78FVm2QCd4IeFqlRiNbQm3bWRXOOW3Zqh4R4o/wSFpFq0qKPrI9WJjOcxD0GxFboq2iGWTegddfDbENV/IBmjurl6NzYY6dUB7GUSmHYy6tdKnxMhjHzZCn2m4OVWltcMtnOV0G+uYvbnre7vXfb67duzJF+mYpJJ7rC0wGh+N50bYvm0BTtPcQMYJibq6sDTY8Lr1b74QGdM/sODre69CbuiwAA7Ed0hajEcMkv8YnwY0De/PL7hthUyCWSD+i1AhtD+3odA64yX/pAbBzfCcqPoI0Nt5ZmAAUKLJ9pAHCc74dlmYzj9wj1z5TS0nLOE2l++vNvgsA3/c+lqrBv6hc9FmSKx4yfNdFCakVLEfdRJw/45ibIRN5dCW5tDdIx8aciBV8c0CyYgSLRvtVuvw5IX7fbwhHOZ8ftTRzCHS0Nd9zs4x3za+1aucWFQEyrkPtXZIiqeuV7yI4S7yYhGeJy/3KmuN7ljDiTElZb/W9W22ryw/UwCyyZBGnvhomAwInS3E51Jv8GuOU9FVliGzGs2yLuVQ1FjIZ25Au5W4TLTor/jE+dxOlH4u25neqsKBxzG4iyJs3AfJnycD8op7JbTG64OqpVvaB8A4N3P416IxGALSFVv2BWSLY4qWBRVKHbZAHn2tTg= - - secure: fte97QoQReAM0obk/tjxYvF/zhRbcyIFxa1jnFuv1m1YKA/pEWue5uMIDZZa1pynN9rFFgOvR2W34Gm2aHl0wJs18Oqi2Es1cSfDDmuYguEIYZmlfbrjXY2gvitH5+6JA6fc4aMmrgOav+WVbzdzBqy511CWEDsejWflAnFpKJqTnYdLqe8L8FAJfteY/cj5Bvz7G5o8WbH+ag2CopjkEKkx4KXsJ7DadKI+BbI9hkMUvPVnTULaf7Q5z3oG92g1XwjKrfN6Z2y8tQukWg+n5pfVY0yLpWvd/Q/9HyilB0s06EzORzE00DTLnvYNGaVsx99m6H11e0Tn5Sx5S6rJOmJa5T2vTPGmsojpgHm1Lz12AYVxRmWvFbTLg8KDNN9H6uTc8DKPGb/mLkkD5ruWXJWjvpd+m+eRcpJOZ9cvPXWFYvCF0VAPCbK0DakInnmCvZyQ6ZLFgGrtkNt51kkTZGR68d0UW9rwrBS/JaaRdKIbSOHB346trSO2raYIQhaaAtv+tHCOVVAuoVC5Erzw+bojrWtTNQl9FZ2NM2jFaoeiRmi/rB9hqs8iK2BD20EnWfaMRf5XOkBJXYDQ804EnaOAHP/ZO94Ziojotf5SaXSeWG/zsxbT13u+zTdEf3auDofe8exzCpXuOHAQrB0b+Dy2OSKRPwzMHsfto6/OU9w= -notifications: - slack: - secure: ipYx0BX7TwWmG+qeyAllxBxrPn21dJubfEbALn8yTOZfykTWpVtohWrqieAnc6kFQRqz1TAs1wzyjvTcutaIMi9C7FcJrYRIMUMpyID3ca5FeZopr/LBW53XHj/SgZWwFRAnWsjYnSydfZJnUBInI6por8jdVqVgsCMTDsvcXFEoHdVj9M93aB7y8pgqZhfYkQOPojktDu7nMxjsjKJN7dT+g/1kVWtS8DQQCXHTPP44YquxOCgAFn+CZjes9Jm+vz5lk5Azksi48yiHwFiLYZo5gcnwr2n2IspjBs6db10rkCe693vIpoW4T3KujMIKwVXrgUl4pDME1nN/loEBHm0DjKoeOD13DHqITMTPX4sR94TCGf0lMyaag/JOETdDgC9hAbh4aSx1cj4hGXiuGrNMbYblMBsjvujqFp2nraw/DE93pHGRY9lbBZIjEVhj/jBmOv1I3yRdXHj4VybZc4JGnfQVGz/RYDOEmKGoLoVWFp+hGAHDqVos9ZvEBByMAAmgVD2/D5cBER3oskp/JJjKmFLk614FcNh4D7/+bYAFhxbCgnoLHH5GeSo0q73O3JSi5pZggEIN9xis7SVQgPl+MUDTe5N3X3J3bQc7cMYGLzh0VNSyYaHuW2P02vWBNE/FAkL8UGrfGsXnDyGRRxo8fYHTXpIjhIkE7tY5eZQ= - on_pull_requests: false - on_success: change - on_failure: always - webhooks: - urls: - # travis2slack webhook to enable DMs on openwhisk-team.slack.com to PR authors with TravisCI results - secure: "JoCPajRbNQ+8Tpu7XyjtLT/pbbA4vhEpScYs7YIE4+iYtZLNXpqXdX/9+tzX9uGsh/+4DoIVMXjcKjDKglgtffgv8RF1wVblIpC8pIcPVaUxWn1KitjZCgFEQnxpT74DgJng3C1ADHon5htNdZ/vhfXDtV6XJ1/mvtWJZCC0ZsWuvRiwnRwZdIkrZi7Fpl6fqTOOAcy7KV8IeKi+GMInjvPrVdG3uLgQO2tOnoKK4oFvDT1sV3hLX8nx6GYAers98AtbvNyiSyg4wAUFV6HTiF7Kc4rHWqPgu8aQRfO8yTlZ4XomAHR1HcujANgoG1lvij28N7pkgRvjUBpPP82qYKlx4xC9RxeH40MjlYiCLHWUswyFb9QGRsnbGtCamME3kBiC3jO86avvD16PWwCbA1q/Y7bLhUZUCUOGHzxvb3n2kCgkcjcbwIiS8+/2aJsIJ8TE7Y6sjrMHJEGILO57gY/JdCrevn4MOfnyCiqPgWdnPTUzcXcYoH/hZctUsOISc2M5yZsNAVHyHFZAbDDdgCLAVi9SAIRhB9ipn/JbpnHzPhu7eW46T6cDMdBAw0FUPvrGch20qhABILU7cFCDZLJ/DouKGAOn1XPXo5FUBjyM854jjm2jVs6IpOdUecW1lGdafB3d0AJXMm4vBXU8VmCuvElurnoE+FNpKZpmjms=" - - + branch: dev + repo: nimbella-corp/openwhisk-runtime-python diff --git a/README.md b/README.md index def82e3a..555d436f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ # Apache OpenWhisk runtimes for Python [![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-python.svg?branch=master)](https://travis-ci.com/apache/openwhisk-runtime-python) +[![Build Status](https://travis-ci.com/nimbella-corp/openwhisk-runtime-python.svg?branch=master)](https://travis-ci.com/nimbella-corp/openwhisk-runtime-python) ## Build Runtimes diff --git a/core/python36AiAction/Dockerfile b/core/python36AiAction/Dockerfile index bb2dab6d..45ace8eb 100644 --- a/core/python36AiAction/Dockerfile +++ b/core/python36AiAction/Dockerfile @@ -17,8 +17,8 @@ # build go proxy from source FROM golang:1.16 AS builder_source -ARG GO_PROXY_GITHUB_USER=apache -ARG GO_PROXY_GITHUB_BRANCH=master +ARG GO_PROXY_GITHUB_USER=nimbella-corp +ARG GO_PROXY_GITHUB_BRANCH=dev RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \ https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\ cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \ @@ -52,7 +52,6 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \ vim \ && rm -rf /var/lib/apt/lists/* -# PyTorch # persistent as it fails often RUN while ! pip list | grep torch ;\ do pip install torch ; done ;\ @@ -64,11 +63,17 @@ RUN curl -L https://downloads.rclone.org/rclone-current-linux-amd64.deb -o rclon && dpkg -i rclone.deb \ && rm rclone.deb +# Copy nimbella version of the sfx library +COPY signalfx-lambda-python /opt/signalfx_lambda + COPY requirements.txt requirements.txt RUN pip3 install --upgrade pip six wheel &&\ pip3 install --no-cache-dir -r requirements.txt &&\ ln -sf /usr/bin/python3 /usr/local/bin/python +# install nim +RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | bash + RUN mkdir -p /action WORKDIR / @@ -84,7 +89,7 @@ ENV OW_LOG_INIT_ERROR=1 # the launcher must wait for an ack ENV OW_WAIT_FOR_ACK=1 # using the runtime name to identify the execution environment -ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.6-ai +#ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.6-ai # compiler script ENV OW_COMPILER=/bin/compile # use utf-8 diff --git a/core/python36AiAction/requirements.txt b/core/python36AiAction/requirements.txt index 44e5a9b7..d784fd6d 100644 --- a/core/python36AiAction/requirements.txt +++ b/core/python36AiAction/requirements.txt @@ -11,6 +11,9 @@ virtualenv == 16.7.9 twisted == 19.10.0 netifaces == 0.10.9 +# Nimbella package +nimbella == 1.0.0 + # package to sync from a variety of cloud blob storage python-rclone == 0.0.2 @@ -30,6 +33,7 @@ numpy == 1.18.1 scikit-learn == 0.22.1 scipy == 1.4.1 pandas == 1.0.1 +spacy == 2.2.4 # packages for image processing Pillow == 7.0.0 @@ -37,6 +41,7 @@ Pillow == 7.0.0 # Etc pymongo == 3.10.1 redis == 3.4.1 +google-cloud-storage == 1.28.1 pika == 1.1.0 elasticsearch == 7.5.1 cassandra-driver == 3.21.0 diff --git a/core/python36AiAction/signalfx-lambda-python/.gitkeep b/core/python36AiAction/signalfx-lambda-python/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index 713a2ea2..9b8114c6 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -17,8 +17,8 @@ # build go proxy from source FROM golang:1.16 AS builder_source -ARG GO_PROXY_GITHUB_USER=apache -ARG GO_PROXY_GITHUB_BRANCH=master +ARG GO_PROXY_GITHUB_USER=nimbella-corp +ARG GO_PROXY_GITHUB_BRANCH=dev RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \ https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\ cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \ @@ -38,10 +38,16 @@ FROM python:3.9-buster # select the builder to use ARG GO_PROXY_BUILD_FROM=release +# Copy nimbella version of the sfx library +COPY signalfx-lambda-python /opt/signalfx_lambda + # Install common modules for python COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt +# install nim +RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | bash + RUN mkdir -p /action WORKDIR / COPY --from=builder_source /bin/proxy /bin/proxy_source @@ -55,7 +61,7 @@ ENV OW_LOG_INIT_ERROR=1 # the launcher must wait for an ack ENV OW_WAIT_FOR_ACK=1 # using the runtime name to identify the execution environment -ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.9 +#ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.9 # compiler script ENV OW_COMPILER=/bin/compile diff --git a/core/python39Action/requirements.txt b/core/python39Action/requirements.txt index 549a80fc..51dc54e5 100644 --- a/core/python39Action/requirements.txt +++ b/core/python39Action/requirements.txt @@ -10,3 +10,19 @@ simplejson == 3.17.2 virtualenv == 20.4.7 twisted == 21.2.0 netifaces == 0.11.0 + +# package to sync from a variety of cloud blob storage +python-rclone == 0.0.2 +google-cloud-storage == 1.35.1 + +# Nimbella package +nimbella == 2.0.0 + +# Etc +pymongo == 3.11.4 +redis == 3.4.1 +pika == 1.2.0 +elasticsearch == 7.13.2 +cassandra-driver == 3.25.0 +etcd3 == 0.12.0 +twilio == 6.60.0 diff --git a/core/python39Action/signalfx-lambda-python/.gitkeep b/core/python39Action/signalfx-lambda-python/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/core/python3Action/Dockerfile b/core/python3Action/Dockerfile index ef4615a3..6f0298b8 100644 --- a/core/python3Action/Dockerfile +++ b/core/python3Action/Dockerfile @@ -17,8 +17,8 @@ # build go proxy from source FROM golang:1.16 AS builder_source -ARG GO_PROXY_GITHUB_USER=apache -ARG GO_PROXY_GITHUB_BRANCH=master +ARG GO_PROXY_GITHUB_USER=nimbella-corp +ARG GO_PROXY_GITHUB_BRANCH=dev RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \ https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\ cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \ @@ -38,10 +38,16 @@ FROM python:3.7-buster # select the builder to use ARG GO_PROXY_BUILD_FROM=release +# Copy nimbella version of the sfx library +COPY signalfx-lambda-python /opt/signalfx_lambda + # Install common modules for python COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt +# install nim +RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | bash + RUN mkdir -p /action WORKDIR / COPY --from=builder_source /bin/proxy /bin/proxy_source @@ -54,8 +60,8 @@ ADD lib/launcher.py /lib/launcher.py ENV OW_LOG_INIT_ERROR=1 # the launcher must wait for an ack ENV OW_WAIT_FOR_ACK=1 -# execution environment -ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.7 +# using the runtime name to identify the execution environment +#ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.7 # compiler script ENV OW_COMPILER=/bin/compile diff --git a/core/python3Action/bin/compile b/core/python3Action/bin/compile index 052f2c4e..4b7180fd 100755 --- a/core/python3Action/bin/compile +++ b/core/python3Action/bin/compile @@ -117,6 +117,15 @@ def check(tgt_dir, module_name): if mod: with open(mod.origin, "rb") as f: ast.parse(f.read().decode("utf-8")) + # check virtualenv + path_to_virtualenv = abspath('%s/virtualenv' % tgt_dir) + if os.path.isdir(path_to_virtualenv): + activate_this_file = path_to_virtualenv + '/bin/activate_this.py' + if not os.path.exists(activate_this_file): + # check if this was packaged for windows + activate_this_file = path_to_virtualenv + '/Scripts/activate_this.py' + if not os.path.exists(activate_this_file): + sys.stderr.write("Invalid virtualenv. Zip file does not include 'activate_this.py'.\n") else: sys.stderr.write("Zip file does not include %s\n" % module_name) except SyntaxError as er: diff --git a/core/python3Action/requirements.txt b/core/python3Action/requirements.txt index d60e88a8..703eb045 100644 --- a/core/python3Action/requirements.txt +++ b/core/python3Action/requirements.txt @@ -1,11 +1,28 @@ # default available packages for python3action -beautifulsoup4 == 4.6.3 -httplib2 == 0.11.3 -kafka_python == 1.4.3 -lxml == 4.2.5 -python-dateutil == 2.7.3 -requests == 2.19.1 -scrapy == 1.5.1 -simplejson == 3.16.0 -virtualenv == 16.0.0 -twisted == 18.7.0 +beautifulsoup4 == 4.8.2 +httplib2 == 0.17.0 +kafka_python == 1.4.7 +lxml == 4.5.0 +python-dateutil == 2.8.1 +requests == 2.22.0 +scrapy == 1.8.0 +simplejson == 3.17.0 +virtualenv == 16.7.9 +twisted == 19.10.0 +netifaces == 0.10.9 + +# package to sync from a variety of cloud blob storage +python-rclone == 0.0.2 +google-cloud-storage == 1.28.1 + +# Nimbella package +nimbella == 1.0.0 + +# Etc +pymongo == 3.10.1 +redis == 3.4.1 +pika == 1.1.0 +elasticsearch == 7.5.1 +cassandra-driver == 3.21.0 +etcd3 == 0.11.1 +twilio == 6.35.4 diff --git a/core/python3Action/signalfx-lambda-python/.gitkeep b/core/python3Action/signalfx-lambda-python/.gitkeep new file mode 100644 index 00000000..e69de29b From 682da5143f02debf999735c9e3c343bc47a0011f Mon Sep 17 00:00:00 2001 From: James Thomas Date: Fri, 6 Aug 2021 13:26:59 +0100 Subject: [PATCH 03/19] Updating Python SDK to latest release. --- core/python36AiAction/requirements.txt | 2 +- core/python39Action/requirements.txt | 2 +- core/python3Action/requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/python36AiAction/requirements.txt b/core/python36AiAction/requirements.txt index d784fd6d..a66b2f35 100644 --- a/core/python36AiAction/requirements.txt +++ b/core/python36AiAction/requirements.txt @@ -12,7 +12,7 @@ twisted == 19.10.0 netifaces == 0.10.9 # Nimbella package -nimbella == 1.0.0 +nimbella == 2.1.1 # package to sync from a variety of cloud blob storage python-rclone == 0.0.2 diff --git a/core/python39Action/requirements.txt b/core/python39Action/requirements.txt index 51dc54e5..d2e89fa2 100644 --- a/core/python39Action/requirements.txt +++ b/core/python39Action/requirements.txt @@ -16,7 +16,7 @@ python-rclone == 0.0.2 google-cloud-storage == 1.35.1 # Nimbella package -nimbella == 2.0.0 +nimbella == 2.1.1 # Etc pymongo == 3.11.4 diff --git a/core/python3Action/requirements.txt b/core/python3Action/requirements.txt index 703eb045..027f954e 100644 --- a/core/python3Action/requirements.txt +++ b/core/python3Action/requirements.txt @@ -16,7 +16,7 @@ python-rclone == 0.0.2 google-cloud-storage == 1.28.1 # Nimbella package -nimbella == 1.0.0 +nimbella == 2.1.1 # Etc pymongo == 3.10.1 From 6e714d61bfdb76251d3312fe23f860ef871804c2 Mon Sep 17 00:00:00 2001 From: Joshua Auerbach Date: Fri, 10 Dec 2021 05:57:37 -0500 Subject: [PATCH 04/19] Make reference to nimbella install symbolic (#1) --- core/python2ActionLoop/Dockerfile | 3 ++- core/python36AiAction/Dockerfile | 3 ++- core/python39Action/Dockerfile | 3 ++- core/python3Action/Dockerfile | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/python2ActionLoop/Dockerfile b/core/python2ActionLoop/Dockerfile index 266fa385..4ee3ae8f 100644 --- a/core/python2ActionLoop/Dockerfile +++ b/core/python2ActionLoop/Dockerfile @@ -71,7 +71,8 @@ RUN pip install --no-cache-dir --upgrade pip setuptools six \ signalfx_lambda==0.2.1 # install nim -RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | sed -e 's/--directory/-d/g'| bash +ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action WORKDIR / diff --git a/core/python36AiAction/Dockerfile b/core/python36AiAction/Dockerfile index 45ace8eb..aea41097 100644 --- a/core/python36AiAction/Dockerfile +++ b/core/python36AiAction/Dockerfile @@ -72,7 +72,8 @@ RUN pip3 install --upgrade pip six wheel &&\ ln -sf /usr/bin/python3 /usr/local/bin/python # install nim -RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | bash +ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action WORKDIR / diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index 9b8114c6..be91a2da 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -46,7 +46,8 @@ COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt # install nim -RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | bash +ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action WORKDIR / diff --git a/core/python3Action/Dockerfile b/core/python3Action/Dockerfile index 6f0298b8..48b18406 100644 --- a/core/python3Action/Dockerfile +++ b/core/python3Action/Dockerfile @@ -46,7 +46,8 @@ COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt # install nim -RUN curl https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh | bash +ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action WORKDIR / From a88c5824bbfac5adb440de7cd7aeaa88051f24af Mon Sep 17 00:00:00 2001 From: Joshua Auerbach Date: Tue, 11 Jan 2022 05:53:40 -0500 Subject: [PATCH 05/19] Remove signal-fx libraries (#2) * Remove signal-fx libraries * Remove directories for signal-fx also --- core/python2ActionLoop/Dockerfile | 3 +-- core/python36AiAction/Dockerfile | 3 --- core/python36AiAction/signalfx-lambda-python/.gitkeep | 0 core/python39Action/Dockerfile | 3 --- core/python39Action/signalfx-lambda-python/.gitkeep | 0 core/python3Action/Dockerfile | 3 --- core/python3Action/signalfx-lambda-python/.gitkeep | 0 7 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 core/python36AiAction/signalfx-lambda-python/.gitkeep delete mode 100644 core/python39Action/signalfx-lambda-python/.gitkeep delete mode 100644 core/python3Action/signalfx-lambda-python/.gitkeep diff --git a/core/python2ActionLoop/Dockerfile b/core/python2ActionLoop/Dockerfile index 4ee3ae8f..81903974 100644 --- a/core/python2ActionLoop/Dockerfile +++ b/core/python2ActionLoop/Dockerfile @@ -67,8 +67,7 @@ RUN pip install --no-cache-dir --upgrade pip setuptools six \ scrapy==1.5.1 \ simplejson==3.16.0 \ virtualenv==16.0.0 \ - twisted==18.7.0 \ - signalfx_lambda==0.2.1 + twisted==18.7.0 # install nim ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh diff --git a/core/python36AiAction/Dockerfile b/core/python36AiAction/Dockerfile index aea41097..8ba36c01 100644 --- a/core/python36AiAction/Dockerfile +++ b/core/python36AiAction/Dockerfile @@ -63,9 +63,6 @@ RUN curl -L https://downloads.rclone.org/rclone-current-linux-amd64.deb -o rclon && dpkg -i rclone.deb \ && rm rclone.deb -# Copy nimbella version of the sfx library -COPY signalfx-lambda-python /opt/signalfx_lambda - COPY requirements.txt requirements.txt RUN pip3 install --upgrade pip six wheel &&\ pip3 install --no-cache-dir -r requirements.txt &&\ diff --git a/core/python36AiAction/signalfx-lambda-python/.gitkeep b/core/python36AiAction/signalfx-lambda-python/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index be91a2da..be92c5aa 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -38,9 +38,6 @@ FROM python:3.9-buster # select the builder to use ARG GO_PROXY_BUILD_FROM=release -# Copy nimbella version of the sfx library -COPY signalfx-lambda-python /opt/signalfx_lambda - # Install common modules for python COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt diff --git a/core/python39Action/signalfx-lambda-python/.gitkeep b/core/python39Action/signalfx-lambda-python/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/core/python3Action/Dockerfile b/core/python3Action/Dockerfile index 48b18406..d9ca7be5 100644 --- a/core/python3Action/Dockerfile +++ b/core/python3Action/Dockerfile @@ -38,9 +38,6 @@ FROM python:3.7-buster # select the builder to use ARG GO_PROXY_BUILD_FROM=release -# Copy nimbella version of the sfx library -COPY signalfx-lambda-python /opt/signalfx_lambda - # Install common modules for python COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt diff --git a/core/python3Action/signalfx-lambda-python/.gitkeep b/core/python3Action/signalfx-lambda-python/.gitkeep deleted file mode 100644 index e69de29b..00000000 From ad7940f914f43e3eea0ab7aff54339dfaca887bd Mon Sep 17 00:00:00 2001 From: Joshua Auerbach Date: Fri, 21 Jan 2022 15:53:40 -0500 Subject: [PATCH 06/19] Fail when curl download of nim fails (#3) --- core/python2ActionLoop/Dockerfile | 1 + core/python36AiAction/Dockerfile | 1 + core/python39Action/Dockerfile | 1 + core/python3Action/Dockerfile | 1 + 4 files changed, 4 insertions(+) diff --git a/core/python2ActionLoop/Dockerfile b/core/python2ActionLoop/Dockerfile index 81903974..2eeabff3 100644 --- a/core/python2ActionLoop/Dockerfile +++ b/core/python2ActionLoop/Dockerfile @@ -71,6 +71,7 @@ RUN pip install --no-cache-dir --upgrade pip setuptools six \ # install nim ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action diff --git a/core/python36AiAction/Dockerfile b/core/python36AiAction/Dockerfile index 8ba36c01..08d02e1a 100644 --- a/core/python36AiAction/Dockerfile +++ b/core/python36AiAction/Dockerfile @@ -70,6 +70,7 @@ RUN pip3 install --upgrade pip six wheel &&\ # install nim ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index be92c5aa..c9714179 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -44,6 +44,7 @@ RUN pip install --no-cache-dir -r requirements.txt # install nim ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action diff --git a/core/python3Action/Dockerfile b/core/python3Action/Dockerfile index d9ca7be5..a5ea67a3 100644 --- a/core/python3Action/Dockerfile +++ b/core/python3Action/Dockerfile @@ -44,6 +44,7 @@ RUN pip install --no-cache-dir -r requirements.txt # install nim ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN curl ${NIM_INSTALL_SCRIPT} | bash RUN mkdir -p /action From 529b2f14386ba07ff990c9217067f31fc973aa96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Tue, 15 Mar 2022 20:41:49 +0100 Subject: [PATCH 07/19] Log the sentinels in the child process rather than the proxy process (#4) To reflect the changes from https://github.com/nimbella/openwhisk-runtime-go/pull/4. --- core/python2ActionLoop/lib/launcher.py | 3 +++ core/python3Action/lib/launcher.py | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/core/python2ActionLoop/lib/launcher.py b/core/python2ActionLoop/lib/launcher.py index 3aa3272b..e87a81cb 100755 --- a/core/python2ActionLoop/lib/launcher.py +++ b/core/python2ActionLoop/lib/launcher.py @@ -20,6 +20,7 @@ sys.stdout = codecs.getwriter('utf8')(sys.stdout) sys.stderr = codecs.getwriter('utf8')(sys.stderr) +log_sentinel="XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n" try: # if the directory 'virtualenv' is extracted out of a zip file @@ -68,6 +69,8 @@ res = {"error": str(ex)} out.write(json.dumps(res, ensure_ascii=False).encode('utf-8')) out.write(b'\n') + sys.stdout.write(log_sentinel) + sys.stderr.write(log_sentinel) sys.stdout.flush() sys.stderr.flush() out.flush() diff --git a/core/python3Action/lib/launcher.py b/core/python3Action/lib/launcher.py index ccf0c680..e6c5e31a 100755 --- a/core/python3Action/lib/launcher.py +++ b/core/python3Action/lib/launcher.py @@ -21,6 +21,8 @@ from os import fdopen import sys, os, json, traceback, warnings +log_sentinel="XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n" + try: # if the directory 'virtualenv' is extracted out of a zip file path_to_virtualenv = os.path.abspath('./virtualenv') @@ -68,6 +70,8 @@ res = {"error": str(ex)} out.write(json.dumps(res, ensure_ascii=False).encode('utf-8')) out.write(b'\n') + stdout.write(log_sentinel) + stderr.write(log_sentinel) stdout.flush() stderr.flush() out.flush() From 6a4e02f37bb353e7a280d21eac12788e99ed258d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Wed, 25 May 2022 08:53:01 +0200 Subject: [PATCH 08/19] SERVERLESS-1465 Update Golang version to more recent one (#5) Updates the Golang version used to build the go proxy and makes it dynamic so we can update this centrally in our build scripts in the future. --- core/python39Action/Dockerfile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index c9714179..f4835bf5 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -16,16 +16,17 @@ # # build go proxy from source -FROM golang:1.16 AS builder_source +ARG GO_PROXY_BASE_IMAGE=golang:1.18 +FROM $GO_PROXY_BASE_IMAGE AS builder_source ARG GO_PROXY_GITHUB_USER=nimbella-corp ARG GO_PROXY_GITHUB_BRANCH=dev RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} \ - https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\ - cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \ - mv proxy /bin/proxy + https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src ;\ + cd /src ; env GO111MODULE=on CGO_ENABLED=0 go build main/proxy.go && \ + mv proxy /bin/proxy # or build it from a release -FROM golang:1.16 AS builder_release +FROM $GO_PROXY_BASE_IMAGE AS builder_release ARG GO_PROXY_RELEASE_VERSION=1.16@1.18.0 RUN curl -sL \ https://github.com/apache/openwhisk-runtime-go/archive/{$GO_PROXY_RELEASE_VERSION}.tar.gz\ From f1d52d36d062db3e151c58c1a399f43e0e63e25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Thu, 23 Jun 2022 09:37:11 +0200 Subject: [PATCH 09/19] SERVERLESS-1395 Implement prelaunch behavior for the Python runtime (#7) As per title, this implements prelaunch mode for the python runtime to start the interpreter alongside the go proxy and initialize the respective function in that existing process. --- core/python39Action/Dockerfile | 3 + core/python3Action/lib/prelauncher.py | 121 ++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100755 core/python3Action/lib/prelauncher.py diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index f4835bf5..b08602ba 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -55,6 +55,7 @@ COPY --from=builder_release /bin/proxy /bin/proxy_release RUN mv /bin/proxy_${GO_PROXY_BUILD_FROM} /bin/proxy ADD bin/compile /bin/compile ADD lib/launcher.py /lib/launcher.py +ADD lib/prelauncher.py /lib/prelauncher.py # log initialization errors ENV OW_LOG_INIT_ERROR=1 @@ -65,4 +66,6 @@ ENV OW_WAIT_FOR_ACK=1 # compiler script ENV OW_COMPILER=/bin/compile +ENV OW_INIT_IN_ACTIONLOOP=/lib/prelauncher.py + ENTRYPOINT ["/bin/proxy"] diff --git a/core/python3Action/lib/prelauncher.py b/core/python3Action/lib/prelauncher.py new file mode 100755 index 00000000..c02e41e3 --- /dev/null +++ b/core/python3Action/lib/prelauncher.py @@ -0,0 +1,121 @@ +#!/usr/local/bin/python + +# +# 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 __future__ import print_function +from sys import stdin +from sys import stdout +from sys import stderr +from os import fdopen +import sys, os, json, traceback, base64, io, zipfile + +log_sentinel="XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n" +def write_sentinels(): + stdout.write(log_sentinel) + stderr.write(log_sentinel) + stdout.flush() + stderr.flush() + +out = fdopen(3, "wb") +def write_result(res): + out.write(json.dumps(res, ensure_ascii=False).encode('utf-8')) + out.write(b'\n') + out.flush() + +def cannot_start(msg): + stderr.write(msg) + write_result({"error": "Cannot start action. Check logs for details."}) + write_sentinels() + sys.exit(1) + +# Notify the Golang proxy that the process is awaiting input. +write_result({"ok": True}) + +# Read the init payload. +line = stdin.readline() +init = json.loads(line)["value"] + +# Set the environment from the init payload. +if init["env"]: + for key, value in init["env"].items(): + if isinstance(value, str): + os.environ[key] = value + else: + # Anything that's not a string needs to be stringified. + os.environ[key] = json.dumps(value) + +if init["binary"]: + # We have a base64 encoded zip as code. + buffer = base64.b64decode(init["code"]) + with zipfile.ZipFile(io.BytesIO(buffer)) as zip_ref: + zip_ref.extractall(".") + + # Note: We're ignoring `exec` here as we don't need a starter script. + if os.path.exists("__main__.py"): + os.rename("__main__.py", "main__.py") + if not os.path.exists("main__.py"): + cannot_start("Zip file does not include '__main__.py'.\n") + + try: + # If the directory 'virtualenv' is extracted out of a zip file. + path_to_virtualenv = os.path.abspath('virtualenv') + if os.path.isdir(path_to_virtualenv): + # Activate the virtualenv using activate_this.py contained in the virtualenv. + activate_this_file = path_to_virtualenv + '/bin/activate_this.py' + if not os.path.exists(activate_this_file): # try windows path + activate_this_file = path_to_virtualenv + '/Scripts/activate_this.py' + if os.path.exists(activate_this_file): + exec(open(activate_this_file).read(), {'__file__': activate_this_file}) + else: + cannot_start("Invalid virtualenv: Zip file does not include 'activate_this.py'.\n") + except Exception as ex: + traceback.print_exc(file=stderr, limit=0) + cannot_start("Invalid virtualenv: Failed to active virtualenv %s.\n" % str(ex)) +else: + # TODO: We can optimize this further by compiling the code in-process. + with open("main__.py", mode="wb") as f: + f.write(init["code"].encode("utf-8")) + +# Import the action itself. +try: + sys.path.append(os.getcwd()) + main = getattr(__import__("main__", fromlist=[init["main"]]), init["main"]) +except Exception as ex: + cannot_start("Invalid action: %s\n" % str(ex)) + +# Acknowledge the initialization. +write_result({"ok": True}) + +# Enter the actual action loop. +while True: + line = stdin.readline() + if not line: break + args = json.loads(line) + payload = {} + for key in args: + if key == "value": + payload = args["value"] + else: + os.environ["__OW_%s" % key.upper()]= args[key] + res = {} + try: + res = main(payload) + except Exception as ex: + print(traceback.format_exc(), file=stderr) + res = {"error": str(ex)} + write_result(res) + write_sentinels() From 605ea88a8b382ed04d089b29baa22182f37b69b2 Mon Sep 17 00:00:00 2001 From: Joshua Auerbach Date: Sun, 30 Oct 2022 08:44:17 -0400 Subject: [PATCH 10/19] Include functions deployer in runtime image (#9) --- core/python39Action/Dockerfile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index b08602ba..714dad6e 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -43,11 +43,18 @@ ARG GO_PROXY_BUILD_FROM=release COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt -# install nim -ARG NIM_INSTALL_SCRIPT=https://apigcp.nimbella.io/downloads/nim/nim-install-linux.sh +# install nim (to be retired once we are fully switched to using functions-deployer) +ARG NIM_INSTALL_SCRIPT= SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN curl ${NIM_INSTALL_SCRIPT} | bash +# install the functions-deployer (co-exist with nim temporarily) +ARG DEPLOYER_DOWNLOAD +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN curl -L ${DEPLOYER_DOWNLOAD} | tar xzf - \ + && rm -fr /usr/local/lib/dosls && mv dosls /usr/local/lib \ + && rm -f /usr/local/bin/dosls && ln -s /usr/local/lib/dosls/bootstrap /usr/local/bin/dosls + RUN mkdir -p /action WORKDIR / COPY --from=builder_source /bin/proxy /bin/proxy_source From df7eb79df7566ec46c7ba93c205443ed08f2f96b Mon Sep 17 00:00:00 2001 From: Joshua Auerbach Date: Thu, 10 Nov 2022 05:49:12 -0500 Subject: [PATCH 11/19] remove nim install (#10) --- core/python39Action/Dockerfile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/python39Action/Dockerfile b/core/python39Action/Dockerfile index 714dad6e..3eb96fcc 100644 --- a/core/python39Action/Dockerfile +++ b/core/python39Action/Dockerfile @@ -43,12 +43,7 @@ ARG GO_PROXY_BUILD_FROM=release COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt -# install nim (to be retired once we are fully switched to using functions-deployer) -ARG NIM_INSTALL_SCRIPT= -SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN curl ${NIM_INSTALL_SCRIPT} | bash - -# install the functions-deployer (co-exist with nim temporarily) +# install the functions-deployer ARG DEPLOYER_DOWNLOAD SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN curl -L ${DEPLOYER_DOWNLOAD} | tar xzf - \ From bd3380bd772c2b00c41613430843fc85e73ccc3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Thu, 1 Dec 2022 08:00:32 +0100 Subject: [PATCH 12/19] Align akka dependencies to allow us to run tests (#13) This aligns the akka dependencies with what we're using in our "main" repository. This is required to run the Scala-based tests in this repository. --- settings.gradle | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/settings.gradle b/settings.gradle index b649190a..5980ad00 100644 --- a/settings.gradle +++ b/settings.gradle @@ -34,13 +34,10 @@ gradle.ext.scala = [ compileFlags: ['-feature', '-unchecked', '-deprecation', '-Xfatal-warnings', '-Ywarn-unused-import'] ] -gradle.ext.akka = [version : '2.6.12'] -gradle.ext.akka_http = [version : '10.2.4'] - gradle.ext.scalafmt = [ version: '1.5.0', config: new File(rootProject.projectDir, '.scalafmt.conf') ] -gradle.ext.akka = [version: '2.6.12'] -gradle.ext.akka_http = [version: '10.2.4'] +gradle.ext.akka = [version: '2.5.32'] +gradle.ext.akka_http = [version: '10.1.15'] From 692db6c578fb5588268c51863091df6d326be83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Fri, 2 Dec 2022 08:33:57 +0100 Subject: [PATCH 13/19] SERVERLESS-2327 Map environment into a context parameter (#11) * SERVERLESS-2327 Map environment into a context parameter This translates our current environment variable based approach into passing a second "context" parameter to the function. The context somewhat resembles Lambda's context parameter but notably keeps the notion of an "activation_id" as that's still an entity we use in our docs and API. * Narrow down test for remaining time * Add request_id to map tid * Add namespace, api_host and api_key --- core/python3Action/lib/launcher.py | 28 ++++++++- core/python3Action/lib/prelauncher.py | 28 ++++++++- .../PythonAdvancedTests.scala | 58 ++++++++++++++++++- 3 files changed, 109 insertions(+), 5 deletions(-) diff --git a/core/python3Action/lib/launcher.py b/core/python3Action/lib/launcher.py index e6c5e31a..7b6d9a61 100755 --- a/core/python3Action/lib/launcher.py +++ b/core/python3Action/lib/launcher.py @@ -19,7 +19,7 @@ from sys import stdout from sys import stderr from os import fdopen -import sys, os, json, traceback, warnings +import sys, os, json, traceback, time log_sentinel="XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n" @@ -45,6 +45,30 @@ # now import the action as process input/output from main__ import main as main +class Context: + def __init__(self, env): + self.function_name = env["__OW_ACTION_NAME"] + self.function_version = env["__OW_ACTION_VERSION"] + self.activation_id = env["__OW_ACTIVATION_ID"] + self.request_id = env["__OW_TRANSACTION_ID"] + self.deadline = int(env["__OW_DEADLINE"]) + self.api_host = env["__OW_API_HOST"] + self.api_key = env.get("__OW_AUTH_KEY", "") + self.namespace = env["__OW_NAMESPACE"] + + def get_remaining_time_in_millis(self): + epoch_now_in_ms = int(time.time() * 1000) + delta_ms = self.deadline - epoch_now_in_ms + return delta_ms if delta_ms > 0 else 0 + +def fun(payload, env): + # Compatibility: Supports "old" context-less functions. + if main.__code__.co_argcount == 1: + return main(payload) + + # Lambda-like "new-style" function. + return main(payload, Context(env)) + out = fdopen(3, "wb") if os.getenv("__OW_WAIT_FOR_ACK", "") != "": out.write(json.dumps({"ok": True}, ensure_ascii=False).encode('utf-8')) @@ -64,7 +88,7 @@ env["__OW_%s" % key.upper()]= args[key] res = {} try: - res = main(payload) + res = fun(payload, env) except Exception as ex: print(traceback.format_exc(), file=stderr) res = {"error": str(ex)} diff --git a/core/python3Action/lib/prelauncher.py b/core/python3Action/lib/prelauncher.py index c02e41e3..e4bfb3dd 100755 --- a/core/python3Action/lib/prelauncher.py +++ b/core/python3Action/lib/prelauncher.py @@ -21,7 +21,7 @@ from sys import stdout from sys import stderr from os import fdopen -import sys, os, json, traceback, base64, io, zipfile +import sys, os, json, traceback, base64, io, zipfile, time log_sentinel="XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX\n" def write_sentinels(): @@ -97,6 +97,30 @@ def cannot_start(msg): except Exception as ex: cannot_start("Invalid action: %s\n" % str(ex)) +class Context: + def __init__(self, env): + self.function_name = env["__OW_ACTION_NAME"] + self.function_version = env["__OW_ACTION_VERSION"] + self.activation_id = env["__OW_ACTIVATION_ID"] + self.request_id = env["__OW_TRANSACTION_ID"] + self.deadline = int(env["__OW_DEADLINE"]) + self.api_host = env["__OW_API_HOST"] + self.api_key = env.get("__OW_AUTH_KEY", "") + self.namespace = env["__OW_NAMESPACE"] + + def get_remaining_time_in_millis(self): + epoch_now_in_ms = int(time.time() * 1000) + delta_ms = self.deadline - epoch_now_in_ms + return delta_ms if delta_ms > 0 else 0 + +def fun(payload, env): + # Compatibility: Supports "old" context-less functions. + if main.__code__.co_argcount == 1: + return main(payload) + + # Lambda-like "new-style" function. + return main(payload, Context(env)) + # Acknowledge the initialization. write_result({"ok": True}) @@ -113,7 +137,7 @@ def cannot_start(msg): os.environ["__OW_%s" % key.upper()]= args[key] res = {} try: - res = main(payload) + res = fun(payload, os.environ) except Exception as ex: print(traceback.format_exc(), file=stderr) res = {"error": str(ex)} diff --git a/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala b/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala index d4bd9d9a..007485ef 100644 --- a/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala +++ b/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala @@ -16,7 +16,9 @@ */ package runtime.actionContainers -import spray.json.{JsObject, JsString} +import spray.json._ +import spray.json.DefaultJsonProtocol._ +import java.time.Instant trait PythonAdvancedTests { this: PythonBasicTests => @@ -91,4 +93,58 @@ trait PythonAdvancedTests { e shouldBe empty }) } + + Map( + "prelaunched" -> Map.empty[String, String], + "non-prelaunched" -> Map("OW_INIT_IN_ACTIONLOOP" -> ""), + ).foreach { case (name, env) => + it should s"support a function with a lambda-like signature $name" in { + val (out, err) = withActionContainer(env + ("__OW_API_HOST" -> "testhost")) { c => + val code = + """ + |def main(event, context): + | return { + | "remaining_time": context.get_remaining_time_in_millis(), + | "activation_id": context.activation_id, + | "request_id": context.request_id, + | "function_name": context.function_name, + | "function_version": context.function_version, + | "api_host": context.api_host, + | "api_key": context.api_key, + | "namespace": context.namespace + | } + """.stripMargin + + val (initCode, _) = c.init(initPayload(code)) + initCode should be(200) + + val (runCode, out) = c.run(runPayload( + JsObject(), + Some(JsObject( + "deadline" -> Instant.now.plusSeconds(10).toEpochMilli.toString.toJson, + "activation_id" -> "testaid".toJson, + "transaction_id" -> "testtid".toJson, + "action_name" -> "testfunction".toJson, + "action_version" -> "0.0.1".toJson, + "namespace" -> "testnamespace".toJson, + "auth_key" -> "testkey".toJson + )) + )) + runCode should be(200) + + val remainingTime = out.get.fields("remaining_time").convertTo[Int] + remainingTime should be > 9500 // We give the test 500ms of slack to invoke the function to avoid flakes. + out shouldBe Some(JsObject( + "remaining_time" -> remainingTime.toJson, + "activation_id" -> "testaid".toJson, + "request_id" -> "testtid".toJson, + "function_name" -> "testfunction".toJson, + "function_version" -> "0.0.1".toJson, + "api_host" -> "testhost".toJson, + "api_key" -> "testkey".toJson, + "namespace" -> "testnamespace".toJson + )) + } + } + } } From 307cc21df8ac64310709abcc2f2a55189fed859e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Fri, 2 Dec 2022 09:56:48 +0100 Subject: [PATCH 14/19] Fix the env name to __OW_API_KEY (#14) --- core/python3Action/lib/launcher.py | 2 +- core/python3Action/lib/prelauncher.py | 2 +- .../scala/runtime/actionContainers/PythonAdvancedTests.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/python3Action/lib/launcher.py b/core/python3Action/lib/launcher.py index 7b6d9a61..f288b8f0 100755 --- a/core/python3Action/lib/launcher.py +++ b/core/python3Action/lib/launcher.py @@ -53,7 +53,7 @@ def __init__(self, env): self.request_id = env["__OW_TRANSACTION_ID"] self.deadline = int(env["__OW_DEADLINE"]) self.api_host = env["__OW_API_HOST"] - self.api_key = env.get("__OW_AUTH_KEY", "") + self.api_key = env.get("__OW_API_KEY", "") self.namespace = env["__OW_NAMESPACE"] def get_remaining_time_in_millis(self): diff --git a/core/python3Action/lib/prelauncher.py b/core/python3Action/lib/prelauncher.py index e4bfb3dd..7f6d70ad 100755 --- a/core/python3Action/lib/prelauncher.py +++ b/core/python3Action/lib/prelauncher.py @@ -105,7 +105,7 @@ def __init__(self, env): self.request_id = env["__OW_TRANSACTION_ID"] self.deadline = int(env["__OW_DEADLINE"]) self.api_host = env["__OW_API_HOST"] - self.api_key = env.get("__OW_AUTH_KEY", "") + self.api_key = env.get("__OW_API_KEY", "") self.namespace = env["__OW_NAMESPACE"] def get_remaining_time_in_millis(self): diff --git a/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala b/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala index 007485ef..e3289de9 100644 --- a/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala +++ b/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala @@ -127,7 +127,7 @@ trait PythonAdvancedTests { "action_name" -> "testfunction".toJson, "action_version" -> "0.0.1".toJson, "namespace" -> "testnamespace".toJson, - "auth_key" -> "testkey".toJson + "api_key" -> "testkey".toJson )) )) runCode should be(200) From d7a83be504867ab28eea7297738a03c7e2550adf Mon Sep 17 00:00:00 2001 From: Matt Welke Date: Wed, 4 Jan 2023 08:36:26 -0500 Subject: [PATCH 15/19] SERVERLESS-2388 Add support for function signatures - no param and returning nothing Add support for function signatures - no param and returning nothing. (#15) All of our other runtimes support having a function that has no parameters. They also support having a function that returns nothing. In the case where nothing is returned by the function, the runtime returns an empty dictionary to the rest of the OpenWhisk system. This changes he Python runtime to match that behavior. --- core/python3Action/lib/launcher.py | 9 +++++++-- core/python3Action/lib/prelauncher.py | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/core/python3Action/lib/launcher.py b/core/python3Action/lib/launcher.py index f288b8f0..c7adc82f 100755 --- a/core/python3Action/lib/launcher.py +++ b/core/python3Action/lib/launcher.py @@ -62,12 +62,17 @@ def get_remaining_time_in_millis(self): return delta_ms if delta_ms > 0 else 0 def fun(payload, env): + # Compatibility: Supporting "old" context-less functions that have no params + # to match other languages. + if main.__code__.co_argcount == 0: + return main() or {} + # Compatibility: Supports "old" context-less functions. if main.__code__.co_argcount == 1: - return main(payload) + return main(payload) or {} # Lambda-like "new-style" function. - return main(payload, Context(env)) + return main(payload, Context(env)) or {} out = fdopen(3, "wb") if os.getenv("__OW_WAIT_FOR_ACK", "") != "": diff --git a/core/python3Action/lib/prelauncher.py b/core/python3Action/lib/prelauncher.py index 7f6d70ad..bb51a08b 100755 --- a/core/python3Action/lib/prelauncher.py +++ b/core/python3Action/lib/prelauncher.py @@ -114,12 +114,17 @@ def get_remaining_time_in_millis(self): return delta_ms if delta_ms > 0 else 0 def fun(payload, env): + # Compatibility: Supporting "old" context-less functions that have no params + # to match other languages. + if main.__code__.co_argcount == 0: + return main() or {} + # Compatibility: Supports "old" context-less functions. if main.__code__.co_argcount == 1: - return main(payload) + return main(payload) or {} # Lambda-like "new-style" function. - return main(payload, Context(env)) + return main(payload, Context(env)) or {} # Acknowledge the initialization. write_result({"ok": True}) From 4f45506dca7d1e5aa1a4e82095762dba244bb67c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Wed, 25 Jan 2023 15:54:16 +0100 Subject: [PATCH 16/19] SERVERLESS-2491 Rename action -> function in error messages (#16) --- core/python3Action/lib/prelauncher.py | 4 ++-- .../scala/runtime/actionContainers/PythonAdvancedTests.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/python3Action/lib/prelauncher.py b/core/python3Action/lib/prelauncher.py index bb51a08b..88189c91 100755 --- a/core/python3Action/lib/prelauncher.py +++ b/core/python3Action/lib/prelauncher.py @@ -38,7 +38,7 @@ def write_result(res): def cannot_start(msg): stderr.write(msg) - write_result({"error": "Cannot start action. Check logs for details."}) + write_result({"error": "Cannot start function. Check logs for details."}) write_sentinels() sys.exit(1) @@ -95,7 +95,7 @@ def cannot_start(msg): sys.path.append(os.getcwd()) main = getattr(__import__("main__", fromlist=[init["main"]]), init["main"]) except Exception as ex: - cannot_start("Invalid action: %s\n" % str(ex)) + cannot_start("Invalid function: %s\n" % str(ex)) class Context: def __init__(self, env): diff --git a/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala b/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala index e3289de9..1417c977 100644 --- a/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala +++ b/tests/src/test/scala/runtime/actionContainers/PythonAdvancedTests.scala @@ -60,7 +60,7 @@ trait PythonAdvancedTests { // action loop detects those errors at init time val (initCode, initRes) = c.init(initPayload(code)) initCode should be(502) - initRes.get.fields.get("error").get.toString() should include("Cannot start action") + initRes.get.fields.get("error").get.toString() should include("Cannot start function") } checkStreams(out, err, { case (o, e) => From a682793adedcd30960c64ef8f8e5e886d027256a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Th=C3=B6mmes?= Date: Mon, 24 Apr 2023 10:58:58 +0200 Subject: [PATCH 17/19] SERVERLESS-2773 Add a Python 3.11 runtime (#17) This adds Python 3.11. It's mostly a 1:1 copy with the only notable change being that this uses the "slim" variant of the base image. --- core/python311Action/Dockerfile | 64 +++++++++++++++++++ core/python311Action/build.gradle | 38 +++++++++++ settings.gradle | 1 + tests/src/test/resources/build.sh | 2 +- .../actionContainers/Python311Tests.scala | 33 ++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 core/python311Action/Dockerfile create mode 100644 core/python311Action/build.gradle create mode 100644 tests/src/test/scala/runtime/actionContainers/Python311Tests.scala diff --git a/core/python311Action/Dockerfile b/core/python311Action/Dockerfile new file mode 100644 index 00000000..0d1bffd4 --- /dev/null +++ b/core/python311Action/Dockerfile @@ -0,0 +1,64 @@ +# +# 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. +# + +# build go proxy from source +ARG GO_PROXY_BASE_IMAGE=golang:1.20 +FROM $GO_PROXY_BASE_IMAGE AS builder +ARG GO_PROXY_GITHUB_USER=nimbella-corp +ARG GO_PROXY_GITHUB_BRANCH=dev +RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src \ + && cd /src \ + && env GO111MODULE=on CGO_ENABLED=0 go build -o /bin/proxy main/proxy.go + +FROM python:3.11-slim-bullseye + +# select the builder to use +ARG GO_PROXY_BUILD_FROM=release + +# Install common modules for python +COPY requirements.txt requirements.txt +RUN pip install --no-cache-dir -r requirements.txt + +# install the functions-deployer +ARG DEPLOYER_DOWNLOAD +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl \ + && curl -L ${DEPLOYER_DOWNLOAD} | tar xzf - \ + && rm -fr /usr/local/lib/dosls && mv dosls /usr/local/lib \ + && rm -f /usr/local/bin/dosls && ln -s /usr/local/lib/dosls/bootstrap /usr/local/bin/dosls \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir -p /action +WORKDIR / +COPY bin/compile /bin/compile +COPY lib/launcher.py /lib/launcher.py +COPY lib/prelauncher.py /lib/prelauncher.py + +# log initialization errors +ENV OW_LOG_INIT_ERROR=1 +# the launcher must wait for an ack +ENV OW_WAIT_FOR_ACK=1 +# using the runtime name to identify the execution environment +#ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.9 +# compiler script +ENV OW_COMPILER=/bin/compile + +ENV OW_INIT_IN_ACTIONLOOP=/lib/prelauncher.py + +COPY --from=builder /bin/proxy /bin/proxy +ENTRYPOINT ["/bin/proxy"] diff --git a/core/python311Action/build.gradle b/core/python311Action/build.gradle new file mode 100644 index 00000000..06b82e76 --- /dev/null +++ b/core/python311Action/build.gradle @@ -0,0 +1,38 @@ +/* + * 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-python-v3.11' +apply from: '../../gradle/docker.gradle' + +distDocker.dependsOn 'copyLib' +distDocker.dependsOn 'copyBin' +distDocker.finalizedBy('cleanup') + +task copyLib(type: Copy) { + from '../python3Action/lib' + into './lib' +} + +task copyBin(type: Copy) { + from '../python3Action/bin' + into './bin' +} + +task cleanup(type: Delete) { + delete 'bin' + delete 'lib' +} diff --git a/settings.gradle b/settings.gradle index 5980ad00..c21b676c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,6 +21,7 @@ include 'core:python2ActionLoop' include 'core:python3Action' include 'core:python36AiAction' include 'core:python39Action' +include 'core:python311Action' rootProject.name = 'runtime-python' diff --git a/tests/src/test/resources/build.sh b/tests/src/test/resources/build.sh index bbc46160..0c9391a7 100755 --- a/tests/src/test/resources/build.sh +++ b/tests/src/test/resources/build.sh @@ -21,7 +21,7 @@ if [ -f ".built" ]; then exit 0 fi -for i in v3.7 v3.6-ai v3.9 +for i in v3.7 v3.6-ai v3.9 v3.11 do echo "*** $i ***" zip -r -j - python_virtualenv | docker run -i action-python-$i -compile main >python-${i}_virtualenv.zip cp python-${i}_virtualenv.zip python-${i}_virtualenv_invalid_main.zip diff --git a/tests/src/test/scala/runtime/actionContainers/Python311Tests.scala b/tests/src/test/scala/runtime/actionContainers/Python311Tests.scala new file mode 100644 index 00000000..e758872e --- /dev/null +++ b/tests/src/test/scala/runtime/actionContainers/Python311Tests.scala @@ -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. + */ + +package runtime.actionContainers + +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class Python311Tests extends Python37Tests { + + override lazy val imageName = "action-python-v3.11" + + override lazy val zipPrefix = "python-v3.11" + + override lazy val errorCodeOnRun = false + + override val testNoSource = TestConfig("", hasCodeStub = false) +} From 08249cc481e830cf3363cecda653056a58298485 Mon Sep 17 00:00:00 2001 From: sdharav Date: Sat, 17 Jan 2026 02:39:07 +0530 Subject: [PATCH 18/19] SERVERLESS-3565: Fix python runtime and update daft to v0.4.8 source build --- build.gradle | 18 ++++++++++--- core/python311Action/Dockerfile | 46 ++++++++++++++++++++++++--------- settings.gradle | 2 +- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index 4ebd4b8c..3522adb1 100644 --- a/build.gradle +++ b/build.gradle @@ -15,16 +15,26 @@ * limitations under the License. */ + + buildscript { repositories { - jcenter() + mavenCentral() + gradlePluginPortal() } dependencies { - classpath "cz.alenkacz:gradle-scalafmt:${gradle.scalafmt.version}" + // Dependencies for the build script itself go here } } +plugins { + id "cz.alenkacz.gradle.scalafmt" version "1.16.2" apply false +} + subprojects { - apply plugin: 'scalafmt' - scalafmt.configFilePath = gradle.scalafmt.config + // Only apply if the project is a Scala project or has the property + if (project.name.contains("scala") || project.hasProperty('scalafmt')) { + apply plugin: 'cz.alenkacz.gradle.scalafmt' + scalafmt.configFilePath = gradle.scalafmt.config + } } diff --git a/core/python311Action/Dockerfile b/core/python311Action/Dockerfile index 0d1bffd4..06ef0181 100644 --- a/core/python311Action/Dockerfile +++ b/core/python311Action/Dockerfile @@ -15,33 +15,56 @@ # limitations under the License. # -# build go proxy from source +# --- BUILDER STAGE: Compile the Go Proxy --- ARG GO_PROXY_BASE_IMAGE=golang:1.20 FROM $GO_PROXY_BASE_IMAGE AS builder -ARG GO_PROXY_GITHUB_USER=nimbella-corp -ARG GO_PROXY_GITHUB_BRANCH=dev + +# Use the standard Apache repository and the correct branch ('master') +ARG GO_PROXY_GITHUB_USER=apache +ARG GO_PROXY_GITHUB_BRANCH=master + RUN git clone --branch ${GO_PROXY_GITHUB_BRANCH} https://github.com/${GO_PROXY_GITHUB_USER}/openwhisk-runtime-go /src \ && cd /src \ && env GO111MODULE=on CGO_ENABLED=0 go build -o /bin/proxy main/proxy.go +# --- RUNTIME STAGE: Python 3.11 --- FROM python:3.11-slim-bullseye # select the builder to use ARG GO_PROXY_BUILD_FROM=release +# --- FIX: Install build tools for daft 0.4.8 source build --- +RUN apt-get update && apt-get install -y --no-install-recommends \ + git \ + gcc \ + build-essential \ + python3-dev \ + curl \ + unzip \ + && rm -rf /var/lib/apt/lists/* + +# Install Bun +RUN curl -fsSL https://bun.sh/install | bash + +# Install Rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + +# Add Bun and Rust to the PATH +ENV PATH="/root/.bun/bin:/root/.cargo/bin:${PATH}" +# --- END FIX --- + # Install common modules for python COPY requirements.txt requirements.txt -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt # install the functions-deployer -ARG DEPLOYER_DOWNLOAD +# ADDED DEFAULT VALUE HERE TO FIX THE CURL ERROR +ARG DEPLOYER_DOWNLOAD=https://do-serverless-tools.nyc3.digitaloceanspaces.com/dosls-5.0.22.tgz SHELL ["/bin/bash", "-o", "pipefail", "-c"] -RUN apt-get update \ - && apt-get install -y --no-install-recommends curl \ - && curl -L ${DEPLOYER_DOWNLOAD} | tar xzf - \ +RUN curl -L ${DEPLOYER_DOWNLOAD} | tar xzf - \ && rm -fr /usr/local/lib/dosls && mv dosls /usr/local/lib \ - && rm -f /usr/local/bin/dosls && ln -s /usr/local/lib/dosls/bootstrap /usr/local/bin/dosls \ - && rm -rf /var/lib/apt/lists/* + && rm -f /usr/local/bin/dosls && ln -s /usr/local/lib/dosls/bootstrap /usr/local/bin/dosls RUN mkdir -p /action WORKDIR / @@ -53,8 +76,6 @@ COPY lib/prelauncher.py /lib/prelauncher.py ENV OW_LOG_INIT_ERROR=1 # the launcher must wait for an ack ENV OW_WAIT_FOR_ACK=1 -# using the runtime name to identify the execution environment -#ENV OW_EXECUTION_ENV=openwhisk/action-python-v3.9 # compiler script ENV OW_COMPILER=/bin/compile @@ -62,3 +83,4 @@ ENV OW_INIT_IN_ACTIONLOOP=/lib/prelauncher.py COPY --from=builder /bin/proxy /bin/proxy ENTRYPOINT ["/bin/proxy"] + diff --git a/settings.gradle b/settings.gradle index c21b676c..5e6a8118 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,7 +36,7 @@ gradle.ext.scala = [ ] gradle.ext.scalafmt = [ - version: '1.5.0', + version: '1.16.2', config: new File(rootProject.projectDir, '.scalafmt.conf') ] From f34e7984e26c8765857606c649ff76824f42c600 Mon Sep 17 00:00:00 2001 From: sdharav Date: Sat, 17 Jan 2026 03:09:46 +0530 Subject: [PATCH 19/19] SERVERLESS-3565: Include Python 311 in the Travis publish pipeline --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 18ec909e..739287de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,13 +39,13 @@ script: - "./tools/travis/build.sh && ./tools/travis/test.sh" deploy: - provider: script - script: "./tools/travis/publish.sh nimbella 3 ${TRAVIS_TAG} && ./tools/travis/publish.sh nimbella 3-ai ${TRAVIS_TAG} && ./tools/travis/publish.sh nimbella 39 ${TRAVIS_TAG}" + script: "./tools/travis/publish.sh nimbella 3 ${TRAVIS_TAG} && ./tools/travis/publish.sh nimbella 3-ai ${TRAVIS_TAG} && ./tools/travis/publish.sh nimbella 39 ${TRAVIS_TAG} **&& ./tools/travis/publish.sh nimbella 311 ${TRAVIS_TAG}**" on: tags: true all_branches: true repo: nimbella-corp/openwhisk-runtime-python - provider: script - script: "./tools/travis/publish.sh nimbella 3 nightly && ./tools/travis/publish.sh nimbella 3-ai nightly && ./tools/travis/publish.sh nimbella 39 nightly" + script: "./tools/travis/publish.sh nimbella 3 nightly && ./tools/travis/publish.sh nimbella 3-ai nightly && ./tools/travis/publish.sh nimbella 39 nightly **&& ./tools/travis/publish.sh nimbella 311 nightly**" on: branch: dev repo: nimbella-corp/openwhisk-runtime-python