diff --git a/CLAUDE.md b/CLAUDE.md index 50776741..dcf503b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -86,43 +86,29 @@ laconic-so deployment --dir deployment start ## Architecture: k8s-kind Deployments ### One Cluster Per Host -There is **one Kind cluster per host by design**. Multiple deployments (stacks) share this cluster. Never request or expect separate clusters for different deployments on the same host. +One Kind cluster per host by design. Never request or expect separate clusters. - `create_cluster()` in `helpers.py` reuses any existing cluster -- Cluster name in deployment.yml is an identifier, not a cluster request -- All deployments share ingress controller, etcd, certificates +- `cluster-id` in deployment.yml is an identifier, not a cluster request +- All deployments share: ingress controller, etcd, certificates -### External Stacks -External stacks are detected by filesystem path existence (`Path(stack).exists()`). Required structure: +### Stack Resolution +- External stacks detected via `Path(stack).exists()` in `util.py` +- Config/compose resolution: external path first, then internal fallback +- External path structure: `stack_orchestrator/data/stacks//stack.yml` -``` -/ - stack_orchestrator/data/ - stacks//stack.yml - compose/docker-compose-.yml - deployment/spec.yml -``` +### Secret Generation Implementation +- `GENERATE_TOKEN_PATTERN` in `deployment_create.py` matches `$generate:type:length$` +- `_generate_and_store_secrets()` creates K8s Secret +- `cluster_info.py` adds `envFrom` with `secretRef` to containers +- Non-secret config written to `config.env` -Config/compose resolution: external path first, then internal fallback. - -### Deployment Lifecycle -- `deploy create`: Initializes deployment dir, generates cluster-id, processes spec.yml -- `deployment start`: Creates/reuses cluster, deploys K8s resources -- `deployment restart`: Git pulls stack repo, syncs spec, redeploys (preserves data) -- `deployment stop`: Removes K8s resources (cluster persists) - -### Secret Generation -`$generate:type:length$` tokens in spec.yml config section: -- Processed during `deploy create` -- Stored in K8s Secret `-generated-secrets` -- Injected via `envFrom` with `secretRef` -- Non-secret config goes to `config.env` - -### Key Files -- `spec.yml`: Deployment specification (in stack repo) -- `deployment.yml`: Cluster-id, stack-source path (generated) -- `config.env`: Non-secret environment variables (generated) -- `kind-config.yml`: Kind cluster configuration (generated) +### Key Files (for codebase navigation) +- `deployment_create.py`: `deploy create` command, secret generation +- `deployment.py`: `deployment start/stop/restart` commands +- `deploy_k8s.py`: K8s deployer, cluster management calls +- `helpers.py`: `create_cluster()`, etcd cleanup, kind operations +- `cluster_info.py`: K8s resource generation (Deployment, Service, Ingress) ## Insights and Observations diff --git a/README.md b/README.md index 375491bf..594ef9b9 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,59 @@ The various [stacks](/stack_orchestrator/data/stacks) each contain instructions - [laconicd with console and CLI](stack_orchestrator/data/stacks/fixturenet-laconic-loaded) - [kubo (IPFS)](stack_orchestrator/data/stacks/kubo) +## Deployment Types + +- **compose**: Docker Compose on local machine +- **k8s**: External Kubernetes cluster (requires kubeconfig) +- **k8s-kind**: Local Kubernetes via Kind - one cluster per host, shared by all deployments + +## External Stacks + +Stacks can live in external git repositories. Required structure: + +``` +/ + stack_orchestrator/data/ + stacks//stack.yml + compose/docker-compose-.yml + deployment/spec.yml +``` + +## Deployment Commands + +```bash +# Create deployment from spec +laconic-so --stack deploy create --spec-file --deployment-dir + +# Start (creates cluster on first run) +laconic-so deployment --dir start + +# GitOps restart (git pull + redeploy, preserves data) +laconic-so deployment --dir restart + +# Stop +laconic-so deployment --dir stop +``` + +## spec.yml Reference + +```yaml +stack: stack-name-or-path +deploy-to: k8s-kind +network: + http-proxy: + - host-name: app.example.com + routes: + - path: / + proxy-to: service-name:port + acme-email: admin@example.com +config: + ENV_VAR: value + SECRET_VAR: $generate:hex:32$ # Auto-generated, stored in K8s Secret +volumes: + volume-name: +``` + ## Contributing See the [CONTRIBUTING.md](/docs/CONTRIBUTING.md) for developer mode install.