Skip to content

Commit 9f43529

Browse files
committed
support loading options from config file
Signed-off-by: Wei Liu <liuweixa@redhat.com>
1 parent 422b238 commit 9f43529

2 files changed

Lines changed: 209 additions & 16 deletions

File tree

pkg/cloudevents/server/grpc/options/options.go

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,44 @@
11
package options
22

33
import (
4-
"github.com/spf13/pflag"
54
"math"
5+
"os"
66
"time"
7+
8+
"github.com/spf13/pflag"
9+
"gopkg.in/yaml.v2"
710
)
811

912
type GRPCServerOptions struct {
10-
TLSCertFile string
11-
TLSKeyFile string
12-
ClientCAFile string
13-
ServerBindPort string
14-
MaxConcurrentStreams uint32
15-
MaxReceiveMessageSize int
16-
MaxSendMessageSize int
17-
ConnectionTimeout time.Duration
18-
WriteBufferSize int
19-
ReadBufferSize int
20-
MaxConnectionAge time.Duration
21-
ClientMinPingInterval time.Duration
22-
ServerPingInterval time.Duration
23-
ServerPingTimeout time.Duration
24-
PermitPingWithoutStream bool
13+
TLSCertFile string `json:"tls_cert_file" yaml:"tls_cert_file"`
14+
TLSKeyFile string `json:"tls_key_file" yaml:"tls_key_file"`
15+
ClientCAFile string `json:"client_ca_file" yaml:"client_ca_file"`
16+
ServerBindPort string `json:"server_bind_port" yaml:"server_bind_port"`
17+
MaxConcurrentStreams uint32 `json:"max_concurrent_streams" yaml:"max_concurrent_streams"`
18+
MaxReceiveMessageSize int `json:"max_receive_message_size" yaml:"max_receive_message_size"`
19+
MaxSendMessageSize int `json:"max_send_message_size" yaml:"max_send_message_size"`
20+
WriteBufferSize int `json:"write_buffer_size" yaml:"write_buffer_size"`
21+
ReadBufferSize int `json:"read_buffer_size" yaml:"read_buffer_size"`
22+
ConnectionTimeout time.Duration `json:"connection_timeout" yaml:"connection_timeout"`
23+
MaxConnectionAge time.Duration `json:"max_connection_age" yaml:"max_connection_age"`
24+
ClientMinPingInterval time.Duration `json:"client_min_ping_interval" yaml:"client_min_ping_interval"`
25+
ServerPingInterval time.Duration `json:"server_ping_interval" yaml:"server_ping_interval"`
26+
ServerPingTimeout time.Duration `json:"server_ping_timeout" yaml:"server_ping_timeout"`
27+
PermitPingWithoutStream bool `json:"permit_ping_without_stream" yaml:"permit_ping_without_stream"`
28+
}
29+
30+
func LoadGRPCServerOptions(configPath string) (*GRPCServerOptions, error) {
31+
opts := NewGRPCServerOptions()
32+
grpcServerConfig, err := os.ReadFile(configPath)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
if err := yaml.Unmarshal(grpcServerConfig, opts); err != nil {
38+
return nil, err
39+
}
40+
41+
return opts, nil
2542
}
2643

2744
func NewGRPCServerOptions() *GRPCServerOptions {
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package options
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
"time"
8+
9+
"github.com/google/go-cmp/cmp"
10+
)
11+
12+
func TestLoadGRPCServerOptions(t *testing.T) {
13+
defaultOpts := NewGRPCServerOptions()
14+
15+
testCases := []struct {
16+
name string
17+
setup func(t *testing.T) string
18+
expectedOpts *GRPCServerOptions
19+
expectErr bool
20+
checkDefaults bool
21+
}{
22+
{
23+
name: "Successful load with all options",
24+
setup: func(t *testing.T) string {
25+
content := `
26+
tls_cert_file: /test/tls.crt
27+
tls_key_file: /test/tls.key
28+
client_ca_file: /test/ca.crt
29+
server_bind_port: "9999"
30+
max_concurrent_streams: 100
31+
max_receive_message_size: 2048
32+
max_send_message_size: 2048
33+
write_buffer_size: 1024
34+
read_buffer_size: 1024
35+
connection_timeout: 60s
36+
max_connection_age: 1h
37+
client_min_ping_interval: 10s
38+
server_ping_interval: 60s
39+
server_ping_timeout: 20s
40+
permit_ping_without_stream: true
41+
`
42+
tmpFile, err := os.CreateTemp(t.TempDir(), "config-*.yaml")
43+
if err != nil {
44+
t.Fatalf("Failed to create temp file: %v", err)
45+
}
46+
if _, err := tmpFile.Write([]byte(content)); err != nil {
47+
t.Fatalf("Failed to write to temp file: %v", err)
48+
}
49+
tmpFile.Close()
50+
return tmpFile.Name()
51+
},
52+
expectedOpts: &GRPCServerOptions{
53+
TLSCertFile: "/test/tls.crt",
54+
TLSKeyFile: "/test/tls.key",
55+
ClientCAFile: "/test/ca.crt",
56+
ServerBindPort: "9999",
57+
MaxConcurrentStreams: 100,
58+
MaxReceiveMessageSize: 2048,
59+
MaxSendMessageSize: 2048,
60+
WriteBufferSize: 1024,
61+
ReadBufferSize: 1024,
62+
ConnectionTimeout: 60 * time.Second,
63+
MaxConnectionAge: 1 * time.Hour,
64+
ClientMinPingInterval: 10 * time.Second,
65+
ServerPingInterval: 60 * time.Second,
66+
ServerPingTimeout: 20 * time.Second,
67+
PermitPingWithoutStream: true,
68+
},
69+
expectErr: false,
70+
},
71+
{
72+
name: "File not found",
73+
setup: func(t *testing.T) string {
74+
return filepath.Join(t.TempDir(), "non-existent-file.yaml")
75+
},
76+
expectedOpts: nil,
77+
expectErr: true,
78+
},
79+
{
80+
name: "Invalid YAML content",
81+
setup: func(t *testing.T) string {
82+
content := "this: is: not: valid: yaml"
83+
tmpFile, err := os.CreateTemp(t.TempDir(), "invalid-*.yaml")
84+
if err != nil {
85+
t.Fatalf("Failed to create temp file: %v", err)
86+
}
87+
if _, err := tmpFile.Write([]byte(content)); err != nil {
88+
t.Fatalf("Failed to write to temp file: %v", err)
89+
}
90+
tmpFile.Close()
91+
return tmpFile.Name()
92+
},
93+
expectedOpts: nil,
94+
expectErr: true,
95+
},
96+
{
97+
name: "Empty config file",
98+
setup: func(t *testing.T) string {
99+
tmpFile, err := os.CreateTemp(t.TempDir(), "empty-*.yaml")
100+
if err != nil {
101+
t.Fatalf("Failed to create temp file: %v", err)
102+
}
103+
tmpFile.Close()
104+
return tmpFile.Name()
105+
},
106+
expectedOpts: defaultOpts,
107+
expectErr: false,
108+
checkDefaults: true,
109+
},
110+
{
111+
name: "Partial config file",
112+
setup: func(t *testing.T) string {
113+
content := `
114+
server_bind_port: "8888"
115+
connection_timeout: 90s
116+
`
117+
tmpFile, err := os.CreateTemp(t.TempDir(), "partial-*.yaml")
118+
if err != nil {
119+
t.Fatalf("Failed to create temp file: %v", err)
120+
}
121+
if _, err := tmpFile.Write([]byte(content)); err != nil {
122+
t.Fatalf("Failed to write to temp file: %v", err)
123+
}
124+
tmpFile.Close()
125+
return tmpFile.Name()
126+
},
127+
expectedOpts: &GRPCServerOptions{
128+
ServerBindPort: "8888",
129+
MaxConcurrentStreams: defaultOpts.MaxConcurrentStreams,
130+
MaxReceiveMessageSize: defaultOpts.MaxReceiveMessageSize,
131+
MaxSendMessageSize: defaultOpts.MaxSendMessageSize,
132+
WriteBufferSize: defaultOpts.WriteBufferSize,
133+
ReadBufferSize: defaultOpts.ReadBufferSize,
134+
ConnectionTimeout: 90 * time.Second,
135+
MaxConnectionAge: defaultOpts.MaxConnectionAge,
136+
ClientMinPingInterval: defaultOpts.ClientMinPingInterval,
137+
ServerPingInterval: defaultOpts.ServerPingInterval,
138+
ServerPingTimeout: defaultOpts.ServerPingTimeout,
139+
PermitPingWithoutStream: false, // a bool's zero value is false
140+
},
141+
expectErr: false,
142+
},
143+
}
144+
145+
for _, tc := range testCases {
146+
t.Run(tc.name, func(t *testing.T) {
147+
configPath := tc.setup(t)
148+
149+
opts, err := LoadGRPCServerOptions(configPath)
150+
151+
if tc.expectErr {
152+
if err == nil {
153+
t.Errorf("Expected an error, but got none")
154+
}
155+
if opts != nil {
156+
t.Errorf("Expected nil options on error, but got %+v", opts)
157+
}
158+
return
159+
}
160+
161+
if err != nil {
162+
t.Fatalf("Unexpected error: %v", err)
163+
}
164+
165+
if !cmp.Equal(opts, tc.expectedOpts) {
166+
t.Errorf("Loaded options do not match expected options.\nGot: %+v\nWant:%+v", opts, tc.expectedOpts)
167+
}
168+
169+
if tc.checkDefaults {
170+
if !cmp.Equal(opts, defaultOpts) {
171+
t.Errorf("Expected default options, but got different values.\nGot: %+v\nWant:%+v", opts, defaultOpts)
172+
}
173+
}
174+
})
175+
}
176+
}

0 commit comments

Comments
 (0)