8.2 KiB
Project Structure
This document explains the purpose and contents of each directory and file in a Fission Python project.
Directory Layout
project/
├── .fission/ # Fission configuration
│ ├── deployment.json # Main deployment configuration
│ ├── dev-deployment.json # Development environment overrides
│ └── local-deployment.json # Local development overrides
├── src/ # Source code
│ ├── __init__.py # Package initialization
│ ├── vault.py # Vault encryption utilities
│ ├── helpers.py # Shared utility functions
│ ├── exceptions.py # Custom exception classes
│ ├── models.py # Pydantic models for validation
│ ├── build.sh # Build script (executable)
│ └── *.py # Your function implementations
├── test/ # Unit and integration tests
│ ├── __init__.py
│ ├── test_*.py # Test files
│ └── requirements.txt # Test dependencies
├── migrates/ # Database migration scripts
│ └── *.sql # SQL migration files
├── manifests/ # Kubernetes manifests (optional)
│ └── *.yaml # K8s resources
├── specs/ # Generated Fission specs
│ ├── fission-deployment-config.yaml
│ └── ...
├── requirements.txt # Runtime dependencies
├── dev-requirements.txt # Development dependencies
├── .env.example # Environment variable template
├── pytest.ini # Pytest configuration
├── README.md # Project documentation
└── (other project files)
File Purposes
.fission/deployment.json
This is the most important configuration file for Fission deployment. It defines:
- environments: Build environment configuration (image, builder, resources)
- archives: Source code packaging (typically "package.zip" from src/)
- packages: Package definitions linking source to environment
- function_common: Default settings applied to all functions
- secrets: Secret definitions (literal values are placeholders - actual secrets go in K8s)
- configmaps: ConfigMap definitions (non-sensitive configuration)
Important: The secret and configmap literals are placeholders only. In production, you create actual K8s secrets/configmaps with the same names containing real values.
Placeholders:
${PROJECT_NAME}- Replaced with your project name bycreate-project.sh- Secret name pattern:
fission-${PROJECT_NAME}-env - ConfigMap name pattern:
fission-${PROJECT_NAME}-config
src/vault.py
Provides encryption/decryption utilities using PyNaCl (SecretBox). This is used when you want to store encrypted values in K8s secrets rather than plaintext.
Key functions:
encrypt_vault(plaintext, key)- Encrypt and return vault format stringdecrypt_vault(vault, key)- Decrypt vault format stringis_valid_vault_format(vault)- Check if string is vault-encrypted
Usage in helpers.py: The get_secret() and get_config() functions automatically detect vault format (vault:v1:...) and decrypt if a valid CRYPTO_KEY is set.
src/helpers.py
Shared utilities used across functions:
Database:
init_db_connection()- Creates PostgreSQL connection from secretsdb_row_to_dict(cursor, row)- Convert row tuple to dictdb_rows_to_array(cursor, rows)- Convert multiple rows to list of dicts
Configuration:
get_secret(key, default=None)- Read from K8s secret volumeget_config(key, default=None)- Read from K8s config volumeget_current_namespace()- Get current K8s namespace
Utilities:
str_to_bool(input)- Convert string to booleancheck_port_open(ip, port, timeout)- TCP port connectivity checkget_user_from_headers()- Extract user ID from request headersformat_error_response(...)- Build standardized error dict
Logging:
- Helper uses
current_app.logger(Flask) for error logging
src/exceptions.py
Custom exception hierarchy:
ServiceException (base)
├── ValidationError (400) - Invalid input
├── NotFoundError (404) - Resource not found
├── ConflictError (409) - Duplicate/conflict
└── DatabaseError (500) - Database failure
All exceptions include:
error_code- Machine-readable codehttp_status- HTTP statuserror_msg- Human-readable messagex_user(optional) - User identifierdetails(optional) - Additional context dict
When raised in a Fission function, these automatically return proper JSON error responses.
src/models.py
Pydantic models for request/response validation:
Patterns included:
- Enums (e.g.,
Status,DataType) - Dataclass filters (e.g.,
ItemFilter,Pagination) - Request models (
ItemCreateRequest,ItemUpdateRequest) - Response models (
ItemResponse,PaginatedResponse) - ErrorResponse model (used by exceptions)
Key concepts:
- Use
Field(...)with constraints (min_length, max_length, ge, le) - Provide
descriptionfor API documentation - Use
json_schema_extrafor example values - Set
from_attributes = Truefor ORM compatibility
src/build.sh
Bash script that builds the dependency package. It:
- Detects OS (Debian vs Alpine)
- Installs build dependencies (gcc, libpq-dev/python3-dev/postgresql-dev)
- Installs Python requirements into
src/directory - Copies
src/to package destination
Important: Must be executable (chmod +x src/build.sh)
The script expects environment variables:
SRC_PKG- Source package directory (e.g.,src)DEPLOY_PKG- Destination package (e.g.,specs/package)
Fission builder sets these automatically.
test/
Contains unit and integration tests.
Structure:
test_*.py- Test files following pytest conventionsrequirements.txt- Test dependencies (pytest, pytest-mock, requests)
Running tests:
pip install -r dev-requirements.txt
pytest
Fission Configuration in Docstrings
Each Python function that should be exposed as a Fission function must include a ````fission` block in its docstring:
def my_function(event, context):
"""
```fission
{
"name": "my-function",
"http_triggers": {
"my-trigger": {
"url": "/api/endpoint",
"methods": ["GET", "POST"]
}
}
}
```
Human-readable description here.
"""
# Implementation
The Fission Python builder parses these docstrings and generates the specs/fission-deployment-config.yaml and other spec files.
Supported trigger types:
http_triggers- HTTP endpointskafka_triggers- Kafka topicstimer_triggers- Scheduled executionmessage_queue_triggers- MQTT, NATS, etc.
Configuration Precedence
- deployment.json - Base configuration (committed to repo)
- dev-deployment.json - Overrides for dev environment (not always committed)
- local-deployment.json - Local overrides (typically .gitignored)
When deploying:
fission deployuses deployment.jsonfission deploy --devuses dev-deployment.json if present
Secrets and Configuration Flow
-
Define placeholders in
deployment.json:"secrets": { "fission-myproject-env": { "literals": ["PG_HOST=localhost", "PG_PORT=5432"] } } -
Create actual K8s secret:
kubectl create secret generic fission-myproject-env \ --from-literal=PG_HOST=prod-db.example.com \ --from-literal=PG_PORT=5432 -
Read in code via
get_secret():host = get_secret("PG_HOST") -
For vault encryption:
- Set
CRYPTO_KEYin helpers.py or as env override - Store encrypted:
vault:v1:base64datain K8s secret get_secret()auto-decrypts
- Set
Summary
- Keep function code in
src/ - Define Fission metadata in docstring blocks
- Use helpers for common operations
- Define custom exceptions for error handling
- Validate inputs with Pydantic models
- Store tests in
test/with pytest - Manage database migrations in
migrates/ - Do not commit actual secrets to repository