Skip to content

Commit 01ee9e9

Browse files
authored
Reintroduce bundled database to the chart (#365)
Resolves #358 # Description Reintroduces a bundled PostgreSQL instance to the Helm chart and restructures the `database` values key to align with [kagent PR #1527](kagent-dev/kagent#1527). **What changed:** - **Bundled PostgreSQL on by default** — `postgres:18` is deployed alongside Agent Registry when `database.postgres.bundled.enabled=true` (the default). Intended for development and evaluation only; a warning is shown in NOTES.txt. - **Restructured `database` values** — replaced the old `database.bundled.*` / `database.external.*` split with a flat `database.postgres.*` structure: - `database.postgres.url` / `database.postgres.urlFile` — external connection string (urlFile takes precedence) - `database.postgres.bundled.*` — bundled instance config (image, storage, resources) - `database.postgres.vectorEnabled` — enables `AGENT_REGISTRY_EMBEDDINGS_ENABLED` and `AGENT_REGISTRY_DATABASE_VECTOR_ENABLED` on the app pod - **Default image is `postgres:18`** (official, plain). Users who want semantic search can opt in via `database.postgres.vectorEnabled=true` with their own pgvector-capable PostgreSQL instance. - **Conditional vector migrations** — base schema no longer requires pgvector. Vector schema (embedding columns, HNSW indexes) is applied in a separate migration set, only when `DatabaseVectorEnabled=true`. - **URL file support** — `AGENT_REGISTRY_DATABASE_URL_FILE` env var / `database.postgres.urlFile` value reads the database URL from a file at startup. - **Separate PostgreSQL Secret** — bundled DB password lives in its own `{release}-postgresql` Secret, decoupled from the JWT key Secret. - **Init container only when needed** — the `wait-for-postgres` init container is skipped when `url` or `urlFile` is set, even if `bundled.enabled=true`. - **Simplified helpers** — removed `agentregistry.secretName`, `agentregistry.passwordSecretName`, and `agentregistry.databaseUrl`; logic inlined into templates. Removed `global.existingSecret`. - **Updated docs** — `README.md`, `DEVELOPMENT.md`, chart `README.md.gotmpl`, and `NOTES.txt` updated for accuracy. - **Helm unit tests** — new `postgresql_test.yaml` suite; `deployment_test.yaml`, `secrets_test.yaml`, and `validation_test.yaml` updated for the new values structure. # Change Type /kind feature /kind install # Changelog ```release-note Reintroduces a bundled PostgreSQL database option to the Helm chart with a new database.postgres.* values structure. The bundled database (postgres:18) is enabled by default for development and evaluation. Set database.postgres.bundled.enabled=false and supply database.postgres.url for production. ```
1 parent 3307499 commit 01ee9e9

33 files changed

Lines changed: 861 additions & 769 deletions

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ AGENT_REGISTRY_SERVER_ADDRESS=:8080
44

55
# Database Configuration
66
# PostgreSQL connection string
7-
AGENT_REGISTRY_DATABASE_URL=postgres://localhost:5432/agent-registry?sslmode=disable
7+
AGENT_REGISTRY_DATABASE_URL=postgres://localhost:5432/agentregistry?sslmode=disable
88

99
# Seed Configuration
1010
# Path to seed data file (optional)

DEVELOPMENT.md

Lines changed: 15 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Local Kubernetes Environment
44

5-
The fastest way to run the full stack locally is with [Kind](https://kind.sigs.k8s.io/). A single `make` target creates the cluster, deploys PostgreSQL/pgvector, builds the server image, and installs AgentRegistry via Helm.
5+
The fastest way to run the full stack locally is with [Kind](https://kind.sigs.k8s.io/). A single `make` target creates the cluster, builds the server image, and installs AgentRegistry via Helm — a PostgreSQL instance with pgvector is bundled and deployed automatically by the Helm chart for local development.
66

77
### Prerequisites
88

@@ -19,13 +19,12 @@ The fastest way to run the full stack locally is with [Kind](https://kind.sigs.k
1919
make setup-kind-cluster
2020
```
2121

22-
This runs three steps in order:
22+
This runs two steps in order:
2323

2424
| Step | Target | What it does |
2525
|------|--------|-------------|
2626
| 1 | `create-kind-cluster` | Installs `kind` to `./bin/`, creates Kind cluster + local registry (`localhost:5001`) + MetalLB |
27-
| 2 | `install-postgresql` | Deploys `pgvector/pgvector:0.8.2-pg16` into the `agentregistry` namespace |
28-
| 3 | `install-agentregistry` | Builds server image, pushes to local registry, Helm installs AgentRegistry |
27+
| 2 | `install-agentregistry` | Builds server image, pushes to local registry, Helm installs AgentRegistry (bundled PostgreSQL with pgvector override for local dev) |
2928

3029
Each target can also be run independently — useful when iterating on code:
3130

@@ -48,9 +47,9 @@ On subsequent runs, `install-agentregistry` reuses the `jwtPrivateKey` already s
4847
kubectl --context kind-agentregistry port-forward -n agentregistry svc/agentregistry 12121:12121
4948
# open http://localhost:12121
5049

51-
# PostgreSQL (for direct inspection)
52-
kubectl --context kind-agentregistry port-forward -n agentregistry svc/postgres-pgvector 5432:5432
53-
psql -h localhost -U agentregistry -d agent-registry
50+
# Bundled PostgreSQL (for direct inspection)
51+
kubectl --context kind-agentregistry port-forward -n agentregistry svc/agentregistry-postgresql 5432:5432
52+
psql -h localhost -U agentregistry -d agentregistry
5453
```
5554

5655
### Teardown
@@ -111,208 +110,30 @@ The UI is available at `http://localhost:12121`.
111110

112111
# Architecture Overview
113112

114-
### 1. CLI Layer (cmd/)
113+
**Tech stack:** Go 1.25+ · PostgreSQL + pgvector (pgx) · [Huma](https://huma.rocks/) (OpenAPI) · [Cobra](https://cobra.dev/) (CLI) · Next.js 14 (App Router) · Tailwind CSS · shadcn/ui
115114

116-
Built with [Cobra](https://github.com/spf13/cobra), provides all command-line functionality:
117-
118-
- **Registry Management**: connect, disconnect, refresh
119-
- **Resource Discovery**: list, search, show
120-
- **Installation**: install, uninstall
121-
- **Configuration**: configure clients
122-
- **UI**: launch web interface
123-
124-
Each command has placeholder implementations ready to be filled with actual logic.
125-
126-
### 2. Data Layer (internal/database/)
127-
128-
Uses **SQLite** for local storage:
129-
130-
**Tables:**
131-
- `registries` - Connected registries
132-
- `servers` - MCP servers from registries
133-
- `skills` - Skills from registries
134-
- `installations` - Installed resources
135-
136-
**Location:** `~/.arctl/arctl.db`
137-
138-
The schema is based on the MCP Registry JSON schema provided, supporting the full `ServerDetail` structure.
139-
140-
### 3. API Layer (internal/api/)
141-
142-
Built with [Gin](https://github.com/gin-gonic/gin), provides REST API:
143-
144-
**Endpoints:**
145-
- `GET /api/health` - Health check
146-
- `GET /api/registries` - List registries
147-
- `GET /api/servers` - List MCP servers
148-
- `GET /api/skills` - List skills
149-
- `GET /api/installations` - List installed resources
150-
- `GET /*` - Serve embedded UI
151-
152-
**Port:** 8080 (configurable with `--port`)
153-
154-
### 4. UI Layer (ui/)
155-
156-
Built with:
157-
- **Framework:** Next.js 14 (App Router)
158-
- **Language:** TypeScript
159-
- **Styling:** Tailwind CSS
160-
- **Components:** shadcn/ui
161-
- **Icons:** Lucide React
162-
163-
**Features:**
164-
- Dashboard with statistics
165-
- Resource browser (registries, MCP servers, skills)
166-
- Real-time data from API
167-
- Responsive design
168-
- Installation status indicators
169-
170-
**Build Output:** Static files exported to `internal/registry/api/ui/dist/`
171-
172-
## Data Flow
173-
174-
### CLI Command Execution
175-
176-
```
177-
User Input
178-
179-
Cobra Command (cmd/)
180-
181-
Business Logic (TODO)
182-
183-
Database Layer (internal/database/)
184-
185-
SQLite (~/.arctl/arctl.db)
186-
```
187-
188-
### Web UI Request
189-
190-
```
191-
Browser Request
192-
193-
Gin Router (internal/api/)
194-
195-
API Handler
196-
197-
Database Query
198-
199-
JSON Response
200-
201-
React Component (ui/)
202-
203-
User Interface
204-
```
205-
206-
## Embedding Strategy
207-
208-
### How It Works
209-
210-
1. **Build Phase** (`make build-ui`):
211-
- Next.js builds static files
212-
- Output goes to `internal/registry/api/ui/dist/`
213-
214-
2. **Compile Phase** (`make build-cli`):
215-
- Go's `embed` directive includes entire `ui/dist/` directory
216-
- Files become part of the binary
217-
218-
3. **Runtime Phase** (`./bin/arctl ui`):
219-
- Gin serves files from embedded FS
220-
- No external dependencies needed
221-
222-
### Embed Directive
223-
224-
```go
225-
//go:embed ui/dist/*
226-
var embeddedUI embed.FS
227-
```
228-
229-
This embeds all files in `internal/registry/api/ui/dist/` at compile time.
115+
For a detailed breakdown of layers, conventions, and contribution guidelines see [`AGENTS.md`](AGENTS.md).
230116

231117
## Build Process
232118

233-
### Development
234-
235119
```bash
236120
# UI only (hot reload)
237121
make dev-ui
238122

239-
# CLI only (quick iteration)
240-
go build -o bin/arctl main.go
241-
```
242-
243-
### Production
123+
# Build CLI binary
124+
make build-cli
244125

245-
```bash
246-
# Full build with embedding
247-
make build
126+
# Build server binary
127+
make build-server
248128

249-
# Creates: ./bin/arctl (single binary with UI embedded)
129+
# Build UI static assets
130+
make build-ui
250131
```
251132

252-
## Extension Points
253-
254-
### Adding a New CLI Command
255-
256-
1. Create `cmd/mycommand.go`
257-
2. Define the command with Cobra
258-
3. Add to `rootCmd` in `init()`
259-
4. Implement logic (call database layer)
260-
261-
### Adding a New API Endpoint
262-
263-
1. Add handler in `internal/api/server.go`
264-
2. Register route in `StartServer()`
265-
3. Call database layer
266-
4. Return JSON response
267-
268-
### Adding a New UI Page
269-
270-
1. Create `ui/app/mypage/page.tsx`
271-
2. Fetch data from `/api/*` endpoints
272-
3. Use shadcn components for UI
273-
4. Rebuild with `make build-ui`
274-
275-
### Adding Database Tables
276-
277-
1. Update schema in `internal/database/database.go`
278-
2. Add model in `internal/models/models.go`
279-
3. Add query methods in database package
280-
4. Database auto-migrates on first run
281-
282-
## Security Considerations
283-
284-
### Database
285-
286-
- Stored in user's home directory (`~/.arctl/`)
287-
- No network access
288-
- File permissions: 0755 (directory), default (file)
289-
290-
### API Server
291-
292-
- Localhost only by default
293-
- CORS not configured (local use)
294-
- No authentication (local tool)
295-
296-
### Embedded UI
297-
298-
- Static files only
299-
- No server-side execution
300-
- Served from memory (embedded)
301-
302-
## Contributing
303-
304-
When adding features:
305-
306-
1. Add placeholder implementations first
307-
2. Create tests (TODO)
308-
3. Update documentation
309-
4. Rebuild with `make build`
310-
5. Test the binary
311-
312133
## Resources
313134

314135
- [Cobra Documentation](https://cobra.dev/)
315-
- [Gin Documentation](https://gin-gonic.com/)
136+
- [Huma Documentation](https://huma.rocks/)
316137
- [Next.js Documentation](https://nextjs.org/docs)
317138
- [shadcn/ui Components](https://ui.shadcn.com/)
318139
- [MCP Protocol Specification](https://spec.modelcontextprotocol.io/)

Makefile

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,6 @@ kind-debug: ## Shell into Kind control-plane and run btop for resource monitorin
343343
docker exec -it $(KIND_CLUSTER_NAME)-control-plane bash -c 'apt-get update -qq && apt-get install -y --no-install-recommends btop htop'
344344
docker exec -it $(KIND_CLUSTER_NAME)-control-plane bash -c 'btop --utf-force'
345345

346-
.PHONY: install-postgresql
347-
install-postgresql: ## Deploy standalone PostgreSQL/pgvector into the Kind cluster
348-
kubectl --context $(KIND_CLUSTER_CONTEXT) apply -f examples/postgres-pgvector.yaml
349-
kubectl --context $(KIND_CLUSTER_CONTEXT) -n agentregistry wait --for=condition=ready pod -l app=postgres-pgvector --timeout=120s
350-
351346
BUILD ?= true
352347

353348
.PHONY: install-agentregistry
@@ -365,14 +360,15 @@ endif
365360
--create-namespace \
366361
--set image.pullPolicy=Always \
367362
--set image.registry=$(DOCKER_REGISTRY) \
368-
--set image.repository=$(DOCKER_REPO)/server \
363+
--set image.repository=$(DOCKER_REPO) \
369364
--set image.tag=$(VERSION) \
370-
--set database.host=postgres-pgvector.$(KIND_NAMESPACE).svc.cluster.local \
371-
--set database.password=agentregistry \
372-
--set database.sslMode=disable \
373365
--set config.jwtPrivateKey="$$JWT_KEY" \
374366
--set config.enableAnonymousAuth="true" \
375367
--set service.type=LoadBalancer \
368+
--set database.postgres.bundled.image.repository=pgvector \
369+
--set database.postgres.bundled.image.name=pgvector \
370+
--set database.postgres.bundled.image.tag=pg16 \
371+
--set database.postgres.vectorEnabled=true \
376372
--wait \
377373
--timeout=5m;
378374

@@ -412,9 +408,9 @@ install-kagent-controller: ## Deploy kagent controller (minimal, no agents/tools
412408
--wait \
413409
--timeout=5m
414410

415-
## Set up a full local K8s dev environment (Kind + PostgreSQL/pgvector + AgentRegistry + kagent).
411+
## Set up a full local K8s dev environment (Kind + AgentRegistry with bundled PostgreSQL + kagent).
416412
.PHONY: setup-kind-cluster
417-
setup-kind-cluster: create-kind-cluster install-postgresql install-kagent install-agentregistry ## Set up the full local Kind development environment
413+
setup-kind-cluster: create-kind-cluster install-kagent install-agentregistry ## Set up the full local Kind development environment
418414

419415
.PHONY: dump-kind-state
420416
dump-kind-state: ## Dump Kind cluster state for debugging (pods, events, kagent logs)
@@ -425,7 +421,12 @@ dump-kind-state: ## Dump Kind cluster state for debugging (pods, events, kagent
425421
@kubectl get pods -A --context $(KIND_CLUSTER_CONTEXT) 2>/dev/null || true
426422
@echo ""
427423
@echo "=== Pod describe ==="
428-
@kubectl describe pods --context $(KIND_CLUSTER_CONTEXT) 2>/dev/null || true
424+
@kubectl describe pods -A --context $(KIND_CLUSTER_CONTEXT) 2>/dev/null || true
425+
@echo ""
426+
@echo "=== AgentRegistry logs ==="
427+
@kubectl logs deployment/agentregistry -n $(KIND_NAMESPACE) --context $(KIND_CLUSTER_CONTEXT) --tail=100 2>/dev/null || true
428+
@echo "=== AgentRegistry previous logs ==="
429+
@kubectl logs deployment/agentregistry -n $(KIND_NAMESPACE) --context $(KIND_CLUSTER_CONTEXT) --tail=100 --previous 2>/dev/null || true
429430
@echo ""
430431
@echo "=== Events ==="
431432
@kubectl get events -A --sort-by='.lastTimestamp' --context $(KIND_CLUSTER_CONTEXT) 2>/dev/null | tail -50 || true
@@ -538,9 +539,7 @@ charts-render-test: charts-deps ## Render chart templates as a smoke test
538539
@echo "Rendering chart templates for $(HELM_CHART_DIR)..."
539540
$(HELM) template test-release $(HELM_CHART_DIR) \
540541
--values $(HELM_CHART_DIR)/values.yaml \
541-
--set config.jwtPrivateKey=deadbeef1234567890abcdef12345678 \
542-
--set database.password=ci-password \
543-
--set database.host=postgres.example.com
542+
--set config.jwtPrivateKey=deadbeef1234567890abcdef12345678
544543

545544
# Package the chart into $(HELM_PACKAGE_DIR)/.
546545
.PHONY: charts-package

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ When you run `arctl deploy`, agentregistry automatically configures the gateway
189189
| [MCP Go SDK](https://github.com/modelcontextprotocol/go-sdk) | Go SDK for building MCP servers |
190190
| [Model Context Protocol](https://modelcontextprotocol.io/) | The open standard for AI-to-tool communication |
191191

192+
> **Semantic search** requires a PostgreSQL instance with the pgvector extension. It is disabled by default. To enable it, ensure your database has pgvector support and set `AGENT_REGISTRY_DATABASE_VECTOR_ENABLED=true` (docker-compose / `.env`) or `--set database.postgres.vectorEnabled=true` (Helm).
193+
192194
---
193195

194196
## Community

charts/agentregistry/Chart-template.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ annotations:
2626
artifacthub.io/images: |
2727
- name: agentregistry
2828
image: ghcr.io/agentregistry-dev/agentregistry/server:${CHART_VERSION}
29+
- name: postgresql
30+
image: docker.io/library/postgres:18

0 commit comments

Comments
 (0)