Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion .github/workflows/build_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,100 @@ jobs:
docker.io/eclipsedaanse/probe:snapshot
ghcr.io/eclipse-daanse/probe:snapshot
# docker.io/eclipsedaanse/probe:${{ github.sha }}
# ghcr.io/eclipse-daanse/probe:${{ github.sha }}
# ghcr.io/eclipse-daanse/probe:${{ github.sha }}

pivot_container_deploy:
if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
needs: build_test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
db: [postgres, mssql, oracle, duckdb, mysql, mariadb, h2]

steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0

- name: Download pivot artifacts
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: jar-files
path: .

- name: Set up JDK
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 25
cache: maven

- name: Set up QEMU
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.2.1
with:
platforms: all

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

# Build the image for the host platform and load it into the local
# Docker daemon so the integration test can verify it before it is pushed.
- name: Build Docker Image for verification
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
file: "application/pivot/${{ matrix.db }}/container/Dockerfile"
platforms: linux/amd64
load: true
tags: daanse-pivot-${{ matrix.db }}:ci

# Runs the Testcontainers integration test against the image built above
# (-Dpivot.image) instead of building a throwaway image.
- name: Verify Docker Image with integration test
run: >
mvn -B -am -pl application/pivot/common,application/pivot/${{ matrix.db }}
package failsafe:integration-test failsafe:verify
-Dpivot.image=daanse-pivot-${{ matrix.db }}:ci

# The Docker Hub description is the database specific README plus the
# shared container documentation maintained once in the common module.
- name: Assemble Docker Hub description
run: >
cat application/pivot/${{ matrix.db }}/README.md
application/pivot/common/README.container.md
> readme-dockerhub.md

- name: Update dockerhub repo description
uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4.0.2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
repository: eclipsedaanse/daanse-pivot-${{ matrix.db }}
readme-filepath: ./readme-dockerhub.md

- name: Login to Docker Hub
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}

- name: Login to Github Docker Registry
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and Push Multi-Arch Docker Image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
context: .
file: "application/pivot/${{ matrix.db }}/container/Dockerfile"
platforms: linux/amd64,linux/arm64/v8
push: true
tags: |
docker.io/eclipsedaanse/daanse-pivot-${{ matrix.db }}:snapshot
ghcr.io/eclipse-daanse/daanse-pivot-${{ matrix.db }}:snapshot
6 changes: 0 additions & 6 deletions application/pivot/.gitignore

This file was deleted.

92 changes: 63 additions & 29 deletions application/pivot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,79 @@ group: Applications
---
# Eclipse Daanse Pivot Application

**Status: Under Construction**
Pivot is the production Daanse OLAP (XMLA) server. It is built once per supported
database, so every image ships exactly one JDBC DataSource implementation, its
driver and the matching SQL dialect — nothing more.

Pivot is the foundation for every production Daanse OLAP server. This container can be adapted to specific needs and requirements.
| Database | Module | Container image |
|------------|------------|------------------------------------------|
| PostgreSQL | `postgres` | `eclipsedaanse/daanse-pivot-postgres` |
| MS SQL Server | `mssql` | `eclipsedaanse/daanse-pivot-mssql` |
| Oracle | `oracle` | `eclipsedaanse/daanse-pivot-oracle` |
| DuckDB | `duckdb` | `eclipsedaanse/daanse-pivot-duckdb` |
| MySQL | `mysql` | `eclipsedaanse/daanse-pivot-mysql` |
| MariaDB | `mariadb` | `eclipsedaanse/daanse-pivot-mariadb` |
| H2 | `h2` | `eclipsedaanse/daanse-pivot-h2` |

## Key Configuration Areas
All images are published with the `:snapshot` tag to Docker Hub
(`docker.io/eclipsedaanse/...`) and the GitHub Container Registry
(`ghcr.io/eclipse-daanse/...`).

### Database Connectivity
- **Dialects and Data Sources**: Support for multiple different database connections
- **Multi-Database Support**: Can connect to various database types simultaneously
## How it works

### XMLA Endpoints
- **Multiple Endpoints**: Configure the number of XMLA endpoints
- **Path Configuration**: Customize endpoint paths
- **Port Mapping**: Assign specific ports to different endpoints
The `common` module contains the shared runtime description
(`daanse.pivot.base.bndrun`) and a setup service that reads the common
environment variables and wires the server: catalog mapping provider →
context group → XMLA service → XMLA servlet (+ optional CORS filter).

### Catalog Management
- **Web Endpoint Assignment**: Map catalogs to specific web endpoints
- **Flexible Routing**: Configure how catalogs are accessed through different entry points
Each database module contributes a small configurator component that reads the
`DAANSE_JDBC_*` environment variables, registers the single DataSource and
creates the OLAP context against it. Every property offered by the underlying
Daanse DataSource bundle is configurable; unset variables fall back to the
bundle defaults.

### Observability Features
- **Health Checks**: Built-in health monitoring capabilities
- **Readiness Checks**: Ensure services are ready to handle requests
- **Caching Configuration**: Configurable caching settings for optimal performance
## Configuration

### Security & Authentication
- **Authentication Providers**: Support for necessary authentication mechanisms
- **Full Control**: Complete control over security configurations
- **Customizable Access**: Adapt authentication to organizational needs
The server is configured exclusively through environment variables.

## Benefits
Common variables (all images): see the per-image README in each module
(`postgres/README.md`, ...) — they document the shared set
(`DAANSE_CATALOG_RESOURCE`, `DAANSE_XMLA_PATH`, `DAANSE_CORS_*`, ...) plus the
full database specific `DAANSE_JDBC_*` set.

### Security & Risk Reduction
This container provides full control and adaptability while ensuring that unnecessary components are not activated at runtime, significantly reducing security risks.
The OLAP catalog (mapping `.xmi` files) is provided via a volume mounted at
`/app/catalog`. A single file is referenced by `DAANSE_CATALOG_RESOURCE`;
additional cross-referenced resources can be included with
`DAANSE_CATALOG_ADDITIONAL_GLOBS`.

### Production Ready
Designed specifically for production environments with enterprise-grade features and reliability.
## Authentication

### Customization
Every aspect can be tailored to meet specific organizational requirements and use cases.
By default the XMLA endpoint is anonymous. Every image can authenticate via
HTTP Basic against an LDAP directory (`DAANSE_LDAP_*` variables, roles from
LDAP groups); `DAANSE_AUTH_ANONYMOUS=false` enforces a login. A self contained
example with an LLDAP side container lives in `common/example/ldap`.

## Examples

Self contained demos live in `common/example`: a Docker Compose demo
(`compose/`), the same demo as a Kubernetes pod for Podman/`kubectl`
(`kube/`), and a Compose demo with LDAP authentication (`ldap/`). Each embeds
a seeded database and a minimal catalog in one file.

## Container builds

Each database module carries its image description in `<db>/container/Dockerfile`
and a Testcontainers integration test that builds the image from that
Dockerfile and verifies it end-to-end (XMLA query against a real database).
CI builds every image in a matrix, runs the integration test against the built
image (`-Dpivot.image=...`) and pushes it multi-arch to Docker Hub and GHCR.
`build_images.sh` does the same locally:

```bash
./build_images.sh # build all images as daanse-pivot-<db>:local
TAG=dev ./build_images.sh postgres h2 # selected databases, custom tag
PUSH=true IMAGE_PREFIX=docker.io/eclipsedaanse ./build_images.sh
```

## Source Code
The pivot application source can be found at: `https://github.com/eclipse-daanse/org.eclipse.daanse.server/tree/main/application/pivot`
The pivot application source can be found at: `https://github.com/eclipse-daanse/org.eclipse.daanse.server/tree/main/application/pivot`
92 changes: 92 additions & 0 deletions application/pivot/build_images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env bash
#*******************************************************************************
# Copyright (c) 2026 Contributors to the Eclipse Foundation
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#*******************************************************************************
#
# Builds the pivot server jars and container images and verifies each image
# with its Testcontainers integration test. The tests run against exactly the
# image built here (-Dpivot.image), the same flow the CI pipeline uses.
#
# Usage: ./build_images.sh [db ...]
# db one or more of: postgres mssql oracle duckdb mysql mariadb h2
# (default: all)
#
# Environment:
# TAG image tag (default: local)
# PUSH set to "true" to push the verified images
# IMAGE_PREFIX registry/namespace for pushed images
# (default: docker.io/eclipsedaanse)
set -euo pipefail

ALL_DBS=(postgres mssql oracle duckdb mysql mariadb h2)
DBS=("$@")
if [ ${#DBS[@]} -eq 0 ]; then
DBS=("${ALL_DBS[@]}")
fi

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
TAG="${TAG:-local}"
PUSH="${PUSH:-false}"
IMAGE_PREFIX="${IMAGE_PREFIX:-docker.io/eclipsedaanse}"

# The build requires JDK 25 (bndruns target JavaSE-25).
JAVA_MAJOR="$(java -version 2>&1 | sed -nE 's/.*version "([0-9]+).*/\1/p' | head -1)"
if [ "${JAVA_MAJOR:-0}" -lt 25 ]; then
echo "ERROR: JDK 25+ required, found ${JAVA_MAJOR:-none}. Set JAVA_HOME accordingly." >&2
exit 1
fi

# Testcontainers may be configured to a different container daemon than the
# docker CLI default (docker.host in ~/.testcontainers.properties, e.g. a
# rootless Podman socket). Build against the same daemon so the verification
# tests find the image.
TC_PROPS="$HOME/.testcontainers.properties"
if [ -z "${DOCKER_HOST:-}" ] && [ -f "$TC_PROPS" ]; then
TC_HOST="$(sed -nE 's/^docker\.host=(.+)$/\1/p' "$TC_PROPS" | head -1)"
TC_HOST="${TC_HOST//\\/}"
if [ -n "$TC_HOST" ]; then
export DOCKER_HOST="$TC_HOST"
echo "==> Using container daemon from ${TC_PROPS}: ${DOCKER_HOST}"
fi
fi

MODULES="application/pivot/common"
for db in "${DBS[@]}"; do
MODULES="${MODULES},application/pivot/${db}"
done

cd "$REPO_ROOT"

echo "==> Building jars for: ${DBS[*]}"
mvn -B -am -pl "$MODULES" package

for db in "${DBS[@]}"; do
echo "==> Building image daanse-pivot-${db}:${TAG}"
# --load makes buildx builders load the result into the image store
docker build --load -f "application/pivot/${db}/container/Dockerfile" \
-t "daanse-pivot-${db}:${TAG}" "$REPO_ROOT"
done

for db in "${DBS[@]}"; do
echo "==> Verifying daanse-pivot-${db}:${TAG} with the integration test"
mvn -B -pl "application/pivot/${db}" \
failsafe:integration-test failsafe:verify \
"-Dpivot.image=daanse-pivot-${db}:${TAG}"
done

if [ "$PUSH" = "true" ]; then
for db in "${DBS[@]}"; do
image="${IMAGE_PREFIX}/daanse-pivot-${db}:${TAG}"
echo "==> Pushing ${image}"
docker tag "daanse-pivot-${db}:${TAG}" "$image"
docker push "$image"
done
fi

echo "==> Done: ${DBS[*]} (tag: ${TAG})"
Empty file removed application/pivot/catalog/.keep
Empty file.
Loading
Loading