diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 8010acf332..19b38e8915 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -41,25 +41,24 @@ jobs: - name: Install missing dependencies to container run: | sudo apt update - sudo apt install -y stunnel make git gcc - - name: Maven offline - run: | - mvn -q dependency:go-offline - - name: Clean environment + - name: Set up Docker Compose environment run: | - make cleanup + mkdir -m 777 $REDIS_ENV_WORK_DIR + make docker-start env: - JVM_OPTS: -Xmx3200m - TERM: dumb - - name: Start servers + REDIS_ENV_WORK_DIR: ${{ github.workspace }}/work + - name: Maven offline run: | - make start + mvn -q dependency:go-offline - name: Run benchmarks run: | mvn -Pjmh clean test env: JVM_OPTS: -Xmx3200m TERM: dumb + - name: Tear down Docker Compose environment + run: | + docker compose $COMPOSE_ENV_FILES -f src/test/resources/docker-env/docker-compose.yml down # Download previous benchmark result from cache (if exists) - name: Download previous benchmark data uses: actions/cache@v4 diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index a065c23210..f4ebe1dc90 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -24,10 +24,11 @@ jobs: fail-fast: false matrix: redis_version: - - "unstable" - "8.0" - "7.4" - "7.2" + env: + REDIS_ENV_WORK_DIR: ${{ github.workspace }}/work steps: - name: Test Redis Server Version @@ -35,15 +36,15 @@ jobs: run: | # Map requested version to github or tag case "${{ matrix.redis_version }}" in - "unstable") redis_branch="unstable" stack_version="8.0-M04-pre" ;; - "8.0") redis_branch="8.0" stack_version="8.0-M04-pre" ;; - "7.4") redis_branch="7.4" stack_version="rs-7.4.0-v2" ;; - "7.2") redis_branch="7.2" stack_version="rs-7.2.0-v14" ;; + "8.0") redis_branch="8.0" stack_version="8.0-M04-pre" redis_test_version="8.0-M04-pre";; + "7.4") redis_branch="7.4" stack_version="rs-7.4.0-v2" redis_test_version="7.4.2";; + "7.2") redis_branch="7.2" stack_version="rs-7.2.0-v14" redis_test_version="7.2.7";; *) echo "Unsupported version: ${{ matrix.redis_version }}" && exit 1 ;; esac # Save them as outputs for later use echo "redis_branch=$redis_branch" >> $GITHUB_OUTPUT echo "redis_stack_version=$stack_version" >> $GITHUB_OUTPUT + echo "redis_test_version=$redis_test_version" >> $GITHUB_OUTPUT - name: Checkout project uses: actions/checkout@v4 - name: Set Java up in the runner @@ -59,24 +60,28 @@ jobs: - name: Install missing dependencies to container run: | sudo apt update - sudo apt install -y stunnel make git gcc + - name: Set up Docker Compose environment + run: | + mkdir -m 777 $REDIS_ENV_WORK_DIR + export REDIS_VERSION="${{ steps.map-tags.outputs.redis_test_version }}" + make docker-start version=$REDIS_VERSION - name: Maven offline run: | mvn -q dependency:go-offline - - name: Clean environment - run: | - make cleanup - env: - JVM_OPTS: -Xmx3200m - TERM: dumb + continue-on-error: true - name: Run tests run: | + export TEST_WORK_FOLDER=$REDIS_ENV_WORK_DIR + echo $TEST_WORK_FOLDER + ls -la $TEST_WORK_FOLDER make test-coverage env: - REDIS: ${{ steps.map-tags.outputs.redis_branch }} REDIS_STACK_VERSION: ${{ steps.map-tags.outputs.redis_stack_version }} JVM_OPTS: -Xmx3200m TERM: dumb + - name: Tear down Docker Compose environment + run: | + docker compose $COMPOSE_ENV_FILES -f src/test/resources/docker-env/docker-compose.yml down - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4 with: diff --git a/.gitignore b/.gitignore index 76cfba0e03..106e035520 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ work/ dependency-reduced-pom.xml .idea .flattened-pom.xml +*.java-version +*.DS_Store \ No newline at end of file diff --git a/Makefile b/Makefile index f288f218da..ec7f088406 100644 --- a/Makefile +++ b/Makefile @@ -1,459 +1,48 @@ SHELL := /bin/bash PATH := ./work/redis-git/src:${PATH} ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) -STUNNEL_BIN := $(shell which stunnel) -BREW_BIN := $(shell which brew) -YUM_BIN := $(shell which yum) -APT_BIN := $(shell which apt-get) PROFILE ?= ci -REDIS ?= unstable - -define REDIS_CLUSTER_CONFIG1 -c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 1434887920102 1434887920002 0 connected 12000-16383 -27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 myself,master - 0 0 1 connected 0-11999 -2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected -1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected -vars currentEpoch 3 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG2 -2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected -27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 1434887920102 1434887920002 1 connected 0-11999 -1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected -c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 myself,master - 0 0 0 connected 12000-16383 -vars currentEpoch 3 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG3 -1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 myself,slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 0 0 3 connected -2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected -c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 1434887920102 1434887920002 0 connected 12000-16383 -27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 1434887920102 1434887920002 1 connected 0-11999 -vars currentEpoch 3 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG4 -c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 0 1434887920102 0 connected 12000-16383 -1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 0 1434887920102 3 connected -2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 myself,slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 0 0 2 connected -27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 0 1434887920102 1 connected 0-11999 -vars currentEpoch 3 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG8 -c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7580 master - 1434887920102 1434887920002 0 connected 10001-16383 -27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7579 myself,master - 0 0 1 connected 0-10000 -2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7582 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected -1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7581 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected -vars currentEpoch 3 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG_SSL_1 -cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 myself,master - 0 1578163609000 0 connected 0-10000 -cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609301 1 connected -6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 master - 0 1578163609301 2 connected 10001-16383 -vars currentEpoch 2 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG_SSL_2 -cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 master - 0 1578163609245 0 connected 0-10000 -cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 myself,slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609000 1 connected -6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 master - 0 1578163609245 2 connected 10001-16383 -vars currentEpoch 2 lastVoteEpoch 0 -endef - -define REDIS_CLUSTER_CONFIG_SSL_3 -cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609279 1 connected -cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 master - 0 1578163609279 0 connected 0-10000 -6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 myself,master - 0 1578163609000 2 connected 10001-16383 -vars currentEpoch 2 lastVoteEpoch 0 -endef - - -####### -# Redis -####### -.PRECIOUS: work/redis-%.conf - -# Sentinel monitored slave -work/redis-6483.conf: - @mkdir -p $(@D) - - @echo port 6483 >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/redis-6483.pid >> $@ - @echo logfile $(shell pwd)/work/redis-6483.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo client-output-buffer-limit pubsub 256k 128k 5 >> $@ - @echo unixsocket $(ROOT_DIR)/work/socket-6483 >> $@ - @echo unixsocketperm 777 >> $@ - @echo enable-debug-command yes >> $@ -ifeq ($(REDIS),unstable) - @echo slaveof localhost 6482 >> $@ - @echo replica-announce-ip localhost >> $@ -else - @echo slaveof 127.0.0.1 6482 >> $@ -endif - - -work/redis-%.conf: - @mkdir -p $(@D) - - @echo port $* >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/redis-$*.pid >> $@ - @echo logfile $(shell pwd)/work/redis-$*.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo client-output-buffer-limit pubsub 256k 128k 5 >> $@ - @echo unixsocket $(ROOT_DIR)/work/socket-$* >> $@ - @echo unixsocketperm 777 >> $@ - @echo enable-debug-command yes >> $@ -ifeq ($(REDIS),unstable) - @echo replica-announce-ip localhost >> $@ -endif - -work/redis-%.pid: work/redis-%.conf work/redis-git/src/redis-server - work/redis-git/src/redis-server $< - -redis-start: work/redis-6479.pid work/redis-6480.pid work/redis-6481.pid work/redis-6482.pid work/redis-6483.pid work/redis-6484.pid - -########## -# Sentinel -########## -.PRECIOUS: work/sentinel-%.conf - -work/sentinel-%.conf: - @mkdir -p $(@D) - - @echo port $* >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/redis-sentinel-$*.pid >> $@ - @echo logfile $(shell pwd)/work/redis-sentinel-$*.log >> $@ - -ifeq ($(REDIS),unstable) - @echo sentinel monitor mymaster localhost 6482 1 >> $@ - @echo sentinel announce-hostnames yes >> $@ - @echo sentinel resolve-hostnames yes >> $@ - @echo sentinel announce-ip localhost >> $@ -else - @echo sentinel monitor mymaster 127.0.0.1 6482 1 >> $@ -endif - @echo sentinel down-after-milliseconds mymaster 200 >> $@ - @echo sentinel failover-timeout mymaster 200 >> $@ - @echo sentinel parallel-syncs mymaster 1 >> $@ - @echo unixsocket $(ROOT_DIR)/work/socket-$* >> $@ - @echo unixsocketperm 777 >> $@ - -work/sentinel-26381.conf: - @mkdir -p $(@D) - - @echo port 26381 >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/redis-sentinel-26381.pid >> $@ - @echo logfile $(shell pwd)/work/redis-sentinel-26381.log >> $@ - -ifeq ($(REDIS),unstable) - @echo sentinel monitor mymaster localhost 6484 1 >> $@ - @echo sentinel announce-hostnames yes >> $@ - @echo sentinel resolve-hostnames yes >> $@ -else - @echo sentinel monitor mymaster 127.0.0.1 6484 1 >> $@ -endif - @echo sentinel down-after-milliseconds mymaster 200 >> $@ - @echo sentinel failover-timeout mymaster 200 >> $@ - @echo sentinel parallel-syncs mymaster 1 >> $@ - @echo unixsocket $(ROOT_DIR)/work/socket-$* >> $@ - @echo unixsocketperm 777 >> $@ - @echo requirepass foobared >> $@ - -work/sentinel-%.pid: work/sentinel-%.conf work/redis-git/src/redis-server - work/redis-git/src/redis-server $< --sentinel - sleep 0.5 - -sentinel-start: work/sentinel-26379.pid work/sentinel-26380.pid work/sentinel-26381.pid - -########## -# Cluster -########## -.PRECIOUS: work/cluster-node-%.conf - -work/cluster-node-7385.conf: - @mkdir -p $(@D) - - @echo port 7385 >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/cluster-node-7385.pid >> $@ - @echo logfile $(shell pwd)/work/cluster-node-7385.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo unixsocket $(ROOT_DIR)/work/socket-7385 >> $@ - @echo cluster-enabled yes >> $@ - @echo cluster-node-timeout 150 >> $@ - @echo cluster-config-file $(shell pwd)/work/cluster-node-config-7385.conf >> $@ - @echo requirepass foobared >> $@ - - -work/cluster-node-7479.conf: - @mkdir -p $(@D) - - @echo port 7479 >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/cluster-node-7479.pid >> $@ - @echo logfile $(shell pwd)/work/cluster-node-7479.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo cluster-enabled yes >> $@ - @echo cluster-node-timeout 150 >> $@ - @echo cluster-config-file $(shell pwd)/work/cluster-node-config-7479.conf >> $@ - @echo cluster-announce-port 7442 >> $@ - @echo requirepass foobared >> $@ - - -work/cluster-node-7480.conf: - @mkdir -p $(@D) - - @echo port 7480 >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/cluster-node-7480.pid >> $@ - @echo logfile $(shell pwd)/work/cluster-node-7480.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo cluster-enabled yes >> $@ - @echo cluster-node-timeout 150 >> $@ - @echo cluster-config-file $(shell pwd)/work/cluster-node-config-7480.conf >> $@ - @echo cluster-announce-port 7444 >> $@ - @echo requirepass foobared >> $@ - - -work/cluster-node-7481.conf: - @mkdir -p $(@D) - - @echo port 7481 >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/cluster-node-7481.pid >> $@ - @echo logfile $(shell pwd)/work/cluster-node-7481.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo cluster-enabled yes >> $@ - @echo cluster-node-timeout 150 >> $@ - @echo cluster-config-file $(shell pwd)/work/cluster-node-config-7481.conf >> $@ - @echo cluster-announce-port 7445 >> $@ - @echo requirepass foobared >> $@ - - -work/cluster-node-%.conf: - @mkdir -p $(@D) - - @echo port $* >> $@ - @echo daemonize yes >> $@ - @echo pidfile $(shell pwd)/work/cluster-node-$*.pid >> $@ - @echo logfile $(shell pwd)/work/cluster-node-$*.log >> $@ - @echo save \"\" >> $@ - @echo appendonly no >> $@ - @echo client-output-buffer-limit pubsub 256k 128k 5 >> $@ - @echo unixsocket $(ROOT_DIR)/work/socket-$* >> $@ - @echo cluster-enabled yes >> $@ - @echo cluster-node-timeout 150 >> $@ - @echo cluster-config-file $(shell pwd)/work/cluster-node-config-$*.conf >> $@ - -work/cluster-node-%.pid: work/cluster-node-%.conf work/redis-git/src/redis-server - work/redis-git/src/redis-server $< || true - -cluster-start: work/cluster-node-7379.pid work/cluster-node-7380.pid work/cluster-node-7381.pid work/cluster-node-7382.pid work/cluster-node-7383.pid work/cluster-node-7384.pid work/cluster-node-7385.pid work/cluster-node-7479.pid work/cluster-node-7480.pid work/cluster-node-7481.pid work/cluster-node-7582.pid - -########## -# stunnel -########## - -work/stunnel.conf: - @mkdir -p $(@D) - - @echo cert=$(ROOT_DIR)/work/ca/certs/localhost.cert.pem >> $@ - @echo key=$(ROOT_DIR)/work/ca/private/localhost.decrypted.key.pem >> $@ - @echo capath=$(ROOT_DIR)/work/ca/certs/ca.cert.pem >> $@ - @echo cafile=$(ROOT_DIR)/work/ca/certs/ca.cert.pem >> $@ - @echo delay=yes >> $@ - @echo pid=$(ROOT_DIR)/work/stunnel.pid >> $@ - @echo foreground = no >> $@ - - @echo [stunnel] >> $@ - @echo accept = 127.0.0.1:6443 >> $@ - @echo connect = 127.0.0.1:6479 >> $@ - - @echo [redis-sni-vritual] >> $@ - @echo accept = 127.0.0.1:36443 >> $@ - @echo cert=$(ROOT_DIR)/work/ca/certs/foo-host.cert.pem >> $@ - @echo key=$(ROOT_DIR)/work/ca/private/foo-host.decrypted.key.pem >> $@ - @echo connect = unavailable.internal.mydomain.com:6666 >> $@ - - @echo [redis-sni1] >> $@ - @echo sni = redis-sni-vritual:redis-sni1.local >> $@ - @echo key=$(ROOT_DIR)/work/ca/private/localhost.decrypted.key.pem >> $@ - @echo cert=$(ROOT_DIR)/work/ca/certs/localhost.cert.pem >> $@ - @echo connect = localhost:6480 >> $@ - - @echo [redis-sni2] >> $@ - @echo sni = redis-sni-vritual:redis-sni2.local >> $@ - @echo connect = localhost:6479 >> $@ - @echo cert=$(ROOT_DIR)/work/ca/certs/foo-host.cert.pem >> $@ - @echo key=$(ROOT_DIR)/work/ca/private/foo-host.decrypted.key.pem >> $@ - - @echo [foo-host] >> $@ - @echo accept = 127.0.0.1:6444 >> $@ - @echo connect = 127.0.0.1:6479 >> $@ - @echo cert=$(ROOT_DIR)/work/ca/certs/foo-host.cert.pem >> $@ - @echo key=$(ROOT_DIR)/work/ca/private/foo-host.decrypted.key.pem >> $@ - - @echo [ssl-cluster-node-1] >> $@ - @echo accept = 127.0.0.1:7442 >> $@ - @echo connect = 127.0.0.1:7479 >> $@ - - @echo [ssl-cluster-node-2] >> $@ - @echo accept = 127.0.0.1:7444 >> $@ - @echo connect = 127.0.0.1:7480 >> $@ - - @echo [ssl-cluster-node-3] >> $@ - @echo accept = 127.0.0.1:7445 >> $@ - @echo connect = 127.0.0.1:7481 >> $@ - - @echo [ssl-sentinel-1] >> $@ - @echo accept = 127.0.0.1:26822 >> $@ - @echo connect = 127.0.0.1:26379 >> $@ - - @echo [ssl-sentinel-2] >> $@ - @echo accept = 127.0.0.1:26823 >> $@ - @echo connect = 127.0.0.1:26380 >> $@ - - @echo [ssl-sentinel-3] >> $@ - @echo accept = 127.0.0.1:26824 >> $@ - @echo connect = 127.0.0.1:26381 >> $@ - - @echo [ssl-sentinel-master] >> $@ - @echo accept = 127.0.0.1:6925 >> $@ - @echo connect = 127.0.0.1:6482 >> $@ - - @echo [ssl-sentinel-slave] >> $@ - @echo accept = 127.0.0.1:6926 >> $@ - @echo connect = 127.0.0.1:6482 >> $@ - - @echo [stunnel-client-cert] >> $@ - @echo accept = 127.0.0.1:6445 >> $@ - @echo connect = 127.0.0.1:6479 >> $@ - @echo verify=2 >> $@ - - @echo [stunnel-master-slave-node-1] >> $@ - @echo accept = 127.0.0.1:8443 >> $@ - @echo connect = 127.0.0.1:6482 >> $@ - - @echo [stunnel-master-slave-node-2] >> $@ - @echo accept = 127.0.0.1:8444 >> $@ - @echo connect = 127.0.0.1:6483 >> $@ - -work/stunnel.pid: work/stunnel.conf ssl-keys - which stunnel4 >/dev/null 2>&1 && stunnel4 $(ROOT_DIR)/work/stunnel.conf || stunnel $(ROOT_DIR)/work/stunnel.conf - -stunnel-start: work/stunnel.pid - -export REDIS_CLUSTER_CONFIG1 -export REDIS_CLUSTER_CONFIG2 -export REDIS_CLUSTER_CONFIG3 -export REDIS_CLUSTER_CONFIG4 -export REDIS_CLUSTER_CONFIG8 -export REDIS_CLUSTER_CONFIG_SSL_1 -export REDIS_CLUSTER_CONFIG_SSL_2 -export REDIS_CLUSTER_CONFIG_SSL_3 - -start: cleanup - @echo "$$REDIS_CLUSTER_CONFIG1" > work/cluster-node-config-7379.conf - @echo "$$REDIS_CLUSTER_CONFIG2" > work/cluster-node-config-7380.conf - @echo "$$REDIS_CLUSTER_CONFIG3" > work/cluster-node-config-7381.conf - @echo "$$REDIS_CLUSTER_CONFIG4" > work/cluster-node-config-7382.conf - @echo "$$REDIS_CLUSTER_CONFIG8" > work/cluster-node-config-7582.conf - @echo "$$REDIS_CLUSTER_CONFIG_SSL_1" > work/cluster-node-config-7479.conf - @echo "$$REDIS_CLUSTER_CONFIG_SSL_2" > work/cluster-node-config-7480.conf - @echo "$$REDIS_CLUSTER_CONFIG_SSL_3" > work/cluster-node-config-7481.conf - $(MAKE) redis-start - $(MAKE) sentinel-start - $(MAKE) cluster-start - $(MAKE) stunnel-start - - -cleanup: stop - @mkdir -p work - rm -f work/cluster-node*.conf 2>/dev/null - rm -f work/*.rdb work/*.aof work/*.conf work/*.log 2>/dev/null - rm -f *.aof - rm -f *.rdb - rm -f work/socket-* - -########## -# SSL Keys -# - remove Java keystore as becomes stale -########## -work/keystore.jks: - @mkdir -p $(@D) - - rm -f work/*.jks - - rm -Rf work/ca - src/test/bash/create_certificates.sh - -ssl-keys: work/keystore.jks - -stop: - pkill stunnel || true - pkill redis-server && sleep 1 || true - pkill redis-sentinel && sleep 1 || true - -test-coverage: start - mvn -DskipITs=false clean compile verify jacoco:report -P$(PROFILE) - $(MAKE) stop - -test: start +SUPPORTED_TEST_ENV_VERSIONS := 8.0-M04-pre 7.4.2 7.2.7 +DEFAULT_TEST_ENV_VERSION := 8.0-M04-pre +REDIS_ENV_WORK_DIR := $(or ${REDIS_ENV_WORK_DIR},$(ROOT_DIR)/work) + +docker-start: + @if [ -z "$(version)" ]; then \ + version=$(arg); \ + if [ -z "$$version" ]; then \ + version="$(DEFAULT_TEST_ENV_VERSION)"; \ + fi; \ + fi; \ + if ! echo "$(SUPPORTED_TEST_ENV_VERSIONS)" | grep -qw "$$version"; then \ + echo "Error: Invalid version '$$version'. Supported versions are: $(SUPPORTED_TEST_ENV_VERSIONS)."; \ + exit 1; \ + fi; \ + echo "Version: $(version)"; \ + default_env_file="src/test/resources/docker-env/.env"; \ + custom_env_file="src/test/resources/docker-env/.env.v$$version"; \ + env_files="--env-file $$default_env_file"; \ + if [ -f "$$custom_env_file" ]; then \ + env_files="$$env_files --env-file $$custom_env_file"; \ + fi; \ + echo "Environment work directory: $(REDIS_ENV_WORK_DIR)"; \ + rm -rf "$(REDIS_ENV_WORK_DIR)"; \ + mkdir -p "$(REDIS_ENV_WORK_DIR)"; \ + export REDIS_VERSION=$$version && \ + docker compose $$env_files -f src/test/resources/docker-env/docker-compose.yml up -d; \ + echo "Started test environment with Redis version $$version." + + +docker-test: mvn -DskipITs=false clean compile verify -P$(PROFILE) - $(MAKE) stop -prepare: stop - -ifndef STUNNEL_BIN -ifeq ($(shell uname -s),Linux) -ifdef APT_BIN - sudo apt-get install -y stunnel -else - -ifdef YUM_BIN - sudo yum install stunnel -else - @@echo "Cannot install stunnel using yum/apt-get" - @exit 1 -endif - -endif - -endif - -ifeq ($(shell uname -s),Darwin) - -ifndef BREW_BIN - @@echo "Cannot install stunnel because missing brew.sh" - @exit 1 -endif - - brew install stunnel - -endif - -endif +test-coverage: + mvn -DskipITs=false clean compile verify jacoco:report -P$(PROFILE) -work/redis-git/src/redis-cli work/redis-git/src/redis-server: - [ -d "work/redis-git" ] && cd work/redis-git && git reset --hard || \ - git clone https://github.com/antirez/redis.git work/redis-git - cd work/redis-git && git checkout -q $(REDIS) && git pull origin $(REDIS) - $(MAKE) -C work/redis-git clean - $(MAKE) -C work/redis-git -j4 +docker-stop: + docker compose --env-file src/test/resources/docker-env/.env -f src/test/resources/docker-env/docker-compose.yml down; \ + rm -rf "$(REDIS_ENV_WORK_DIR)" clean: - rm -Rf work/ rm -Rf target/ release: diff --git a/README.md b/README.md index 21860f8784..d06e87be9c 100644 --- a/README.md +++ b/README.md @@ -155,22 +155,20 @@ Building ----------- Lettuce is built with Apache Maven. The tests require multiple running Redis instances for different test cases which -are configured using a ```Makefile```. Tests run by default against Redis `unstable`. +are configured using a ```Makefile```. Tests run by default against Redis `latest`. To build: ``` $ git clone https://github.com/redis/lettuce.git $ cd lettuce/ -$ make prepare ssl-keys -$ make test +$ make docker-start ``` -* Initial environment setup (clone and build `redis`): ```make prepare``` -* Setup SSL Keys: ```make ssl-keys``` -* Run the build: ```make test``` -* Start Redis (manually): ```make start``` -* Stop Redis (manually): ```make stop``` +* Run the build: ```make docker-test``` +* Start Redis (manually): ```make docker-start``` +* Stop Redis (manually): ```make docker-stop``` +* Clean up: ```make clean``` Bugs and Feedback ----------- diff --git a/src/test/bash/create_certificates.sh b/src/test/bash/create_certificates.sh deleted file mode 100755 index 28db1eb517..0000000000 --- a/src/test/bash/create_certificates.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/bash - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -CA_DIR=work/ca -TRUSTSTORE_FILE=work/truststore.jks -KEYSTORE_FILE=work/keystore.jks - -if [[ -d work/ca ]] ; then - rm -Rf ${CA_DIR} -fi - -if [[ -f ${TRUSTSTORE_FILE} ]] ; then - rm -Rf ${TRUSTSTORE_FILE} -fi - -if [[ -f ${KEYSTORE_FILE} ]] ; then - rm -Rf ${KEYSTORE_FILE} -fi - -if [ ! -x "$(which openssl)" ] ; then - echo "[ERROR] No openssl in PATH" - exit 1 -fi - -KEYTOOL=keytool - -if [ ! -x "${KEYTOOL}" ] ; then - KEYTOOL=${JAVA_HOME}/bin/keytool -fi - -if [ ! -x "${KEYTOOL}" ] ; then - echo "[ERROR] No keytool in PATH/JAVA_HOME" - exit 1 -fi - -mkdir -p ${CA_DIR}/private ${CA_DIR}/certs ${CA_DIR}/crl ${CA_DIR}/csr ${CA_DIR}/newcerts ${CA_DIR}/intermediate - -echo "[INFO] Generating CA private key" -# Less bits = less secure = faster to generate -openssl genrsa -passout pass:changeit -aes256 -out ${CA_DIR}/private/ca.key.pem 2048 - -chmod 400 ${CA_DIR}/private/ca.key.pem - -echo "[INFO] Generating CA certificate" -openssl req -config ${DIR}/openssl.cnf \ - -key ${CA_DIR}/private/ca.key.pem \ - -new -x509 -days 7300 -sha256 -extensions v3_ca \ - -out ${CA_DIR}/certs/ca.cert.pem \ - -passin pass:changeit \ - -subj "/C=NN/ST=Unknown/L=Unknown/O=lettuce/CN=CA Certificate" - -echo "[INFO] Prepare CA database" -echo 1000 > ${CA_DIR}/serial -touch ${CA_DIR}/index.txt - -function generateKey { - - host=$1 - ip=$2 - - echo "[INFO] Generating server private key" - openssl genrsa -aes256 \ - -passout pass:changeit \ - -out ${CA_DIR}/private/${host}.key.pem 2048 - - openssl rsa -in ${CA_DIR}/private/${host}.key.pem \ - -out ${CA_DIR}/private/${host}.decrypted.key.pem \ - -passin pass:changeit - - chmod 400 ${CA_DIR}/private/${host}.key.pem - chmod 400 ${CA_DIR}/private/${host}.decrypted.key.pem - - echo "[INFO] Generating server certificate request" - openssl req -config <(cat ${DIR}/openssl.cnf \ - <(printf "\n[SAN]\nsubjectAltName=DNS:${host},IP:${ip}")) \ - -reqexts SAN \ - -key ${CA_DIR}/private/${host}.key.pem \ - -passin pass:changeit \ - -new -sha256 -out ${CA_DIR}/csr/${host}.csr.pem \ - -subj "/C=NN/ST=Unknown/L=Unknown/O=lettuce/CN=${host}" - - echo "[INFO] Signing certificate request" - openssl ca -config ${DIR}/openssl.cnf \ - -extensions server_cert -days 375 -notext -md sha256 \ - -passin pass:changeit \ - -batch \ - -in ${CA_DIR}/csr/${host}.csr.pem \ - -out ${CA_DIR}/certs/${host}.cert.pem -} - -generateKey "localhost" "127.0.0.1" -generateKey "foo-host" "1.2.3.4" - -echo "[INFO] Generating client auth private key" -openssl genrsa -aes256 \ - -passout pass:changeit \ - -out ${CA_DIR}/private/client.key.pem 2048 - -openssl rsa -in ${CA_DIR}/private/client.key.pem \ - -out ${CA_DIR}/private/client.decrypted.key.pem \ - -passin pass:changeit - -chmod 400 ${CA_DIR}/private/client.key.pem - -echo "[INFO] Generating client certificate request" -openssl req -config ${DIR}/openssl.cnf \ - -key ${CA_DIR}/private/client.key.pem \ - -passin pass:changeit \ - -new -sha256 -out ${CA_DIR}/csr/client.csr.pem \ - -subj "/C=NN/ST=Unknown/L=Unknown/O=lettuce/CN=client" - -echo "[INFO] Signing certificate request" -openssl ca -config ${DIR}/openssl.cnf \ - -extensions usr_cert -days 375 -notext -md sha256 \ - -passin pass:changeit \ - -batch \ - -in ${CA_DIR}/csr/client.csr.pem \ - -out ${CA_DIR}/certs/client.cert.pem - -echo "[INFO] Creating PKCS12 file with client certificate" -openssl pkcs12 -export -clcerts \ - -in ${CA_DIR}/certs/client.cert.pem \ - -inkey ${CA_DIR}/private/client.decrypted.key.pem \ - -passout pass:changeit \ - -out ${CA_DIR}/client.p12 - -${KEYTOOL} -importcert -keystore ${TRUSTSTORE_FILE} -file ${CA_DIR}/certs/ca.cert.pem -noprompt -storepass changeit -${KEYTOOL} -importkeystore \ - -srckeystore ${CA_DIR}/client.p12 -srcstoretype PKCS12 -srcstorepass changeit\ - -destkeystore ${KEYSTORE_FILE} -deststoretype PKCS12 \ - -noprompt -storepass changeit diff --git a/src/test/bash/openssl.cnf b/src/test/bash/openssl.cnf deleted file mode 100644 index 721bd488db..0000000000 --- a/src/test/bash/openssl.cnf +++ /dev/null @@ -1,107 +0,0 @@ -[ ca ] -# `man ca` -default_ca = CA_default - -[ CA_default ] -# Directory and file locations. -dir = work/ca -certs = $dir/certs -crl_dir = $dir/crl -new_certs_dir = $dir/newcerts -database = $dir/index.txt -serial = $dir/serial -RANDFILE = $dir/private/.rand - -# The root key and root certificate. -private_key = $dir/private/ca.key.pem -certificate = $dir/certs/ca.cert.pem - -# For certificate revocation lists. -crlnumber = $dir/crlnumber -crl = $dir/crl/ca.crl.pem -crl_extensions = crl_ext -default_crl_days = 30 - -# SHA-1 is deprecated, so use SHA-2 instead. -default_md = sha256 - -name_opt = ca_default -cert_opt = ca_default -default_days = 375 -preserve = no -policy = policy_strict -copy_extensions = copy - -[ policy_strict ] -# The root CA should only sign intermediate certificates that match. -# See the POLICY FORMAT section of `man ca`. -countryName = match -stateOrProvinceName = match -organizationName = match -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ req ] -# Options for the `req` tool (`man req`). -default_bits = 2048 -distinguished_name = req_distinguished_name -string_mask = utf8only - -# SHA-1 is deprecated, so use SHA-2 instead. -default_md = sha256 - -# Extension to add when the -x509 option is used. -x509_extensions = v3_ca - -[ req_distinguished_name ] -# See . -countryName = Country Name (2 letter code) -stateOrProvinceName = State or Province Name -localityName = Locality Name -0.organizationName = Organization Name -organizationalUnitName = Organizational Unit Name -commonName = Common Name -emailAddress = Email Address - -# Optionally, specify some defaults. -countryName_default = NN -stateOrProvinceName_default = Vault Test -localityName_default = -0.organizationName_default = spring-cloud-vault-config -#organizationalUnitName_default = -#emailAddress_default = info@spring-cloud-vault-config.dummy - -[ v3_ca ] -# Extensions for a typical CA (`man x509v3_config`). -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer -basicConstraints = critical, CA:true -keyUsage = critical, digitalSignature, cRLSign, keyCertSign - -[ v3_intermediate_ca ] -# Extensions for a typical intermediate CA (`man x509v3_config`). -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer -basicConstraints = critical, CA:true, pathlen:0 -keyUsage = critical, digitalSignature, cRLSign, keyCertSign - -[ usr_cert ] -# Extensions for client certificates (`man x509v3_config`). -basicConstraints = CA:FALSE -nsCertType = client, email -nsComment = "OpenSSL Generated Client Certificate" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer -keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = clientAuth, emailProtection - -[ server_cert ] -# Extensions for server certificates (`man x509v3_config`). -basicConstraints = CA:FALSE -nsCertType = server -nsComment = "OpenSSL Generated Server Certificate" -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid,issuer:always -keyUsage = critical, digitalSignature, keyEncipherment -extendedKeyUsage = serverAuth diff --git a/src/test/java/io/lettuce/core/SslIntegrationTests.java b/src/test/java/io/lettuce/core/SslIntegrationTests.java index bbad87472a..dbea9f90b1 100644 --- a/src/test/java/io/lettuce/core/SslIntegrationTests.java +++ b/src/test/java/io/lettuce/core/SslIntegrationTests.java @@ -42,6 +42,8 @@ import java.io.File; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Duration; import java.util.List; import java.util.function.Function; @@ -50,6 +52,7 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static io.lettuce.test.settings.TestSettings.sslPort; +import static io.lettuce.test.settings.TlsSettings.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -66,11 +69,13 @@ class SslIntegrationTests extends TestSupport { private static final String KEYSTORE = "work/keystore.jks"; - private static final String TRUSTSTORE = "work/truststore.jks"; + private static File truststoreFile0; - private static final File TRUSTSTORE_FILE = new File(TRUSTSTORE); + private static File truststoreFile1; - private static final File CA_CERT_FILE = new File("work/ca/certs/ca.cert.pem"); + private static File truststoreFile2; + + private static File truststoreFile3; private static final int MASTER_SLAVE_BASE_PORT_OFFSET = 2000; @@ -111,9 +116,25 @@ class SslIntegrationTests extends TestSupport { @BeforeAll static void beforeClass() { + Path path0 = createAndSaveTestTruststore("redis-standalone-0", Paths.get("redis-standalone-0/work/tls"), "changeit"); + truststoreFile0 = path0.toFile(); + + Path path = createAndSaveTestTruststore("redis-standalone-1", Paths.get("redis-standalone-1/work/tls"), "changeit"); + truststoreFile1 = path.toFile(); + + Path path2 = createAndSaveTestTruststore("redis-standalone-sentinel-controlled", + Paths.get("redis-standalone-sentinel-controlled/work/tls"), "changeit"); + truststoreFile2 = path2.toFile(); + + truststoreFile3 = createAndSaveTestTruststore("redis-standalone-5-client-cert", + Paths.get("redis-standalone-5-client-cert/work/tls"), "changeit").toFile(); assumeTrue(CanConnect.to(TestSettings.host(), sslPort()), "Assume that stunnel runs on port 6443"); - assertThat(TRUSTSTORE_FILE).exists(); + // Maybe we should do a list. + assertThat(truststoreFile0).exists(); + assertThat(truststoreFile1).exists(); + assertThat(truststoreFile2).exists(); + assertThat(truststoreFile3).exists(); } @Test @@ -130,7 +151,7 @@ void standaloneWithJdkSsl() { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile1, "changeit") // .build(); setOptions(sslOptions); @@ -142,7 +163,7 @@ void standaloneWithVerifyCaOnly() { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile0, "changeit") // .build(); setOptions(sslOptions); @@ -153,7 +174,7 @@ void standaloneWithVerifyCaOnly() { void standaloneWithPemCert() { SslOptions sslOptions = SslOptions.builder() // - .trustManager(CA_CERT_FILE) // + .trustManager(envCa(Paths.get("redis-standalone-1/work/tls")).toFile()) // .build(); setOptions(sslOptions); verifyConnection(URI_VERIFY); @@ -164,7 +185,7 @@ void standaloneWithPemCertAndImpossibleTimeout() { Assertions.setMaxStackTraceElementsDisplayed(30); SslOptions sslOptions = SslOptions.builder() // - .trustManager(CA_CERT_FILE) // + .trustManager(envCa(Paths.get("redis-standalone-1/work/tls")).toFile()) // .build(); setOptions(sslOptions); redisClient.setOptions(ClientOptions.builder().protocolVersion(ProtocolVersion.RESP3).sslOptions(sslOptions).build()); @@ -183,7 +204,7 @@ void standaloneWithJdkSslUsingTruststoreUrl() throws Exception { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(truststoreURL()) // + .truststore(truststoreURL(truststoreFile1), "changeit") // .build(); setOptions(sslOptions); @@ -192,11 +213,12 @@ void standaloneWithJdkSslUsingTruststoreUrl() throws Exception { @Test void standaloneWithClientCertificates() { - + // 6445 + File keystore = envClientP12(Paths.get("redis-standalone-5-client-cert/work/tls")).toFile(); SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .keystore(new File(KEYSTORE), "changeit".toCharArray()) // - .truststore(TRUSTSTORE_FILE) // + .keystore(keystore, "changeit".toCharArray()) // + .truststore(truststoreFile3, "changeit") // .build(); setOptions(sslOptions); @@ -208,7 +230,7 @@ void standaloneWithClientCertificatesWithoutKeystore() { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile1, "changeit") // .build(); setOptions(sslOptions); @@ -220,7 +242,7 @@ void standaloneWithJdkSslUsingTruststoreUrlWithWrongPassword() throws Exception SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(truststoreURL(), "knödel") // + .truststore(truststoreURL(truststoreFile0), "knödel") // .build(); setOptions(sslOptions); @@ -245,7 +267,7 @@ void standaloneWithOpenSsl() { SslOptions sslOptions = SslOptions.builder() // .openSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile0, "changeit") // .build(); setOptions(sslOptions); @@ -298,7 +320,7 @@ void masterSlaveWithJdkSsl() { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile2, "changeit") // .build(); setOptions(sslOptions); @@ -310,7 +332,7 @@ void masterSlaveWithJdkSslUsingTruststoreUrl() throws Exception { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(truststoreURL()) // + .truststore(truststoreURL(truststoreFile2), "changeit") // .build(); setOptions(sslOptions); @@ -322,7 +344,7 @@ void masterSlaveWithJdkSslUsingTruststoreUrlWithWrongPassword() throws Exception SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(truststoreURL(), "knödel") // + .truststore(truststoreURL(truststoreFile0), "knödel") // .build(); setOptions(sslOptions); @@ -363,7 +385,7 @@ void masterSlaveSslWithOneInvalidHostWillSucceed() { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile2, "changeit") // .build(); setOptions(sslOptions); @@ -375,7 +397,7 @@ void masterSlaveSslWithAllInvalidHostsWillFail() { SslOptions sslOptions = SslOptions.builder() // .jdkSslProvider() // - .truststore(TRUSTSTORE_FILE) // + .truststore(truststoreFile0, "changeit") // .build(); setOptions(sslOptions); @@ -415,8 +437,8 @@ private static List sslUris(IntStream masterSlaveOffsets, .map(builderCustomizer).map(RedisURI.Builder::build).collect(Collectors.toList()); } - private URL truststoreURL() throws MalformedURLException { - return TRUSTSTORE_FILE.toURI().toURL(); + private URL truststoreURL(File truststoreFile) throws MalformedURLException { + return truststoreFile.toURI().toURL(); } private void setOptions(SslOptions sslOptions) { diff --git a/src/test/java/io/lettuce/core/commands/KeyCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/KeyCommandIntegrationTests.java index c24e231f17..2e1ba647c3 100644 --- a/src/test/java/io/lettuce/core/commands/KeyCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/KeyCommandIntegrationTests.java @@ -33,10 +33,8 @@ import javax.inject.Inject; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; +import org.junit.Ignore; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import io.lettuce.core.CopyArgs; @@ -410,6 +408,7 @@ void restoreReplace() { } @Test + @Disabled("https://github.com/redis/lettuce/issues/3181") void restoreIdleTime() { redis.set(key, value); diff --git a/src/test/java/io/lettuce/core/commands/RunOnlyOnceServerCommandIntegrationTests.java b/src/test/java/io/lettuce/core/commands/RunOnlyOnceServerCommandIntegrationTests.java index 2e94eb035c..ca8233e023 100644 --- a/src/test/java/io/lettuce/core/commands/RunOnlyOnceServerCommandIntegrationTests.java +++ b/src/test/java/io/lettuce/core/commands/RunOnlyOnceServerCommandIntegrationTests.java @@ -9,9 +9,7 @@ import javax.inject.Inject; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import io.lettuce.core.MigrateArgs; @@ -32,6 +30,7 @@ */ @Tag(INTEGRATION_TEST) @ExtendWith(LettuceExtension.class) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) class RunOnlyOnceServerCommandIntegrationTests extends TestSupport { private final RedisClient client; @@ -54,6 +53,7 @@ class RunOnlyOnceServerCommandIntegrationTests extends TestSupport { */ @Test @Disabled + @Order(1) void debugSegfault() { assumeTrue(CanConnect.to(host(), port(1))); @@ -74,13 +74,14 @@ void debugSegfault() { * Executed in order: 2 */ @Test + @Order(2) void migrate() { - assumeTrue(CanConnect.to(host(), port(2))); + assumeTrue(CanConnect.to(host(), port(7))); redis.set(key, value); - String result = redis.migrate("localhost", TestSettings.port(2), key, 0, 10); + String result = redis.migrate("localhost", TestSettings.port(7), key, 0, 10); assertThat(result).isEqualTo("OK"); } @@ -88,18 +89,19 @@ void migrate() { * Executed in order: 3 */ @Test + @Order(3) void migrateCopyReplace() { - assumeTrue(CanConnect.to(host(), port(2))); + assumeTrue(CanConnect.to(host(), port(7))); redis.set(key, value); - redis.set("key1", value); redis.set("key2", value); + redis.set("key3", value); - String result = redis.migrate("localhost", TestSettings.port(2), 0, 10, MigrateArgs.Builder.keys(key).copy().replace()); + String result = redis.migrate("localhost", TestSettings.port(7), 0, 10, MigrateArgs.Builder.keys(key).copy().replace()); assertThat(result).isEqualTo("OK"); - result = redis.migrate("localhost", TestSettings.port(2), 0, 10, + result = redis.migrate("localhost", TestSettings.port(7), 0, 10, MigrateArgs.Builder.keys(Arrays.asList("key1", "key2")).replace()); assertThat(result).isEqualTo("OK"); } @@ -109,9 +111,10 @@ void migrateCopyReplace() { * redis. */ @Test + @Order(4) void shutdown() { - assumeTrue(CanConnect.to(host(), port(2))); + assumeTrue(CanConnect.to(host(), port(7))); final RedisAsyncCommands commands = client.connect(RedisURI.Builder.redis(host(), port(2)).build()) .async(); diff --git a/src/test/java/io/lettuce/core/masterreplica/MasterReplicaSentinelSslIntegrationTests.java b/src/test/java/io/lettuce/core/masterreplica/MasterReplicaSentinelSslIntegrationTests.java index 1697835398..e6e0e00b31 100644 --- a/src/test/java/io/lettuce/core/masterreplica/MasterReplicaSentinelSslIntegrationTests.java +++ b/src/test/java/io/lettuce/core/masterreplica/MasterReplicaSentinelSslIntegrationTests.java @@ -2,14 +2,11 @@ import javax.inject.Inject; +import io.lettuce.core.*; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import io.lettuce.core.ReadFrom; -import io.lettuce.core.RedisClient; -import io.lettuce.core.RedisURI; -import io.lettuce.core.TestSupport; import io.lettuce.core.codec.StringCodec; import io.lettuce.core.internal.HostAndPort; import io.lettuce.core.resource.ClientResources; @@ -19,7 +16,15 @@ import io.lettuce.test.resource.FastShutdown; import io.lettuce.test.settings.TestSettings; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + import static io.lettuce.TestTags.INTEGRATION_TEST; +import static io.lettuce.test.settings.TlsSettings.createAndSaveTestTruststore; /** * Integration test for Master/Replica using Redis Sentinel over SSL. @@ -32,19 +37,33 @@ class MasterReplicaSentinelSslIntegrationTests extends TestSupport { private final ClientResources clientResources; + private static File truststoreFile; + + private static Map portMap = new HashMap<>(); + static { + portMap.put(26379, 26822); + portMap.put(6482, 8443); + portMap.put(6483, 8444); + } + @Inject MasterReplicaSentinelSslIntegrationTests(ClientResources clientResources) { + this.clientResources = clientResources.mutate() .socketAddressResolver(MappingSocketAddressResolver.create(DnsResolver.jvmDefault(), hostAndPort -> { + int port = hostAndPort.getPort(); + if (portMap.containsKey(port)) { + return HostAndPort.of(hostAndPort.getHostText(), portMap.get(port)); + } - return HostAndPort.of(hostAndPort.getHostText(), hostAndPort.getPort() + 443); + return hostAndPort; })).build(); } @Test void testMasterReplicaSentinelBasic() { - RedisClient client = RedisClient.create(clientResources); + RedisURI redisURI = RedisURI.create("rediss-sentinel://" + TestSettings.host() + ":26379?sentinelMasterId=mymaster"); redisURI.setVerifyPeer(false); StatefulRedisMasterReplicaConnection connection = MasterReplica.connect(client, StringCodec.UTF8, diff --git a/src/test/java/io/lettuce/core/sentinel/SentinelSslIntegrationTests.java b/src/test/java/io/lettuce/core/sentinel/SentinelSslIntegrationTests.java index b8fdc03138..9fd831328b 100644 --- a/src/test/java/io/lettuce/core/sentinel/SentinelSslIntegrationTests.java +++ b/src/test/java/io/lettuce/core/sentinel/SentinelSslIntegrationTests.java @@ -2,10 +2,15 @@ import static io.lettuce.TestTags.INTEGRATION_TEST; import static io.lettuce.test.settings.TestSettings.sslPort; +import static io.lettuce.test.settings.TlsSettings.createAndSaveTestTruststore; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; @@ -36,23 +41,38 @@ @ExtendWith(LettuceExtension.class) class SentinelSslIntegrationTests extends TestSupport { - private static final File TRUSTSTORE_FILE = new File("work/truststore.jks"); + private static File truststoreFile; private final ClientResources clientResources; + private static Map portMap = new HashMap<>(); + static { + portMap.put(26379, 26822); + portMap.put(6482, 8443); + portMap.put(6483, 8444); + } + @Inject SentinelSslIntegrationTests(ClientResources clientResources) { + this.clientResources = clientResources.mutate() .socketAddressResolver(MappingSocketAddressResolver.create(DnsResolver.jvmDefault(), hostAndPort -> { + int port = hostAndPort.getPort(); + if (portMap.containsKey(port)) { + return HostAndPort.of(hostAndPort.getHostText(), portMap.get(port)); + } - return HostAndPort.of(hostAndPort.getHostText(), hostAndPort.getPort() + 443); + return hostAndPort; })).build(); } @BeforeAll static void beforeAll() { assumeTrue(CanConnect.to(TestSettings.host(), sslPort()), "Assume that stunnel runs on port 6443"); - assertThat(TRUSTSTORE_FILE).exists(); + Path path2 = createAndSaveTestTruststore("redis-standalone-sentinel-controlled", + Paths.get("redis-standalone-sentinel-controlled/work/tls"), "changeit"); + truststoreFile = path2.toFile(); + assertThat(truststoreFile).exists(); } @Test @@ -75,7 +95,7 @@ void shouldConnectToMasterUsingSentinel() { RedisURI redisURI = RedisURI.create("rediss-sentinel://" + TestSettings.host() + ":" + RedisURI.DEFAULT_SENTINEL_PORT + "?sentinelMasterId=mymaster"); - SslOptions options = SslOptions.builder().truststore(TRUSTSTORE_FILE).build(); + SslOptions options = SslOptions.builder().truststore(truststoreFile, "changeit").build(); RedisClient client = RedisClient.create(clientResources); client.setOptions(ClientOptions.builder().sslOptions(options).build()); diff --git a/src/test/java/io/lettuce/test/settings/TestSettings.java b/src/test/java/io/lettuce/test/settings/TestSettings.java index cf5411b1ef..3c56dfb5c6 100644 --- a/src/test/java/io/lettuce/test/settings/TestSettings.java +++ b/src/test/java/io/lettuce/test/settings/TestSettings.java @@ -49,7 +49,7 @@ public static String host() { * {@code -Ddomainsocket=YourSocket} */ public static String socket() { - return System.getProperty("domainsocket", "work/socket-6479"); + return System.getProperty("domainsocket", "work/socket-6482"); } /** diff --git a/src/test/java/io/lettuce/test/settings/TlsSettings.java b/src/test/java/io/lettuce/test/settings/TlsSettings.java new file mode 100644 index 0000000000..0187e84f12 --- /dev/null +++ b/src/test/java/io/lettuce/test/settings/TlsSettings.java @@ -0,0 +1,133 @@ +package io.lettuce.test.settings; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class TlsSettings { + + private static final String TRUST_STORE_TYPE = "PKCS12"; + + private static final String TEST_WORK_FOLDER = System.getenv().getOrDefault("TEST_WORK_FOLDER", "work/docker"); + + private static final String TEST_SERVER_CERT = "redis.crt"; + + private static final String TEST_CLIENT_P12 = "client.p12"; + + private static final String TEST_CLIENT_CERT = "client.crt"; + + private static final String TEST_CLIENT_KEY = "client.key"; + + private static final String TEST_CA_CERT = "ca.crt"; + + private static final String TEST_TRUSTSTORE = "truststore.jks"; + + public static Path envClientP12(Path certLocation) { + return Paths.get(TEST_WORK_FOLDER, certLocation.toString(), TEST_CLIENT_P12); + } + + public static Path envServerCert(Path certLocation) { + return Paths.get(TEST_WORK_FOLDER, certLocation.toString(), TEST_SERVER_CERT); + } + + public static Path envCa(Path certLocation) { + return Paths.get(TEST_WORK_FOLDER, certLocation.toString(), TEST_CA_CERT); + } + + public static Path testTruststorePath(String name) { + return Paths.get(TEST_WORK_FOLDER, name + '-' + TEST_TRUSTSTORE); + } + + /** + * Creates an empty truststore. + * + * @return An empty KeyStore object. + * @throws KeyStoreException If there's an error initializing the truststore. + * @throws IOException If there's an error loading the truststore. + * @throws NoSuchAlgorithmException If the algorithm used to check the integrity of the truststore cannot be found. + * @throws CertificateException If any of the certificates in the truststore could not be loaded. + */ + private static KeyStore createTruststore() + throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + KeyStore trustStore = KeyStore.getInstance(TRUST_STORE_TYPE); + trustStore.load(null, null); + return trustStore; + } + + /** + * Loads an X.509 certificate from the given file path. + * + * @param certPath Path to the certificate file. + * @return An X509Certificate object. + * @throws Exception If there's an error loading the certificate. + */ + private static X509Certificate loadCertificate(Path certPath) throws Exception { + try (FileInputStream fis = new FileInputStream(certPath.toFile())) { + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + return (X509Certificate) certFactory.generateCertificate(fis); + } + } + + /** + * Adds a trusted certificate to the given truststore. + * + * @param trustStore The KeyStore object. + * @param alias Alias for the certificate. + * @param certPath Path to the certificate file. + * @throws Exception If there's an error adding the certificate. + */ + private static void addTrustedCertificate(KeyStore trustStore, String alias, Path certPath) throws Exception { + X509Certificate cert = loadCertificate(certPath); + trustStore.setCertificateEntry(alias, cert); + } + + /** + * Creates a truststore, adds multiple trusted certificates, and saves it to the specified path. + * + * @param trustedCertPaths List of certificate file paths to add to the truststore. + * @param truststorePath Path to save the generated truststore. + * @param truststorePassword Password for the truststore. + * @return Path to the saved truststore file. + */ + public static Path createAndSaveTruststore(List trustedCertPaths, Path truststorePath, String truststorePassword) { + try { + KeyStore trustStore = createTruststore(); + + for (Path certPath : trustedCertPaths) { + addTrustedCertificate(trustStore, "trusted-cert-" + UUID.randomUUID(), certPath); + } + + try (FileOutputStream fos = new FileOutputStream(truststorePath.toFile())) { + trustStore.store(fos, truststorePassword.toCharArray()); + } catch (IOException e) { + throw new RuntimeException("Failed to save truststore to " + truststorePath + ": " + e.getMessage(), e); + } + } catch (Exception e) { + throw new RuntimeException("Failed to create and save truststore: " + e.getMessage(), e); + } + + return truststorePath; + } + + public static Path createAndSaveTestTruststore(String trustStoreName, Path certificateLocations, + String truststorePassword) { + List trustedCertPaths = new ArrayList<>(); + trustedCertPaths.add(envCa(certificateLocations).toAbsolutePath()); + trustedCertPaths.add(envServerCert(certificateLocations).toAbsolutePath()); + + Path trustStorePath = testTruststorePath(trustStoreName).toAbsolutePath(); + + return createAndSaveTruststore(trustedCertPaths, trustStorePath, truststorePassword); + } + +} diff --git a/src/test/resources/docker-env/.env b/src/test/resources/docker-env/.env new file mode 100644 index 0000000000..b294422b69 --- /dev/null +++ b/src/test/resources/docker-env/.env @@ -0,0 +1,2 @@ +REDIS_ENV_WORK_DIR=../../../../work/docker +REDIS_VERSION=8.0-M04-pre diff --git a/src/test/resources/docker-env/docker-compose.yml b/src/test/resources/docker-env/docker-compose.yml new file mode 100644 index 0000000000..130fb1f717 --- /dev/null +++ b/src/test/resources/docker-env/docker-compose.yml @@ -0,0 +1,141 @@ +x-client-libs-image: &client-libs-image + image: "redislabs/client-libs-test:${REDIS_VERSION:-8.0-M04-pre}" + +services: + # Standalone Redis Servers + redis-standalone-0: + <<: *client-libs-image + container_name: redis-standalone-0 + environment: + - TLS_ENABLED=yes + volumes: + - ./redis-standalone-0/config:/redis/config:r + - ${REDIS_ENV_WORK_DIR}/redis-standalone-0/work:/redis/work:rw + ports: + - "6478:6478" + - "6444:6444" # TLS Port + networks: + - redis-network + + redis-standalone-1: + <<: *client-libs-image + container_name: redis-standalone-1 + environment: + - TLS_ENABLED=yes + volumes: + - ./redis-standalone-1/config:/redis/config:r + - ${REDIS_ENV_WORK_DIR}/redis-standalone-1/work:/redis/work:rw + ports: + - "6479:6479" + - "6486:6486" + - "6443:6443" # TLS Port + networks: + - redis-network + + redis-standalone-2: + <<: *client-libs-image + container_name: redis-standalone-2 + volumes: + - ./redis-standalone-2/config:/redis/config:r + ports: + - "6480:6480" + networks: + - redis-network + + redis-standalone-3: + <<: *client-libs-image + container_name: redis-standalone-3 + volumes: + - ./redis-standalone-3/config:/redis/config:r + ports: + - "6481:6481" + networks: + - redis-network + + redis-standalone-4: + <<: *client-libs-image + container_name: redis-standalone-4 + volumes: + - ./redis-standalone-4/config:/redis/config:r + + environment: + - REDIS_CLUSTER=no + ports: + - "6484:6484" + - "26381:26381" + networks: + - redis-network + + redis-standalone-5-client-cert: + <<: *client-libs-image + container_name: redis-standalone-5-client-cert + environment: + - TLS_ENABLED=yes + volumes: + - ./redis-standalone-5-client-cert/config:/redis/config:r + - ${REDIS_ENV_WORK_DIR}/redis-standalone-5-client-cert/work:/redis/work:rw + ports: + - "6485:6485" + - "6445:6445" # TLS Port + networks: + - redis-network + + redis-standalone-sentinel-controlled: + <<: *client-libs-image + container_name: redis-standalone-sentinel-controlled + environment: + - REDIS_CLUSTER=no + - TLS_ENABLED=yes + volumes: + - ./redis-standalone-sentinel-controlled/config:/redis/config:r + - ${REDIS_ENV_WORK_DIR}/redis-standalone-sentinel-controlled/work:/redis/work:rw + - ${REDIS_ENV_WORK_DIR}:/work + ports: + - "26380:26380" + - "26822:26822" # sentinel tls port + - "26379:26379" + - "6482:6482" + - "6483:6483" + - "8443:8443" # TLS Port + - "8444:8444" # TLS Port + networks: + - redis-network + + + ssl-test-cluster: + <<: *client-libs-image + container_name: ssl-test-cluster + environment: + - REDIS_CLUSTER=yes + volumes: + - ./ssl-test-cluster/config:/redis/config:r + ports: + - "7479:7479" + - "7480:7480" + - "7481:7481" + networks: + - redis-network + + # Non-SSL Cluster + test-cluster: + <<: *client-libs-image + container_name: test-cluster + environment: + - REDIS_CLUSTER=yes + volumes: + - ./test-cluster/config:/redis/config:r + ports: + - "7379:7379" + - "7380:7380" + - "7381:7381" + - "7382:7382" + - "7383:7383" + - "7384:7384" + - "7385:7385" + - "7582:7582" + networks: + - redis-network + +networks: + redis-network: + driver: bridge diff --git a/src/test/resources/docker-env/redis-standalone-0/config/node-6478/redis.conf b/src/test/resources/docker-env/redis-standalone-0/config/node-6478/redis.conf new file mode 100644 index 0000000000..6fa6ea2177 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-0/config/node-6478/redis.conf @@ -0,0 +1,10 @@ +port 6478 +tls-port 6444 +tls-auth-clients no +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +enable-debug-command yes +unixsocket /work/socket-6478 +unixsocketperm 777 +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-1/config/node-6479/redis.conf b/src/test/resources/docker-env/redis-standalone-1/config/node-6479/redis.conf new file mode 100644 index 0000000000..544300d1ee --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-1/config/node-6479/redis.conf @@ -0,0 +1,10 @@ +port 6479 +tls-port 6443 +tls-auth-clients no +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +enable-debug-command yes +unixsocket /work/socket-6479 +unixsocketperm 777 +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-1/config/node-6486/redis.conf b/src/test/resources/docker-env/redis-standalone-1/config/node-6486/redis.conf new file mode 100644 index 0000000000..4fa8e59d35 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-1/config/node-6486/redis.conf @@ -0,0 +1,8 @@ +port 6486 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-6486 +unixsocketperm 777 +enable-debug-command yes +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-2/config/node-6480/redis.conf b/src/test/resources/docker-env/redis-standalone-2/config/node-6480/redis.conf new file mode 100644 index 0000000000..ebaf1511a7 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-2/config/node-6480/redis.conf @@ -0,0 +1,8 @@ +port 6480 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-6480 +unixsocketperm 777 +enable-debug-command yes +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-3/config/node-6481/redis.conf b/src/test/resources/docker-env/redis-standalone-3/config/node-6481/redis.conf new file mode 100644 index 0000000000..25e45088cf --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-3/config/node-6481/redis.conf @@ -0,0 +1,8 @@ +port 6481 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-6481 +unixsocketperm 777 +enable-debug-command yes +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-4/config/node-6484/redis.conf b/src/test/resources/docker-env/redis-standalone-4/config/node-6484/redis.conf new file mode 100644 index 0000000000..1afd6beb3f --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-4/config/node-6484/redis.conf @@ -0,0 +1,8 @@ +port 6484 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-6484 +unixsocketperm 777 +enable-debug-command yes +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-4/config/node-sentinel-26381/redis.conf b/src/test/resources/docker-env/redis-standalone-4/config/node-sentinel-26381/redis.conf new file mode 100644 index 0000000000..5208b41f51 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-4/config/node-sentinel-26381/redis.conf @@ -0,0 +1,11 @@ +port 26381 +sentinel monitor mymaster localhost 6484 1 +sentinel announce-hostnames yes +sentinel resolve-hostnames yes +sentinel announce-ip localhost +sentinel down-after-milliseconds mymaster 200 +sentinel failover-timeout mymaster 200 +sentinel parallel-syncs mymaster 1 +sentinel auth-pass mymaster foobared +unixsocket /work/socket-26381 +unixsocketperm 777 \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-5-client-cert/config/node-6478/redis.conf b/src/test/resources/docker-env/redis-standalone-5-client-cert/config/node-6478/redis.conf new file mode 100644 index 0000000000..e5e275ca42 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-5-client-cert/config/node-6478/redis.conf @@ -0,0 +1,8 @@ +port 6485 +tls-port 6445 +#tls-auth-clients no +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +enable-debug-command yes +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6482/redis.conf b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6482/redis.conf new file mode 100644 index 0000000000..1b15dfab27 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6482/redis.conf @@ -0,0 +1,10 @@ +port 6482 +tls-port 8443 +tls-auth-clients no +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-6482 +unixsocketperm 777 +enable-debug-command yes +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6483/redis.conf b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6483/redis.conf new file mode 100644 index 0000000000..2d40968e1a --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6483/redis.conf @@ -0,0 +1,11 @@ +port 6483 +tls-port 8444 +tls-auth-clients no +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-6483 +unixsocketperm 777 +enable-debug-command yes +slaveof 127.0.0.1 6482 +replica-announce-ip localhost \ No newline at end of file diff --git a/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26379/redis.conf b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26379/redis.conf new file mode 100644 index 0000000000..96b2c5beb4 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26379/redis.conf @@ -0,0 +1,12 @@ +port 26379 +tls-port 26822 +tls-auth-clients no +sentinel monitor mymaster localhost 6482 1 +sentinel announce-hostnames yes +sentinel resolve-hostnames yes +sentinel announce-ip localhost +sentinel down-after-milliseconds mymaster 200 +sentinel failover-timeout mymaster 200 +sentinel parallel-syncs mymaster 1 +unixsocket /work/socket-26379 +unixsocketperm 777 diff --git a/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26380/redis.conf b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26380/redis.conf new file mode 100644 index 0000000000..5eba90ec35 --- /dev/null +++ b/src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26380/redis.conf @@ -0,0 +1,10 @@ +port 26380 +sentinel monitor mymaster localhost 6482 1 +sentinel announce-hostnames yes +sentinel resolve-hostnames yes +sentinel announce-ip localhost +sentinel down-after-milliseconds mymaster 200 +sentinel failover-timeout mymaster 200 +sentinel parallel-syncs mymaster 1 +unixsocket /work/socket-26380 +unixsocketperm 777 \ No newline at end of file diff --git a/src/test/resources/docker-env/ssl-test-cluster/config/node-7479/nodes.conf b/src/test/resources/docker-env/ssl-test-cluster/config/node-7479/nodes.conf new file mode 100644 index 0000000000..d578e24d7d --- /dev/null +++ b/src/test/resources/docker-env/ssl-test-cluster/config/node-7479/nodes.conf @@ -0,0 +1,4 @@ +cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 myself,master - 0 1578163609000 0 connected 0-10000 +cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609301 1 connected +6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 master - 0 1578163609301 2 connected 10001-16383 +vars currentEpoch 2 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/ssl-test-cluster/config/node-7479/redis.conf b/src/test/resources/docker-env/ssl-test-cluster/config/node-7479/redis.conf new file mode 100644 index 0000000000..8a51dd683f --- /dev/null +++ b/src/test/resources/docker-env/ssl-test-cluster/config/node-7479/redis.conf @@ -0,0 +1,7 @@ +port 7479 +save "" +appendonly no +cluster-enabled yes +cluster-node-timeout 150 +cluster-announce-port 7445 +requirepass foobared \ No newline at end of file diff --git a/src/test/resources/docker-env/ssl-test-cluster/config/node-7480/nodes.conf b/src/test/resources/docker-env/ssl-test-cluster/config/node-7480/nodes.conf new file mode 100644 index 0000000000..8da078b924 --- /dev/null +++ b/src/test/resources/docker-env/ssl-test-cluster/config/node-7480/nodes.conf @@ -0,0 +1,4 @@ +cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 master - 0 1578163609245 0 connected 0-10000 +cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 myself,slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609000 1 connected +6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 master - 0 1578163609245 2 connected 10001-16383 +vars currentEpoch 2 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/ssl-test-cluster/config/node-7480/redis.conf b/src/test/resources/docker-env/ssl-test-cluster/config/node-7480/redis.conf new file mode 100644 index 0000000000..190236043c --- /dev/null +++ b/src/test/resources/docker-env/ssl-test-cluster/config/node-7480/redis.conf @@ -0,0 +1,7 @@ +port 7480 +save "" +appendonly no +cluster-enabled yes +cluster-node-timeout 150 +cluster-announce-port 7444 +requirepass foobared \ No newline at end of file diff --git a/src/test/resources/docker-env/ssl-test-cluster/config/node-7481/nodes.conf b/src/test/resources/docker-env/ssl-test-cluster/config/node-7481/nodes.conf new file mode 100644 index 0000000000..fdca668d22 --- /dev/null +++ b/src/test/resources/docker-env/ssl-test-cluster/config/node-7481/nodes.conf @@ -0,0 +1,4 @@ +cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609279 1 connected +cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 master - 0 1578163609279 0 connected 0-10000 +6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 myself,master - 0 1578163609000 2 connected 10001-16383 +vars currentEpoch 2 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/ssl-test-cluster/config/node-7481/redis.conf b/src/test/resources/docker-env/ssl-test-cluster/config/node-7481/redis.conf new file mode 100644 index 0000000000..3892728a3d --- /dev/null +++ b/src/test/resources/docker-env/ssl-test-cluster/config/node-7481/redis.conf @@ -0,0 +1,7 @@ +port 7481 +save "" +appendonly no +cluster-enabled yes +cluster-node-timeout 150 +cluster-announce-port 7445 +requirepass foobared \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7379/nodes.conf b/src/test/resources/docker-env/test-cluster/config/node-7379/nodes.conf new file mode 100644 index 0000000000..8a59dbabda --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7379/nodes.conf @@ -0,0 +1,5 @@ +c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 1434887920102 1434887920002 0 connected 12000-16383 +27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 myself,master - 0 0 1 connected 0-11999 +2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected +1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected +vars currentEpoch 3 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7379/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7379/redis.conf new file mode 100644 index 0000000000..61ab74a1f1 --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7379/redis.conf @@ -0,0 +1,7 @@ +port 7379 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7379 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7380/nodes.conf b/src/test/resources/docker-env/test-cluster/config/node-7380/nodes.conf new file mode 100644 index 0000000000..f71c380f9c --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7380/nodes.conf @@ -0,0 +1,5 @@ +2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected +27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 1434887920102 1434887920002 1 connected 0-11999 +1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected +c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 myself,master - 0 0 0 connected 12000-16383 +vars currentEpoch 3 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7380/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7380/redis.conf new file mode 100644 index 0000000000..2f2ed61e25 --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7380/redis.conf @@ -0,0 +1,7 @@ +port 7380 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7380 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7381/nodes.conf b/src/test/resources/docker-env/test-cluster/config/node-7381/nodes.conf new file mode 100644 index 0000000000..aed925c86a --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7381/nodes.conf @@ -0,0 +1,5 @@ +1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 myself,slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 0 0 3 connected +2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected +c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 1434887920102 1434887920002 0 connected 12000-16383 +27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 1434887920102 1434887920002 1 connected 0-11999 +vars currentEpoch 3 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7381/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7381/redis.conf new file mode 100644 index 0000000000..0bfd25910f --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7381/redis.conf @@ -0,0 +1,7 @@ +port 7381 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7381 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7382/nodes.conf b/src/test/resources/docker-env/test-cluster/config/node-7382/nodes.conf new file mode 100644 index 0000000000..bdcf179a5e --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7382/nodes.conf @@ -0,0 +1,5 @@ +c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 0 1434887920102 0 connected 12000-16383 +1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 0 1434887920102 3 connected +2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 myself,slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 0 0 2 connected +27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 0 1434887920102 1 connected 0-11999 +vars currentEpoch 3 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7382/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7382/redis.conf new file mode 100644 index 0000000000..a658fe1149 --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7382/redis.conf @@ -0,0 +1,7 @@ +port 7382 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7382 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7383/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7383/redis.conf new file mode 100644 index 0000000000..262122f52b --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7383/redis.conf @@ -0,0 +1,7 @@ +port 7383 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7383 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7384/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7384/redis.conf new file mode 100644 index 0000000000..1594941ae0 --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7384/redis.conf @@ -0,0 +1,7 @@ +port 7384 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7384 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7385/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7385/redis.conf new file mode 100644 index 0000000000..3aee9a7dae --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7385/redis.conf @@ -0,0 +1,8 @@ +port 7385 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7385 +cluster-enabled yes +cluster-node-timeout 150 +requirepass foobared \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7582/nodes.conf b/src/test/resources/docker-env/test-cluster/config/node-7582/nodes.conf new file mode 100644 index 0000000000..1c71f1fd5d --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7582/nodes.conf @@ -0,0 +1,5 @@ +c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7580 master - 1434887920102 1434887920002 0 connected 10001-16383 +27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7579 myself,master - 0 0 1 connected 0-10000 +2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7582 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected +1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7581 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected +vars currentEpoch 3 lastVoteEpoch 0 \ No newline at end of file diff --git a/src/test/resources/docker-env/test-cluster/config/node-7582/redis.conf b/src/test/resources/docker-env/test-cluster/config/node-7582/redis.conf new file mode 100644 index 0000000000..e6fb7424a8 --- /dev/null +++ b/src/test/resources/docker-env/test-cluster/config/node-7582/redis.conf @@ -0,0 +1,7 @@ +port 7582 +save "" +appendonly no +client-output-buffer-limit pubsub 256k 128k 5 +unixsocket /work/socket-7582 +cluster-enabled yes +cluster-node-timeout 150 \ No newline at end of file