py-serverless-kit 0.1.3__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/CHANGELOG.md +8 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/PKG-INFO +11 -9
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/README.md +8 -6
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/README.md +1 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/architecture.md +1 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/cli.md +1 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/configuration.md +3 -2
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/events.md +12 -7
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/getting-started.md +1 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/handlers.md +4 -2
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/local-development.md +4 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/providers.md +63 -2
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/troubleshooting.md +1 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/workflows.md +1 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/01-hello-http/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/02-rest-api/pskit.yml +6 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/03-scheduled-jobs/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/04-queue-worker/README.md +5 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/04-queue-worker/app/worker.py +16 -10
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/04-queue-worker/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/05-storage-events/pskit.yml +9 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/06-pubsub-topic/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/README.md +5 -3
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/app/handlers.py +1 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/pskit.yml +7 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/09-function-invoke/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/pskit.yml +7 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/pskit.yml +11 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/12-async-and-context/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/after/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/pskit.yml +3 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/15-ci-cd-deploy/pskit.yml +5 -0
- py_serverless_kit-0.2.0/examples/16-on-premises/README.md +60 -0
- py_serverless_kit-0.2.0/examples/16-on-premises/app/handlers.py +54 -0
- py_serverless_kit-0.2.0/examples/16-on-premises/pskit.yml +69 -0
- py_serverless_kit-0.2.0/examples/16-on-premises/requirements.txt +1 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/README.md +2 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/pyproject.toml +2 -2
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/_version.py +1 -1
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/cli/templates.py +8 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/config/loader.py +13 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/config/schema.py +1 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/base.py +4 -1
- py_serverless_kit-0.2.0/src/py_serverless_kit/providers/onprem.py +436 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/registry.py +1 -0
- py_serverless_kit-0.2.0/src/py_serverless_kit/runtime/adapters/onprem.py +117 -0
- py_serverless_kit-0.2.0/src/py_serverless_kit/runtime/cron.py +143 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/dispatch.py +3 -3
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/invoke.py +13 -3
- py_serverless_kit-0.2.0/src/py_serverless_kit/runtime/onprem_host.py +1083 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/config/test_loader.py +18 -0
- py_serverless_kit-0.2.0/tests/providers/test_onprem.py +127 -0
- py_serverless_kit-0.2.0/tests/runtime/test_adapter_onprem.py +58 -0
- py_serverless_kit-0.2.0/tests/runtime/test_cron.py +46 -0
- py_serverless_kit-0.2.0/tests/runtime/test_onprem_host.py +239 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/test_examples.py +24 -2
- py_serverless_kit-0.2.0/tests/workflows/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/.gitignore +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/CONTRIBUTING.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/LICENSE +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/deploy_docs/CONTRIBUTING.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/dashboard.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/docs/migrating-from-aws.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/01-hello-http/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/01-hello-http/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/01-hello-http/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/01-hello-http/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/02-rest-api/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/02-rest-api/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/02-rest-api/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/02-rest-api/app/store.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/02-rest-api/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/03-scheduled-jobs/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/03-scheduled-jobs/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/03-scheduled-jobs/app/jobs.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/03-scheduled-jobs/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/04-queue-worker/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/04-queue-worker/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/05-storage-events/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/05-storage-events/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/05-storage-events/app/files.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/05-storage-events/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/06-pubsub-topic/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/06-pubsub-topic/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/06-pubsub-topic/app/subscribers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/06-pubsub-topic/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/app/orders.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/events/b2b.json +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/events/declined.json +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/events/happy.json +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/07-workflow-orders/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/pskit.aws.yml +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/pskit.azure.yml +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/pskit.gcp.yml +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/08-multi-cloud/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/09-function-invoke/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/09-function-invoke/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/09-function-invoke/app/quotes.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/09-function-invoke/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/.env.example +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/app/settings.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/config/limits.json +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/10-stages-and-config/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/app/repository.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/scripts/smoke_test.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/11-custom-terraform/tests/test_orders.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/12-async-and-context/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/12-async-and-context/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/12-async-and-context/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/12-async-and-context/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/after/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/after/app/orders.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/after/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/before/lambda_function.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/before/state_machine.asl.json +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/13-migrate-from-aws-lambda/before/template.yaml +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/ci.github-workflow.yml +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/requirements.txt +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/tests/conftest.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/tests/test_handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/14-testing/tests/test_workflow.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/15-ci-cd-deploy/README.md +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/15-ci-cd-deploy/app/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/15-ci-cd-deploy/app/handlers.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/15-ci-cd-deploy/deploy.github-workflow.yml +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/examples/15-ci-cd-deploy/requirements.txt +0 -0
- {py_serverless_kit-0.1.3/src/py_serverless_kit/cli → py_serverless_kit-0.2.0/examples/16-on-premises/app}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/__main__.py +0 -0
- {py_serverless_kit-0.1.3/src/py_serverless_kit/core → py_serverless_kit-0.2.0/src/py_serverless_kit/cli}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/cli/main.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/config/__init__.py +0 -0
- {py_serverless_kit-0.1.3/tests → py_serverless_kit-0.2.0/src/py_serverless_kit/core}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/core/deployer.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/core/describe.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/core/project.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/dashboard/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/dashboard/generator.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/dashboard/template.html +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/local/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/local/runner.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/local/server.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/packaging/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/packaging/builder.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/alibaba.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/aws.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/azure.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/cloudflare.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/digitalocean.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/gcp.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/huawei.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/ibm.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/oracle.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/schedule.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/tencent.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/providers/terraform_doc.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/_httpfn.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/alibaba.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/aws.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/azure.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/base.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/cloudflare.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/digitalocean.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/gcp.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/huawei.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/ibm.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/oracle.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/adapters/tencent.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/batch.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/context.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/errors.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/event.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/log.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/manifest.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/response.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/routing.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/runtime/workflow.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/terraform/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/terraform/runner.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/workflows/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/workflows/asl.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/src/py_serverless_kit/workflows/gcp.py +0 -0
- {py_serverless_kit-0.1.3/tests/config → py_serverless_kit-0.2.0/tests}/__init__.py +0 -0
- {py_serverless_kit-0.1.3/tests/local → py_serverless_kit-0.2.0/tests/config}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/config/test_schema.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/conftest.py +0 -0
- {py_serverless_kit-0.1.3/tests/providers → py_serverless_kit-0.2.0/tests/local}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/local/test_server.py +0 -0
- {py_serverless_kit-0.1.3/tests/runtime → py_serverless_kit-0.2.0/tests/providers}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_alibaba.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_aws.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_azure.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_cloudflare.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_digitalocean.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_gcp.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_huawei.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_ibm.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_oracle.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_schedule.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/providers/test_tencent.py +0 -0
- {py_serverless_kit-0.1.3/tests/workflows → py_serverless_kit-0.2.0/tests/runtime}/__init__.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_alibaba.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_aws.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_azure.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_cloudflare.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_digitalocean.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_gcp.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_huawei.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_ibm.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_oracle.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_adapter_tencent.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_dispatch.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_models.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/runtime/test_workflow_engine.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/test_cli.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/test_dashboard.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/test_packaging.py +0 -0
- {py_serverless_kit-0.1.3 → py_serverless_kit-0.2.0}/tests/workflows/test_compilers.py +0 -0
|
@@ -6,6 +6,14 @@ All notable changes to this project are documented here. The format follows [Kee
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.2.0] - 2026-10-17
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- On-premises provider (`provider.name: onprem`). `pskit deploy` starts one long-lived Python process on the machine that runs the command. HTTP is served directly. Schedules, file queues (with dead-letter and partial batch failure), directory storage and file topics are created at start when they do not already exist. Point `provider.options.services.<kind>` at `{use: directory, path: ...}` to use a directory you already have. `existing: true` waits for that directory instead of creating it. Workflows run on the embedded engine inside the host, and `invoke()` stays in-process. `pskit remove` stops the process and leaves the data directory in place.
|
|
13
|
+
- Example [16-on-premises](examples/16-on-premises). Every other example has an `providers.onprem` block (its own port, public auth where a cloud authorizer does not apply, local state where the file used a cloud backend).
|
|
14
|
+
|
|
15
|
+
No change to handlers that already run on a cloud. Redeploy to pick up the new runtime if you use `BatchResult` or `invoke()` on premises.
|
|
16
|
+
|
|
9
17
|
## [0.1.3] - 2026-10-15
|
|
10
18
|
|
|
11
19
|
### Fixed
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: py-serverless-kit
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Write a Python serverless function once and deploy it to AWS, Azure, GCP
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Write a Python serverless function once and deploy it to AWS, Azure, GCP, 7 more clouds, or an on-premises host with one YAML file, powered by Terraform.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ak9347128658/serverless_kit
|
|
6
6
|
Project-URL: Documentation, https://github.com/ak9347128658/serverless_kit/tree/main/docs
|
|
7
7
|
Project-URL: Issues, https://github.com/ak9347128658/serverless_kit/issues
|
|
@@ -10,7 +10,7 @@ Author: Asif Khan @ Kavion.ai
|
|
|
10
10
|
Maintainer: Asif Khan @ Kavion.ai
|
|
11
11
|
License: MIT
|
|
12
12
|
License-File: LICENSE
|
|
13
|
-
Keywords: aws,azure,faas,gcp,lambda,multi-cloud,serverless,step-functions,terraform
|
|
13
|
+
Keywords: aws,azure,faas,gcp,lambda,multi-cloud,on-premises,serverless,step-functions,terraform
|
|
14
14
|
Classifier: Development Status :: 4 - Beta
|
|
15
15
|
Classifier: Environment :: Console
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
|
@@ -48,12 +48,12 @@ Description-Content-Type: text/markdown
|
|
|
48
48
|
[](https://pypi.org/project/py-serverless-kit/)
|
|
49
49
|
[](https://github.com/ak9347128658/serverless_kit/blob/main/LICENSE)
|
|
50
50
|
|
|
51
|
-
**Write your Python functions once. Deploy them to any of 10 clouds by changing one line of YAML.**
|
|
51
|
+
**Write your Python functions once. Deploy them to any of 10 clouds, or to your own machine, by changing one line of YAML.**
|
|
52
52
|
|
|
53
53
|
`py-serverless-kit` (CLI: `pskit`) is a Serverless-Framework-style toolkit built on **Terraform**. Your handlers use one small, provider-neutral API (`Event`, `Context`, `Response`). A `pskit.yml` file says which cloud they run on and what triggers them: HTTP, schedules, queues, storage, topics. The same file can also define workflows in the style of Step Functions. `pskit deploy` generates Terraform for the chosen cloud, applies it, and builds an HTML dashboard of everything you deployed.
|
|
54
54
|
|
|
55
55
|
```python
|
|
56
|
-
# app/handlers.py - identical on AWS, Azure, GCP, Alibaba, Oracle, IBM, DigitalOcean, Tencent, Huawei, Cloudflare
|
|
56
|
+
# app/handlers.py - identical on AWS, Azure, GCP, Alibaba, Oracle, IBM, DigitalOcean, Tencent, Huawei, Cloudflare, and on premises
|
|
57
57
|
from py_serverless_kit import Event, Context, NotFound
|
|
58
58
|
|
|
59
59
|
def get_order(event: Event, ctx: Context):
|
|
@@ -67,7 +67,7 @@ def get_order(event: Event, ctx: Context):
|
|
|
67
67
|
# pskit.yml
|
|
68
68
|
service: orders
|
|
69
69
|
provider:
|
|
70
|
-
name: aws # <- change to gcp, azure,
|
|
70
|
+
name: aws # <- change to gcp, azure, onprem, ... and redeploy. That's the migration.
|
|
71
71
|
region: us-east-1
|
|
72
72
|
functions:
|
|
73
73
|
get-order:
|
|
@@ -97,7 +97,7 @@ Teams that build on AWS Lambda and Step Functions end up with code full of API G
|
|
|
97
97
|
|
|
98
98
|
## Features
|
|
99
99
|
|
|
100
|
-
- **10
|
|
100
|
+
- **10 clouds and an on-premises host:** AWS Lambda, Azure Functions, Google Cloud Functions (gen2), Alibaba Function Compute, Oracle Functions, IBM Code Engine, DigitalOcean Functions, Tencent SCF, Huawei FunctionGraph, Cloudflare Workers, plus a process on your own machine (`onprem`).
|
|
101
101
|
- **Triggers:** HTTP (path params, CORS, auth), schedules (rate/cron, translated into each cloud's cron dialect), queues, object storage, pub/sub topics, and direct function-to-function `invoke()`.
|
|
102
102
|
- **Workflows:** task / choice / wait / pass / parallel / map / succeed / fail with retry and catch. Native on AWS and GCP; an embedded engine on the other clouds; runnable locally with `pskit workflow run`.
|
|
103
103
|
- **Terraform underneath:** real, reviewable `main.tf.json`, any backend (S3, GCS, azurerm, ...), works with OpenTofu. Escape hatches: `terraform.extra`, `${tf:...}` references, per-function `options`.
|
|
@@ -120,6 +120,7 @@ Teams that build on AWS Lambda and Step Functions end up with code full of API G
|
|
|
120
120
|
| IBM Code Engine | beta | ✅ | – | – | – | – | embedded |
|
|
121
121
|
| Oracle Cloud Functions | experimental | ✅ | – | – | ✅ | – | embedded |
|
|
122
122
|
| Cloudflare Workers (Python) | experimental | ✅ | ✅ | – | – | – | embedded |
|
|
123
|
+
| On-premises | experimental | ✅ | ✅ | ✅ files | ✅ directory | ✅ files | embedded (in the host) |
|
|
123
124
|
|
|
124
125
|
Run `pskit providers` for the live matrix. If a config uses a trigger the target cloud can't support, **`pskit validate` fails with a clear message instead of deploying something half-working.**
|
|
125
126
|
|
|
@@ -251,7 +252,7 @@ More: [docs/architecture.md](https://github.com/ak9347128658/serverless_kit/blob
|
|
|
251
252
|
|
|
252
253
|
## Examples
|
|
253
254
|
|
|
254
|
-
|
|
255
|
+
Sixteen runnable scenarios live in [`examples/`](https://github.com/ak9347128658/serverless_kit/tree/main/examples/). They are tested in CI.
|
|
255
256
|
|
|
256
257
|
| | |
|
|
257
258
|
|---|---|
|
|
@@ -262,7 +263,8 @@ Fifteen runnable scenarios live in [`examples/`](https://github.com/ak9347128658
|
|
|
262
263
|
| [05-storage-events](https://github.com/ak9347128658/serverless_kit/tree/main/examples/05-storage-events) | Object created/deleted with filters |
|
|
263
264
|
| [06-pubsub-topic](https://github.com/ak9347128658/serverless_kit/tree/main/examples/06-pubsub-topic) | Topic fan-out and filters |
|
|
264
265
|
| [07-workflow-orders](https://github.com/ak9347128658/serverless_kit/tree/main/examples/07-workflow-orders) | Every workflow state type, retry/catch |
|
|
265
|
-
| [08-multi-cloud](https://github.com/ak9347128658/serverless_kit/tree/main/examples/08-multi-cloud) | Same code, all
|
|
266
|
+
| [08-multi-cloud](https://github.com/ak9347128658/serverless_kit/tree/main/examples/08-multi-cloud) | Same code, all 11 providers |
|
|
267
|
+
| [16-on-premises](https://github.com/ak9347128658/serverless_kit/tree/main/examples/16-on-premises) | HTTP, schedule, queue, storage, topic and a workflow on one machine |
|
|
266
268
|
| [09-function-invoke](https://github.com/ak9347128658/serverless_kit/tree/main/examples/09-function-invoke) | Function-to-function `invoke()` |
|
|
267
269
|
| [10-stages-and-config](https://github.com/ak9347128658/serverless_kit/tree/main/examples/10-stages-and-config) | Stages, variables, secrets |
|
|
268
270
|
| [11-custom-terraform](https://github.com/ak9347128658/serverless_kit/tree/main/examples/11-custom-terraform) | `terraform.extra`, `${tf:...}`, remote state, hooks |
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
[](https://pypi.org/project/py-serverless-kit/)
|
|
5
5
|
[](https://github.com/ak9347128658/serverless_kit/blob/main/LICENSE)
|
|
6
6
|
|
|
7
|
-
**Write your Python functions once. Deploy them to any of 10 clouds by changing one line of YAML.**
|
|
7
|
+
**Write your Python functions once. Deploy them to any of 10 clouds, or to your own machine, by changing one line of YAML.**
|
|
8
8
|
|
|
9
9
|
`py-serverless-kit` (CLI: `pskit`) is a Serverless-Framework-style toolkit built on **Terraform**. Your handlers use one small, provider-neutral API (`Event`, `Context`, `Response`). A `pskit.yml` file says which cloud they run on and what triggers them: HTTP, schedules, queues, storage, topics. The same file can also define workflows in the style of Step Functions. `pskit deploy` generates Terraform for the chosen cloud, applies it, and builds an HTML dashboard of everything you deployed.
|
|
10
10
|
|
|
11
11
|
```python
|
|
12
|
-
# app/handlers.py - identical on AWS, Azure, GCP, Alibaba, Oracle, IBM, DigitalOcean, Tencent, Huawei, Cloudflare
|
|
12
|
+
# app/handlers.py - identical on AWS, Azure, GCP, Alibaba, Oracle, IBM, DigitalOcean, Tencent, Huawei, Cloudflare, and on premises
|
|
13
13
|
from py_serverless_kit import Event, Context, NotFound
|
|
14
14
|
|
|
15
15
|
def get_order(event: Event, ctx: Context):
|
|
@@ -23,7 +23,7 @@ def get_order(event: Event, ctx: Context):
|
|
|
23
23
|
# pskit.yml
|
|
24
24
|
service: orders
|
|
25
25
|
provider:
|
|
26
|
-
name: aws # <- change to gcp, azure,
|
|
26
|
+
name: aws # <- change to gcp, azure, onprem, ... and redeploy. That's the migration.
|
|
27
27
|
region: us-east-1
|
|
28
28
|
functions:
|
|
29
29
|
get-order:
|
|
@@ -53,7 +53,7 @@ Teams that build on AWS Lambda and Step Functions end up with code full of API G
|
|
|
53
53
|
|
|
54
54
|
## Features
|
|
55
55
|
|
|
56
|
-
- **10
|
|
56
|
+
- **10 clouds and an on-premises host:** AWS Lambda, Azure Functions, Google Cloud Functions (gen2), Alibaba Function Compute, Oracle Functions, IBM Code Engine, DigitalOcean Functions, Tencent SCF, Huawei FunctionGraph, Cloudflare Workers, plus a process on your own machine (`onprem`).
|
|
57
57
|
- **Triggers:** HTTP (path params, CORS, auth), schedules (rate/cron, translated into each cloud's cron dialect), queues, object storage, pub/sub topics, and direct function-to-function `invoke()`.
|
|
58
58
|
- **Workflows:** task / choice / wait / pass / parallel / map / succeed / fail with retry and catch. Native on AWS and GCP; an embedded engine on the other clouds; runnable locally with `pskit workflow run`.
|
|
59
59
|
- **Terraform underneath:** real, reviewable `main.tf.json`, any backend (S3, GCS, azurerm, ...), works with OpenTofu. Escape hatches: `terraform.extra`, `${tf:...}` references, per-function `options`.
|
|
@@ -76,6 +76,7 @@ Teams that build on AWS Lambda and Step Functions end up with code full of API G
|
|
|
76
76
|
| IBM Code Engine | beta | ✅ | – | – | – | – | embedded |
|
|
77
77
|
| Oracle Cloud Functions | experimental | ✅ | – | – | ✅ | – | embedded |
|
|
78
78
|
| Cloudflare Workers (Python) | experimental | ✅ | ✅ | – | – | – | embedded |
|
|
79
|
+
| On-premises | experimental | ✅ | ✅ | ✅ files | ✅ directory | ✅ files | embedded (in the host) |
|
|
79
80
|
|
|
80
81
|
Run `pskit providers` for the live matrix. If a config uses a trigger the target cloud can't support, **`pskit validate` fails with a clear message instead of deploying something half-working.**
|
|
81
82
|
|
|
@@ -207,7 +208,7 @@ More: [docs/architecture.md](https://github.com/ak9347128658/serverless_kit/blob
|
|
|
207
208
|
|
|
208
209
|
## Examples
|
|
209
210
|
|
|
210
|
-
|
|
211
|
+
Sixteen runnable scenarios live in [`examples/`](https://github.com/ak9347128658/serverless_kit/tree/main/examples/). They are tested in CI.
|
|
211
212
|
|
|
212
213
|
| | |
|
|
213
214
|
|---|---|
|
|
@@ -218,7 +219,8 @@ Fifteen runnable scenarios live in [`examples/`](https://github.com/ak9347128658
|
|
|
218
219
|
| [05-storage-events](https://github.com/ak9347128658/serverless_kit/tree/main/examples/05-storage-events) | Object created/deleted with filters |
|
|
219
220
|
| [06-pubsub-topic](https://github.com/ak9347128658/serverless_kit/tree/main/examples/06-pubsub-topic) | Topic fan-out and filters |
|
|
220
221
|
| [07-workflow-orders](https://github.com/ak9347128658/serverless_kit/tree/main/examples/07-workflow-orders) | Every workflow state type, retry/catch |
|
|
221
|
-
| [08-multi-cloud](https://github.com/ak9347128658/serverless_kit/tree/main/examples/08-multi-cloud) | Same code, all
|
|
222
|
+
| [08-multi-cloud](https://github.com/ak9347128658/serverless_kit/tree/main/examples/08-multi-cloud) | Same code, all 11 providers |
|
|
223
|
+
| [16-on-premises](https://github.com/ak9347128658/serverless_kit/tree/main/examples/16-on-premises) | HTTP, schedule, queue, storage, topic and a workflow on one machine |
|
|
222
224
|
| [09-function-invoke](https://github.com/ak9347128658/serverless_kit/tree/main/examples/09-function-invoke) | Function-to-function `invoke()` |
|
|
223
225
|
| [10-stages-and-config](https://github.com/ak9347128658/serverless_kit/tree/main/examples/10-stages-and-config) | Stages, variables, secrets |
|
|
224
226
|
| [11-custom-terraform](https://github.com/ak9347128658/serverless_kit/tree/main/examples/11-custom-terraform) | `terraform.extra`, `${tf:...}`, remote state, hooks |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# py-serverless-kit documentation
|
|
2
2
|
|
|
3
|
-
Write a Python function once, describe its triggers in `pskit.yml`, and deploy it to any of 10 clouds with Terraform. Moving to another
|
|
3
|
+
Write a Python function once, describe its triggers in `pskit.yml`, and deploy it to any of 10 clouds or to an on-premises host with Terraform. Moving to another target means changing `provider.name`. The handler code stays the same.
|
|
4
4
|
|
|
5
5
|
| Page | What it covers |
|
|
6
6
|
|---|---|
|
|
@@ -45,6 +45,7 @@ artifact.zip
|
|
|
45
45
|
├── <shim> pskit_entry.py (aws) · main.py (gcp) · function_app.py + host.json (azure)
|
|
46
46
|
│ index.py (alibaba/tencent/huawei) · __main__.py (ibm/do)
|
|
47
47
|
│ func.py + func.yaml + Dockerfile (oracle) · generated worker module (cloudflare)
|
|
48
|
+
│ onprem_handler.py (onprem; the host process is started beside the zip)
|
|
48
49
|
└── dependencies or requirements.txt
|
|
49
50
|
```
|
|
50
51
|
|
|
@@ -13,7 +13,7 @@ Every command that loads a project accepts:
|
|
|
13
13
|
| Flag | Meaning |
|
|
14
14
|
|---|---|
|
|
15
15
|
| `-c, --config FILE` | config file (default: `pskit.yml`, `pskit.yaml`, `serverless_kit.yml`, `serverless_kit.yaml`) |
|
|
16
|
-
| `-p, --provider NAME` | override `provider.name` (`aws`, `azure`, `gcp`, `alibaba`, `oracle`, `ibm`, `digitalocean`, `tencent`, `huawei`, `cloudflare`) |
|
|
16
|
+
| `-p, --provider NAME` | override `provider.name` (`aws`, `azure`, `gcp`, `alibaba`, `oracle`, `ibm`, `digitalocean`, `tencent`, `huawei`, `cloudflare`, `onprem`) |
|
|
17
17
|
| `-s, --stage NAME` | stage, e.g. `dev`, `staging`, `prod` |
|
|
18
18
|
| `-r, --region NAME` | override `provider.region` |
|
|
19
19
|
| `-v, --verbose` | print tracebacks on errors |
|
|
@@ -33,7 +33,7 @@ extends: base.yml # inherit another file (see below)
|
|
|
33
33
|
|
|
34
34
|
| Key | Type | Default | Notes |
|
|
35
35
|
|---|---|---|---|
|
|
36
|
-
| `name` | `aws` \| `azure` \| `gcp` \| `alibaba` \| `oracle` \| `ibm` \| `digitalocean` \| `tencent` \| `huawei` \| `cloudflare` | — | required (or `--provider`) |
|
|
36
|
+
| `name` | `aws` \| `azure` \| `gcp` \| `alibaba` \| `oracle` \| `ibm` \| `digitalocean` \| `tencent` \| `huawei` \| `cloudflare` \| `onprem` | — | required (or `--provider`) |
|
|
37
37
|
| `region` | string | provider default | e.g. `us-east-1`, `europe-west1`, `eastus` |
|
|
38
38
|
| `stage` | string | `dev` | `[a-z][a-z0-9-]{0,15}`; overridden by `--stage` |
|
|
39
39
|
| `runtime` | `python3.9` … `python3.14` | see [default runtime](#default-runtime) | provider support varies |
|
|
@@ -189,7 +189,8 @@ Relative paths resolve from the extending file. Circular `extends` is an error.
|
|
|
189
189
|
|
|
190
190
|
So a child file's explicit values beat its parent's per-provider overrides.
|
|
191
191
|
2. `stages.<active stage>` (merged across all files; the child wins).
|
|
192
|
-
3.
|
|
192
|
+
3. `stages.<active stage>.providers.<active provider>`, when that stage must differ for one target (for example a cloud state backend on `prod` and local state for `onprem`).
|
|
193
|
+
4. CLI flags: `--provider`, `--stage`, `--region`.
|
|
193
194
|
|
|
194
195
|
Dicts are deep-merged; lists are replaced, not appended.
|
|
195
196
|
|
|
@@ -18,13 +18,13 @@ A function with no events is *invoke-only*: it can be called by workflows, by `i
|
|
|
18
18
|
|
|
19
19
|
Support at a glance (the full detail is below and in [providers.md](providers.md)):
|
|
20
20
|
|
|
21
|
-
| Trigger | aws | gcp | azure | alibaba | oracle | ibm | digitalocean | tencent | huawei | cloudflare |
|
|
22
|
-
|
|
23
|
-
| `http` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓¹ | ✓ |
|
|
24
|
-
| `schedule` | ✓ | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | ✓ | ✓ |
|
|
25
|
-
| `queue` | ✓ SQS | ✓ Pub/Sub | ✓ Storage Queue | – | – | – | – | – | – | – |
|
|
26
|
-
| `storage` | ✓ S3 | ✓ GCS | ✓ Blob (created only) | ✓ OSS | ✓ Object Storage | – | – | ✓ COS | ✓ OBS | – |
|
|
27
|
-
| `topic` | ✓ SNS | ✓ Pub/Sub | ✓ Service Bus | ✓ MNS | – | – | – | – | ✓ SMN | – |
|
|
21
|
+
| Trigger | aws | gcp | azure | alibaba | oracle | ibm | digitalocean | tencent | huawei | cloudflare | onprem |
|
|
22
|
+
|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
23
|
+
| `http` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓¹ | ✓ | ✓ |
|
|
24
|
+
| `schedule` | ✓ | ✓ | ✓ | ✓ | – | – | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
25
|
+
| `queue` | ✓ SQS | ✓ Pub/Sub | ✓ Storage Queue | – | – | – | – | – | – | – | ✓ files |
|
|
26
|
+
| `storage` | ✓ S3 | ✓ GCS | ✓ Blob (created only) | ✓ OSS | ✓ Object Storage | – | – | ✓ COS | ✓ OBS | – | ✓ directory |
|
|
27
|
+
| `topic` | ✓ SNS | ✓ Pub/Sub | ✓ Service Bus | ✓ MNS | – | – | – | – | ✓ SMN | – | ✓ files |
|
|
28
28
|
|
|
29
29
|
¹ Huawei HTTP needs `provider.options.apig_instance_id`.
|
|
30
30
|
|
|
@@ -110,6 +110,7 @@ pskit converts the portable syntax to each cloud's dialect:
|
|
|
110
110
|
| huawei | timer trigger | `Rate` (`5m`) or 6-field cron with `?` |
|
|
111
111
|
| digitalocean | `project.yml` scheduler trigger | 5-field cron |
|
|
112
112
|
| cloudflare | Cron Triggers | 5-field cron |
|
|
113
|
+
| onprem | in-process scheduler | rate in seconds, or 5-field cron. A rate such as `7 minutes` is valid here |
|
|
113
114
|
|
|
114
115
|
A rate that can't be expressed as cron on cron-only clouds (e.g. `7 minutes`) fails validation; use a divisor of 60 minutes or 24 hours. `timezone` is honoured by AWS, GCP and Alibaba (cron form); Azure ignores it with a warning.
|
|
115
116
|
|
|
@@ -139,6 +140,8 @@ The handler gets `event.type == "queue"` and `event.records`, one `Record` per m
|
|
|
139
140
|
| `fifo` | ✓ (`.fifo` suffix, content-based dedup) | ignored (warning) | ignored (warning) |
|
|
140
141
|
| partial batch failure | ✓ `batchItemFailures` | whole delivery retried | whole delivery retried |
|
|
141
142
|
|
|
143
|
+
On premises the same options are implemented by a file broker (`batch_size`, `batch_window`, visibility, dead-letter, `max_receive`, `fifo`). `BatchResult` retries only the failed message ids, as on AWS. Set `provider.options.services.queue` to `builtin` (created at start) or `{use: directory, path: ...}`. `existing: true` waits for that directory. Example: [`examples/04-queue-worker`](../examples/04-queue-worker) and [`examples/16-on-premises`](../examples/16-on-premises).
|
|
144
|
+
|
|
142
145
|
On GCP a "queue" is a Pub/Sub topic with a push trigger, because GCP has no SQS-style pull trigger. Azure queue names must be 3–63 lowercase letters, digits and dashes. Example: [`examples/04-queue-worker`](../examples/04-queue-worker).
|
|
143
146
|
|
|
144
147
|
---
|
|
@@ -166,6 +169,7 @@ Each record has `bucket`, `key`, `size` and `action` (`"created"` / `"deleted"`)
|
|
|
166
169
|
| oracle | Events rule | not supported (warning) – filter in your handler | bucket must have "Emit Object Events" enabled |
|
|
167
170
|
| tencent | COS trigger | native | bucket name must be `<name>-<APPID>`, e.g. `uploads-1250000000` |
|
|
168
171
|
| huawei | OBS trigger | native | |
|
|
172
|
+
| onprem | a directory of files | prefix/suffix in the host | `created` and `deleted`. `builtin` creates the directory; `{use: directory, path}` uses one you already have. The first start records current files and does not emit them |
|
|
169
173
|
|
|
170
174
|
Example: [`examples/05-storage-events`](../examples/05-storage-events).
|
|
171
175
|
|
|
@@ -188,6 +192,7 @@ Example: [`examples/05-storage-events`](../examples/05-storage-events).
|
|
|
188
192
|
| azure | Service Bus topic + subscription | not applied (warning); `existing` needs `options.servicebus_namespace_id` and `options.servicebus_connection` |
|
|
189
193
|
| alibaba | MNS topic | `filter.tag` (string) only |
|
|
190
194
|
| huawei | SMN topic | – |
|
|
195
|
+
| onprem | file topic, fan-out | exact match on attributes, then on JSON body fields |
|
|
191
196
|
|
|
192
197
|
Example: [`examples/06-pubsub-topic`](../examples/06-pubsub-topic).
|
|
193
198
|
|
|
@@ -109,6 +109,7 @@ pskit runs Terraform, so credentials come from each Terraform provider's standar
|
|
|
109
109
|
| `tencent` | `TENCENTCLOUD_SECRET_ID` / `TENCENTCLOUD_SECRET_KEY`, or `options.profile` |
|
|
110
110
|
| `huawei` | `HW_ACCESS_KEY` / `HW_SECRET_KEY` (+ `HW_REGION_NAME`), or `options.profile` |
|
|
111
111
|
| `cloudflare` | `CLOUDFLARE_API_TOKEN`. `options.account_id` is required |
|
|
112
|
+
| `onprem` | nothing to configure. Terraform's built-in provider starts a process with the Python that runs `pskit` |
|
|
112
113
|
|
|
113
114
|
Provider-specific required options are listed in [providers.md](providers.md).
|
|
114
115
|
|
|
@@ -156,6 +156,7 @@ def worker(event, ctx):
|
|
|
156
156
|
| Provider | Behaviour |
|
|
157
157
|
|---|---|
|
|
158
158
|
| aws (SQS) | becomes `batchItemFailures`, so only the failed messages are retried |
|
|
159
|
+
| onprem | the host retries only the failed message ids, and moves a message to `dead_letter` after `max_receive` |
|
|
159
160
|
| local | printed as `batchItemFailures` |
|
|
160
161
|
| everyone else | any failure raises `BatchFailure`, so the whole delivery is retried |
|
|
161
162
|
|
|
@@ -173,7 +174,7 @@ invoke("audit", {"order_id": 42}, asynchronous=True) # fire and forget
|
|
|
173
174
|
How the target is resolved:
|
|
174
175
|
|
|
175
176
|
1. If `PSKIT_ENDPOINT_<NAME>` is set (`billing` → `PSKIT_ENDPOINT_BILLING`, non-alphanumerics become `_`), pskit POSTs to that http(s) URL. This works on any provider.
|
|
176
|
-
2. `local` (CLI, tests)
|
|
177
|
+
2. `local` (CLI, tests) and `onprem`: call the handler in-process. `asynchronous=True` still finishes before `invoke()` returns.
|
|
177
178
|
3. `aws`: `lambda:InvokeFunction` via boto3 (`pip install py-serverless-kit[aws]`, and add `boto3` to requirements). Grant `lambda:InvokeFunction` in `iam.statements`.
|
|
178
179
|
4. `gcp`: authenticated HTTPS call to `https://<region>-<project>.cloudfunctions.net/<service>-<stage>-<name>` with an ID token from the metadata server.
|
|
179
180
|
5. Other providers raise `InvokeError` unless `PSKIT_ENDPOINT_<NAME>` is set. Point it at the target's HTTP URL from `pskit info`. On Azure, invoke-only functions expose `POST /_pskit/invoke/<name>` (function key required).
|
|
@@ -186,7 +187,8 @@ pskit injects:
|
|
|
186
187
|
|
|
187
188
|
| Variable | Value |
|
|
188
189
|
|---|---|
|
|
189
|
-
| `PSKIT_PROVIDER` | `aws`, `gcp`, … (`local` under the CLI) |
|
|
190
|
+
| `PSKIT_PROVIDER` | `aws`, `gcp`, `onprem`, … (`local` under the CLI) |
|
|
191
|
+
| `PSKIT_ONPREM_ROOT` | on-premises only: directory of the running host. Handlers use it to publish into the file broker |
|
|
190
192
|
| `PSKIT_SERVICE`, `PSKIT_STAGE`, `PSKIT_REGION` | deployment identity |
|
|
191
193
|
| `PSKIT_FUNCTION`, `PSKIT_HANDLER` | the logical function and its handler (not app settings on Azure, where they're passed explicitly) |
|
|
192
194
|
| `PSKIT_GCP_PROJECT` | GCP only |
|
|
@@ -92,6 +92,10 @@ def test_workflow():
|
|
|
92
92
|
| `LocalRunner(project, env_file=".env")` | in-process runner |
|
|
93
93
|
| `runner.invoke(function, event)` | run a handler; HTTP returns a `Response` |
|
|
94
94
|
| `runner.run_workflow(name, data, sleep=False)` | returns `{"output", "history"}`; raises `WorkflowFailed` |
|
|
95
|
+
|
|
96
|
+
## On-premises is a deploy, not `pskit dev`
|
|
97
|
+
|
|
98
|
+
`pskit dev` reloads HTTP handlers and drops the process when you stop it. `provider.name: onprem` is the durable run: `pskit deploy` starts a process that keeps schedules, file queues, directory storage, topics and embedded workflows after the command returns. See [providers.md](providers.md#onprem-on-premises) and [`examples/16-on-premises`](../examples/16-on-premises).
|
|
95
99
|
| `http_event(method, path, body=None, headers=None, query=None)` | dict/list bodies are JSON-encoded; `?query` in `path` is parsed |
|
|
96
100
|
| `build_event(type, data, **http)` | `queue`/`topic` (list → records), `storage` (`{"bucket", "key", "size", "action"}`), `schedule`, `invoke`, `workflow`, `http` |
|
|
97
101
|
|
|
@@ -14,12 +14,13 @@ Run `pskit providers` (or `pskit providers --json`) to print this matrix from th
|
|
|
14
14
|
| [`digitalocean`](#digitalocean-functions) | beta | ✓ | ✓ | – | – | – | embedded | 3.9, 3.11 | 900 s |
|
|
15
15
|
| [`oracle`](#oracle-oci-functions) | experimental | ✓ | – | – | ✓ | – | embedded | 3.9, 3.11 | 300 s |
|
|
16
16
|
| [`cloudflare`](#cloudflare-python-workers) | experimental | ✓ | ✓ | – | – | – | embedded | 3.11–3.13 | 900 s |
|
|
17
|
+
| [`onprem`](#onprem-on-premises) | experimental | ✓ | ✓ | ✓ | ✓ | ✓ | embedded | 3.9–3.14 | 3600 s |
|
|
17
18
|
|
|
18
19
|
**Tiers**
|
|
19
20
|
|
|
20
21
|
- **stable:** the generated Terraform is validated against the real provider plugin, and the full trigger set is supported.
|
|
21
22
|
- **beta:** validated with `terraform validate`; event payload formats follow vendor documentation.
|
|
22
|
-
- **experimental:** works with notable constraints (container images, Pyodide), so read the section below first.
|
|
23
|
+
- **experimental:** works with notable constraints (container images, Pyodide, or a process on your own machine), so read the section below first.
|
|
23
24
|
|
|
24
25
|
**Common to all providers**
|
|
25
26
|
|
|
@@ -27,7 +28,7 @@ Run `pskit providers` (or `pskit providers --json`) to print this matrix from th
|
|
|
27
28
|
- Resources are tagged or labelled with `pskit-service`, `pskit-stage` and `managed-by: py-serverless-kit` where the cloud supports tags.
|
|
28
29
|
- With no pinned `runtime`, pskit picks python3.12 or the newest version below it that the cloud supports (see [configuration.md](configuration.md#default-runtime)).
|
|
29
30
|
|
|
30
|
-
Every generated configuration (all
|
|
31
|
+
Every generated configuration (all 11 providers) passes `terraform validate`. The repository's `scripts/validate_all_providers.py` re-checks this in CI. On-premises uses Terraform's built-in provider, so that check does not download a plugin for it.
|
|
31
32
|
|
|
32
33
|
---
|
|
33
34
|
|
|
@@ -353,6 +354,66 @@ One Worker script per function. pskit generates a single Python module per Worke
|
|
|
353
354
|
|
|
354
355
|
---
|
|
355
356
|
|
|
357
|
+
## onprem (On-premises)
|
|
358
|
+
|
|
359
|
+
- **Terraform:** built-in `terraform_data` (no plugin download)
|
|
360
|
+
- **Credentials:** none. The host is the same Python that runs `pskit deploy`
|
|
361
|
+
- **Dependencies:** pip wheels for this machine and interpreter, not a Linux cloud image. `tzdata` is vendored so cron timezones work on Windows
|
|
362
|
+
|
|
363
|
+
```yaml
|
|
364
|
+
provider:
|
|
365
|
+
name: onprem
|
|
366
|
+
region: local
|
|
367
|
+
options:
|
|
368
|
+
host: 127.0.0.1 # bind address. 0.0.0.0 is advertised as 127.0.0.1 unless advertise is set
|
|
369
|
+
port: 8080 # 1-65535. Give each service its own port
|
|
370
|
+
advertise: https://fn.internal.example # optional URL written into outputs
|
|
371
|
+
data_dir: .pskit/onprem-data # default .pskit/onprem-data/<service>-<stage>
|
|
372
|
+
poll_seconds: 0.5
|
|
373
|
+
admin_token: "${env:PSKIT_ADMIN_TOKEN, }" # header x-pskit-token on /__pskit/* except health
|
|
374
|
+
services:
|
|
375
|
+
schedule: builtin # the only schedule implementation
|
|
376
|
+
queue: builtin # or {use: directory, path: /var/pskit/queues}
|
|
377
|
+
storage: {use: directory, path: .onprem/buckets}
|
|
378
|
+
topic: builtin
|
|
379
|
+
workflow: embedded # builtin is an alias of embedded
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
`pskit deploy` writes the bundle under `.pskit/onprem-<stage>/onprem_app/` and starts `onprem_ctl.py`. The process serves your HTTP routes and polls the service directories. `pskit remove` stops the process and does not delete `data_dir`.
|
|
383
|
+
|
|
384
|
+
Omitted services default to `builtin` and are created at start. `existing: true` on one queue, bucket or topic skips that create and waits until the directory appears. Names are a single path segment (`..`, slashes and NUL are rejected).
|
|
385
|
+
|
|
386
|
+
| Trigger | Implementation |
|
|
387
|
+
|---|---|
|
|
388
|
+
| http | the host process. `auth` must be `none` (check tokens in the handler) |
|
|
389
|
+
| schedule | in-process rate (any positive number of minutes, hours or days, including values that are not cron) and 5-field cron. A missing IANA timezone warns and is evaluated in UTC |
|
|
390
|
+
| queue | one JSON file per message. `batch_size`, `batch_window`, `visibility_timeout` (default `max(30, 6 x timeout)`), `dead_letter`, `max_receive` and `fifo` are honoured. `BatchResult` retries only the failed ids |
|
|
391
|
+
| storage | files under `<bucket>/<key>`. `prefix`, `suffix`, `created` and `deleted`. The first start records the current files and does not emit them |
|
|
392
|
+
| topic | fan-out. `filter` is an exact match on message attributes, then on JSON body fields |
|
|
393
|
+
| workflows | embedded engine inside the host, so a workflow is not cut off by a function timeout |
|
|
394
|
+
|
|
395
|
+
Publish from outside the process:
|
|
396
|
+
|
|
397
|
+
| Request | Effect |
|
|
398
|
+
|---|---|
|
|
399
|
+
| `GET /__pskit/health` | status, no token |
|
|
400
|
+
| `POST /__pskit/queues/<name>` | enqueue one JSON value, a list, or `{"messages": [...]}`. `202 {"queued": [ids]}` |
|
|
401
|
+
| `GET /__pskit/queues/<name>` | `{"depth": n}` |
|
|
402
|
+
| `POST /__pskit/topics/<name>` | publish, then deliver. `{"message", "attributes"}` sets attributes when those are the only keys |
|
|
403
|
+
| `PUT` / `DELETE /__pskit/storage/<bucket>/<key>` | write or remove an object, then deliver |
|
|
404
|
+
| `POST /__pskit/invoke/<function>` | in-process invoke |
|
|
405
|
+
| `POST /__pskit/workflows/<name>` | run the embedded workflow |
|
|
406
|
+
|
|
407
|
+
From a handler in that process (`PSKIT_ONPREM_ROOT` is set), call `submit_queue`, `submit_topic`, `put_object` or `delete_object` in `py_serverless_kit.runtime.onprem_host`.
|
|
408
|
+
|
|
409
|
+
**Resources:** `terraform_data.host` with create and destroy `local-exec` provisioners.
|
|
410
|
+
|
|
411
|
+
**Limits:** no cloud authorizer and no IAM mapping. A `terraform.extra` resource from another cloud (`aws_*`, `google_*`, `azurerm_*`, and the other cloud prefixes) is omitted with a warning. A state backend of `s3`, `gcs` or `azurerm` warns; set `provider.state.backend` empty (see `providers.onprem` in examples 11 and 15) to keep state on this machine. Delivery is at-least-once. A missed schedule fires once on the next poll, not as a burst. The host does not kill a handler at `timeout`; `ctx.remaining_time_ms()` still counts down. If `provider.runtime` is not the interpreter running `pskit`, validation warns and the host still uses that interpreter.
|
|
412
|
+
|
|
413
|
+
Example: [`examples/16-on-premises`](../examples/16-on-premises).
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
356
417
|
## Writing your own provider
|
|
357
418
|
|
|
358
419
|
See [architecture.md](architecture.md#third-party-providers) and [`deploy_docs/CONTRIBUTING.md`](../deploy_docs/CONTRIBUTING.md).
|
|
@@ -82,6 +82,7 @@ Add `-v` to any command to see the full traceback. Start with `pskit validate`,
|
|
|
82
82
|
| digitalocean | `doctl` must be installed and authenticated (`doctl auth init`); `options.namespace` required; set `options.api_host` to get URLs |
|
|
83
83
|
| ibm | HTTP only, python3.11 only, 120 s / 4 GB max; large bundles → `options.code_reference` |
|
|
84
84
|
| cloudflare | Pyodide: only stdlib and Pyodide packages; `options.account_id` and `CLOUDFLARE_API_TOKEN` required; non-`.py` files aren't uploaded |
|
|
85
|
+
| onprem | one process per service, so give each service its own `options.port`. `pskit remove` stops it and leaves `data_dir`. `auth` must be `none`. A cloud `terraform.extra` resource is omitted. Set `state.backend` empty when the file points at S3, GCS or Azure Storage |
|
|
85
86
|
| alibaba / tencent / huawei | `iam.statements` aren't translated; set `iam.role` |
|
|
86
87
|
|
|
87
88
|
## FAQ
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
A workflow chains functions with branching, retries, error handling, waits, parallel branches and fan-out. You define it once in `pskit.yml`, and pskit runs it:
|
|
4
4
|
|
|
5
5
|
- **natively**, as AWS Step Functions (ASL) or Google Cloud Workflows;
|
|
6
|
-
- on the **embedded engine** on every other
|
|
6
|
+
- on the **embedded engine** on every other target, inside an auto-generated orchestrator function (on premises that function runs inside the long-lived host, so the workflow is not cut off by a function timeout);
|
|
7
7
|
- **locally** with `pskit workflow run`, using the same engine.
|
|
8
8
|
|
|
9
9
|
```yaml
|
|
@@ -20,6 +20,7 @@ return result
|
|
|
20
20
|
| Cloud | What `BatchResult` does |
|
|
21
21
|
| --- | --- |
|
|
22
22
|
| AWS SQS | partial batch response: only failed messages are retried |
|
|
23
|
+
| On-premises | partial batch response: only failed messages are retried, then dead-lettered |
|
|
23
24
|
| GCP Pub/Sub, Azure Storage Queues, others | any failure fails the invocation, so the whole batch is redelivered |
|
|
24
25
|
|
|
25
26
|
Make processing **idempotent**: on most clouds a message can be delivered more than once.
|
|
@@ -34,6 +35,8 @@ Make processing **idempotent**: on most clouds a message can be delivered more t
|
|
|
34
35
|
| `fifo` | SQS FIFO | warning | not supported |
|
|
35
36
|
| `existing: true` | look up instead of create | yes | yes |
|
|
36
37
|
|
|
38
|
+
On premises every option in the YAML is implemented by a directory of message files. `builtin` (the default) creates that directory at start. `{use: directory, path: ...}` under `provider.options.services.queue` uses a directory you already have.
|
|
39
|
+
|
|
37
40
|
`pskit validate --provider <cloud>` prints the warnings for your configuration.
|
|
38
41
|
|
|
39
42
|
## The producer
|
|
@@ -53,7 +56,7 @@ def send_job(job: dict) -> None:
|
|
|
53
56
|
...
|
|
54
57
|
```
|
|
55
58
|
|
|
56
|
-
The example's `enqueue` handler
|
|
59
|
+
The example's `enqueue` handler logs on a cloud, so it runs anywhere without credentials. On premises (`PSKIT_ONPREM_ROOT`) it writes the job into the file queue with `submit_queue`.
|
|
57
60
|
|
|
58
61
|
## Run locally
|
|
59
62
|
|
|
@@ -77,4 +80,5 @@ pskit invoke -f enqueue -d '{"kind": "invoice", "id": 7}' # 202
|
|
|
77
80
|
pskit deploy # SQS queues + DLQ + event source mappings
|
|
78
81
|
pskit deploy --provider gcp # Pub/Sub topics + Eventarc triggers
|
|
79
82
|
pskit deploy --provider azure # Storage queues + queue triggers
|
|
83
|
+
pskit deploy --provider onprem # file queues on this machine, http://127.0.0.1:8084
|
|
80
84
|
```
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
``event.records`` holds the messages of one batch. Return a ``BatchResult``
|
|
4
4
|
naming the records that failed:
|
|
5
5
|
|
|
6
|
-
* AWS SQS:
|
|
7
|
-
(``ReportBatchItemFailures``
|
|
6
|
+
* AWS SQS and the on-premises host: only those messages become visible again
|
|
7
|
+
and are retried (``ReportBatchItemFailures`` on AWS);
|
|
8
8
|
* other clouds: any failure fails the invocation, so the whole batch is redelivered.
|
|
9
9
|
|
|
10
10
|
Either way a message that keeps failing ends up in the dead-letter queue
|
|
@@ -62,14 +62,20 @@ def _log_dead_letter(record: Record, ctx: Context) -> None:
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
def enqueue(event: Event, ctx: Context):
|
|
65
|
-
"""HTTP producer
|
|
65
|
+
"""HTTP producer.
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
``send_message``
|
|
70
|
-
that
|
|
71
|
-
|
|
67
|
+
On premises the host is in this process, so the message is written to the
|
|
68
|
+
file queue. On a cloud, publishing is a cloud SDK call (boto3
|
|
69
|
+
``sqs.send_message``, ``google-cloud-pubsub`` ``publish``,
|
|
70
|
+
``azure-storage-queue`` ``send_message``). Keep that call behind a small
|
|
71
|
+
function of your own (see README).
|
|
72
72
|
"""
|
|
73
73
|
job = event.http.json()
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
queue = ctx.env.get("JOBS_QUEUE") or "jobs"
|
|
75
|
+
if ctx.env.get("PSKIT_ONPREM_ROOT"):
|
|
76
|
+
from py_serverless_kit.runtime.onprem_host import submit_queue
|
|
77
|
+
|
|
78
|
+
message_id = submit_queue(queue, job)
|
|
79
|
+
return {"accepted": True, "queue": queue, "message_id": message_id}, 202
|
|
80
|
+
ctx.logger.info("would enqueue", extra={"job": job, "queue": queue})
|
|
81
|
+
return {"accepted": True, "queue": queue}, 202
|
|
@@ -52,3 +52,12 @@ providers:
|
|
|
52
52
|
audit-existing:
|
|
53
53
|
events:
|
|
54
54
|
- storage: {bucket: audit-uploads, events: [created]}
|
|
55
|
+
onprem:
|
|
56
|
+
region: local
|
|
57
|
+
options: {host: 127.0.0.1, port: 8085}
|
|
58
|
+
# The shared audit bucket is not on this machine. Create a local directory
|
|
59
|
+
# bucket with the host so the function has somewhere to listen.
|
|
60
|
+
functions:
|
|
61
|
+
audit-existing:
|
|
62
|
+
events:
|
|
63
|
+
- storage: {bucket: shared-uploads, events: [created, deleted]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# 08 · Multi-cloud: same code,
|
|
1
|
+
# 08 · Multi-cloud: same code, every provider
|
|
2
2
|
|
|
3
|
-
`app/handlers.py` deploys unchanged to all
|
|
4
|
-
differs, and you can organise it in either of two ways.
|
|
3
|
+
`app/handlers.py` deploys unchanged to all eleven providers, including an on-premises
|
|
4
|
+
host. Only the configuration differs, and you can organise it in either of two ways.
|
|
5
5
|
|
|
6
6
|
## Option A: one file with `providers:` overrides
|
|
7
7
|
|
|
@@ -18,6 +18,7 @@ pskit deploy --provider oracle
|
|
|
18
18
|
pskit deploy --provider ibm
|
|
19
19
|
pskit deploy --provider digitalocean
|
|
20
20
|
pskit deploy --provider cloudflare
|
|
21
|
+
pskit deploy --provider onprem
|
|
21
22
|
```
|
|
22
23
|
|
|
23
24
|
## Option B: one small file per cloud with `extends:`
|
|
@@ -49,6 +50,7 @@ of them on one page.
|
|
|
49
50
|
| ibm | beta | `IC_API_KEY` | Code Engine functions; HTTP only, Python 3.11, max 120 s |
|
|
50
51
|
| digitalocean | beta | `options.namespace`, `doctl` on PATH | deployed with `doctl serverless` |
|
|
51
52
|
| cloudflare | experimental | `options.account_id` | Python Workers (stdlib + Pyodide packages only) |
|
|
53
|
+
| onprem | experimental | nothing (optional `options.port`) | a Python process on this machine; queues, storage and topics are directories |
|
|
52
54
|
|
|
53
55
|
Where a cloud lacks a feature, the override says so explicitly. For example
|
|
54
56
|
`functions.ticker.events: []` on IBM and Oracle deploys `ticker` without a schedule
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# One file for
|
|
1
|
+
# One file for every provider, including an on-premises host. Pick the target with:
|
|
2
2
|
# pskit deploy -> provider.name below (aws)
|
|
3
3
|
# pskit deploy --provider gcp -> applies providers.gcp on top
|
|
4
4
|
#
|
|
@@ -88,3 +88,9 @@ providers:
|
|
|
88
88
|
options: # credentials: CLOUDFLARE_API_TOKEN
|
|
89
89
|
account_id: "${env:CLOUDFLARE_ACCOUNT_ID, 0123456789abcdef0123456789abcdef}"
|
|
90
90
|
workers_subdomain: "${env:CLOUDFLARE_WORKERS_SUBDOMAIN, my-team}" # <name>.<subdomain>.workers.dev
|
|
91
|
+
|
|
92
|
+
onprem:
|
|
93
|
+
region: local # a long-lived process on this machine; no cloud account
|
|
94
|
+
options:
|
|
95
|
+
host: 127.0.0.1
|
|
96
|
+
port: 8088
|