From af8de6779c6b30deddd78a4bf9fda29044165623 Mon Sep 17 00:00:00 2001 From: Jiadong Bai <43344272+bobbai00@users.noreply.github.com> Date: Wed, 29 Jul 2026 00:02:13 -0400 Subject: [PATCH] fix(local-dev): refresh Lakekeeper warehouse S3 endpoint when it already exists (#6197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What changes were proposed in this PR? Makes `lakekeeper-init` (in `bin/single-node/docker-compose.yml`) keep the Iceberg warehouse's S3 endpoint in sync with the current `STORAGE_S3_ENDPOINT`. The warehouse persists its endpoint in Lakekeeper's own DB; `local-dev` sets `STORAGE_S3_ENDPOINT` to the host **LAN IP** (not `localhost`) so both the containerized Lakekeeper and the host JVMs — which reach MinIO directly via Iceberg remote-signing — use the same address. But that IP changes across networks / DHCP leases, and the init was idempotent: it **skipped** the warehouse when it already existed, so the stale endpoint was never refreshed. Workflow execution then failed with an opaque `org.apache.iceberg.exceptions.RESTException: Unable to process` at `createTable`. Instead of skipping, the existing-warehouse branch now `POST`s the current endpoint + credentials to `/management/v1/warehouse/{id}/storage` on every run. This is non-destructive and preserves existing Iceberg tables (their metadata stores `s3://bucket/...` paths, not the endpoint). ### Any related issues, documentation, discussions? Closes #6195 ### How was this PR tested? - Verified the same `POST /management/v1/warehouse/{id}/storage` call heals a live stack whose warehouse had a stale IP: it returned HTTP 200 and the vended endpoint updated to the current host IP, after which workflow execution succeeded. - `docker compose -f bin/single-node/docker-compose.yml config -q` validates the file. - Extracted the rendered `lakekeeper-init` command and confirmed `bash -n` passes (after applying compose's runtime `$$`→`$` unescaping), so the added heredoc/shell is syntactically sound. ### Was this PR authored or co-authored using generative AI tooling? (backported from commit aaed0857c8a73a4b13fd174417cd9a823f1bab25) Generated-by: Claude Opus 4.8 (1M context) --- bin/single-node/docker-compose.yml | 45 +++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/bin/single-node/docker-compose.yml b/bin/single-node/docker-compose.yml index a7efb813825..64247d9d66c 100644 --- a/bin/single-node/docker-compose.yml +++ b/bin/single-node/docker-compose.yml @@ -219,7 +219,50 @@ services: fi if jq -e --arg name "$$STORAGE_ICEBERG_CATALOG_REST_WAREHOUSE_NAME" '.warehouses[]? | select(.name == $$name)' /tmp/warehouses.txt >/dev/null; then - echo "Lakekeeper Warehouse '$$STORAGE_ICEBERG_CATALOG_REST_WAREHOUSE_NAME' already exists. Skipping creation." + # The warehouse persists its S3 endpoint in Lakekeeper's own DB. The + # local-dev launcher sets STORAGE_S3_ENDPOINT to the host LAN IP so + # both this container and the host JVMs (Iceberg remote-signing) reach + # the same MinIO — but that IP changes across networks / DHCP leases. + # This init is idempotent and would otherwise just skip, leaving a + # stale endpoint that breaks workflow execution with an opaque Iceberg + # RESTException. Refresh the stored endpoint on every run (#6195). + echo "Lakekeeper Warehouse '$$STORAGE_ICEBERG_CATALOG_REST_WAREHOUSE_NAME' already exists. Refreshing its storage endpoint to '$$STORAGE_S3_ENDPOINT'..." + WAREHOUSE_ID=$$(jq -r --arg name "$$STORAGE_ICEBERG_CATALOG_REST_WAREHOUSE_NAME" '.warehouses[]? | select(.name == $$name) | .id' /tmp/warehouses.txt) + UPDATE_PAYLOAD=$$(cat <