Skip to content

[Antithesis] Configuration for 1 node cluster #20176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2025
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
3 changes: 2 additions & 1 deletion tests/antithesis/Dockerfile.config
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ FROM golang:$GO_VERSION AS build
RUN go install github.com/a8m/envsubst/cmd/envsubst@v1.4.3

ARG IMAGE_TAG
COPY docker-compose.yml /docker-compose.yml.template
ARG NODE_COUNT
COPY docker-compose-${NODE_COUNT}-node.yml /docker-compose.yml.template
RUN IMAGE_TAG=${IMAGE_TAG} cat /docker-compose.yml.template | envsubst > /docker-compose.yml

FROM scratch
Expand Down
42 changes: 28 additions & 14 deletions tests/antithesis/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ ARCH ?= $(shell go env GOARCH)
REF = main
IMAGE_TAG = latest

CFG_NODE_COUNT ?= 3

.PHONY: antithesis-build-client-docker-image
antithesis-build-client-docker-image:
docker build --build-arg GO_VERSION=$(shell cat $(REPOSITORY_ROOT)/.go-version) -f $(REPOSITORY_ROOT)/tests/antithesis/test-template/Dockerfile $(REPOSITORY_ROOT) -t etcd-client:latest
antithesis-build-client-docker-image: validate-node-count
docker build \
--build-arg GO_VERSION=$(shell cat $(REPOSITORY_ROOT)/.go-version) \
--build-arg CFG_NODE_COUNT=$(CFG_NODE_COUNT) \
-f $(REPOSITORY_ROOT)/tests/antithesis/test-template/Dockerfile $(REPOSITORY_ROOT) -t etcd-client:latest

.PHONY: antithesis-build-etcd-image
antithesis-build-etcd-image:
Expand All @@ -30,30 +35,39 @@ antithesis-build-etcd-image-main: REF=main
antithesis-build-etcd-image-main: antithesis-build-etcd-image

.PHONY: antithesis-build-config-image
antithesis-build-config-image:
docker build -f ./Dockerfile.config . -t etcd-config:latest --build-arg IMAGE_TAG=$(IMAGE_TAG)
antithesis-build-config-image: validate-node-count
docker build -f ./Dockerfile.config . -t etcd-config:latest \
--build-arg IMAGE_TAG=$(IMAGE_TAG) \
--build-arg NODE_COUNT=$(CFG_NODE_COUNT)

.PHONY: antithesis-docker-compose-up
antithesis-docker-compose-up:
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker-compose up
antithesis-docker-compose-up: validate-node-count
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker compose -f docker-compose-$(CFG_NODE_COUNT)-node.yml up

.PHONY: antithesis-run-container-traffic
antithesis-run-container-traffic:
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker-compose exec client /opt/antithesis/test/v1/robustness/singleton_driver_traffic
antithesis-run-container-traffic: validate-node-count
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker compose -f docker-compose-$(CFG_NODE_COUNT)-node.yml exec client /opt/antithesis/test/v1/robustness/singleton_driver_traffic

.PHONY: antithesis-run-container-validation
antithesis-run-container-validation:
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker-compose exec client /opt/antithesis/test/v1/robustness/finally_validation
antithesis-run-container-validation: validate-node-count
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker compose -f docker-compose-$(CFG_NODE_COUNT)-node.yml exec client /opt/antithesis/test/v1/robustness/finally_validation

.PHONY: antithesis-run-local-traffic
antithesis-run-local-traffic:
go run --race ./test-template/robustness/traffic/main.go --local
go run -ldflags "-X main.NodeCount=$(CFG_NODE_COUNT)" --race ./test-template/robustness/traffic/main.go --local

.PHONY: antithesis-run-local-validation
antithesis-run-local-validation:
go run --race ./test-template/robustness/finally/main.go --local
go run -ldflags "-X main.NodeCount=$(CFG_NODE_COUNT)" --race ./test-template/robustness/finally/main.go --local

.PHONY: antithesis-clean
antithesis-clean:
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker-compose down
antithesis-clean: validate-node-count
export USER_ID=$(USER_ID) && export GROUP_ID=$(GROUP_ID) && docker compose -f docker-compose-$(CFG_NODE_COUNT)-node.yml down --remove-orphans
rm -rf /tmp/etcddata0 /tmp/etcddata1 /tmp/etcddata2 /tmp/etcdreport

.PHONY: validate-node-count
validate-node-count:
@if [ "$(CFG_NODE_COUNT)" != "1" ] && [ "$(CFG_NODE_COUNT)" != "3" ]; then \
echo "CFG_NODE_COUNT must be either 1 or 3 (got $(CFG_NODE_COUNT))"; \
exit 1; \
fi
54 changes: 54 additions & 0 deletions tests/antithesis/docker-compose-1-node.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
services:
# This is needed for creating non-root data folders on host.
# By default, if the folders don't exist when mounting, compose creates them with root as owner.
# With root owner, accessing the WAL files from local tests will fail due to an unauthorized access error.
init:
image: 'docker.io/library/ubuntu:latest'
user: root
group_add:
- '${GROUP_ID:-root}'
volumes:
- ${ETCD_ROBUSTNESS_DATA_PATH:-/tmp/etcddata}0:/var/etcddata0
- ${ETCD_ROBUSTNESS_REPORT_PATH:-/tmp/etcdreport}:/var/report
command:
- /bin/sh
- -c
- |
rm -rf /var/etcddata0/* /var/report/*
chown -R ${USER_ID:-root}:${GROUP_ID:-root} /var/etcddata0 /var/report

etcd0:
image: 'etcd-server:${IMAGE_TAG:-latest}'
container_name: etcd0
hostname: etcd0
environment:
ETCD_NAME: "etcd0"
ETCD_INITIAL_ADVERTISE_PEER_URLS: "http://etcd0:2380"
ETCD_LISTEN_PEER_URLS: "http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS: "http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS: "http://etcd0.etcd:2379"
ETCD_INITIAL_CLUSTER_TOKEN: "etcd-cluster-1"
ETCD_INITIAL_CLUSTER: "etcd0=http://etcd0:2380"
ETCD_INITIAL_CLUSTER_STATE: "new"
ETCD_DATA_DIR: "/var/etcd/data"
user: "${USER_ID:-root}:${GROUP_ID:-root}"
depends_on:
init:
condition: service_completed_successfully
ports:
- 12379:2379
volumes:
- ${ETCD_ROBUSTNESS_DATA_PATH:-/tmp/etcddata}0:/var/etcd/data

client:
image: 'etcd-client:${IMAGE_TAG:-latest}'
container_name: client
entrypoint: ["/opt/antithesis/entrypoint/entrypoint"]
user: "${USER_ID:-root}:${GROUP_ID:-root}"
depends_on:
etcd0:
condition: service_started
volumes:
- ${ETCD_ROBUSTNESS_DATA_PATH:-/tmp/etcddata}0:/var/etcddata0
- ${ETCD_ROBUSTNESS_REPORT_PATH:-/tmp/etcdreport}:/var/report
7 changes: 4 additions & 3 deletions tests/antithesis/test-template/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ ARG GO_VERSION=1.24.4
ARG ARCH=amd64

FROM golang:$GO_VERSION
ARG CFG_NODE_COUNT=3
WORKDIR /build
COPY . .

WORKDIR /build/tests
RUN go build -o /opt/antithesis/entrypoint/entrypoint -race ./antithesis/test-template/entrypoint/main.go
RUN go build -o /opt/antithesis/test/v1/robustness/singleton_driver_traffic -race ./antithesis/test-template/robustness/traffic/main.go
RUN go build -o /opt/antithesis/test/v1/robustness/finally_validation -race ./antithesis/test-template/robustness/finally/main.go
RUN go build -ldflags "-X main.NodeCount=$CFG_NODE_COUNT" -o /opt/antithesis/entrypoint/entrypoint -race ./antithesis/test-template/entrypoint/main.go
RUN go build -ldflags "-X main.NodeCount=$CFG_NODE_COUNT" -o /opt/antithesis/test/v1/robustness/singleton_driver_traffic -race ./antithesis/test-template/robustness/traffic/main.go
RUN go build -ldflags "-X main.NodeCount=$CFG_NODE_COUNT" -o /opt/antithesis/test/v1/robustness/finally_validation -race ./antithesis/test-template/robustness/finally/main.go
7 changes: 6 additions & 1 deletion tests/antithesis/test-template/entrypoint/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ import (
"github.com/antithesishq/antithesis-sdk-go/lifecycle"

clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/tests/v3/antithesis/test-template/robustness/common"
)

// Sleep duration
const SLEEP = 10

var NodeCount = "3"

// CheckHealth checks health of all etcd nodes
func CheckHealth() bool {
nodeOptions := []string{"etcd0", "etcd1", "etcd2"}
cfg := common.MakeConfig(NodeCount)

nodeOptions := []string{"etcd0", "etcd1", "etcd2"}[:cfg.NodeCount]

// iterate over each node and check health
for _, node := range nodeOptions {
Expand Down
29 changes: 29 additions & 0 deletions tests/antithesis/test-template/robustness/common/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2025 The etcd Authors
//
// Licensed 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.

package common

import "strconv"

type Config struct {
NodeCount int
}

func MakeConfig(nodeCount string) *Config {
cfg := &Config{}

cfg.NodeCount, _ = strconv.Atoi(nodeCount)

return cfg
}
20 changes: 10 additions & 10 deletions tests/antithesis/test-template/robustness/common/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,23 @@ const (
localReportPath = "report"
)

func DefaultPaths() (string, []string, map[string]string) {
hosts := []string{defaultetcd0, defaultetcd1, defaultetcd2}
reportPath := defaultReportPath
dataPaths := etcdDataPaths(defaultetcdDataPath, len(hosts))
return reportPath, hosts, dataPaths
func DefaultPaths(cfg *Config) (hosts []string, reportPath string, dataPaths map[string]string) {
hosts = []string{defaultetcd0, defaultetcd1, defaultetcd2}[:cfg.NodeCount]
reportPath = defaultReportPath
dataPaths = etcdDataPaths(defaultetcdDataPath, cfg.NodeCount)
return hosts, reportPath, dataPaths
}

func LocalPaths() (string, []string, map[string]string) {
hosts := []string{localetcd0, localetcd1, localetcd2}
reportPath := localReportPath
func LocalPaths(cfg *Config) (hosts []string, reportPath string, dataPaths map[string]string) {
hosts = []string{localetcd0, localetcd1, localetcd2}[:cfg.NodeCount]
reportPath = localReportPath
etcdDataPath := defaultetcdLocalDataPath
envPath := os.Getenv(localetcdDataPathEnv)
if envPath != "" {
etcdDataPath = envPath + "%d"
}
dataPaths := etcdDataPaths(etcdDataPath, len(hosts))
return reportPath, hosts, dataPaths
dataPaths = etcdDataPaths(etcdDataPath, cfg.NodeCount)
return hosts, reportPath, dataPaths
}

func etcdDataPaths(dir string, amount int) map[string]string {
Expand Down
8 changes: 6 additions & 2 deletions tests/antithesis/test-template/robustness/finally/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@ const (
reportFileName = "history.html"
)

var NodeCount = "3"

func main() {
local := flag.Bool("local", false, "run finally locally and connect to etcd instances via localhost")
flag.Parse()

reportPath, _, dirs := common.DefaultPaths()
cfg := common.MakeConfig(NodeCount)

_, reportPath, dirs := common.DefaultPaths(cfg)
if *local {
reportPath, _, dirs = common.LocalPaths()
_, reportPath, dirs = common.LocalPaths(cfg)
}

lg, err := zap.NewProduction()
Expand Down
7 changes: 5 additions & 2 deletions tests/antithesis/test-template/robustness/traffic/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,18 @@ var (
traffic.EtcdPutDeleteLease,
traffic.Kubernetes,
}
NodeCount = "3"
)

func main() {
local := flag.Bool("local", false, "run tests locally and connect to etcd instances via localhost")
flag.Parse()

reportPath, hosts, etcdetcdDataPaths := common.DefaultPaths()
cfg := common.MakeConfig(NodeCount)

hosts, reportPath, etcdetcdDataPaths := common.DefaultPaths(cfg)
if *local {
reportPath, hosts, etcdetcdDataPaths = common.LocalPaths()
hosts, reportPath, etcdetcdDataPaths = common.LocalPaths(cfg)
}

ctx := context.Background()
Expand Down