Skip to content

Commit 17333a1

Browse files
authored
Merge pull request #465 from hookdeck/chore/azure-managed-redis
feat: support redis clusters
2 parents 4283719 + 74d709d commit 17333a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+5251
-311
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ REDIS_HOST="redis"
1717
REDIS_PORT="6379"
1818
REDIS_PASSWORD="password"
1919
REDIS_DATABASE="0"
20+
REDIS_TLS_ENABLED="false" # Enable TLS encryption (required for Azure Managed Redis)
21+
REDIS_CLUSTER_ENABLED="false" # Enable cluster mode (required for Azure Managed Redis)
2022

2123
# ============================== Log Store ==============================
2224

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ cmd/dev
3030
.cursor/
3131
.claude/
3232
*.local.*
33+
bin/

Makefile

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
11
TEST?=$$(go list ./...)
22

3+
# Build targets
4+
.PHONY: build
5+
build:
6+
@echo "Building all binaries..."
7+
go build -o bin/outpost ./cmd/outpost
8+
go build -o bin/outpost-server ./cmd/outpost-server
9+
go build -o bin/outpost-migrate-redis ./cmd/outpost-migrate-redis
10+
@echo "Binaries built in ./bin/"
11+
12+
build/goreleaser:
13+
goreleaser release -f ./build/.goreleaser.yaml --snapshot --clean
14+
15+
build/outpost:
16+
go build -o bin/outpost ./cmd/outpost
17+
18+
build/server:
19+
go build -o bin/outpost-server ./cmd/outpost-server
20+
21+
build/migrate-redis:
22+
go build -o bin/outpost-migrate-redis ./cmd/outpost-migrate-redis
23+
24+
install:
25+
@echo "Installing binaries to GOPATH/bin..."
26+
go install ./cmd/outpost
27+
go install ./cmd/outpost-server
28+
go install ./cmd/outpost-migrate-redis
29+
@echo "Installation complete"
30+
31+
clean:
32+
rm -f bin/outpost bin/outpost-server bin/outpost-migrate-redis
33+
334
up:
435
make up/deps
536
make up/outpost
@@ -53,8 +84,42 @@ up/test:
5384
down/test:
5485
docker-compose -f build/test/compose.yml down --volumes
5586

87+
up/test/rediscluster:
88+
@echo "Ensuring test network exists..."
89+
@docker network create outpost-test_default 2>/dev/null || true
90+
@UNAME_S=$$(uname -s); \
91+
if [ "$$UNAME_S" = "Darwin" ]; then \
92+
REDIS_IMAGE=neohq/redis-cluster:latest; \
93+
echo "Detected macOS, using neohq/redis-cluster image..."; \
94+
else \
95+
REDIS_IMAGE=grokzen/redis-cluster:7.2.4; \
96+
echo "Using grokzen/redis-cluster image..."; \
97+
fi; \
98+
REDIS_IMAGE=$$REDIS_IMAGE docker-compose -f build/test/redis-cluster-compose.yml up -d
99+
@echo "Starting Redis cluster and test runner containers..."
100+
@echo " - Redis cluster: 6 nodes (3 masters + 3 replicas)"
101+
@echo " - Test runner: Alpine container with Go code mounted"
102+
@echo ""
103+
@echo "Waiting for cluster to initialize..."
104+
@sleep 10
105+
@echo "Checking Redis cluster status:"
106+
@docker exec redis-cluster redis-cli -p 7000 cluster info | grep cluster_state || echo "Failed to check cluster status"
107+
@echo ""
108+
@echo "Test environment ready. Run: make test/e2e/rediscluster"
109+
110+
down/test/rediscluster:
111+
@echo "Stopping Redis cluster test environment..."
112+
@docker-compose -f build/test/redis-cluster-compose.yml down --volumes
113+
@echo "Redis cluster test environment stopped."
114+
56115
test/setup:
57-
bash scripts/test-setup-info.sh
116+
@echo "To setup the test environment, run the following command:"
117+
@echo "$$ make up/test"
118+
@echo "$$ make up/azure"
119+
@echo ""
120+
@echo "Before running the tests, make sure to:"
121+
@echo "$$ export TESTINFRA=1 TESTAZURE=1"
122+
@echo ""
58123

59124
test:
60125
go test $(TEST) $(TESTARGS)
@@ -65,6 +130,15 @@ test/unit:
65130
test/integration:
66131
go test $(TEST) $(TESTARGS) -run "Integration"
67132

133+
test/e2e/rediscluster:
134+
@echo "Running Redis cluster e2e tests in Docker container..."
135+
@if ! docker ps | grep -q test-runner; then \
136+
echo "Error: test-runner container not running. Run 'make up/test/rediscluster' first."; \
137+
exit 1; \
138+
fi
139+
@docker exec test-runner sh -c "cd /app && go test ./cmd/e2e -v -run TestRedisClusterBasicSuite"
140+
@echo "Redis cluster e2e tests completed."
141+
68142
test/race:
69143
TESTRACE=1 go test $(TEST) $(TESTARGS) -race
70144

@@ -77,6 +151,9 @@ test/coverage/html:
77151
docs/generate/config:
78152
go run cmd/configdocsgen/main.go
79153

154+
redis/debug:
155+
go run cmd/redis-debug/main.go $(ARGS)
156+
80157
network:
81158
docker network create outpost
82159

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ SDKs:
4747

4848
Outpost is a self-hosted and open-source infrastructure that enables event producers to add outbound webhooks and [Event Destinations](https://eventdestinations.org?ref=github-outpost) to their platform with support for destination types such as Webhooks, Hookdeck Event Gateway, Amazon EventBridge, AWS SQS, AWS S3, GCP Pub/Sub, RabbitMQ, and Kafka.
4949

50-
The Outpost runtime has minimal dependencies (Redis, PostgreSQL or Clickhouse, and one of the supported message queues), is 100% backward compatible with your existing webhooks implementation and is optimized for high-throughput, low-cost operation.
50+
The Outpost runtime has minimal dependencies (Redis or Redis cluster, PostgreSQL, and one of the supported message queues), is 100% backward compatible with your existing webhooks implementation, and is optimized for high-throughput, low-cost operation.
5151

5252
Outpost is built and maintained by [Hookdeck](https://hookdeck.com?ref=github-outpost). It's written in Go and distributed as a binary and Docker container under the Apache-2.0 license.
5353

@@ -118,6 +118,34 @@ cp .env.example .env
118118

119119
Update the `$API_KEY` value within the new `.env` file.
120120

121+
#### Redis Configuration
122+
123+
Outpost supports both standard Redis and cluster Redis configurations:
124+
125+
**Standard Redis** (default, for local development and single-node Redis):
126+
```env
127+
REDIS_HOST="redis"
128+
REDIS_PORT="6379"
129+
REDIS_TLS_ENABLED="false"
130+
REDIS_CLUSTER_ENABLED="false"
131+
```
132+
133+
**Redis Cluster** (for Redis Enterprise and managed Redis services):
134+
```env
135+
REDIS_HOST="your-redis-cluster.example.com"
136+
REDIS_PORT="10000"
137+
REDIS_TLS_ENABLED="true"
138+
REDIS_CLUSTER_ENABLED="true"
139+
```
140+
141+
For other cloud Redis services or self-hosted Redis clusters, set `REDIS_CLUSTER_ENABLED="true"` if using Redis clustering.
142+
143+
**Troubleshooting Redis connectivity**: Use the built-in diagnostic tool to test your Redis connection:
144+
```sh
145+
go run cmd/redis-debug/main.go your-redis-host 6379 password 0 [tls] [cluster]
146+
```
147+
See the [Redis Troubleshooting Guide](https://docs.outpost.hookdeck.com/references/troubleshooting-redis) for detailed guidance.
148+
121149
Start the Outpost dependencies and services:
122150

123151
```sh

build/.goreleaser.yaml

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ before:
77

88
project_name: outpost
99

10+
git:
11+
# Ignore SDK tags when determining version
12+
ignore_tags:
13+
- 'sdks/*'
14+
1015
builds:
16+
# Orchestrator binary
1117
- id: outpost
1218
ldflags:
1319
- -s -w
@@ -16,7 +22,7 @@ builds:
1622
binary: outpost
1723
env:
1824
- CGO_ENABLED=0
19-
main: ./cmd/outpost/main.go
25+
main: ./cmd/outpost
2026
goos:
2127
- linux
2228
goarch:
@@ -29,7 +35,63 @@ builds:
2935
binary: outpost
3036
env:
3137
- CGO_ENABLED=0
32-
main: ./cmd/outpost/main.go
38+
main: ./cmd/outpost
39+
goos:
40+
- linux
41+
goarch:
42+
- arm64
43+
44+
# Server binary
45+
- id: outpost-server
46+
ldflags:
47+
- -s -w
48+
- -X github.com/hookdeck/outpost/internal/version.version={{.Version}}
49+
- -X github.com/hookdeck/outpost/internal/version.commit={{.FullCommit}}
50+
binary: outpost-server
51+
env:
52+
- CGO_ENABLED=0
53+
main: ./cmd/outpost-server
54+
goos:
55+
- linux
56+
goarch:
57+
- amd64
58+
- id: outpost-server-arm64
59+
ldflags:
60+
- -s -w
61+
- -X github.com/hookdeck/outpost/internal/version.version={{.Version}}
62+
- -X github.com/hookdeck/outpost/internal/version.commit={{.FullCommit}}
63+
binary: outpost-server
64+
env:
65+
- CGO_ENABLED=0
66+
main: ./cmd/outpost-server
67+
goos:
68+
- linux
69+
goarch:
70+
- arm64
71+
72+
# Migration binary
73+
- id: outpost-migrate-redis
74+
ldflags:
75+
- -s -w
76+
- -X github.com/hookdeck/outpost/internal/version.version={{.Version}}
77+
- -X github.com/hookdeck/outpost/internal/version.commit={{.FullCommit}}
78+
binary: outpost-migrate-redis
79+
env:
80+
- CGO_ENABLED=0
81+
main: ./cmd/outpost-migrate-redis
82+
goos:
83+
- linux
84+
goarch:
85+
- amd64
86+
- id: outpost-migrate-redis-arm64
87+
ldflags:
88+
- -s -w
89+
- -X github.com/hookdeck/outpost/internal/version.version={{.Version}}
90+
- -X github.com/hookdeck/outpost/internal/version.commit={{.FullCommit}}
91+
binary: outpost-migrate-redis
92+
env:
93+
- CGO_ENABLED=0
94+
main: ./cmd/outpost-migrate-redis
3395
goos:
3496
- linux
3597
goarch:
@@ -63,6 +125,10 @@ dockers:
63125
dockerfile: ./build/Dockerfile.goreleaser
64126
ids:
65127
- outpost
128+
- outpost-server
129+
- outpost-migrate-redis
130+
extra_files:
131+
- build/entrypoint.sh
66132
image_templates:
67133
- "hookdeck/outpost:latest-amd64"
68134
- "hookdeck/outpost:{{ .Tag }}-amd64"
@@ -80,6 +146,10 @@ dockers:
80146
dockerfile: ./build/Dockerfile.goreleaser
81147
ids:
82148
- outpost-arm64
149+
- outpost-server-arm64
150+
- outpost-migrate-redis-arm64
151+
extra_files:
152+
- build/entrypoint.sh
83153
image_templates:
84154
- "hookdeck/outpost:latest-arm64"
85155
- "hookdeck/outpost:{{ .Tag }}-arm64"

build/Dockerfile

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
# Stage 0
2-
# Build the binary
2+
# Build the binaries
33
FROM golang:1.23-alpine
44
WORKDIR /app
55
COPY . .
66

7-
RUN go build -o ./bin/outpost ./cmd/outpost/main.go
7+
# Build all binaries
8+
RUN go build -o ./bin/outpost ./cmd/outpost/main.go && \
9+
go build -o ./bin/outpost-server ./cmd/outpost-server/main.go && \
10+
go build -o ./bin/outpost-migrate-redis ./cmd/outpost-migrate-redis/main.go
811

912
# Stage 1
10-
# Copy binary to a new image
13+
# Copy binaries to a new image
1114
FROM scratch
1215
COPY --from=0 /app/bin/outpost /bin/outpost
13-
ENTRYPOINT ["/bin/outpost"]
16+
COPY --from=0 /app/bin/outpost-server /bin/outpost-server
17+
COPY --from=0 /app/bin/outpost-migrate-redis /bin/outpost-migrate-redis
18+
19+
# Default to running the server
20+
ENTRYPOINT ["/bin/outpost", "serve"]

build/Dockerfile.goreleaser

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1-
FROM gcr.io/distroless/base
2-
COPY outpost outpost
3-
ENTRYPOINT ["./outpost"]
1+
FROM busybox:1.36-musl AS busybox
2+
3+
FROM gcr.io/distroless/base-debian12:nonroot
4+
5+
# Copy statically linked shell from busybox for entrypoint script
6+
COPY --from=busybox /bin/sh /bin/sh
7+
8+
# Copy all binaries
9+
COPY outpost /usr/local/bin/outpost
10+
COPY outpost-server /usr/local/bin/outpost-server
11+
COPY outpost-migrate-redis /usr/local/bin/outpost-migrate-redis
12+
13+
# Copy entrypoint script
14+
COPY build/entrypoint.sh /usr/local/bin/entrypoint.sh
15+
16+
# Default entrypoint runs migrations and starts server
17+
ENTRYPOINT ["/bin/sh", "/usr/local/bin/entrypoint.sh"]

build/dev/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ FROM golang:1.23-alpine AS fetch
22
RUN go install github.com/air-verse/[email protected]
33
WORKDIR /app
44
COPY . .
5-
CMD ["air"]
5+
ENTRYPOINT ["sh", "./build/dev/entrypoint.sh"]

build/dev/entrypoint.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/sh
2+
set -e
3+
4+
echo "- Running: go run ./cmd/outpost-migrate-redis init --current"
5+
6+
go run ./cmd/outpost-migrate-redis init --current
7+
8+
echo "- Running: air serve"
9+
10+
exec air serve

build/entrypoint.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# If any arguments are passed, delegate to outpost binary
5+
# Examples: docker run hookdeck/outpost serve
6+
# docker run hookdeck/outpost migrate plan
7+
# docker run hookdeck/outpost --version
8+
# docker run hookdeck/outpost --help
9+
if [ "$#" -gt 0 ]; then
10+
exec /usr/local/bin/outpost "$@"
11+
fi
12+
13+
# Default behavior when no args: check migrations, then start server
14+
15+
echo "Checking database migrations..."
16+
if ! /usr/local/bin/outpost migrate init --current --log-format=json; then
17+
echo ""
18+
echo "ERROR: Database migrations are pending."
19+
echo "Please run migrations before starting the server:"
20+
echo " docker run --rm -it hookdeck/outpost migrate apply"
21+
echo ""
22+
echo "For help with migration commands and configuration:"
23+
echo " docker run --rm hookdeck/outpost migrate --help"
24+
echo ""
25+
echo "Learn more about Outpost migration workflow at:"
26+
echo " https://outpost.hookdeck.com/docs/guides/migration"
27+
echo ""
28+
exit 1
29+
fi
30+
31+
echo "Starting Outpost server..."
32+
exec /usr/local/bin/outpost serve

0 commit comments

Comments
 (0)