Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

Rust-based toy control plane for a managed Postgres service. Mainly to experiment with duroxide.

License

Notifications You must be signed in to change notification settings

affandar/toygres

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

33 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Toygres

A Rust-based toy control plane for hosting PostgreSQL containers as a service on Azure Kubernetes Service (AKS).

Features

  • Durable Workflows: Uses Duroxide for reliable orchestration
  • Kubernetes Native: Deploys PostgreSQL as pods in AKS
  • Public & Private Access: Supports LoadBalancer (public IP) or ClusterIP (internal only)
  • DNS Support: Automatic Azure DNS names for instances
  • YAML Templates: Kubernetes resources defined in clean, readable YAML
  • REST API: Full-featured API for instance management
  • PostgreSQL Metadata: Complete CMS database for tracking instances
  • Web UI: Modern React-based dashboard for visual management
  • Health Monitoring: Continuous per-instance health checks via durable actors

Architecture

  • Deployment: PostgreSQL containers as StatefulSets in AKS
  • Storage: Persistent volumes for durable data
  • Networking: LoadBalancer services with Azure DNS names
  • Workflow Engine: Duroxide for durable orchestrations
  • Control Plane: Rust-based API server

Quick Start

Prerequisites

  1. Rust (1.85.0 or newer)

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. Docker Desktop (for kind local testing)

  3. Azure CLI

    brew install azure-cli
    az login
  4. kubectl

    brew install kubectl
  5. kind (optional, for local testing)

    brew install kind

Azure Infrastructure Setup

Option 1: Use Existing AKS Cluster

If you already have an AKS cluster:

# Get cluster credentials
az aks get-credentials --resource-group <your-rg> --name <your-cluster>

# Verify connection
kubectl cluster-info

# Create toygres namespace
kubectl create namespace toygres

# Update .env with your cluster details
cp .env.example .env
# Edit .env and set:
#   AKS_CLUSTER_NAME=<your-cluster>
#   AKS_RESOURCE_GROUP=<your-rg>
#   AKS_NAMESPACE=toygres

Option 2: Create New AKS Cluster

Use the provided infrastructure setup script:

# This will create:
# - Azure Resource Group
# - AKS Cluster (takes 10-15 minutes)
# - toygres namespace
# - Storage class configuration
./scripts/setup-infra.sh

# Script will prompt for configuration and output values for .env

Configuration

  1. Copy the example environment file:

    cp .env.example .env
  2. Edit .env with your values:

    Required for Control Plane:

    DATABASE_URL=postgresql://user:password@host:5432/toygres
    AKS_CLUSTER_NAME=your-aks-cluster
    AKS_RESOURCE_GROUP=your-resource-group

    Optional (for examples/testing with manual_deploy):

    INSTANCE_NAME=my-test-pg
    POSTGRES_PASSWORD=your-secure-password
    USE_LOAD_BALANCER=true
  3. Set up metadata database (⚠️ REQUIRED before running toygres-server):

    ./scripts/db-init.sh
    ./scripts/db-migrate.sh   # (no-op until we add 0002+ migrations)

    This creates the toygres_cms schema and all required tables. The server will verify tables exist on startup and fail with a clear error if this step is skipped.

  4. Verify kubectl connection (required before running toygres-server):

    # Get AKS credentials (use values from your .env)
    az aks get-credentials --resource-group <your-rg> --name <your-cluster> --overwrite-existing
    
    # Verify connection works
    kubectl cluster-info
    
    # Verify namespace exists
    kubectl get namespace toygres

    ⚠️ Important: The toygres-server requires kubectl to be configured to access your AKS cluster. If you see errors like "Failed to create K8s client", ensure you've run the az aks get-credentials command above.

Test Deployment

Test that everything works by deploying a PostgreSQL instance:

# Deploy with auto-generated DNS name
cargo run --example manual_deploy -- --dns-name mytest --clean

# Or deploy with defaults
cargo run --example manual_deploy

# Expected output:
# βœ“ PostgreSQL deployed to AKS
# βœ“ External IP: 4.249.xxx.xxx
# βœ“ DNS name: mytest-toygres.westus3.cloudapp.azure.com
# βœ“ Connection verified

Build and Run Control Plane

Prerequisites: Ensure kubectl is configured (see step 4 above) and database is initialized (step 3).

# Build all crates
cargo build --workspace

# For convenience, use the wrapper script (in project root)
# Instead of: cargo run --bin toygres-server -- <command>
# Use: ./toygres <command>

# Start the server (API + Workers)
./toygres server start

# List instances
./toygres list

# Create a PostgreSQL instance
# The name you provide becomes the DNS name: <name>.<region>.cloudapp.azure.com
# Returns immediately - instance is created in the background
./toygres create adardb1 --password mySecurePass123

# Check instance status (state will show 'creating' β†’ 'running')
./toygres get adardb1

# List all instances
./toygres list

# Delete an instance (use the same DNS name you used to create it)
# Returns immediately - instance is deleted in the background
./toygres delete adardb1

# Stop the server
./toygres server stop

# Advanced diagnostics (for debugging orchestrations)
./toygres server orchestrations              # List all orchestrations
./toygres server orchestration <id> --history  # Show execution details

# Or use the full cargo command:
cargo run --bin toygres-server -- create adardb1 --password mySecurePass123

Web UI

Access the visual dashboard at http://localhost:3000:

# Start the backend server first
./toygres server start

# In a new terminal, start the Web UI
cd toygres-ui
npm install
npm start

# Open http://localhost:3000 in your browser

The Web UI provides:

  • πŸ“Š Dashboard - System overview and recent activity
  • πŸ—„οΈ Instance Management - View all PostgreSQL instances
  • πŸ“ˆ System Monitoring - Real-time stats and worker status
  • πŸ”¬ Debug Tools - Orchestration viewer and log browser
  • πŸ”„ Auto-refresh - Live updates every 5 seconds

Deploy to AKS (Production)

Deploy the complete solution (control plane + data plane) to Azure Kubernetes Service:

# 1. Copy and configure environment
cp .env.example .env
# Edit .env with your values (see required variables below)

# 2. Deploy with HTTP only
./deploy/deploy-to-aks.sh

# 3. Or deploy with HTTPS (recommended for production)
./deploy/deploy-to-aks.sh --https --dns-label mytoygres
# This will create: https://mytoygres.<region>.cloudapp.azure.com

Required environment variables for AKS deployment:

Variable Description
DATABASE_URL PostgreSQL connection string for metadata (can be Azure Database for PostgreSQL)
AKS_CLUSTER_NAME Your AKS cluster name
AKS_RESOURCE_GROUP Azure resource group containing the AKS cluster
AZURE_CLIENT_ID Service Principal client ID
AZURE_CLIENT_SECRET Service Principal secret
AZURE_TENANT_ID Azure AD tenant ID
TOYGRES_ADMIN_USERNAME Admin username for web UI login
TOYGRES_ADMIN_PASSWORD Admin password for web UI login

Create a Service Principal:

az ad sp create-for-rbac --name "toygres-sp" --role contributor \
    --scopes /subscriptions/<subscription-id>/resourceGroups/<resource-group>

What gets deployed:

  • toygres-server - Control plane API and orchestration workers
  • toygres-ui - Web dashboard (proxies to server)
  • RBAC - ServiceAccount with permissions to create PostgreSQL pods
  • Secrets - Database credentials and Azure authentication
  • (Optional) nginx-ingress + cert-manager for HTTPS

Project Structure

toygres/
β”œβ”€β”€ toygres-models/          # Shared data structures
β”œβ”€β”€ toygres-orchestrations/  # Duroxide orchestrations & activities
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ activities/      # Atomic K8s operations
β”‚   β”‚   β”œβ”€β”€ orchestrations/  # Durable workflows
β”‚   β”‚   └── templates/       # Kubernetes YAML templates
β”œβ”€β”€ toygres-server/          # Control plane server
β”‚   β”œβ”€β”€ src/                 # Main server code (API + CLI)
β”‚   └── examples/            # Working examples (manual_deploy.rs)
β”œβ”€β”€ toygres-ui/              # Web interface (React + TypeScript)
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ components/      # React components
β”‚   β”‚   └── lib/             # API client and utilities
β”œβ”€β”€ migrations/              # Database schema migrations
β”œβ”€β”€ docs/                    # Documentation
β”œβ”€β”€ scripts/                 # Setup and management scripts
└── prompts/                 # AI assistant context docs

Scripts

Infrastructure Management

# Setup AKS cluster
./scripts/setup-infra.sh

# Setup metadata database schema + future migrations
./scripts/db-init.sh
./scripts/db-migrate.sh

Deployment Management

# List all PostgreSQL deployments
./scripts/list-deployments.sh

# Clean up all deployments
./scripts/cleanup-deployments.sh

# Clean up a specific deployment
./scripts/cleanup-single.sh <instance-name>

Examples

Deploy PostgreSQL Instance

# With custom DNS name and auto-cleanup
cargo run --example manual_deploy -- --dns-name mydb --clean

# Keep instance running for testing
cargo run --example manual_deploy -- --dns-name prod-db

# Deploy without public DNS (IP only)
# Remove DNS_LABEL from .env, then:
cargo run --example manual_deploy

Connect to Deployed Instance

The deployment tool outputs connection strings:

# Via DNS (recommended) - when using toygres-server
psql 'postgresql://postgres:[email protected]:5432/postgres'

# Via DNS - when using manual_deploy example (with DNS_LABEL=toygres)
psql 'postgresql://postgres:[email protected]:5432/postgres'

# Via IP
psql 'postgresql://postgres:[email protected]:5432/postgres'

Clean Up Resources

# List current deployments
AKS_NAMESPACE=toygres ./scripts/list-deployments.sh

# Clean up a specific instance
AKS_NAMESPACE=toygres ./scripts/cleanup-single.sh mydb

# Or clean up all instances
AKS_NAMESPACE=toygres ./scripts/cleanup-deployments.sh

Documentation

API Endpoints (Coming in Phase 3)

  • POST /instances - Create a new PostgreSQL instance
  • DELETE /instances/{id} - Delete an instance
  • GET /instances - List all instances
  • GET /instances/{id} - Get instance details
  • GET /operations/{id} - Monitor operation status
  • GET /health - Control plane health check

Development Status

βœ… Phase 0: Complete

  • Proof of concept working
  • YAML-based K8s templates
  • LoadBalancer with public IPs
  • Azure DNS name support
  • Connection testing
  • Cleanup scripts

πŸ”„ Phase 1: In Progress

  • Extracting into Duroxide activities
  • Following cross-crate registry pattern

⏳ Coming Soon

  • Phase 2: Metadata database tracking
  • Phase 3: REST API
  • Phase 4: Duroxide orchestrations
  • Phase 5: Health monitoring

Troubleshooting

Can't connect to AKS / "Failed to create K8s client"

Symptoms:

  • Error: Failed to create K8s client: Failed to create Kubernetes client
  • kubectl shows: The connection to the server localhost:8080 was refused
  • Activity failures in duroxide logs

Solution:

# Get credentials (use your actual resource group and cluster name from .env)
az aks get-credentials --resource-group <rg> --name <cluster> --overwrite-existing

# Verify connection works
kubectl cluster-info

# Should show: Kubernetes control plane is running at https://...

Root Cause: The Kubernetes client (kube-rs) requires kubectl to be configured with valid cluster credentials in ~/.kube/config. Without this, it defaults to localhost:8080 and fails.

Deployment fails

# Check namespace exists
kubectl get namespace toygres

# Create if missing
kubectl create namespace toygres

# Check storage classes
kubectl get storageclass

Resources stuck

# Force delete
kubectl delete statefulset,svc,pvc -n toygres -l app=postgres --grace-period=0

Contributing

See docs/plan.md for the implementation roadmap.

License

MIT

About

Rust-based toy control plane for a managed Postgres service. Mainly to experiment with duroxide.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published