From bf64898aeef51bc41aaf7cc7cd5851fb80fdb5d1 Mon Sep 17 00:00:00 2001 From: "Alex Ellis (OpenFaaS Ltd)" Date: Mon, 3 Oct 2022 15:50:50 +0100 Subject: [PATCH] Remove armhf templates and move to multi-arch / buildx Migrate as per the python3 template in the classic Go templates, where a separate -armhf/-arm64 template is not required and TARGETPLATFORM is introduced for use with buildkit / buildx and faas-cli publish. Tested with an RPi with a 32-bit OS and with a 64-bit ARM OS (Ubuntu 20.04). Signed-off-by: Alex Ellis (OpenFaaS Ltd) --- README.md | 13 ++- template/python3-flask-armhf/Dockerfile | 54 ------------- .../python3-flask-armhf/function/__init__.py | 0 .../python3-flask-armhf/function/handler.py | 7 -- .../function/handler_test.py | 10 --- .../function/requirements.txt | 0 template/python3-flask-armhf/function/tox.ini | 41 ---------- template/python3-flask-armhf/index.py | 41 ---------- template/python3-flask-armhf/requirements.txt | 3 - template/python3-flask-armhf/template.yml | 2 - template/python3-flask-debian/Dockerfile | 4 +- template/python3-flask/Dockerfile | 4 +- template/python3-http-armhf/Dockerfile | 51 ------------ .../python3-http-armhf/function/handler.py | 6 -- .../function/handler_test.py | 10 --- .../function/requirements.txt | 0 template/python3-http-armhf/function/tox.ini | 41 ---------- template/python3-http-armhf/index.py | 81 ------------------- template/python3-http-armhf/requirements.txt | 3 - template/python3-http-armhf/template.yml | 14 ---- template/python3-http-debian/Dockerfile | 4 +- template/python3-http/Dockerfile | 4 +- 22 files changed, 14 insertions(+), 379 deletions(-) delete mode 100644 template/python3-flask-armhf/Dockerfile delete mode 100644 template/python3-flask-armhf/function/__init__.py delete mode 100644 template/python3-flask-armhf/function/handler.py delete mode 100644 template/python3-flask-armhf/function/handler_test.py delete mode 100644 template/python3-flask-armhf/function/requirements.txt delete mode 100644 template/python3-flask-armhf/function/tox.ini delete mode 100644 template/python3-flask-armhf/index.py delete mode 100644 template/python3-flask-armhf/requirements.txt delete mode 100644 template/python3-flask-armhf/template.yml delete mode 100644 template/python3-http-armhf/Dockerfile delete mode 100644 template/python3-http-armhf/function/handler.py delete mode 100644 template/python3-http-armhf/function/handler_test.py delete mode 100644 template/python3-http-armhf/function/requirements.txt delete mode 100644 template/python3-http-armhf/function/tox.ini delete mode 100644 template/python3-http-armhf/index.py delete mode 100644 template/python3-http-armhf/requirements.txt delete mode 100644 template/python3-http-armhf/template.yml diff --git a/README.md b/README.md index 7d25a9d..2c0d85d 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,16 @@ The Python Flask templates that make use of the incubator project [of-watchdog]( Templates available in this repository: -- python27-flask +- python3-http +- python3-http-debian (ideal for compiled dependencies like numpy, pandas, pillow) + - python3-flask -- python3-flask-debian -- python3-flask-armhf +- python3-flask-debian (ideal for compiled dependencies like numpy, pandas, pillow) -- python3-http -- python3-http-debian -- python3-http-armhf +- python27-flask (Python 2.7 is deprecated) Notes: -- To build and deploy a function for Raspberry Pi or ARMv7 in general, use the language templates ending in *-armhf* +- To build and deploy a function for an ARM computer, you'll need to use `faas-cli publish --platforms` ## Picking your template diff --git a/template/python3-flask-armhf/Dockerfile b/template/python3-flask-armhf/Dockerfile deleted file mode 100644 index 1d34249..0000000 --- a/template/python3-flask-armhf/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -FROM ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog -FROM armhf/python:3.6-alpine - -ARG ADDITIONAL_PACKAGE - -COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog -RUN chmod +x /usr/bin/fwatchdog - -RUN apk --no-cache add openssl-dev ${ADDITIONAL_PACKAGE} - -# Add non root user -RUN addgroup -S app && adduser app -S -G app -RUN chown app /home/app - -USER app - -ENV PATH=$PATH:/home/app/.local/bin - -WORKDIR /home/app/ - -COPY index.py . -COPY requirements.txt . -USER root -RUN pip install -r requirements.txt -USER app - -RUN mkdir -p function -RUN touch ./function/__init__.py -WORKDIR /home/app/function/ -COPY function/requirements.txt . -RUN pip install --user -r requirements.txt - -USER root -COPY function/ . -RUN chown -R app:app ../ - -ARG TEST_COMMAND=tox -ARG TEST_ENABLED=true -RUN [ "$TEST_ENABLED" = "false" ] && echo "skipping tests" || eval "$TEST_COMMAND" - -WORKDIR /home/app/ - -USER app - -ENV fprocess="python index.py" - -ENV cgi_headers="true" -ENV mode="http" -ENV upstream_url="http://127.0.0.1:5000" - - -HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1 - -CMD ["fwatchdog"] diff --git a/template/python3-flask-armhf/function/__init__.py b/template/python3-flask-armhf/function/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/template/python3-flask-armhf/function/handler.py b/template/python3-flask-armhf/function/handler.py deleted file mode 100644 index a7098fa..0000000 --- a/template/python3-flask-armhf/function/handler.py +++ /dev/null @@ -1,7 +0,0 @@ -def handle(req): - """handle a request to the function - Args: - req (str): request body - """ - - return req diff --git a/template/python3-flask-armhf/function/handler_test.py b/template/python3-flask-armhf/function/handler_test.py deleted file mode 100644 index b07d5bf..0000000 --- a/template/python3-flask-armhf/function/handler_test.py +++ /dev/null @@ -1,10 +0,0 @@ -from .handler import handle - -# Test your handler here - -# To disable testing, you can set the build_arg `TEST_ENABLED=false` on the CLI or in your stack.yml -# https://docs.openfaas.com/reference/yaml/#function-build-args-build-args - -def test_handle(): - # assert handle("input") == "input" - pass diff --git a/template/python3-flask-armhf/function/requirements.txt b/template/python3-flask-armhf/function/requirements.txt deleted file mode 100644 index e69de29..0000000 diff --git a/template/python3-flask-armhf/function/tox.ini b/template/python3-flask-armhf/function/tox.ini deleted file mode 100644 index a64a800..0000000 --- a/template/python3-flask-armhf/function/tox.ini +++ /dev/null @@ -1,41 +0,0 @@ -# If you would like to disable -# automated testing during faas-cli build, - -# Replace the content of this file with -# [tox] -# skipsdist = true - -# You can also edit, remove, or add additional test steps -# by editing, removing, or adding new testenv sections - - -# find out more about tox: https://tox.readthedocs.io/en/latest/ -[tox] -envlist = lint,test -skipsdist = true - -[testenv:test] -deps = - flask - pytest - -rrequirements.txt -commands = - # run unit tests with pytest - # https://docs.pytest.org/en/stable/ - # configure by adding a pytest.ini to your handler - pytest - -[testenv:lint] -deps = - flake8 -commands = - flake8 . - -[flake8] -count = true -max-line-length = 127 -max-complexity = 10 -statistics = true -# stop the build if there are Python syntax errors or undefined names -select = E9,F63,F7,F82 -show-source = true diff --git a/template/python3-flask-armhf/index.py b/template/python3-flask-armhf/index.py deleted file mode 100644 index 48554ff..0000000 --- a/template/python3-flask-armhf/index.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (c) Alex Ellis 2017. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -from flask import Flask, request -from function import handler -from waitress import serve -import os - -app = Flask(__name__) - -# distutils.util.strtobool() can throw an exception -def is_true(val): - return len(val) > 0 and val.lower() == "true" or val == "1" - -@app.before_request -def fix_transfer_encoding(): - """ - Sets the "wsgi.input_terminated" environment flag, thus enabling - Werkzeug to pass chunked requests as streams. The gunicorn server - should set this, but it's not yet been implemented. - """ - - transfer_encoding = request.headers.get("Transfer-Encoding", None) - if transfer_encoding == u"chunked": - request.environ["wsgi.input_terminated"] = True - -@app.route("/", defaults={"path": ""}, methods=["POST", "GET"]) -@app.route("/", methods=["POST", "GET"]) -def main_route(path): - raw_body = os.getenv("RAW_BODY", "false") - - as_text = True - - if is_true(raw_body): - as_text = False - - ret = handler.handle(request.get_data(as_text=as_text)) - return ret - -if __name__ == '__main__': - serve(app, host='0.0.0.0', port=5000) diff --git a/template/python3-flask-armhf/requirements.txt b/template/python3-flask-armhf/requirements.txt deleted file mode 100644 index 5c3b5e8..0000000 --- a/template/python3-flask-armhf/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -flask -waitress -tox==3.* diff --git a/template/python3-flask-armhf/template.yml b/template/python3-flask-armhf/template.yml deleted file mode 100644 index 106d489..0000000 --- a/template/python3-flask-armhf/template.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: python3-flask-armhf -fprocess: python index.py diff --git a/template/python3-flask-debian/Dockerfile b/template/python3-flask-debian/Dockerfile index 4495c36..b3c8e84 100644 --- a/template/python3-flask-debian/Dockerfile +++ b/template/python3-flask-debian/Dockerfile @@ -1,5 +1,5 @@ -FROM ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog -FROM python:3.7-slim-buster +FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog +FROM --platform=${TARGETPLATFORM:-linux/amd64} python:3.7-slim-buster COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog RUN chmod +x /usr/bin/fwatchdog diff --git a/template/python3-flask/Dockerfile b/template/python3-flask/Dockerfile index b225651..205633c 100644 --- a/template/python3-flask/Dockerfile +++ b/template/python3-flask/Dockerfile @@ -1,5 +1,5 @@ -FROM ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog -FROM python:3.7-alpine +FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog +FROM --platform=${TARGETPLATFORM:-linux/amd64} python:3.7-alpine COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog RUN chmod +x /usr/bin/fwatchdog diff --git a/template/python3-http-armhf/Dockerfile b/template/python3-http-armhf/Dockerfile deleted file mode 100644 index 708a65f..0000000 --- a/template/python3-http-armhf/Dockerfile +++ /dev/null @@ -1,51 +0,0 @@ -FROM ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog -FROM armhf/python:3.6-alpine - -ARG ADDITIONAL_PACKAGE - -COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog -RUN chmod +x /usr/bin/fwatchdog - -# Add non root user -RUN addgroup -S app && adduser app -S -G app -RUN chown app /home/app - -USER app - -ENV PATH=$PATH:/home/app/.local/bin - -WORKDIR /home/app/ - -COPY index.py . -COPY requirements.txt . -USER root -RUN pip install -r requirements.txt -USER app - -RUN mkdir -p function -RUN touch ./function/__init__.py -WORKDIR /home/app/function/ -COPY function/requirements.txt . -RUN pip install --user -r requirements.txt - -USER root -COPY function/ . -RUN chown -R app:app ../ - -ARG TEST_COMMAND=tox -ARG TEST_ENABLED=true -RUN [ "$TEST_ENABLED" = "false" ] && echo "skipping tests" || eval "$TEST_COMMAND" - -WORKDIR /home/app/ - -USER app - -# Set up of-watchdog for HTTP mode -ENV fprocess="python index.py" -ENV cgi_headers="true" -ENV mode="http" -ENV upstream_url="http://127.0.0.1:5000" - -HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1 - -CMD ["fwatchdog"] diff --git a/template/python3-http-armhf/function/handler.py b/template/python3-http-armhf/function/handler.py deleted file mode 100644 index 14a5f7d..0000000 --- a/template/python3-http-armhf/function/handler.py +++ /dev/null @@ -1,6 +0,0 @@ -def handle(event, context): - # TODO implement - return { - "statusCode": 200, - "body": "Hello from OpenFaaS!" - } \ No newline at end of file diff --git a/template/python3-http-armhf/function/handler_test.py b/template/python3-http-armhf/function/handler_test.py deleted file mode 100644 index b07d5bf..0000000 --- a/template/python3-http-armhf/function/handler_test.py +++ /dev/null @@ -1,10 +0,0 @@ -from .handler import handle - -# Test your handler here - -# To disable testing, you can set the build_arg `TEST_ENABLED=false` on the CLI or in your stack.yml -# https://docs.openfaas.com/reference/yaml/#function-build-args-build-args - -def test_handle(): - # assert handle("input") == "input" - pass diff --git a/template/python3-http-armhf/function/requirements.txt b/template/python3-http-armhf/function/requirements.txt deleted file mode 100644 index e69de29..0000000 diff --git a/template/python3-http-armhf/function/tox.ini b/template/python3-http-armhf/function/tox.ini deleted file mode 100644 index a64a800..0000000 --- a/template/python3-http-armhf/function/tox.ini +++ /dev/null @@ -1,41 +0,0 @@ -# If you would like to disable -# automated testing during faas-cli build, - -# Replace the content of this file with -# [tox] -# skipsdist = true - -# You can also edit, remove, or add additional test steps -# by editing, removing, or adding new testenv sections - - -# find out more about tox: https://tox.readthedocs.io/en/latest/ -[tox] -envlist = lint,test -skipsdist = true - -[testenv:test] -deps = - flask - pytest - -rrequirements.txt -commands = - # run unit tests with pytest - # https://docs.pytest.org/en/stable/ - # configure by adding a pytest.ini to your handler - pytest - -[testenv:lint] -deps = - flake8 -commands = - flake8 . - -[flake8] -count = true -max-line-length = 127 -max-complexity = 10 -statistics = true -# stop the build if there are Python syntax errors or undefined names -select = E9,F63,F7,F82 -show-source = true diff --git a/template/python3-http-armhf/index.py b/template/python3-http-armhf/index.py deleted file mode 100644 index 2e2ec70..0000000 --- a/template/python3-http-armhf/index.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -from flask import Flask, request, jsonify -from waitress import serve -import os - -from function import handler - -app = Flask(__name__) - -class Event: - def __init__(self): - self.body = request.get_data() - self.headers = request.headers - self.method = request.method - self.query = request.args - self.path = request.path - -class Context: - def __init__(self): - self.hostname = os.getenv('HOSTNAME', 'localhost') - -def format_status_code(res): - if 'statusCode' in res: - return res['statusCode'] - - return 200 - -def format_body(res, content_type): - if content_type == 'application/octet-stream': - return res['body'] - - if 'body' not in res: - return "" - elif type(res['body']) == dict: - return jsonify(res['body']) - else: - return str(res['body']) - -def format_headers(res): - if 'headers' not in res: - return [] - elif type(res['headers']) == dict: - headers = [] - for key in res['headers'].keys(): - header_tuple = (key, res['headers'][key]) - headers.append(header_tuple) - return headers - - return res['headers'] - -def get_content_type(res): - content_type = "" - if 'headers' in res: - content_type = res['headers'].get('Content-type', '') - return content_type - -def format_response(res): - if res == None: - return ('', 200) - - statusCode = format_status_code(res) - content_type = get_content_type(res) - body = format_body(res, content_type) - - headers = format_headers(res) - - return (body, statusCode, headers) - -@app.route('/', defaults={'path': ''}, methods=['GET', 'PUT', 'POST', 'PATCH', 'DELETE']) -@app.route('/', methods=['GET', 'PUT', 'POST', 'PATCH', 'DELETE']) -def call_handler(path): - event = Event() - context = Context() - - response_data = handler.handle(event, context) - - res = format_response(response_data) - return res - -if __name__ == '__main__': - serve(app, host='0.0.0.0', port=5000) diff --git a/template/python3-http-armhf/requirements.txt b/template/python3-http-armhf/requirements.txt deleted file mode 100644 index 668a25a..0000000 --- a/template/python3-http-armhf/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -flask -waitress -tox==3.* \ No newline at end of file diff --git a/template/python3-http-armhf/template.yml b/template/python3-http-armhf/template.yml deleted file mode 100644 index 44ac678..0000000 --- a/template/python3-http-armhf/template.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: python3-http-armhf -fprocess: python index.py -build_options: - - name: dev - packages: - - make - - automake - - gcc - - g++ - - subversion - - python3-dev - - musl-dev - - libffi-dev - - git \ No newline at end of file diff --git a/template/python3-http-debian/Dockerfile b/template/python3-http-debian/Dockerfile index 388e587..70ed450 100644 --- a/template/python3-http-debian/Dockerfile +++ b/template/python3-http-debian/Dockerfile @@ -1,5 +1,5 @@ -FROM ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog -FROM python:3.7-slim-buster +FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog +FROM --platform=${TARGETPLATFORM:-linux/amd64} python:3.7-slim-buster COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog RUN chmod +x /usr/bin/fwatchdog diff --git a/template/python3-http/Dockerfile b/template/python3-http/Dockerfile index d3fd4e3..7c91cc9 100644 --- a/template/python3-http/Dockerfile +++ b/template/python3-http/Dockerfile @@ -1,5 +1,5 @@ -FROM ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog -FROM python:3.7-alpine +FROM --platform=${TARGETPLATFORM:-linux/amd64} ghcr.io/openfaas/of-watchdog:0.9.6 as watchdog +FROM --platform=${TARGETPLATFORM:-linux/amd64} python:3.7-alpine COPY --from=watchdog /fwatchdog /usr/bin/fwatchdog RUN chmod +x /usr/bin/fwatchdog