Add L7 and PROXY protocol fields to gRPC API and CLI

Proto: Route message gains mode, tls_cert, tls_key, backend_tls,
send_proxy_protocol fields. ListenerStatus gains proxy_protocol.
Generated code regenerated with protoc v29.5.

gRPC server: AddRoute validates mode ("l4"/"l7", defaults to "l4"),
requires tls_cert/tls_key for L7 routes, persists all fields via
write-through. ListRoutes returns full route info. GetStatus
includes proxy_protocol on listener status.

Client package: Route struct expanded with Mode, TLSCert, TLSKey,
BackendTLS, SendProxyProtocol. AddRoute signature changed to accept
a Route struct instead of individual hostname/backend strings.
ListenerStatus gains ProxyProtocol. ListRoutes maps all proto fields.

mcproxyctl: routes add gains --mode, --tls-cert, --tls-key,
--backend-tls, --send-proxy-protocol flags. routes list displays
mode and option tags for each route.

New tests: add L7 route via gRPC with field round-trip verification,
L7 route missing cert/key (InvalidArgument), invalid mode rejection,
default-to-L4 backward compatibility, proxy_protocol in status.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 13:55:43 -07:00
parent 97909b7fbc
commit 498f040cbe
9 changed files with 341 additions and 35 deletions

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v5.29.5
// source: proto/mc_proxy/v1/admin.proto
package mcproxyv1
@@ -75,11 +75,16 @@ func (FirewallRuleType) EnumDescriptor() ([]byte, []int) {
}
type Route struct {
state protoimpl.MessageState `protogen:"open.v1"`
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
Backend string `protobuf:"bytes,2,opt,name=backend,proto3" json:"backend,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
Backend string `protobuf:"bytes,2,opt,name=backend,proto3" json:"backend,omitempty"`
Mode string `protobuf:"bytes,3,opt,name=mode,proto3" json:"mode,omitempty"` // "l4" (default) or "l7"
TlsCert string `protobuf:"bytes,4,opt,name=tls_cert,json=tlsCert,proto3" json:"tls_cert,omitempty"` // PEM certificate path (L7 only)
TlsKey string `protobuf:"bytes,5,opt,name=tls_key,json=tlsKey,proto3" json:"tls_key,omitempty"` // PEM private key path (L7 only)
BackendTls bool `protobuf:"varint,6,opt,name=backend_tls,json=backendTls,proto3" json:"backend_tls,omitempty"` // re-encrypt to backend (L7 only)
SendProxyProtocol bool `protobuf:"varint,7,opt,name=send_proxy_protocol,json=sendProxyProtocol,proto3" json:"send_proxy_protocol,omitempty"` // send PROXY v2 header to backend
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Route) Reset() {
@@ -126,6 +131,41 @@ func (x *Route) GetBackend() string {
return ""
}
func (x *Route) GetMode() string {
if x != nil {
return x.Mode
}
return ""
}
func (x *Route) GetTlsCert() string {
if x != nil {
return x.TlsCert
}
return ""
}
func (x *Route) GetTlsKey() string {
if x != nil {
return x.TlsKey
}
return ""
}
func (x *Route) GetBackendTls() bool {
if x != nil {
return x.BackendTls
}
return false
}
func (x *Route) GetSendProxyProtocol() bool {
if x != nil {
return x.SendProxyProtocol
}
return false
}
type ListRoutesRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
ListenerAddr string `protobuf:"bytes,1,opt,name=listener_addr,json=listenerAddr,proto3" json:"listener_addr,omitempty"`
@@ -695,6 +735,7 @@ type ListenerStatus struct {
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
RouteCount int32 `protobuf:"varint,2,opt,name=route_count,json=routeCount,proto3" json:"route_count,omitempty"`
ActiveConnections int64 `protobuf:"varint,3,opt,name=active_connections,json=activeConnections,proto3" json:"active_connections,omitempty"`
ProxyProtocol bool `protobuf:"varint,4,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -750,6 +791,13 @@ func (x *ListenerStatus) GetActiveConnections() int64 {
return 0
}
func (x *ListenerStatus) GetProxyProtocol() bool {
if x != nil {
return x.ProxyProtocol
}
return false
}
type GetStatusRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
@@ -858,10 +906,16 @@ var File_proto_mc_proxy_v1_admin_proto protoreflect.FileDescriptor
const file_proto_mc_proxy_v1_admin_proto_rawDesc = "" +
"\n" +
"\x1dproto/mc_proxy/v1/admin.proto\x12\vmc_proxy.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"=\n" +
"\x1dproto/mc_proxy/v1/admin.proto\x12\vmc_proxy.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd6\x01\n" +
"\x05Route\x12\x1a\n" +
"\bhostname\x18\x01 \x01(\tR\bhostname\x12\x18\n" +
"\abackend\x18\x02 \x01(\tR\abackend\"8\n" +
"\abackend\x18\x02 \x01(\tR\abackend\x12\x12\n" +
"\x04mode\x18\x03 \x01(\tR\x04mode\x12\x19\n" +
"\btls_cert\x18\x04 \x01(\tR\atlsCert\x12\x17\n" +
"\atls_key\x18\x05 \x01(\tR\x06tlsKey\x12\x1f\n" +
"\vbackend_tls\x18\x06 \x01(\bR\n" +
"backendTls\x12.\n" +
"\x13send_proxy_protocol\x18\a \x01(\bR\x11sendProxyProtocol\"8\n" +
"\x11ListRoutesRequest\x12#\n" +
"\rlistener_addr\x18\x01 \x01(\tR\flistenerAddr\"e\n" +
"\x12ListRoutesResponse\x12#\n" +
@@ -886,12 +940,13 @@ const file_proto_mc_proxy_v1_admin_proto_rawDesc = "" +
"\x17AddFirewallRuleResponse\"J\n" +
"\x19RemoveFirewallRuleRequest\x12-\n" +
"\x04rule\x18\x01 \x01(\v2\x19.mc_proxy.v1.FirewallRuleR\x04rule\"\x1c\n" +
"\x1aRemoveFirewallRuleResponse\"t\n" +
"\x1aRemoveFirewallRuleResponse\"\x9b\x01\n" +
"\x0eListenerStatus\x12\x12\n" +
"\x04addr\x18\x01 \x01(\tR\x04addr\x12\x1f\n" +
"\vroute_count\x18\x02 \x01(\x05R\n" +
"routeCount\x12-\n" +
"\x12active_connections\x18\x03 \x01(\x03R\x11activeConnections\"\x12\n" +
"\x12active_connections\x18\x03 \x01(\x03R\x11activeConnections\x12%\n" +
"\x0eproxy_protocol\x18\x04 \x01(\bR\rproxyProtocol\"\x12\n" +
"\x10GetStatusRequest\"\xd0\x01\n" +
"\x11GetStatusResponse\x12\x18\n" +
"\aversion\x18\x01 \x01(\tR\aversion\x129\n" +