# Plan: Update Fission Python Template Based on Example Projects ## Context The current Fission Python template (`fission-python/template/`) is essentially a copy of the `py-eom-quota` example project, making it **quota-specific** rather than a **generic starting point** for new Fission Python projects. Three example projects were analyzed: - `py-eom-quota` - User quota management API - `py-eom-storage` - Storage resource management with S3 integration - `py-ailbl-scheduler` - Background job scheduler with Dagster integration All examples share common infrastructure patterns but differ in business logic. This plan will make the template **generic, reusable, and production-ready** by extracting shared best practices. --- ## Key Findings from Examples ### 1. Common Infrastructure (All Projects Share) - **vault.py** - Identical across all three projects (encryption/decryption using PyNaCl) - **helpers.py** - Nearly identical core utilities: - `get_secret()` / `get_config()` (K8s secrets/configmaps with vault support) - `init_db_connection()` (PostgreSQL connection) - `db_row_to_dict()` / `db_rows_to_array()` - `get_user_from_headers()` (extract user for audit logging) - `format_error_response()` (standardized error format) - `check_port_open()` (DB readiness check) - `str_to_bool()` utility - **Fission Configuration** - Using docstring format in `main()` functions - **Exception Patterns** - Custom exception hierarchies with: - `error_code` (machine-readable) - `http_status` (HTTP status) - `error_msg` (human-readable) - `x_user` (optional user tracking) - `details` (optional additional context) - **Pydantic Models** - Request validation, response schemas, pagination/filtering - **Project Structure** - Consistent layout: ``` project/ ├── .fission/deployment.json ├── src/ │ ├── __init__.py │ ├── exceptions.py │ ├── helpers.py │ ├── models.py │ ├── vault.py │ ├── build.sh │ └── .py ├── test/ ├── migrates/ ├── manifests/ ├── specs/ ├── requirements.txt ├── dev-requirements.txt └── README.md ``` ### 2. Variations Between Projects **Database Connection:** - `py-eom-quota`: Advanced `DBConfig` dataclass with `from_remote_config()` support - `py-eom-storage` & `py-ailbl-scheduler`: Simplified direct connection from secrets **Additional Dependencies:** - Storage: `boto3` (S3/MinIO), `botocore` - Scheduler: `gql` (GraphQL), `cron-descriptor` - All: `pydantic`, `psycopg2-binary`, `PyNaCl`, `Flask`, `requests` **Executors:** - Quota: `poolmgr` (concurrency=1) - Storage: `poolmgr` (concurrency=3, maxscale=3) - Scheduler: `newdeploy` (minscale=1, maxscale=1) ### 3. Issues to Fix - **README outdated** - References `pymake`, `fission.json`, `fission.yaml` (not used) - **Missing Flask** - `src/requirements.txt` needs Flask (currently only in dev-requirements) - **Quota-specific code** - Template should be generic (no `QuotaException`, `QuotaResponse`, etc.) - **No .env.example** - Missing environment variable template - **Test dependencies minimal** - Should include `pytest`, `pytest-mock`, `requests`, `flake8`, `black` - **build.sh** - Should handle both alpine (apk) and debian (apt) properly - **deployment.json** - Should not hardcode `fission-eom-quota-env` secret names - **Missing Python version** - Should specify Python 3.11+ (scheduler uses 3.11-alpine) --- ## Recommended Changes ### Phase 1: Core Infrastructure (Keep Generic) **Files to MODIFY:** 1. **`src/vault.py`** - Keep as-is (already perfect, identical in all examples) 2. **`src/helpers.py`** - Use the simplified pattern from `py-eom-storage` but add: - Keep: `get_secret()`, `get_config()`, `init_db_connection()`, `db_row_to_dict()`, `db_rows_to_array()`, `get_current_namespace()`, `str_to_bool()`, `check_port_open()`, `get_user_from_headers()`, `format_error_response()` - Remove: `DBConfig` class (too specific to quota, keep it simple) - Add: `.strip()` when reading files (as in scheduler) - Keep CORS_HEADERS and constants but make them configurable 3. **`src/exceptions.py`** - Replace quota-specific with generic patterns: ```python class ServiceException(Exception): """Base exception for service errors.""" def __init__(self, error_code, http_status, error_msg, x_user=None, details=None): ... class ValidationError(ServiceException): # 400 class NotFoundError(ServiceException): # 404 class ConflictError(ServiceException): # 409 class DatabaseError(ServiceException): # 500 ``` (Based on `py-eom-storage` pattern - cleaner and more generic) 4. **`src/models.py`** - Replace with generic example patterns: - Remove: All quota-specific models - Add: Generic `ItemResponse`, `PaginatedResponse`, `ErrorResponse` - Include examples of Pydantic models with Field descriptions and json_schema_extra - Show patterns for: Enums, nested models, dataclasses for filters 5. **`src/requirements.txt`** - Update to include actual runtime deps: ``` Flask==2.1.1 pydantic==2.11.7 psycopg2-binary==2.9.10 PyNaCl==1.6.0 requests==2.32.2 ``` (Remove commented examples - these go in docs, not requirements.txt) 6. **`dev-requirements.txt`** - Expand with useful dev tools: ``` Flask==2.1.1 requests==2.32.2 pytest==8.2.0 pytest-mock==3.14.0 flake8==7.0.0 black==24.1.1 mypy==1.8.0 ``` 7. **`README.md`** - Complete rewrite: - Remove references to pymake, fission.json - Explain actual project structure - Document Fission configuration in docstrings - Show how to use deployment.json - Document environment variables (secrets/configmaps) - Explain testing approach - Add development workflow - Include examples from all three projects as inspiration 8. **`.fission/deployment.json`** - Make generic with placeholders: - Use `your-service-py` as environment name - Use `your-package` as package name - Use generic secret/configmap names: `fission-${PROJECT_NAME}-env`, `fission-${PROJECT_NAME}-config` - Show both `poolmgr` and `newdeploy` executor examples (commented) - Include optional fields like `imagepullsecret`, `runtime_envs`, `configmaps` 9. **`test/requirements.txt`** - Add: ``` pytest==8.2.0 pytest-mock==3.14.0 requests==2.32.3 ``` 10. **`build.sh`** - Fix to use `${SRC_PKG}` properly (current version is correct) ### Phase 2: Documentation & Examples **New Files to ADD:** 1. **`src/__init__.py`** - Already exists, keep as is 2. **`examples/` directory** (new) - Sample function implementations: - `example_crud.py` - Basic CRUD with Pydantic validation - `example_webhook.py` - Webhook receiver pattern - `example_scheduler.py` - Background job pattern (from ailbl-scheduler) - Each should have proper Fission docstring config 3. **`.env.example`** - Template showing all environment variables: ``` # PostgreSQL PG_HOST= PG_PORT=5432 PG_DB= PG_USER= PG_PASS= PG_DBSCHEMA= # Optional: Service-specific config (via ConfigMap) # YOUR_SERVICE_CONFIG_ENDPOINT= # Optional: Vault encryption key (if using encrypted secrets) # CRYPTO_KEY= ``` 4. **`docs/` directory** (new) - Additional documentation: - `STRUCTURE.md` - Detailed file structure explanation - `TESTING.md` - How to write and run tests - `DEPLOYMENT.md` - Deployment options and tuning - `SECRETS.md` - Managing secrets and configmaps - `MIGRATIONS.md` - Database migration workflow 5. **`pytest.ini`** - Default pytest configuration: ```ini [pytest] testpaths = test python_files = test_*.py python_classes = Test* python_functions = test_* log_cli = true log_cli_level = INFO ``` 6. **`.gitignore`** - Ensure it excludes: - `__pycache__/` - `*.pyc` - `.env` - `.venv/` - `venv/` - `.pytest_cache/` - `.mypy_cache/` - `.coverage` - `coverage.xml` - `specs/` (optional - generated files) 7. **`MANIFEST.md`** - Template for Kubernetes manifests (if not using auto-generated) ### Phase 3: Modernization **Update CI/CD:** Review `.gitea/workflows/` files: - Ensure they install dependencies correctly - Add linting (flake8/black) steps - Add test execution - Add deployment steps with proper environment detection - Consider adding security scanning **Python Version:** - Ensure all files are compatible with Python 3.11+ - Update `build.sh` to use Python 3.11 image (like scheduler does) or keep generic - Consider adding `runtime.txt` or `pyproject.toml` to specify Python version --- ## Files to Modify Summary **Direct modifications:** - `src/helpers.py` - Simplify, improve - `src/exceptions.py` - Make generic - `src/models.py` - Replace with generic patterns - `src/requirements.txt` - Add Flask, remove commented section - `dev-requirements.txt` - Comprehensive dev dependencies - `test/requirements.txt` - Test dependencies - `README.md` - Complete rewrite - `.fission/deployment.json` - Generic placeholders - `build.sh` - Already good, just ensure compatibility **New files to add:** - `.env.example` - `pytest.ini` - `.gitignore` (enhance) - `examples/` directory with sample functions - `docs/` directory with detailed guides - `src/example_crud.py` (or in examples/) - `src/example_webhook.py` (or in examples/) - `src/example_scheduler.py` (or in examples/) **New directories:** - `examples/` - `docs/` --- ## Implementation Approach 1. **Backup current template** (git branch) 2. **Modify core files** in order: helpers → exceptions → models → requirements → deployment.json → README 3. **Add new files** (examples, docs, configs) 4. **Test the template**: - Run `create-project.sh` to generate a new project - Verify build.sh works - Run tests - Check Fission spec generation 5. **Commit with clear message** 6. **Update plugin documentation** if needed --- ## Verification Steps After implementing the changes: 1. **Create a test project** from the updated template: ```bash ./create-project.sh test-project ./tmp-test/ ``` 2. **Inspect generated project**: - Verify all files are present - Check that placeholders are substituted correctly - Ensure imports work 3. **Build the package**: ```bash cd tmp-test ./src/build.sh ``` 4. **Run tests** (if any): ```bash pip install -r dev-requirements.txt pytest ``` 5. **Check syntax**: ```bash python -m py_compile src/*.py flake8 src/ black --check src/ ``` 6. **Validate Fission config**: ```bash fission spec verify --file=.fission/deployment.json ``` 7. **Review README** - Does it accurately describe the project? --- ## Success Criteria - Template is **generic**, not domain-specific - All examples' best practices are incorporated - Documentation is accurate and complete - Dependencies are correctly listed (Flask in requirements, not just dev) - README reflects actual Fission workflow (docstrings, not fission.yaml) - Multiple example implementations provided (CRUD, webhook, scheduler) - Secrets/configuration clearly explained - Testing setup is comprehensive - Project passes linting and type checks --- ## Risks & Mitigations | Risk | Mitigation | |------|------------| | Breaking existing template users | Keep changes minimal in helpers; preserve backward compatibility where possible | | Over-engineering | Stick to patterns that appear in at least 2 of 3 examples | | Missing edge cases | Include optional advanced patterns (like DBConfig) in docs, not in core | | Documentation drift | Keep docs close to code; add examples that mirror real projects | --- ## Post-Implementation After the template is updated: 1. Consider creating a **template validation script** to ensure quality 2. Update the **plugin SKILL.md** to reflect template changes 3. Add **templating tests** to the fission-python-skill test suite 4. Document the **update process** for future template modifications 5. Consider **versioning** the template (e.g., `template-v2/`)