Generate Kubernetes manifests, Airflow DAGs, and initialization jobs for Yellow deployment.
Bootstrap artifacts are the Kubernetes manifests and Airflow DAGs needed to deploy and operate a DataSurface Yellow environment.
docker login registry.gitlab.com -u "$GITLAB_CUSTOMER_USER" -p "$GITLAB_CUSTOMER_TOKEN"
docker pull registry.gitlab.com/datasurface-inc/datasurface/datasurface:v${DATASURFACE_VERSION}
eco.py:GIT_REPO_OWNER: str = "yourorg"
GIT_REPO_NAME: str = "demo1_actual"
rte_demo.py with proper credentials and database configuration.Yellow uses a "ring" system for staged deployment:
| Ring Level | Purpose | When to Run | Artifacts Generated |
|---|---|---|---|
| 0 | Initial bootstrap | Once, before K8s setup | kubernetes-bootstrap.yaml, infrastructure DAG, init job, merge job |
| 1 | Schema initialization | After K8s bootstrap applied | Creates database schemas, tables, initializes merge DB |
Ring 0 generates the files you need to set up Kubernetes. Ring 1 runs inside Kubernetes to initialize the database schemas.
Run this from your model directory:
docker run --rm \
-v "$(pwd)":/workspace/model \
-w /workspace/model \
registry.gitlab.com/datasurface-inc/datasurface/datasurface:v${DATASURFACE_VERSION} \
python -m datasurface.cmd.platform generatePlatformBootstrap \
--ringLevel 0 \
--model /workspace/model \
--output /workspace/model/generated_output \
--psp Demo_PSP \
--rte-name demo
| Parameter | Description | Example |
|---|---|---|
--ringLevel | Bootstrap stage (0 or 1) | 0 |
--model | Path to model directory (inside container) | /workspace/model |
--output | Output directory for generated files | /workspace/model/generated_output |
--psp | Platform Service Provider name from model | Demo_PSP |
--rte-name | Runtime Environment name from model | demo |
After running Ring 0 generation, you'll have:
generated_output/
└── Demo_PSP/
├── kubernetes-bootstrap.yaml # PVC, ConfigMap, NetworkPolicy, MCP Server
├── demo_psp_infrastructure_dag.py # Airflow DAG for ongoing operations
├── demo_psp_ring1_init_job.yaml # K8s Job for Ring 1 initialization
├── demo_psp_model_merge_job.yaml # K8s Job for model merge operations
└── demo_psp_reconcile_views_job.yaml # K8s Job for view reconciliation
kubernetes-bootstrap.yaml contains:
git-cache-pvc - PersistentVolumeClaim for caching git repositorydemo-logging-config - ConfigMap for logging configurationdemo-network-policy - NetworkPolicy for pod communicationdemo-psp-mcp-server - Deployment for Model Context Protocol serverdemo-psp-mcp - Service exposing MCP serverdemo_psp_infrastructure_dag.py - Airflow DAG that:
demo_psp_ring1_init_job.yaml - Kubernetes Job that:
demo_psp_model_merge_job.yaml - Kubernetes Job that:
After generating Ring 0 artifacts:
# 1. Apply Kubernetes bootstrap (creates PVC, MCP server, network policies)
kubectl apply -f generated_output/Demo_PSP/kubernetes-bootstrap.yaml
# 2. Copy DAG to GitSync repository
cp generated_output/Demo_PSP/demo_psp_infrastructure_dag.py /path/to/demo1_airflow/dags/
cd /path/to/demo1_airflow
git add dags/
git commit -m "Add infrastructure DAG"
git push
# 3. Run Ring 1 initialization (creates database schemas)
kubectl apply -f generated_output/Demo_PSP/demo_psp_ring1_init_job.yaml
# 4. Wait for Ring 1 to complete
kubectl wait --for=condition=complete job/demo-psp-ring1-init -n $NAMESPACE --timeout=120s
# 5. Run model merge job
kubectl apply -f generated_output/Demo_PSP/demo_psp_model_merge_job.yaml
If you update your model (eco.py, rte_demo.py), regenerate artifacts:
# Remove old artifacts
rm -rf generated_output/
# Regenerate
docker run --rm \
-v "$(pwd)":/workspace/model \
-w /workspace/model \
registry.gitlab.com/datasurface-inc/datasurface/datasurface:v${DATASURFACE_VERSION} \
python -m datasurface.cmd.platform generatePlatformBootstrap \
--ringLevel 0 \
--model /workspace/model \
--output /workspace/model/generated_output \
--psp Demo_PSP \
--rte-name demo
# Reapply to Kubernetes
kubectl apply -f generated_output/Demo_PSP/kubernetes-bootstrap.yaml
# Delete and recreate jobs (jobs are immutable)
kubectl delete job demo-psp-ring1-init -n $NAMESPACE --ignore-not-found
kubectl delete job demo-psp-model-merge-job -n $NAMESPACE --ignore-not-found
kubectl apply -f generated_output/Demo_PSP/demo_psp_ring1_init_job.yaml
kubectl apply -f generated_output/Demo_PSP/demo_psp_model_merge_job.yaml
To use a different DataSurface version:
# Set version
export DATASURFACE_VERSION="1.2.0"
# Pull new image
docker pull registry.gitlab.com/datasurface-inc/datasurface/datasurface:v${DATASURFACE_VERSION}
# Update rte_demo.py to use new image
# datasurfaceDockerImage="registry.gitlab.com/datasurface-inc/datasurface/datasurface:v1.2.0"
# Regenerate artifacts
docker run --rm \
-v "$(pwd)":/workspace/model \
-w /workspace/model \
registry.gitlab.com/datasurface-inc/datasurface/datasurface:v${DATASURFACE_VERSION} \
python -m datasurface.cmd.platform generatePlatformBootstrap \
--ringLevel 0 \
--model /workspace/model \
--output /workspace/model/generated_output \
--psp Demo_PSP \
--rte-name demo
Error:
ModuleNotFoundError: No module named 'eco'
ImportError: cannot import name 'Ecosystem' from 'eco'
Solution: Ensure you're running from the model directory and the volume mount is correct:
cd /path/to/demo1_actual
docker run --rm -v "$(pwd)":/workspace/model ...
Error:
ValueError: PSP 'Demo_PSP' not found in ecosystem
Solution: Check the PSP name matches exactly what's defined in your model. Look in rte_demo.py for:
YellowPlatformServiceProvider(
"Demo_PSP",
...
)
Error:
ValueError: RTE 'demo' not found
Solution: Check the RTE name matches the runtime environment in your model:
YellowRunTimeEnvironment(
"demo",
...
)
Error:
PermissionError: [Errno 13] Permission denied: '/workspace/model/generated_output'
Solution: The Docker container runs as a specific user. Either:
mkdir -p generated_outputdocker run --rm -u $(id -u):$(id -g) -v ...Error:
AttributeError: 'NoneType' object has no attribute 'name'
Solution: Usually indicates a missing or misconfigured credential in the model. Verify all credentials are defined:
mergeRW_Credential=Credential("postgres-demo-merge", CredentialType.USER_PASSWORD)
gitPlatformRepoCredential=Credential("git", CredentialType.API_TOKEN)
To compare artifacts after regeneration (useful when debugging):
# Save old artifacts
cp -r generated_output/Demo_PSP generated_output/Demo_PSP_old
# Regenerate
docker run --rm ...
# Compare
diff generated_output/Demo_PSP_old/demo_psp_model_merge_job.yaml \
generated_output/Demo_PSP/demo_psp_model_merge_job.yaml
Before applying to Kubernetes:
# Dry-run to check for errors
kubectl apply -f generated_output/Demo_PSP/kubernetes-bootstrap.yaml --dry-run=client
# Validate YAML syntax
kubectl apply -f generated_output/Demo_PSP/demo_psp_ring1_init_job.yaml --dry-run=server