Skip to content

Commit dd5d6ff

Browse files
authored
chore: enable grpc reflection for config-manager reconfigure service (#10084)
1 parent d444fef commit dd5d6ff

2 files changed

Lines changed: 106 additions & 0 deletions

File tree

cmd/reloader/app/cmd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"go.uber.org/zap"
3434
"go.uber.org/zap/zapcore"
3535
"google.golang.org/grpc"
36+
"google.golang.org/grpc/reflection"
3637

3738
cfgcm "github.com/apecloud/kubeblocks/pkg/parameters/configmanager"
3839
cfgutil "github.com/apecloud/kubeblocks/pkg/parameters/core"
@@ -119,6 +120,7 @@ func startGRPCService(opts *serviceOptions, handler cfgcm.ConfigHandler) error {
119120

120121
server = grpc.NewServer(grpc.UnaryInterceptor(logUnaryServerInterceptor))
121122
cfgproto.RegisterReconfigureServer(server, proxy)
123+
reflection.Register(server)
122124

123125
go func() {
124126
if err := server.Serve(listener); err != nil {

cmd/reloader/app/cmd_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
Copyright (C) 2022-2025 ApeCloud Co., Ltd
3+
4+
This file is part of KubeBlocks project
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License as published by
8+
the Free Software Foundation, either version 3 of the License, or
9+
(at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Affero General Public License for more details.
15+
16+
You should have received a copy of the GNU Affero General Public License
17+
along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
package app
21+
22+
import (
23+
"context"
24+
"net"
25+
"strconv"
26+
"testing"
27+
"time"
28+
29+
"go.uber.org/zap"
30+
"google.golang.org/grpc"
31+
"google.golang.org/grpc/credentials/insecure"
32+
"google.golang.org/grpc/reflection/grpc_reflection_v1"
33+
34+
cfgcm "github.com/apecloud/kubeblocks/pkg/parameters/configmanager"
35+
)
36+
37+
type fakeConfigHandler struct{}
38+
39+
func (f *fakeConfigHandler) OnlineUpdate(context.Context, string, map[string]string) error {
40+
return nil
41+
}
42+
43+
func TestStartGRPCServiceEnablesReflection(t *testing.T) {
44+
t.Helper()
45+
46+
logger = zap.NewNop().Sugar()
47+
cfgcm.SetLogger(zap.NewNop())
48+
49+
listener, err := net.Listen("tcp", "127.0.0.1:0")
50+
if err != nil {
51+
t.Fatalf("failed to allocate port: %v", err)
52+
}
53+
port := listener.Addr().(*net.TCPAddr).Port
54+
_ = listener.Close()
55+
56+
opts := &serviceOptions{
57+
GrpcPort: port,
58+
PodIP: localhostAddress,
59+
}
60+
if err := startGRPCService(opts, &fakeConfigHandler{}); err != nil {
61+
t.Fatalf("failed to start grpc service: %v", err)
62+
}
63+
64+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
65+
defer cancel()
66+
67+
conn, err := grpc.DialContext(ctx, net.JoinHostPort(localhostAddress, strconv.Itoa(port)), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
68+
if err != nil {
69+
t.Fatalf("failed to dial grpc service: %v", err)
70+
}
71+
defer func() {
72+
_ = conn.Close()
73+
}()
74+
75+
client := grpc_reflection_v1.NewServerReflectionClient(conn)
76+
stream, err := client.ServerReflectionInfo(ctx)
77+
if err != nil {
78+
t.Fatalf("failed to create reflection stream: %v", err)
79+
}
80+
81+
if err := stream.Send(&grpc_reflection_v1.ServerReflectionRequest{
82+
MessageRequest: &grpc_reflection_v1.ServerReflectionRequest_ListServices{},
83+
}); err != nil {
84+
t.Fatalf("failed to send reflection request: %v", err)
85+
}
86+
87+
resp, err := stream.Recv()
88+
if err != nil {
89+
t.Fatalf("failed to receive reflection response: %v", err)
90+
}
91+
92+
servicesResp := resp.GetListServicesResponse()
93+
if servicesResp == nil {
94+
t.Fatalf("expected list services response, got: %T", resp.MessageResponse)
95+
}
96+
97+
serviceNames := map[string]bool{}
98+
for _, svc := range servicesResp.Service {
99+
serviceNames[svc.Name] = true
100+
}
101+
if !serviceNames["proto.Reconfigure"] {
102+
t.Fatalf("expected proto.Reconfigure service in reflection response, got: %v", serviceNames)
103+
}
104+
}

0 commit comments

Comments
 (0)