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
63 changes: 63 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,69 @@ jobs:
reporter: java-junit
path: "**/*-report.xml"

openshift-compat:
needs: [ compat-e2e-test, e2e-test ]
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, openshift, operator]
continue-on-error: true
timeout-minutes: 60
concurrency:
group: openshift-compatibility
cancel-in-progress: false
permissions:
contents: read
packages: write
env:
KUBECONFIG: /home/runner/okd-install/auth/kubeconfig
VERSION: 0.0.99-test
IMG: ghcr.io/clickhouse/clickhouse-operator:test
BUNDLE_IMG: ghcr.io/clickhouse/clickhouse-operator-bundle:test
CATALOG_IMG: ghcr.io/clickhouse/clickhouse-operator-catalog:test
SINGLE_BUNDLE_IMAGE: ghcr.io/clickhouse/clickhouse-operator-bundle:test
OPENSHIFT_CATALOG_IMAGE: ghcr.io/clickhouse/clickhouse-operator-catalog:test
OPENSHIFT_CHANNEL: stable-v0
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'

- name: Log in to ghcr.io
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push test operator + bundle + catalog
run: make docker-buildx bundle bundle-buildx catalog-buildx

- name: Clean up cluster state from previous runs
run: sudo /usr/local/bin/okd-cleanup.sh

- name: Install OLM tooling
run: make operator-sdk opm

- name: Run OLM compatibility e2e
run: make test-compat-e2e-olm-openshift

- name: Test Report
uses: dorny/test-reporter@v3
with:
name: E2E tests
badge-title: E2E tests
reporter: java-junit
path: "**/report/*"

- name: Wipe workspace
if: always()
run: rm -rf "$GITHUB_WORKSPACE/.git" "$GITHUB_WORKSPACE/_work" || true

ci-success-check:
name: All CI checks passed
runs-on: ubuntu-latest
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/openshift-runner-rebuild.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: OpenShift runner rebuild

on:
schedule:
- cron: '0 6 * * 0'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: openshift-compatibility
cancel-in-progress: false

jobs:
rebuild:
runs-on: [self-hosted, openshift, operator]
timeout-minutes: 120
env:
KUBECONFIG: /home/runner/okd-install/auth/kubeconfig
steps:
- name: Show pre-rebuild cluster state
run: |
oc get nodes || true
oc get co --no-headers || true
sudo virsh -c qemu:///system list --all || true

- name: Rebuild OKD cluster
run: sudo --preserve-env=GITHUB_ACTIONS /usr/local/bin/okd-rebuild.sh

- name: Show post-rebuild cluster state
run: |
oc get nodes
oc get clusterversion
oc get co
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,12 @@ vet: ## Run go vet against code.

.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e | grep -v /deploy) \
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e | grep -v /deploy | grep -v /openshift) \
--ginkgo.v

.PHONY: test-ci
test-ci: manifests generate fmt vet envtest ## Run tests in CI env.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e | grep -v /deploy) \
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e | grep -v /deploy | grep -v /openshift) \
-v -count=1 -race -coverprofile cover.out --ginkgo.v --ginkgo.junit-report=report/junit-report.xml

fuzz-keeper: generate # Run keeper spec fuzz tests
Expand All @@ -166,12 +166,16 @@ test-clickhouse-e2e: ## Run clickhouse e2e tests.

.PHONY: test-compat-e2e # Run compatibility smoke tests across ClickHouse versions.
test-compat-e2e: ## Run compatibility e2e tests (requires CLICKHOUSE_VERSION env var).
go test ./test/deploy/ -test.timeout 30m -v --ginkgo.v --ginkgo.label-filter=!olm --ginkgo.junit-report=report/junit-report.xml
go test ./test/deploy/ -test.timeout 30m -v --ginkgo.v --ginkgo.label-filter='!olm' --ginkgo.junit-report=report/junit-report.xml

.PHONY: test-compat-e2e-olm # Run OLM deployment smoke test.
test-compat-e2e-olm: ## Run OLM deployment e2e test on a dedicated cluster.
go test ./test/deploy/ -test.timeout 30m -v --ginkgo.v --ginkgo.label-filter=olm --ginkgo.junit-report=report/junit-report.xml

.PHONY: test-compat-e2e-olm-openshift # Run OLM deployment smoke test on OpenShift.
test-compat-e2e-olm-openshift: ## Run OLM deployment e2e against an OpenShift cluster.
go test ./test/openshift/ -test.timeout 30m -v --ginkgo.v --ginkgo.junit-report=report/junit-report.xml

.PHONY: test-compat-e2e-manifest # Run compatibility smoke tests (manifests deployment only).
test-compat-e2e-manifest: ## Run compatibility e2e tests using manifests deployment only (requires CLICKHOUSE_VERSION env var).
go test ./test/deploy/ -test.timeout 30m -v --ginkgo.v --ginkgo.label-filter=manifest --ginkgo.junit-report=report/junit-report.xml
Expand Down
3 changes: 3 additions & 0 deletions ci/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
self-hosted-runner:
labels:
- amd-medium
- openshift
- operator
- openshift-okd
29 changes: 21 additions & 8 deletions ci/generate-catalog-template.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail

# Generate OLM catalog template with all available bundles from registry
# Usage: ./ci/generate-catalog-template.sh [<bundle-image>]
# Default mode: list released + fast bundle tags from ghcr, emit stable-v0
# + fast-v0 template.
#
# SINGLE_BUNDLE_IMAGE=<image> mode: emit a one-bundle stable-v0 template
# pointing at the given image. Used by the per-PR OpenShift compatibility
# job which builds its own bundle for the PR head.

# Image repository
BUNDLE_IMAGE=${1-ghcr.io/clickhouse/clickhouse-operator-bundle}
# Output file
OUTPUT_FILE="catalog/clickhouse-operator-template.yaml"
mkdir -p catalog

if [ -n "${SINGLE_BUNDLE_IMAGE:-}" ]; then
cat > "$OUTPUT_FILE" <<EOF
Schema: olm.semver
GenerateMajorChannels: true
GenerateMinorChannels: false
Stable:
Bundles:
- Image: ${SINGLE_BUNDLE_IMAGE}
EOF
echo "Single-bundle catalog: ${SINGLE_BUNDLE_IMAGE}"
cat "$OUTPUT_FILE"
exit 0
fi

# Function to get all tags from ghcr.io
get_bundle_tags() {
Expand Down Expand Up @@ -39,10 +56,6 @@ get_bundle_tags() {
| sort -V
}

# Create catalog directory if it doesn't exist
mkdir -p catalog

# Generate the template YAML
cat > "$OUTPUT_FILE" <<EOF
Schema: olm.semver
GenerateMajorChannels: true
Expand Down
12 changes: 12 additions & 0 deletions internal/controller/clickhouse/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,13 @@ func buildVolumes(r *clickhouseReconciler, id v1.ClickHouseReplicaID) []corev1.V
})
}

if r.Cluster.Spec.DataVolumeClaimSpec == nil && !controller.UserMountsAt(r.Cluster.Spec.ContainerTemplate.VolumeMounts, internal.ClickHouseDataPath) {
volumes = append(volumes, corev1.Volume{
Name: internal.PersistentVolumeName,
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
})
}

return volumes
}

Expand All @@ -722,6 +729,11 @@ func buildMounts(r *clickhouseReconciler) []corev1.VolumeMount {
SubPath: "var-log-clickhouse",
},
)
} else if !controller.UserMountsAt(r.Cluster.Spec.ContainerTemplate.VolumeMounts, internal.ClickHouseDataPath) {
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: internal.PersistentVolumeName,
MountPath: internal.ClickHouseDataPath,
})
}

seenPaths := map[string]struct{}{}
Expand Down
10 changes: 5 additions & 5 deletions internal/controller/clickhouse/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ var _ = Describe("BuildVolumes", func() {
volumes := buildVolumes(&ctx, v1.ClickHouseReplicaID{})
mounts := buildMounts(&ctx)

Expect(volumes).To(HaveLen(4))
Expect(mounts).To(HaveLen(4))
Expect(volumes).To(HaveLen(5))
Expect(mounts).To(HaveLen(5))
checkVolumeMounts(volumes, mounts)
})

Expand Down Expand Up @@ -487,14 +487,14 @@ var _ = Describe("getConfigurationRevisions", func() {
})

func checkVolumeMounts(volumes []corev1.Volume, mounts []corev1.VolumeMount) {
volumeMap := map[string]struct{}{
internal.PersistentVolumeName: {},
}
volumeMap := map[string]struct{}{}
for _, volume := range volumes {
ExpectWithOffset(1, volumeMap).NotTo(HaveKey(volume.Name))
volumeMap[volume.Name] = struct{}{}
}

volumeMap[internal.PersistentVolumeName] = struct{}{}

mountPaths := map[string]struct{}{}
for _, mount := range mounts {
ExpectWithOffset(1, mountPaths).NotTo(HaveKey(mount.MountPath))
Expand Down
11 changes: 11 additions & 0 deletions internal/controller/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ type OpenSSLConfig struct {
Client OpenSSLParams `yaml:"client,omitempty"`
}

// UserMountsAt reports whether any of the given mounts targets path.
func UserMountsAt(mounts []corev1.VolumeMount, path string) bool {
for _, m := range mounts {
if m.MountPath == path {
return true
}
}

return false
}

// ProjectVolumes replaces volumes with the same mount path with a single projected volume.
func ProjectVolumes(volumes []corev1.Volume, volumeMounts []corev1.VolumeMount) ([]corev1.Volume, []corev1.VolumeMount, error) {
mountPaths := map[string][]corev1.VolumeMount{}
Expand Down
12 changes: 12 additions & 0 deletions internal/controller/keeper/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,13 @@ func buildVolumes(cr *v1.KeeperCluster, id v1.KeeperReplicaID) []corev1.Volume {
})
}

if cr.Spec.DataVolumeClaimSpec == nil && !controller.UserMountsAt(cr.Spec.ContainerTemplate.VolumeMounts, internal.KeeperDataPath) {
volumes = append(volumes, corev1.Volume{
Name: internal.PersistentVolumeName,
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
})
}

return volumes
}

Expand Down Expand Up @@ -649,6 +656,11 @@ func buildMounts(cr *v1.KeeperCluster) []corev1.VolumeMount {
MountPath: "/var/log/clickhouse-keeper",
SubPath: "var-log-clickhouse",
})
} else if !controller.UserMountsAt(cr.Spec.ContainerTemplate.VolumeMounts, internal.KeeperDataPath) {
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: internal.PersistentVolumeName,
MountPath: internal.KeeperDataPath,
})
}

if cr.Spec.Settings.TLS.Enabled {
Expand Down
Loading
Loading