Skip to content

Commit 9f796d9

Browse files
author
Alexander Indenbaum
committed
Add build-time protobuf generation infrastructure
This commit implements build-time protobuf generation that automatically fetches .proto files from the ceph-nvmeof project and generates Go stubs before compilation begins. Changes: - Makefile: Added generate-proto target and build integration - scripts/Dockerfile.devel: Added protobuf-compiler and Go plugins - scripts/generate-proto.sh: Complete protobuf generation script Features: - Fetches gateway.proto from ceph-nvmeof repository - Generates Go stubs with proper protoc flags - Handles proto3 optional fields and go_package options - Integrated with Makefile build process - Works in both local and containerized environments The system ensures the Ceph-CSI project always has up-to-date protobuf definitions without version drift.
1 parent 1f2706f commit 9f796d9

File tree

3 files changed

+202
-5
lines changed

3 files changed

+202
-5
lines changed

Makefile

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,15 @@ commitlint:
168168
@test $(REBASE) -eq 0 || git -c user.name=commitlint -c user.email=commitline@localhost rebase FETCH_HEAD
169169
commitlint --verbose --from $(GIT_SINCE)
170170

171-
.PHONY: cephcsi
172-
cephcsi: check-env
171+
.PHONY: cephcsi generate-proto
172+
cephcsi: check-env generate-proto
173173
if [ ! -d ./vendor ]; then (go mod tidy && go mod vendor); fi
174174
GOOS=linux go build $(GO_TAGS) -mod vendor -a -ldflags '$(LDFLAGS)' -o _output/cephcsi ./cmd/
175175

176+
generate-proto: check-env
177+
@echo "Generating protobuf stubs..."
178+
./scripts/generate-proto.sh
179+
176180
e2e.test: check-env
177181
cd e2e && go test $(GO_TAGS) -mod=vendor -c -o ../e2e.test ./
178182

@@ -217,6 +221,9 @@ containerized-build: TARGET = cephcsi
217221
containerized-build: .container-cmd .devel-container-id
218222
$(CONTAINER_CMD) run --rm -v $(CURDIR):/go/src/github.com/ceph/ceph-csi$(SELINUX_VOL_FLAG) $(CSI_IMAGE_NAME):devel make $(TARGET) CONTAINERIZED=yes
219223

224+
containerized-generate-proto: .container-cmd .devel-container-id
225+
$(CONTAINER_CMD) run --rm -v $(CURDIR):/go/src/github.com/ceph/ceph-csi$(SELINUX_VOL_FLAG) $(CSI_IMAGE_NAME):devel make generate-proto CONTAINERIZED=yes
226+
220227
containerized-test: TARGET = test
221228
containerized-test: REBASE ?= 0
222229
containerized-test: .container-cmd .test-container-id
@@ -272,6 +279,8 @@ clean:
272279
rm -f _output/cephcsi
273280
$(RM) scripts/golangci.yml
274281
$(RM) e2e.test
282+
rm -rf internal/proto/generated
283+
rm -f internal/proto/*.proto
275284
[ ! -f .devel-container-id ] || $(CONTAINER_CMD) rmi $(CSI_IMAGE_NAME):devel
276285
$(RM) .devel-container-id
277286
[ ! -f .test-container-id ] || $(CONTAINER_CMD) rmi $(CSI_IMAGE_NAME):test

scripts/Dockerfile.devel

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,21 @@ RUN true \
2929

3030
RUN mkdir -p /etc/selinux && touch /etc/selinux/config
3131

32-
# other/conflicting versions of protobuf get installed as dependency
33-
RUN dnf -y remove protobuf
34-
3532
RUN dnf -y install \
3633
git \
3734
make \
3835
gcc \
3936
librados-devel \
4037
libcephfs-devel \
4138
librbd-devel \
39+
protobuf-compiler \
4240
&& dnf -y --nobest update \
4341
&& dnf clean all \
4442
&& rm -rf /var/cache/yum \
4543
&& true
4644

45+
# Install Go protobuf plugins
46+
RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest \
47+
&& go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
48+
4749
WORKDIR "/go/src/github.com/ceph/ceph-csi"

scripts/generate-proto.sh

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
#!/bin/bash
2+
3+
# Copyright 2025 The Ceph-CSI Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -e
18+
19+
# Script to fetch protobuf files from ceph-nvmeof project and generate Go stubs using protoc.
20+
21+
# Configuration
22+
CEPH_NVMEOF_REPO="https://github.com/ceph/ceph-nvmeof"
23+
CEPH_NVMEOF_BRANCH="devel"
24+
PROTO_DIR="internal/proto"
25+
PROTO_FILES=(
26+
"control/proto/gateway.proto"
27+
# Add more proto files as needed
28+
)
29+
30+
# Logging functions (plain text, no color)
31+
log_info() {
32+
echo "[INFO] $1"
33+
}
34+
35+
log_warn() {
36+
echo "[WARN] $1"
37+
}
38+
39+
log_error() {
40+
echo "[ERROR] $1"
41+
}
42+
43+
# Check if protoc is installed
44+
check_protoc() {
45+
if ! command -v protoc &> /dev/null; then
46+
log_error "protoc is not installed. Please install Protocol Buffers compiler."
47+
log_info "Installation instructions:"
48+
log_info " Ubuntu/Debian: sudo apt-get install protobuf-compiler"
49+
log_info " CentOS/RHEL: sudo yum install protobuf"
50+
log_info " macOS: brew install protobuf"
51+
exit 1
52+
fi
53+
54+
# Check protoc version
55+
PROTOC_VERSION=$(protoc --version | cut -d' ' -f2)
56+
log_info "Using protoc version: $PROTOC_VERSION"
57+
}
58+
59+
# Check if go is installed
60+
check_go() {
61+
if ! command -v go &> /dev/null; then
62+
log_error "go is not installed. Please install Go."
63+
exit 1
64+
fi
65+
66+
GO_VERSION=$(go version | cut -d' ' -f3)
67+
log_info "Using Go version: $GO_VERSION"
68+
69+
# Add Go bin directory to PATH if not already there
70+
if [[ ":$PATH:" != *":$GOPATH/bin:"* ]]; then
71+
export PATH="$GOPATH/bin:$PATH"
72+
log_info "Added $GOPATH/bin to PATH"
73+
fi
74+
}
75+
76+
# Create proto directory
77+
create_proto_dir() {
78+
if [ ! -d "$PROTO_DIR" ]; then
79+
log_info "Creating proto directory: $PROTO_DIR"
80+
mkdir -p "$PROTO_DIR"
81+
fi
82+
}
83+
84+
# Fetch proto file from ceph-nvmeof repository
85+
fetch_proto_file() {
86+
local proto_file="$1"
87+
local local_path="$PROTO_DIR/$(basename "$proto_file")"
88+
89+
log_info "Fetching $proto_file from $CEPH_NVMEOF_REPO..."
90+
91+
# Use the raw.githubusercontent.com URL directly
92+
local url="https://raw.githubusercontent.com/ceph/ceph-nvmeof/refs/heads/$CEPH_NVMEOF_BRANCH/$proto_file"
93+
94+
if curl -f -L -s -o "$local_path" "$url"; then
95+
log_info "Successfully fetched $proto_file"
96+
else
97+
log_error "Failed to fetch $proto_file from $url"
98+
return 1
99+
fi
100+
}
101+
102+
# Generate Go stubs from proto file
103+
generate_go_stubs() {
104+
local proto_file="$1"
105+
local local_path="$PROTO_DIR/$(basename "$proto_file")"
106+
107+
if [ ! -f "$local_path" ]; then
108+
log_error "Proto file not found: $local_path"
109+
return 1
110+
fi
111+
112+
log_info "Generating Go stubs from $local_path..."
113+
114+
# Create output directory for generated files
115+
local output_dir="$PROTO_DIR/generated"
116+
mkdir -p "$output_dir"
117+
118+
# Add go_package option if not present
119+
if ! grep -q "go_package" "$local_path"; then
120+
log_info "Adding go_package option to $local_path"
121+
# Add go_package option after the syntax line
122+
sed -i '/^syntax = "proto3";$/a option go_package = "github.com/ceph/ceph-csi/internal/proto/generated/gateway";' "$local_path"
123+
fi
124+
125+
# Generate Go stubs
126+
if protoc \
127+
--experimental_allow_proto3_optional \
128+
--go_out="$output_dir" \
129+
--go_opt=paths=source_relative \
130+
--go-grpc_out="$output_dir" \
131+
--go-grpc_opt=paths=source_relative \
132+
--proto_path="$PROTO_DIR" \
133+
"$local_path"; then
134+
log_info "Successfully generated Go stubs for $proto_file"
135+
else
136+
log_error "Failed to generate Go stubs for $proto_file"
137+
return 1
138+
fi
139+
}
140+
141+
# Clean up old generated files
142+
cleanup_old_files() {
143+
local output_dir="$PROTO_DIR/generated"
144+
if [ -d "$output_dir" ]; then
145+
log_info "Cleaning up old generated files..."
146+
rm -rf "$output_dir"
147+
fi
148+
}
149+
150+
# Main function
151+
main() {
152+
log_info "Starting protobuf generation process..."
153+
154+
# Check prerequisites
155+
check_protoc
156+
check_go
157+
158+
# Create proto directory
159+
create_proto_dir
160+
161+
# Clean up old files
162+
cleanup_old_files
163+
164+
# Process each proto file
165+
for proto_file in "${PROTO_FILES[@]}"; do
166+
log_info "Processing $proto_file..."
167+
168+
if fetch_proto_file "$proto_file"; then
169+
if generate_go_stubs "$proto_file"; then
170+
log_info "Successfully processed $proto_file"
171+
else
172+
log_error "Failed to generate stubs for $proto_file"
173+
exit 1
174+
fi
175+
else
176+
log_error "Failed to fetch $proto_file"
177+
exit 1
178+
fi
179+
done
180+
181+
log_info "Protobuf generation completed successfully!"
182+
log_info "Generated files are available in: $PROTO_DIR/generated"
183+
}
184+
185+
# Run main function
186+
main "$@"

0 commit comments

Comments
 (0)