This is an automated email from the ASF dual-hosted git repository. bsalzano pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/openserverless-admin-api.git
The following commit(s) were added to refs/heads/main by this push: new 9ddf072 chore: improved README, Dockerfile and tasks 9ddf072 is described below commit 9ddf07293066d70ae4c26db060289a42a015dc55 Author: Bruno Salzano <d4rks...@gmail.com> AuthorDate: Sun Jul 27 09:24:30 2025 +0200 chore: improved README, Dockerfile and tasks Improved tasks inside Taskfile. Tested the image build process. Improved documentation in README.md --- .env.example | 12 +++-- Dockerfile | 18 +++---- README.md | 85 ++++++++++++++++++++++++++++-- Taskfile.yml | 128 +++++++++++++++++++++++++++++++++++---------- openserverless/__init__.py | 20 +++++-- openserverless/__main__.py | 24 +++++++++ 6 files changed, 238 insertions(+), 49 deletions(-) diff --git a/.env.example b/.env.example index b4f2b02..341218c 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,15 @@ LISTEN_PORT=5000 COUCHDB_SERVICE_PORT=5984 -COUCHDB_SERVICE_HOST=127.0.0.1 +COUCHDB_SERVICE_HOST=host.docker.internal COUCHDB_ADMIN_USER=whisk_admin COUCHDB_ADMIN_PASSWORD= -KUBERNETES_SERVICE_HOST=127.0.0.1 +KUBERNETES_SERVICE_HOST=host.docker.internal KUBERNETES_SERVICE_PORT=56490 KUBERNETES_TOKEN_FILENAME=./tokens/token -KUBERNETES_CERT_FILENAME=./tokens/ca.crt \ No newline at end of file +KUBERNETES_CERT_FILENAME=./tokens/ca.crt + +# registry to use (ghcr or dockerhub or apache) +# if not set, the image is build with local tag and will not be pushed +REGISTRY= +# namespace is required if REGISTRY is set +NAMESPACE= \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b221464..f0fd10b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,24 +27,24 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ unzip \ && rm -rf /var/lib/apt/lists/* -# Add nuvolaris user -RUN useradd -m -u 1001 -s /bin/bash nuvolaris -WORKDIR /home/nuvolaris +# Add openserverless user +RUN useradd -m -u 1001 -s /bin/bash openserverless +WORKDIR /home/openserverless # Copy source code con permessi corretti -ADD --chown=nuvolaris:nuvolaris nuvolaris /home/nuvolaris/nuvolaris/ -ADD --chown=nuvolaris:nuvolaris run.sh pyproject.toml uv.lock /home/nuvolaris/ +ADD --chown=openserverless:openserverless openserverless /home/openserverless/openserverless/ +ADD --chown=openserverless:openserverless run.sh pyproject.toml uv.lock /home/openserverless/ # Install uv (Python dependency manager) RUN pip install --no-cache-dir uv # Install Python dependencies usando il lockfile -RUN uv pip install --system --requirement pyproject.toml +RUN uv venv && uv pip install --requirement pyproject.toml # ...existing code... -USER nuvolaris -ENV HOME=/home/nuvolaris +USER openserverless +ENV HOME=/home/openserverless EXPOSE 5000 -CMD ["./run.sh"] +CMD ["uv", "run", "-m", "openserverless"] diff --git a/README.md b/README.md index aee68d5..affd74f 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ Lighweight OpenServerless Admin REST API Layer. + +## Endpoints + Available APIs at the moment: ### Authentication API @@ -38,15 +41,91 @@ Available APIs at the moment: ## Developer instructions -You need to have access to the kubernetes cluster. +You need to have access to be Apache OpenServerless admin and have access to kubernetes cluster. + +Refer to the [Apache OpenServerless installation page](https://openserverless.apache.org/docs/installation/install/docker/): -Give the command task `setup-developer` will: +Give the command `task setup-developer` and it will: - extract the required ca.crt and token from operator service account - copy a sample .env file -- install dependencies +- install required python dependencies After that, you can use VSCode debugger to start the application. Otherwise you can give an `uv run -m openserverless` to start. Open http://localhost:5002/system/apidocs/ to see the API documentation. + +## Tasks + +Taskfile supports the following tasks: + +```yaml +* build: Build the image locally +* build-and-load: Build the image and loads it to local Kind cluster +* buildx: Build the docker image using buildx. Set PUSH=1 to push the image to the registry. +* docker-login: Login to the docker registry. Set REGISTRY=ghcr or REGISTRY=dockerhub in .env to use the respective registry. +* get-tokens: Get Service Account tokens and save them to tokens directory +* image-tag: Create a new tag for the current git commit. +* run: Run the admin api locally, using configuration from .env file +* setup-developer: Setup developer environment +``` + +## Build and push + +### Private registry or local image + +To build an image and push it on a private repository, firstly choose which +registry you want to use. +Tasks support is for Github (ghcr) and Dockerhub (dockerhub). +So copy the `.env.example` to `.env` and configure the required variables for +authentication and set the `REGISTRY` and `NAMESPACE` accordly. + +Now create a new tag + +```bash +$ task image-tag +``` +You should see an output like this: + +```bash +Deleted tag '0.1.0-incubating.2507270903' (was 434b400) +0.1.0-incubating.2507270910 +``` + +:bulb: **NOTE** If you leave unset `REGISTRY` a local `openserverless-admin-api` +image will be built, using the generated tag. + +If you setup the `REGISTRY` and `NAMESPACE`, you can give a: + +```bash +$ task docker-login +``` + +To build: + +```bash +$ task buildx +``` + +To build and push + +```bash +$ task buildx PUSH=1 +``` + +### Apache repository +To build an official Apache OpensSrverless Admin Api image, you +need to be a committer. + +If you have the proper permissions, the build process will start pushing a +new tag to apache/openserverless-admin-api repository. +So, for example, if your tag is `0.1.0-incubating.2507270910` and your +git remote is `apache` + +```bash +$ git push apache 0.1.0-incubating.2507270910 +``` + +This will trigger the build workflow, and the process will be visible at +https://github.com/apache/openserverless-admin-api/actions \ No newline at end of file diff --git a/Taskfile.yml b/Taskfile.yml index 966e52b..cbb9d02 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -19,12 +19,11 @@ version: '3' vars: - BASETAG: 0.1.0 - -env: - OPS_API_TAG: - sh: git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD - OPS_API_IMAGE: registry.hub.docker.com/apache/openserverless-admin-api + BASETAG: 0.1.0-incubating + COMMIT_ID: + sh: git rev-parse --short HEAD + TAG: + sh: git describe --tags --abbrev=0 2>/dev/null || echo latest dotenv: - .env @@ -49,34 +48,105 @@ tasks: then cp .env.example .env echo "Please edit .env file with your local CouchDB and Kubernetes credentials" fi + - | + if [ ! -d .venv ]; + then uv venv + fi - uv pip install -r pyproject.toml 2>/dev/null - - - image-tag: - - git tag -d $(git tag) - - git tag -f {{.P}}{{.BASETAG}}.$(date +%y%m%d%H%M) - - env PAGER= git tag - docker-login: > - echo $DOCKER_HUB_TOKEN | docker login registry.hub.docker.com -u $DOCKER_HUB_USER --password-stdin + docker-login-ghcr: > + silent: true + cmds: + - | + echo "Logging in to ghcr.io as $GITHUB_USER" + echo $GITHUB_TOKEN | docker login ghcr.io -u $GITHUB_USER --password-stdin + + docker-login-dockerhub: + silent: true + cmds: + - | + echo "Logging in to dockerhub as $DOCKERHUB_USER" + echo $DOCKERHUB_TOKEN | docker login -u $DOCKERHUB_USER --password-stdin - docker-setup: - - docker buildx create --use - - docker run -it --rm --privileged tonistiigi/binfmt --install all + docker-login: + desc: | + Login to the docker registry. Set REGISTRY=ghcr or REGISTRY=dockerhub in .env + to use the respective registry. + silent: true + cmds: + - | + if [ -z "$REGISTRY" ]; then + echo "Error: REGISTRY variable is not set in .env" + exit 1 + fi + task docker-login-$REGISTRY + + image-tag: + silent: true + desc: | + Create a new tag for the current git commit. + cmds: + - git tag -d $(git tag) + - git tag -f {{.BASETAG}}.$(date +%y%m%d%H%M) + - env PAGER= git tag + + base-image-name: + silent: true + cmds: + - | + if [ -n "$REGISTRY" ] && [ -z "$NAMESPACE" ]; then + echo "Error: NAMESPACE variable is not set in .env" + exit 1 + fi + if [ "$REGISTRY" = "ghcr" ]; then + echo "ghcr.io/$NAMESPACE/openserverless-admin-api" + elif [ "$REGISTRY" = "dockerhub" ]; then + echo "docker.io/$NAMESPACE/openserverless-admin-api" + elif [ "$REGISTRY" = "apache" ]; then + echo "registry.hub.docker.com/apache/openserverless-admin-api" + else + echo "openserverless-admin-api" + fi - build: - - > - docker build . -t {{.OPS_API_IMAGE}}:{{.OPS_API_TAG}} --load + buildx: + desc: | + Build the docker image using buildx. Set PUSH=1 to push the image to the registry. + silent: true + cmds: + - | + BASEIMG=$(task base-image-name) + IMG="$BASEIMG:{{.TAG}}" + if [ -n "{{.PUSH}}" ]; then + if [ -z "$REGISTRY" ]; then + echo "Error: REGISTRY variable must be set in .env to push the image" + exit 1 + fi + {{.DRY}} docker buildx build -t $IMG --platform linux/amd64,linux/arm64 . --push + else + {{.DRY}} docker buildx build -t $IMG . --load + fi + + build: + silent: true + desc: Build the image locally + cmds: + - | + BASEIMG=$(task base-image-name) + IMG="$BASEIMG:{{.TAG}}" + docker build . -t $IMG --load build-and-load: - - task: build - - > - kind load docker-image {{.OPS_API_IMAGE}}:{{.OPS_API_TAG}} --name=nuvolaris + silent: true + desc: Build the image and loads it to local Kind cluster + cmds: + - task: build + - | + BASEIMG=$(task base-image-name) + IMG="$BASEIMG:{{.TAG}}" + kind load docker-image $IMG --name=nuvolaris - # Docker image - build-and-push: + run: + desc: | + Run the admin api locally, using configuration from .env file cmds: - - task: docker-setup - - task: docker-login - - "docker buildx build --platform linux/amd64,linux/arm64 . -t {{.OPS_API_IMAGE}}:{{.OPS_API_TAG}} --push" - + - uv run -m openserverless \ No newline at end of file diff --git a/openserverless/__init__.py b/openserverless/__init__.py index e313bc1..211968a 100644 --- a/openserverless/__init__.py +++ b/openserverless/__init__.py @@ -20,7 +20,7 @@ __version__ = '0.1.0' import logging import os -from flask import Flask +from flask import Flask, request from flasgger import Swagger from flask_cors import CORS from dotenv import load_dotenv @@ -57,8 +57,21 @@ swagger_config = { "auth": dict({}) } -logging.basicConfig(level=logging.DEBUG) +logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s %(levelname)s %(name)s %(message)s' +) + + app = Flask(__name__) + +@app.before_request +def log_request_info(): + logging.debug( + f"Request: {request.method} {request.path} | " + f"Remote: {request.remote_addr}" + ) + cors = CORS(app) swagger = Swagger(app=app,config=swagger_config,merge=True) @@ -67,6 +80,3 @@ listen_port = os.environ.get("LISTEN_PORT", "5000") import openserverless.rest.api import openserverless.rest.auth -if __name__ == "openserverless": - from waitress import serve - serve(app, host="0.0.0.0", port=listen_port) \ No newline at end of file diff --git a/openserverless/__main__.py b/openserverless/__main__.py new file mode 100644 index 0000000..496cc34 --- /dev/null +++ b/openserverless/__main__.py @@ -0,0 +1,24 @@ +# 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 . import app +import os + +if __name__ == "__main__": + from waitress import serve + listen_port = os.environ.get("LISTEN_PORT", "5000") + serve(app, host="0.0.0.0", port=listen_port)