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
89 changes: 84 additions & 5 deletions dev-support/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pipeline {
OUTPUT_DIR_RELATIVE_JDK11_HADOOP3 = 'output-jdk11-hadoop3'
OUTPUT_DIR_RELATIVE_JDK17_HADOOP3 = 'output-jdk17-hadoop3'
OUTPUT_DIR_RELATIVE_JDK21_HADOOP3 = 'output-jdk21-hadoop3'
OUTPUT_DIR_RELATIVE_READ_REPLICA = 'output-read-replica'

PROJECT = 'hbase'
PROJECT_PERSONALITY = 'https://raw.githubusercontent.com/apache/hbase/master/dev-support/hbase-personality.sh'
Expand Down Expand Up @@ -137,6 +138,7 @@ pipeline {
stash name: 'jdk11-hadoop3-result', allowEmpty: true, includes: "${OUTPUT_DIR_RELATIVE_JDK11_HADOOP3}/doesn't-match"
stash name: 'jdk17-hadoop3-result', allowEmpty: true, includes: "${OUTPUT_DIR_RELATIVE_JDK17_HADOOP3}/doesn't-match"
stash name: 'jdk21-hadoop3-result', allowEmpty: true, includes: "${OUTPUT_DIR_RELATIVE_JDK21_HADOOP3}/doesn't-match"
stash name: 'read-replica-result', allowEmpty: true, includes: "${OUTPUT_DIR_RELATIVE_READ_REPLICA}/doesn't-match"
}
}
stage ('health checks') {
Expand Down Expand Up @@ -321,7 +323,7 @@ pipeline {
else
echo "No archiver directory, skipping compressing."
fi
'''
'''
sshPublisher(publishers: [
sshPublisherDesc(configName: 'Nightlies',
transfers: [
Expand All @@ -340,7 +342,7 @@ pipeline {
else
echo "No test_logs.zip, skipping"
fi
'''
'''
// Has to be relative to WORKSPACE.
archiveArtifacts artifacts: "${env.OUTPUT_DIR_RELATIVE}/*"
archiveArtifacts artifacts: "${env.OUTPUT_DIR_RELATIVE}/**/*"
Expand Down Expand Up @@ -434,7 +436,7 @@ pipeline {
else
echo "No archiver directory, skipping compressing."
fi
'''
'''
sshPublisher(publishers: [
sshPublisherDesc(configName: 'Nightlies',
transfers: [
Expand All @@ -453,7 +455,7 @@ pipeline {
else
echo "No test_logs.zip, skipping"
fi
'''
'''
// Has to be relative to WORKSPACE.
archiveArtifacts artifacts: "${env.OUTPUT_DIR_RELATIVE}/*"
archiveArtifacts artifacts: "${env.OUTPUT_DIR_RELATIVE}/**/*"
Expand Down Expand Up @@ -582,7 +584,6 @@ pipeline {
}
}
}

stage ('yetus jdk17 hadoop3 checks') {
agent {
node {
Expand Down Expand Up @@ -803,6 +804,81 @@ pipeline {
}
}
}
stage ('hbase read-replica feature checks') {
agent {
node {
label 'hbase'
}
}
when {
anyOf {
branch 'master'
branch 'branch-3'
}
}
environment {
BASEDIR = "${env.WORKSPACE}/component"
OUTPUT_DIR_RELATIVE = "${env.OUTPUT_DIR_RELATIVE_READ_REPLICA}"
OUTPUT_DIR = "${env.WORKSPACE}/${env.OUTPUT_DIR_RELATIVE_READ_REPLICA}"
}
steps {
sh '''#!/usr/bin/env bash
set -e
rm -rf "${OUTPUT_DIR}" && mkdir -p "${OUTPUT_DIR}"
echo '(x) {color:red}-1 read-replica checks{color}' >"${OUTPUT_DIR}/commentfile"
echo "-- Something went wrong running this stage, please [check relevant console output|${BUILD_URL}/console]." >> "${OUTPUT_DIR}/commentfile"
'''
dir('component') {
checkout scm
}
sh '''#!/usr/bin/env bash
set -e
rm -rf "${OUTPUT_DIR}/machine" && mkdir -p "${OUTPUT_DIR}/machine"
"${BASEDIR}/dev-support/gather_machine_environment.sh" "${OUTPUT_DIR_RELATIVE}/machine"
echo "got the following saved stats in '${OUTPUT_DIR_RELATIVE}/machine'"
ls -lh "${OUTPUT_DIR_RELATIVE}/machine"
'''
script {
def ret = sh(
returnStatus: true,
script: '''#!/usr/bin/env bash
set -e
declare -i status=0
if "${BASEDIR}/dev-support/hbase_nightly_read_replica_test.sh" ; then
echo '(/) {color:green}+1 read-replica checks{color}' > "${OUTPUT_DIR}/commentfile"
else
echo '(x) {color:red}-1 read-replica checks{color}' > "${OUTPUT_DIR}/commentfile"
status=1
fi
echo "-- For more information [see read-replica test report|${BUILD_URL}Read_20Replica_20Nightly_20Test_20Report/]" >> "${OUTPUT_DIR}/commentfile"
exit "${status}"
'''
)
if (ret != 0) {
// mark the build as UNSTABLE instead of FAILURE, to avoid skipping the later publish of
// test output. See HBASE-26339 for more details.
currentBuild.result = 'UNSTABLE'
}
}
}
post {
always {
junit testResults: "${env.OUTPUT_DIR_RELATIVE}/read-replica-nightly-test-results.xml", allowEmptyResults: true

publishHTML target: [
allowMissing : true,
keepAll : true,
alwaysLinkToLastBuild: true,
reportDir : "${env.OUTPUT_DIR_RELATIVE}",
reportFiles : 'read-replica-nightly-test-report.html',
reportName : 'Read Replica Nightly Test Report'
]

stash name: 'read-replica-result', includes: "${OUTPUT_DIR_RELATIVE}/commentfile"
archiveArtifacts artifacts: "${env.OUTPUT_DIR_RELATIVE}/**/*", allowEmptyArchive: true
}
}
}
} // parallel
} //stage:_health checks
} //stages
Expand All @@ -820,20 +896,23 @@ pipeline {
rm -rf ${OUTPUT_DIR_RELATIVE_JDK11_HADOOP3}
rm -rf ${OUTPUT_DIR_RELATIVE_JDK17_HADOOP3}
rm -rf ${OUTPUT_DIR_RELATIVE_JDK21_HADOOP3}
rm -rf ${OUTPUT_DIR_RELATIVE_READ_REPLICA}
'''
unstash 'general-result'
unstash 'jdk8-hadoop2-result'
unstash 'jdk8-hadoop3-result'
unstash 'jdk11-hadoop3-result'
unstash 'jdk17-hadoop3-result'
unstash 'jdk21-hadoop3-result'
unstash 'read-replica-result'

def results = ["${env.OUTPUT_DIR_RELATIVE_GENERAL}/commentfile",
"${env.OUTPUT_DIR_RELATIVE_JDK8_HADOOP2}/commentfile",
"${env.OUTPUT_DIR_RELATIVE_JDK8_HADOOP3}/commentfile",
"${env.OUTPUT_DIR_RELATIVE_JDK11_HADOOP3}/commentfile",
"${env.OUTPUT_DIR_RELATIVE_JDK17_HADOOP3}/commentfile",
"${env.OUTPUT_DIR_RELATIVE_JDK21_HADOOP3}/commentfile"]
"${env.OUTPUT_DIR_RELATIVE_READ_REPLICA}/commentfile"]
echo env.BRANCH_NAME
echo env.BUILD_URL
echo currentBuild.result
Expand Down
6 changes: 6 additions & 0 deletions dev-support/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ configurations in this directory:

- `docker/` -- Dockerfile for CI build environment
- `hbase_docker/`, `hbase_docker.sh` -- Docker-based local test cluster
- `hbase_nightly_read_replica_test.sh` -- Builds a Docker image and runs two
HBase clusters (primary + read-replica) to execute end-to-end replication
integration tests via pytest. Optional `--keep-containers` and `--keep-image`
flags skip cleanup on exit.
- `read-replica/` -- Python test suite, Docker Compose configuration, and
cluster config used by `hbase_nightly_read_replica_test.sh`
- `adhoc_run_tests/` -- Scripts for running test suites outside CI
- `integration-test/` -- Integration test support

Expand Down
142 changes: 142 additions & 0 deletions dev-support/hbase_nightly_read_replica_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Run the read-replica Docker integration test suite.

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPLICA_DIR="${SCRIPT_DIR}/read-replica"
Comment thread
kgeisz marked this conversation as resolved.
OUTPUT_DIR="${OUTPUT_DIR:-${REPLICA_DIR}/output}"
export HBASE_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

export HBASE_IMAGE="hbase-read-replica:${BUILD_NUMBER:-local}"

KEEP_IMAGE=false
KEEP_CONTAINERS=false

while [[ $# -gt 0 ]]; do
case "$1" in
-i|--keep-image)
KEEP_IMAGE=true
shift
;;
-c|--keep-containers)
KEEP_CONTAINERS=true
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [-i|--keep-image] [-c|--keep-containers]"
exit 1
;;
esac
done

echo "Script dir: ${SCRIPT_DIR}"
echo "Replica dir: ${REPLICA_DIR}"
echo "Output dir: ${OUTPUT_DIR}"
echo "HBase root: ${HBASE_ROOT}"

echo "Changing to replica dir: REPLICA_DIR"
cd "${REPLICA_DIR}"

echo "Sourcing environment file: $(pwd)/.env"
set -a
source .env
set +a

echo "HBASE_IMAGE=${HBASE_IMAGE}"
echo "ACTIVE_CLUSTER_CONF_DIR=${ACTIVE_CLUSTER_CONF_DIR}"
echo "REPLICA_CLUSTER_CONF_DIR=${REPLICA_CLUSTER_CONF_DIR}"
echo "DOCKER_COMPOSE_FILE=${DOCKER_COMPOSE_FILE}"
echo "HBASE_DATA_STORE_ROOT=${HBASE_DATA_STORE_ROOT}"
echo "realpath of HBASE_DATA_STORE_ROOT=$(realpath ${HBASE_DATA_STORE_ROOT})"

echo "Removing HBase log directories from mounted volumes that may exist from a previous test run:"
echo "ACTIVE_CLUSTER_LOGS_DIR=${ACTIVE_CLUSTER_LOGS_DIR}"
echo "REPLICA_CLUSTER_LOGS_DIR=${REPLICA_CLUSTER_LOGS_DIR}"
rm -rf "${ACTIVE_CLUSTER_LOGS_DIR}" "${REPLICA_CLUSTER_LOGS_DIR}"
mkdir -p "${ACTIVE_CLUSTER_LOGS_DIR}" "${REPLICA_CLUSTER_LOGS_DIR}"
chmod 777 "${ACTIVE_CLUSTER_LOGS_DIR}" "${REPLICA_CLUSTER_LOGS_DIR}"

# Clone HBase source for Docker build context (Docker COPY doesn't follow symlinks)
echo "Cloning HBase source into ${REPLICA_DIR}/hbase for Docker build context..."
rm -rf "${REPLICA_DIR}/hbase"
git clone --local "${HBASE_ROOT}" "${REPLICA_DIR}/hbase"
rm -rf "${REPLICA_DIR}/hbase/.git"

cleanup() {
local exit_code=$?
if [ ${exit_code} -ne 0 ]; then
echo "=== FAILURE ==="
echo "An error occurred during this stage in the Jenkins run."
fi
if [ "${KEEP_CONTAINERS}" = "false" ]; then
echo "=== Cleanup: Stopping Docker containers ==="
docker compose -f "${DOCKER_COMPOSE_FILE}" down 2>/dev/null || true
else
echo "=== Cleanup: Keeping Docker containers (--keep-containers) ==="
fi
if [ "${KEEP_IMAGE}" = "false" ]; then
echo "=== Cleanup: Removing Docker image: ${HBASE_IMAGE} ==="
docker rmi --force "${HBASE_IMAGE}" 2>/dev/null || true
else
echo "=== Cleanup: Keeping Docker image: ${HBASE_IMAGE} (--keep-image) ==="
fi
echo "=== Cleanup: Deleting cloned HBase directory: ${REPLICA_DIR}/hbase ==="
rm -rf "${REPLICA_DIR}/hbase"
exit "${exit_code}"
}
trap cleanup EXIT

# Copy latest proto file from source
echo "Copying latest version of ActiveClusterSuffix.proto to $(pwd)/python/proto/"
cp "${HBASE_ROOT}/hbase-protocol-shaded/src/main/protobuf/server/ActiveClusterSuffix.proto" \
python/proto/

export PYTHONPATH="$(pwd)"
echo "Set PYTHONPATH=${PYTHONPATH}"

# Create Python environment
echo "Creating Python environment: .venv"
python3 -m venv .venv
source .venv/bin/activate

# Install Python dependencies
echo "Installing Python libraries"
pip install --upgrade pip
pip install -r requirements.txt

# Compile protobuf
echo "Compiling Protobuf"
python3 python/proto/proto_compiler.py

# Build Docker images
echo "Building hbase-docker image"
./build-images.sh

# Run read-replica integration test suite
echo "Starting read-replica integration test scripts"
echo "Starting read-replica integration test suite via Pytest..."
pytest --html="${OUTPUT_DIR}/read-replica-nightly-test-report.html" \
--self-contained-html \
--junitxml="${OUTPUT_DIR}/read-replica-nightly-test-results.xml" \
python/test/test_read_replica_feature.py

echo "=== Success: All read-replica integration tests passed. ==="
50 changes: 50 additions & 0 deletions dev-support/read-replica/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

# The name of the HBase Docker image
HBASE_IMAGE=${HBASE_IMAGE:-kgeisz/hbase-docker:read-replica-jenkins}
# The name of the HBase docker container
HBASE_CONTAINER_NAME=hbase-docker
# This is the host running the hbase-docker containers. Use localhost if the containers
# are running locally. If they are started by another container, such as a Jenkins
# container in a Docker-out-of-Docker setup, then try setting this to host.docker.internal.
HBASE_HOST=${HBASE_HOST:-localhost}
# The directory within the docker container that contains the config files
HBASE_CONF_DIR=/opt/hbase/conf
# The directory containing the 'data-store/<hbase.rootdir>' directory.
# This directory is mounted with the HBase Docker container.
HBASE_DATA_STORE_ROOT=./tmp-read-replica-data
# The port for the active cluster's HBase UI (used for cluster readiness)
ACTIVE_CLUSTER_PORT=16010
# The port for the replica cluster's HBase UI (used for cluster readiness)
REPLICA_CLUSTER_PORT=26010
# Local path to the active cluster's HBase config file.
# This file is part of a mounted volume, so modifying it
# locally also modifies it within the container (and vise-versa).
ACTIVE_CLUSTER_CONF_DIR=${HBASE_ROOT}/dev-support/read-replica/cluster1/conf
# Local path to docker volume where HBase sends active cluster logs
ACTIVE_CLUSTER_LOGS_DIR=${HBASE_ROOT}/dev-support/read-replica/cluster1/logs
# Same as above, except for the replica cluster
REPLICA_CLUSTER_CONF_DIR=${HBASE_ROOT}/dev-support/read-replica/cluster2/conf
# Local path to docker volume where HBase sends replica cluster logs
REPLICA_CLUSTER_LOGS_DIR=${HBASE_ROOT}/dev-support/read-replica/cluster2/logs
# The path to the docker-compose file
DOCKER_COMPOSE_FILE=${HBASE_ROOT}/dev-support/read-replica/docker-compose.yml
# The location of the utils directory within the docker container
CONTAINER_UTILS_DIR=/opt/utils
# The log level for the Python scripts
LOG_LEVEL=DEBUG
Loading
Loading