Skip to content

Commit f542cce

Browse files
mjudeikisclaude
andauthored
fix(kuery): postgres store fixes + run dev on postgres (#333)
* fix(kuery): bump engine for postgres store fixes + run dev on postgres Revendor github.com/faroshq/kuery to pick up two Postgres-only query fixes (the local store now runs Postgres, so these surfaced): - owner/linked relation traversal tolerated a JSON scalar owner_refs ("null") that aborted with "cannot extract elements from a scalar". - the ID filter cast id to text so synthetic relation-node ids ("<uid>:references:0") no longer abort with "invalid input syntax for type uuid". Local dev now runs the kuery store on Postgres, matching production — SQLite silently masked both bugs. Mirrors the existing app-studio-db pattern: - Makefile: kuery-db-up / kuery-db-down spin a throwaway postgres:16 container on 127.0.0.1:55433; run-provider-kuery depends on it and always sets KUERY_STORE_DRIVER=postgres (override the DSN via KUERY_STORE_DSN to point at an external Postgres). No SQLite option. - Tiltfile + Tiltfile.cluster: kuery-db resource (+ kuery-db-down teardown) under providers-kuery; the kuery resource depends on it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * add current release printer --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 14515c9 commit f542cce

6 files changed

Lines changed: 140 additions & 7 deletions

File tree

Makefile

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: dev-edge-create dev-run-edge build test lint fix-lint codegen crds clean certs dev-setup run-dex run-hub run-hub-static run-hub-embedded run-hub-embedded-static run-hub-standalone run-hub-embedded-graphql run-kcp dev-login dev-login-static dev-create-workload dev dev-infra dev-run-kcp path boilerplate verify-boilerplate verify-codegen ldflags tools docker-build docker-build-hub docker-build-agent docker-build-dex docker-push-dex verify help-dev dev-status dev-clean-hooks helm-build-local helm-push-local helm-clean build-quickstart-provider build-quickstart-provider-portal build-kuery-provider build-kuery-provider-portal run-provider-kuery install-provider-kuery init-provider-kuery uninstall-provider-kuery run-provider-quickstart install-provider-quickstart init-provider-quickstart uninstall-provider-quickstart build-infrastructure-provider build-infrastructure-provider-portal codegen-infrastructure-provider run-provider-infrastructure install-provider-infrastructure init-provider-infrastructure uninstall-provider-infrastructure build-app-studio-provider build-app-studio-provider-portal codegen-app-studio-provider app-studio-db-up app-studio-db-down run-provider-app-studio install-provider-app-studio init-provider-app-studio uninstall-provider-app-studio build-code-provider build-code-provider-portal codegen-code-provider run-provider-code install-provider-code init-provider-code uninstall-provider-code dev-kro-up dev-kro-down dev-kro-seed dev-kro-register-self e2e-infrastructure portal-provider-symlinks build-mcp-provider-portal build-kubernetes-edges-provider-portal build-server-edges-provider-portal e2e-provider e2e-provider-flags e2e-provider-all
1+
.PHONY: dev-edge-create dev-run-edge build test lint fix-lint codegen crds clean certs dev-setup run-dex run-hub run-hub-static run-hub-embedded run-hub-embedded-static run-hub-standalone run-hub-embedded-graphql run-kcp dev-login dev-login-static dev-create-workload dev dev-infra dev-run-kcp path boilerplate verify-boilerplate verify-codegen ldflags tools docker-build docker-build-hub docker-build-agent docker-build-dex docker-push-dex verify help-dev dev-status dev-clean-hooks helm-build-local helm-push-local helm-clean build-quickstart-provider build-quickstart-provider-portal build-kuery-provider build-kuery-provider-portal run-provider-kuery kuery-db-up kuery-db-down install-provider-kuery init-provider-kuery uninstall-provider-kuery run-provider-quickstart install-provider-quickstart init-provider-quickstart uninstall-provider-quickstart build-infrastructure-provider build-infrastructure-provider-portal codegen-infrastructure-provider run-provider-infrastructure install-provider-infrastructure init-provider-infrastructure uninstall-provider-infrastructure build-app-studio-provider build-app-studio-provider-portal codegen-app-studio-provider app-studio-db-up app-studio-db-down run-provider-app-studio install-provider-app-studio init-provider-app-studio uninstall-provider-app-studio build-code-provider build-code-provider-portal codegen-code-provider run-provider-code install-provider-code init-provider-code uninstall-provider-code dev-kro-up dev-kro-down dev-kro-seed dev-kro-register-self e2e-infrastructure portal-provider-symlinks build-mcp-provider-portal build-kubernetes-edges-provider-portal build-server-edges-provider-portal e2e-provider e2e-provider-flags e2e-provider-all
22

33
BINDIR ?= bin
44
GOFLAGS ?=
@@ -676,7 +676,65 @@ KUERY_EDGES_IDENTITY_HASH ?=
676676
# init-provider-kuery from the provider SA token the hub mints.
677677
KUERY_RUNTIME_KUBECONFIG ?= $(KCP_DATA_DIR)/kuery-runtime.kubeconfig
678678

679-
run-provider-kuery: build-kuery-provider ## Run the kuery provider (requires: make run-hub-embedded-static + make install-provider-kuery; engagement needs init-provider-kuery)
679+
# Local store backend. Dev always runs Postgres — the same backend as
680+
# production — because Postgres-only SQL (jsonb_array_elements, uuid columns,
681+
# …) diverges from SQLite and passing on SQLite has shipped real query bugs.
682+
# kuery-db-up starts a throwaway container matching KUERY_DEV_DATABASE_URL.
683+
KUERY_POSTGRES_CONTAINER ?= kedge-kuery-postgres
684+
KUERY_POSTGRES_IMAGE ?= postgres:16-alpine
685+
KUERY_POSTGRES_PORT ?= 55433
686+
KUERY_POSTGRES_DATA_DIR ?= $(KCP_DATA_DIR)/kuery-postgres
687+
KUERY_POSTGRES_USER ?= kuery
688+
KUERY_POSTGRES_PASSWORD ?= kuery
689+
KUERY_POSTGRES_DB ?= kuery
690+
KUERY_DEV_DATABASE_URL ?= postgres://$(KUERY_POSTGRES_USER):$(KUERY_POSTGRES_PASSWORD)@localhost:$(KUERY_POSTGRES_PORT)/$(KUERY_POSTGRES_DB)?sslmode=disable
691+
# Connection string the provider uses. Defaults to the local dev container
692+
# above; point it at any external Postgres to override.
693+
KUERY_STORE_DSN ?=
694+
695+
kuery-db-up: ## Start/reuse local Postgres for the kuery store (no-op when KUERY_STORE_DSN points at an external DB)
696+
@if [ -n "$(KUERY_STORE_DSN)" ]; then \
697+
echo "Using externally configured KUERY_STORE_DSN; not starting local kuery Postgres"; \
698+
exit 0; \
699+
fi; \
700+
mkdir -p "$(KUERY_POSTGRES_DATA_DIR)"; \
701+
if docker ps --format '{{.Names}}' | grep -qx "$(KUERY_POSTGRES_CONTAINER)"; then \
702+
echo "kuery Postgres already running ($(KUERY_POSTGRES_CONTAINER))"; \
703+
elif docker ps -a --format '{{.Names}}' | grep -qx "$(KUERY_POSTGRES_CONTAINER)"; then \
704+
echo "Starting existing kuery Postgres container ($(KUERY_POSTGRES_CONTAINER))"; \
705+
docker start "$(KUERY_POSTGRES_CONTAINER)" >/dev/null; \
706+
else \
707+
echo "Creating kuery Postgres container ($(KUERY_POSTGRES_CONTAINER))"; \
708+
docker run -d \
709+
--name "$(KUERY_POSTGRES_CONTAINER)" \
710+
-e POSTGRES_USER="$(KUERY_POSTGRES_USER)" \
711+
-e POSTGRES_PASSWORD="$(KUERY_POSTGRES_PASSWORD)" \
712+
-e POSTGRES_DB="$(KUERY_POSTGRES_DB)" \
713+
-p 127.0.0.1:$(KUERY_POSTGRES_PORT):5432 \
714+
-v "$(abspath $(KUERY_POSTGRES_DATA_DIR)):/var/lib/postgresql/data" \
715+
"$(KUERY_POSTGRES_IMAGE)" >/dev/null; \
716+
fi; \
717+
echo "Waiting for kuery Postgres..."; \
718+
for _ in $$(seq 1 30); do \
719+
if docker exec "$(KUERY_POSTGRES_CONTAINER)" pg_isready -U "$(KUERY_POSTGRES_USER)" -d "$(KUERY_POSTGRES_DB)" >/dev/null 2>&1; then \
720+
echo " database: $(KUERY_DEV_DATABASE_URL)"; \
721+
exit 0; \
722+
fi; \
723+
sleep 1; \
724+
done; \
725+
echo "ERROR: kuery Postgres did not become ready"; \
726+
docker logs "$(KUERY_POSTGRES_CONTAINER)" --tail=50; \
727+
exit 1
728+
729+
kuery-db-down: ## Stop and remove the local kuery Postgres container (data remains in KUERY_POSTGRES_DATA_DIR)
730+
@if docker ps -a --format '{{.Names}}' | grep -qx "$(KUERY_POSTGRES_CONTAINER)"; then \
731+
echo "Removing kuery Postgres container ($(KUERY_POSTGRES_CONTAINER))"; \
732+
docker rm -f "$(KUERY_POSTGRES_CONTAINER)" >/dev/null; \
733+
else \
734+
echo "No kuery Postgres container to remove ($(KUERY_POSTGRES_CONTAINER))"; \
735+
fi
736+
737+
run-provider-kuery: build-kuery-provider kuery-db-up ## Run the kuery provider (requires: make run-hub-embedded-static + make install-provider-kuery; engagement needs init-provider-kuery)
680738
@echo "Starting kuery provider on :$(KUERY_PORT)"
681739
@echo " hub: $(KUERY_HUB_URL)"
682740
@echo " token: $(KUERY_TOKEN)"
@@ -685,13 +743,22 @@ run-provider-kuery: build-kuery-provider ## Run the kuery provider (requires: ma
685743
else \
686744
echo " engagement: DISABLED (run 'make init-provider-kuery' after install-provider-kuery)"; \
687745
fi
746+
@# Dev always runs Postgres. Fall back to the local dev container DSN when
747+
@# KUERY_STORE_DSN is unset (external Postgres overrides it).
748+
STORE_DSN="$${KUERY_STORE_DSN:-$(KUERY_STORE_DSN)}"; \
749+
if [ -z "$$STORE_DSN" ]; then \
750+
STORE_DSN="$(KUERY_DEV_DATABASE_URL)"; \
751+
fi; \
752+
echo " store: postgres ($$STORE_DSN)"; \
688753
PORT=$(KUERY_PORT) \
689754
KEDGE_HUB_URL=$(KUERY_HUB_URL) \
690755
KEDGE_HUB_TOKEN=$(KUERY_TOKEN) \
691756
KEDGE_HUB_INSECURE=true \
692757
KEDGE_PROVIDER_NAME=kuery \
693758
KEDGE_PROVIDER_KUBECONFIG=$(KUERY_RUNTIME_KUBECONFIG) \
694759
KEDGE_DEV_ALLOW_TENANT_QUERY=true \
760+
KUERY_STORE_DRIVER=postgres \
761+
KUERY_STORE_DSN="$$STORE_DSN" \
695762
$(BINDIR)/kuery-provider
696763

697764
install-provider-kuery: ## Apply kuery Provider + CatalogEntry into root:kedge:providers

Tiltfile

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,18 @@ local_resource(
319319
)
320320

321321
# --- providers-kuery (fleet query engine) ---
322+
# Local Postgres for the kuery store. Dev always runs the same SQL backend
323+
# as production — SQLite hid real Postgres-only query bugs, so it is not an
324+
# option here. make run-provider-kuery also depends on this; the resource
325+
# gives Tilt visibility + a restart button.
326+
local_resource(
327+
'kuery-db',
328+
cmd='make kuery-db-up',
329+
deps=['Makefile'],
330+
resource_deps=['hub'],
331+
labels=['providers-kuery'],
332+
)
333+
322334
# Long-lived provider embedding the kuery engine. Serves the portal +
323335
# /api/query + MCP on :8084 immediately; the edge engagement controller
324336
# additionally needs the dev runtime kubeconfig, minted by ▶ kuery-init
@@ -341,14 +353,22 @@ local_resource(
341353
'providers/kuery/go.sum',
342354
'.kcp/kuery-runtime.kubeconfig',
343355
],
344-
resource_deps=['hub'],
356+
resource_deps=['hub', 'kuery-db'],
345357
readiness_probe=probe(
346358
period_secs=5,
347359
http_get=http_get_action(port=8084, path='/healthz'),
348360
),
349361
labels=['providers-kuery'],
350362
)
351363

364+
local_resource(
365+
'kuery-db-down',
366+
cmd='make kuery-db-down',
367+
trigger_mode=TRIGGER_MODE_MANUAL,
368+
auto_init=False,
369+
labels=['providers-kuery'],
370+
)
371+
352372
local_resource(
353373
'kuery-register',
354374
cmd='make install-provider-kuery',

Tiltfile.cluster

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,17 @@ local_resource(
569569
)
570570

571571
# --- providers-kuery (fleet query engine, port :8084) ---
572+
# Local Postgres for the kuery store. Dev always runs the same SQL backend
573+
# as production — SQLite hid real Postgres-only query bugs, so it is not an
574+
# option here. make run-provider-kuery depends on this too.
575+
local_resource(
576+
'kuery-db',
577+
cmd='make kuery-db-up',
578+
deps=['Makefile'],
579+
resource_deps=['kedge-hub'],
580+
labels=['providers-kuery'],
581+
)
582+
572583
# Same shape as the embedded Tiltfile: serve immediately; engagement
573584
# needs ▶ kuery-register then ▶ kuery-init (mints the runtime kubeconfig
574585
# from the provider SA token + ensures the APIExportEndpointSlice).
@@ -588,14 +599,22 @@ local_resource(
588599
'providers/kuery/go.mod',
589600
'.kcp/kuery-runtime.kubeconfig',
590601
],
591-
resource_deps=['kedge-hub'],
602+
resource_deps=['kedge-hub', 'kuery-db'],
592603
readiness_probe=probe(
593604
period_secs=5,
594605
http_get=http_get_action(port=8084, path='/healthz'),
595606
),
596607
labels=['providers-kuery'],
597608
)
598609

610+
local_resource(
611+
'kuery-db-down',
612+
cmd='make kuery-db-down',
613+
trigger_mode=TRIGGER_MODE_MANUAL,
614+
auto_init=False,
615+
labels=['providers-kuery'],
616+
)
617+
599618
local_resource(
600619
'kuery-register',
601620
cmd=('{rewrite} && KUERY_KCP_KUBECONFIG={kc} ' +

cmd/kedge-release/main.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
//
3030
// kedge-release <component|all> [flags]
3131
//
32+
// kedge-release current # print every component's latest tag
3233
// kedge-release quickstart # bump providers/quickstart/v* patch and push
3334
// kedge-release hub --minor # bump v* minor
3435
// kedge-release quickstart --tag v0.0.1 # explicit version
@@ -99,6 +100,9 @@ func run(args []string) error {
99100
return nil
100101
}
101102
target := args[0]
103+
if target == "current" {
104+
return printCurrent()
105+
}
102106
opts := options{bump: "patch", ref: "HEAD"}
103107

104108
for i := 1; i < len(args); i++ {
@@ -223,6 +227,27 @@ func run(args []string) error {
223227
return nil
224228
}
225229

230+
// printCurrent prints the latest existing tag for every component, in
231+
// componentOrder, so you can see each release line's current version at a
232+
// glance without cutting anything.
233+
func printCurrent() error {
234+
fmt.Println("Current latest versions:")
235+
fmt.Println()
236+
for _, name := range componentOrder {
237+
comp := components[name]
238+
latest, hasLatest, err := latestTag(comp.prefix)
239+
if err != nil {
240+
return err
241+
}
242+
current := "(none)"
243+
if hasLatest {
244+
current = comp.prefix + strings.TrimPrefix(latest.String(), "v")
245+
}
246+
fmt.Printf(" %-15s %s\n", name, current)
247+
}
248+
return nil
249+
}
250+
226251
// latestTag returns the highest semver tag carrying prefix, with the prefix
227252
// stripped. hasLatest is false when no matching tag exists.
228253
func latestTag(prefix string) (version, bool, error) {
@@ -352,6 +377,7 @@ Components:
352377
infrastructure providers/infrastructure/v<X.Y.Z>
353378
code providers/code/v<X.Y.Z>
354379
all every component (independent versions)
380+
current print every component's latest existing tag (no changes)
355381
356382
Flags:
357383
--tag <vX.Y.Z> set the exact version (single component only)
@@ -362,6 +388,7 @@ Flags:
362388
-y, --yes skip the confirmation prompt
363389
364390
Examples:
391+
kedge-release current print every component's latest tag
365392
kedge-release quickstart bump providers/quickstart/v* patch and push
366393
kedge-release hub --minor bump v* minor
367394
kedge-release quickstart --tag v0.0.1

providers/kuery/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/faroshq/provider-kuery
33
go 1.26.3
44

55
require (
6-
github.com/faroshq/kuery v0.0.0-20260620185321-788efcebcc4f
6+
github.com/faroshq/kuery v0.0.0-20260621053041-5342a07fc777
77
github.com/faroshq/provider-sdk v0.0.1
88
github.com/kcp-dev/multicluster-provider v0.8.0
99
github.com/kcp-dev/sdk v0.32.0

providers/kuery/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv
5050
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
5151
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
5252
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
53-
github.com/faroshq/kuery v0.0.0-20260620185321-788efcebcc4f h1:gYDb4pLUtmmSE/VeLH2gQ6qJ5YIRDL1yGZ7H0h2iBSs=
54-
github.com/faroshq/kuery v0.0.0-20260620185321-788efcebcc4f/go.mod h1:TfZU4DmN/ir3/3XSkVoLhXXoIed8cu8jaQMBYWigJmY=
53+
github.com/faroshq/kuery v0.0.0-20260621053041-5342a07fc777 h1:K50qMui1ThmLOYKz9Dwau3UFxKU0DJwsmYcD8ShoWFs=
54+
github.com/faroshq/kuery v0.0.0-20260621053041-5342a07fc777/go.mod h1:TfZU4DmN/ir3/3XSkVoLhXXoIed8cu8jaQMBYWigJmY=
5555
github.com/faroshq/provider-sdk v0.0.1 h1:nJeNHfYfuUf+nyd6/iSC6xWAJuSjiSZYtnDW6yAMWys=
5656
github.com/faroshq/provider-sdk v0.0.1/go.mod h1:0nSxc6lF9tux2DHDc7mPx3z3x98xZUduNjStTgdqG/E=
5757
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=

0 commit comments

Comments
 (0)