Skip to content

Commit af2e79e

Browse files
pranavsriram8YashwantGohokar
authored andcommitted
Support for gRPC Protocol on OKE managed LB and add e2e test case
1 parent 8b508ed commit af2e79e

File tree

4 files changed

+413
-3
lines changed

4 files changed

+413
-3
lines changed

pkg/cloudprovider/providers/oci/load_balancer_spec.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ const (
246246
ServiceAnnotationNetworkLoadBalancerIsPpv2Enabled = "oci-network-load-balancer.oraclecloud.com/is-ppv2-enabled"
247247
)
248248

249+
const (
250+
ProtocolGrpc = "GRPC"
251+
DefaultCipherSuiteForGRPC = "oci-default-http2-ssl-cipher-suite-v1"
252+
)
253+
249254
// certificateData is a structure containing the data about a K8S secret required
250255
// to store SSL information required for BackendSets and Listeners
251256
type certificateData struct {
@@ -1032,10 +1037,10 @@ func getListenersOciLoadBalancer(svc *v1.Service, sslCfg *SSLConfig) (map[string
10321037
if p == "" {
10331038
p = DefaultLoadBalancerBEProtocol
10341039
}
1035-
if strings.EqualFold(p, "HTTP") || strings.EqualFold(p, "TCP") {
1040+
if strings.EqualFold(p, "HTTP") || strings.EqualFold(p, "TCP") || strings.EqualFold(p, "GRPC") {
10361041
protocol = p
10371042
} else {
1038-
return nil, fmt.Errorf("invalid backend protocol %q requested for load balancer listener. Only 'HTTP' and 'TCP' protocols supported", p)
1043+
return nil, fmt.Errorf("invalid backend protocol %q requested for load balancer listener. Only 'HTTP', 'TCP' and 'GRPC' protocols supported", p)
10391044
}
10401045
}
10411046
port := int(servicePort.Port)
@@ -1051,6 +1056,15 @@ func getListenersOciLoadBalancer(svc *v1.Service, sslCfg *SSLConfig) (map[string
10511056
return nil, err
10521057
}
10531058
}
1059+
if strings.EqualFold(protocol, "GRPC") {
1060+
protocol = ProtocolGrpc
1061+
if sslConfiguration == nil {
1062+
return nil, fmt.Errorf("SSL configuration cannot be empty for GRPC protocol")
1063+
}
1064+
if sslConfiguration.CipherSuiteName == nil {
1065+
sslConfiguration.CipherSuiteName = common.String(DefaultCipherSuiteForGRPC)
1066+
}
1067+
}
10541068
name := getListenerName(protocol, port)
10551069

10561070
listener := client.GenericListener{

pkg/cloudprovider/providers/oci/load_balancer_spec_test.go

Lines changed: 283 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4543,6 +4543,162 @@ func TestNewLBSpecSuccess(t *testing.T) {
45434543
},
45444544
},
45454545
},
4546+
"GRPC listeners": {
4547+
defaultSubnetOne: "one",
4548+
defaultSubnetTwo: "two",
4549+
IpVersions: &IpVersions{
4550+
IpFamilies: []string{IPv4},
4551+
IpFamilyPolicy: common.String(string(v1.IPFamilyPolicySingleStack)),
4552+
LbEndpointIpVersion: GenericIpVersion(client.GenericIPv4),
4553+
ListenerBackendIpVersion: []client.GenericIpVersion{client.GenericIPv4},
4554+
},
4555+
nodes: []*v1.Node{
4556+
{
4557+
TypeMeta: metav1.TypeMeta{},
4558+
ObjectMeta: metav1.ObjectMeta{},
4559+
Spec: v1.NodeSpec{
4560+
ProviderID: testNodeString,
4561+
},
4562+
Status: v1.NodeStatus{
4563+
Capacity: nil,
4564+
Allocatable: nil,
4565+
Phase: "",
4566+
Conditions: nil,
4567+
Addresses: []v1.NodeAddress{
4568+
{
4569+
Address: "0.0.0.0",
4570+
Type: "InternalIP",
4571+
},
4572+
},
4573+
DaemonEndpoints: v1.NodeDaemonEndpoints{},
4574+
NodeInfo: v1.NodeSystemInfo{},
4575+
Images: nil,
4576+
VolumesInUse: nil,
4577+
VolumesAttached: nil,
4578+
Config: nil,
4579+
},
4580+
},
4581+
},
4582+
service: &v1.Service{
4583+
ObjectMeta: metav1.ObjectMeta{
4584+
Namespace: "kube-system",
4585+
Name: "testservice",
4586+
UID: "test-uid",
4587+
Annotations: map[string]string{
4588+
ServiceAnnotationLoadBalancerBEProtocol: "GRPC",
4589+
},
4590+
},
4591+
Spec: v1.ServiceSpec{
4592+
IPFamilies: []v1.IPFamily{v1.IPFamily(IPv4)},
4593+
SessionAffinity: v1.ServiceAffinityNone,
4594+
Ports: []v1.ServicePort{
4595+
{
4596+
Protocol: v1.ProtocolTCP,
4597+
Port: int32(443),
4598+
},
4599+
},
4600+
},
4601+
},
4602+
expected: &LBSpec{
4603+
Name: "test-uid",
4604+
Type: "lb",
4605+
Shape: "100Mbps",
4606+
Internal: false,
4607+
Subnets: []string{"one", "two"},
4608+
Listeners: map[string]client.GenericListener{
4609+
fmt.Sprintf("GRPC-443"): {
4610+
Name: common.String("GRPC-443"),
4611+
DefaultBackendSetName: common.String("TCP-443"),
4612+
Port: common.Int(443),
4613+
Protocol: common.String("GRPC"),
4614+
SslConfiguration: &client.GenericSslConfigurationDetails{
4615+
CertificateName: &listenerSecret,
4616+
VerifyDepth: common.Int(0),
4617+
VerifyPeerCertificate: common.Bool(false),
4618+
CipherSuiteName: common.String(DefaultCipherSuiteForGRPC),
4619+
},
4620+
},
4621+
},
4622+
BackendSets: map[string]client.GenericBackendSetDetails{
4623+
"TCP-443": {
4624+
Name: common.String("TCP-443"),
4625+
Backends: []client.GenericBackend{{IpAddress: common.String("0.0.0.0"), Port: common.Int(0), Weight: common.Int(1), TargetId: &testNodeString}},
4626+
HealthChecker: &client.GenericHealthChecker{
4627+
Protocol: "HTTP",
4628+
IsForcePlainText: common.Bool(false),
4629+
Port: common.Int(10256),
4630+
UrlPath: common.String("/healthz"),
4631+
Retries: common.Int(3),
4632+
TimeoutInMillis: common.Int(3000),
4633+
IntervalInMillis: common.Int(10000),
4634+
ReturnCode: common.Int(http.StatusOK),
4635+
},
4636+
IsPreserveSource: common.Bool(false),
4637+
Policy: common.String("ROUND_ROBIN"),
4638+
SslConfiguration: &client.GenericSslConfigurationDetails{
4639+
CertificateName: &backendSecret,
4640+
VerifyDepth: common.Int(0),
4641+
VerifyPeerCertificate: common.Bool(false),
4642+
},
4643+
IpVersion: GenericIpVersion(client.GenericIPv4),
4644+
},
4645+
},
4646+
IsPreserveSource: common.Bool(false),
4647+
NetworkSecurityGroupIds: []string{},
4648+
SourceCIDRs: []string{"0.0.0.0/0"},
4649+
Ports: map[string]portSpec{
4650+
"TCP-443": {
4651+
ListenerPort: 443,
4652+
HealthCheckerPort: 10256,
4653+
},
4654+
},
4655+
securityListManager: newSecurityListManagerNOOP(),
4656+
SSLConfig: &SSLConfig{
4657+
Ports: sets.NewInt(443),
4658+
ListenerSSLSecretName: listenerSecret,
4659+
BackendSetSSLSecretName: backendSecret,
4660+
},
4661+
ManagedNetworkSecurityGroup: &ManagedNetworkSecurityGroup{frontendNsgId: "", backendNsgId: []string{}, nsgRuleManagementMode: ManagementModeNone},
4662+
IpVersions: &IpVersions{
4663+
IpFamilies: []string{IPv4},
4664+
IpFamilyPolicy: common.String(string(v1.IPFamilyPolicySingleStack)),
4665+
LbEndpointIpVersion: GenericIpVersion(client.GenericIPv4),
4666+
ListenerBackendIpVersion: []client.GenericIpVersion{client.GenericIPv4},
4667+
},
4668+
nodes: []*v1.Node{
4669+
{
4670+
TypeMeta: metav1.TypeMeta{},
4671+
ObjectMeta: metav1.ObjectMeta{},
4672+
Spec: v1.NodeSpec{
4673+
ProviderID: testNodeString,
4674+
},
4675+
Status: v1.NodeStatus{
4676+
Capacity: nil,
4677+
Allocatable: nil,
4678+
Phase: "",
4679+
Conditions: nil,
4680+
Addresses: []v1.NodeAddress{
4681+
{
4682+
Address: "0.0.0.0",
4683+
Type: "InternalIP",
4684+
},
4685+
},
4686+
DaemonEndpoints: v1.NodeDaemonEndpoints{},
4687+
NodeInfo: v1.NodeSystemInfo{},
4688+
Images: nil,
4689+
VolumesInUse: nil,
4690+
VolumesAttached: nil,
4691+
Config: nil,
4692+
},
4693+
},
4694+
},
4695+
},
4696+
sslConfig: &SSLConfig{
4697+
Ports: sets.NewInt(443),
4698+
ListenerSSLSecretName: listenerSecret,
4699+
BackendSetSSLSecretName: backendSecret,
4700+
},
4701+
},
45464702
}
45474703

45484704
cp := &CloudProvider{
@@ -4577,7 +4733,7 @@ func TestNewLBSpecSuccess(t *testing.T) {
45774733
if !reflect.DeepEqual(result, tc.expected) {
45784734
results, _ := json.Marshal(result)
45794735
expected, _ := json.Marshal(tc.expected)
4580-
t.Errorf("Expected load balancer spec failed want: %s \n got: %s \n", expected, results)
4736+
t.Errorf("Expected load balancer spec failed\nExpected: %s\nResults: %s\n", expected, results)
45814737
}
45824738
})
45834739
}
@@ -8291,6 +8447,132 @@ func Test_getListeners(t *testing.T) {
82918447
},
82928448
},
82938449
},
8450+
{
8451+
name: "grpc protocol no ssl",
8452+
service: &v1.Service{
8453+
Spec: v1.ServiceSpec{
8454+
Ports: []v1.ServicePort{
8455+
{
8456+
Protocol: v1.Protocol("GRPC"),
8457+
Port: int32(80),
8458+
},
8459+
},
8460+
},
8461+
ObjectMeta: metav1.ObjectMeta{
8462+
Annotations: map[string]string{},
8463+
},
8464+
},
8465+
sslConfig: nil,
8466+
listenerBackendIpVersion: []string{IPv4},
8467+
want: nil,
8468+
},
8469+
{
8470+
name: "grpc protocol with ssl configuration and smart default cipher suite",
8471+
service: &v1.Service{
8472+
Spec: v1.ServiceSpec{
8473+
Ports: []v1.ServicePort{
8474+
{
8475+
Protocol: v1.Protocol("TCP"),
8476+
Port: int32(443),
8477+
},
8478+
},
8479+
},
8480+
ObjectMeta: metav1.ObjectMeta{
8481+
Annotations: map[string]string{
8482+
ServiceAnnotationLoadBalancerBEProtocol: ProtocolGrpc,
8483+
},
8484+
},
8485+
},
8486+
listenerBackendIpVersion: []string{IPv4},
8487+
sslConfig: &SSLConfig{
8488+
Ports: sets.NewInt(443),
8489+
ListenerSSLSecretName: listenerSecret,
8490+
BackendSetSSLSecretName: backendSecret,
8491+
},
8492+
want: map[string]client.GenericListener{
8493+
"GRPC-443": {
8494+
Name: common.String("GRPC-443"),
8495+
Port: common.Int(443),
8496+
Protocol: common.String("GRPC"),
8497+
DefaultBackendSetName: common.String("TCP-443"),
8498+
SslConfiguration: &client.GenericSslConfigurationDetails{
8499+
CertificateName: &listenerSecret,
8500+
VerifyDepth: common.Int(0),
8501+
VerifyPeerCertificate: common.Bool(false),
8502+
CipherSuiteName: common.String(DefaultCipherSuiteForGRPC),
8503+
},
8504+
},
8505+
},
8506+
},
8507+
{
8508+
name: "grpc protocol with ssl configuration and cipher suite",
8509+
service: &v1.Service{
8510+
Spec: v1.ServiceSpec{
8511+
Ports: []v1.ServicePort{
8512+
{
8513+
Protocol: v1.Protocol("TCP"),
8514+
Port: int32(443),
8515+
},
8516+
},
8517+
},
8518+
ObjectMeta: metav1.ObjectMeta{
8519+
Annotations: map[string]string{
8520+
ServiceAnnotationLoadBalancerBEProtocol: ProtocolGrpc,
8521+
ServiceAnnotationLoadbalancerListenerSSLConfig: `{"cipherSuiteName":"oci-default-http2-ssl-cipher-suite-v1", "protocols":["TLSv1.2"]}`,
8522+
ServiceAnnotationLoadBalancerSSLPorts: "443",
8523+
},
8524+
},
8525+
},
8526+
listenerBackendIpVersion: []string{IPv4},
8527+
sslConfig: &SSLConfig{
8528+
Ports: sets.NewInt(443),
8529+
ListenerSSLSecretName: listenerSecret,
8530+
BackendSetSSLSecretName: backendSecret,
8531+
},
8532+
want: map[string]client.GenericListener{
8533+
"GRPC-443": {
8534+
Name: common.String("GRPC-443"),
8535+
Port: common.Int(443),
8536+
Protocol: common.String("GRPC"),
8537+
DefaultBackendSetName: common.String("TCP-443"),
8538+
SslConfiguration: &client.GenericSslConfigurationDetails{
8539+
CertificateName: &listenerSecret,
8540+
VerifyDepth: common.Int(0),
8541+
VerifyPeerCertificate: common.Bool(false),
8542+
CipherSuiteName: common.String("oci-default-http2-ssl-cipher-suite-v1"),
8543+
Protocols: []string{"TLSv1.2"},
8544+
},
8545+
},
8546+
},
8547+
},
8548+
{
8549+
name: "Listeners with cipher suites",
8550+
service: &v1.Service{
8551+
Spec: v1.ServiceSpec{
8552+
Ports: []v1.ServicePort{
8553+
{
8554+
Protocol: v1.ProtocolTCP,
8555+
Port: int32(80),
8556+
},
8557+
},
8558+
},
8559+
ObjectMeta: metav1.ObjectMeta{
8560+
Annotations: map[string]string{
8561+
ServiceAnnotationLoadbalancerListenerSSLConfig: `{"cipherSuiteName":"oci-default-http2-ssl-cipher-suite-v1", "protocols":["TLSv1.2"]}`,
8562+
},
8563+
},
8564+
},
8565+
listenerBackendIpVersion: []string{IPv4},
8566+
sslConfig: nil,
8567+
want: map[string]client.GenericListener{
8568+
"TCP-80": {
8569+
Name: common.String("TCP-80"),
8570+
Port: common.Int(80),
8571+
Protocol: common.String("TCP"),
8572+
DefaultBackendSetName: common.String("TCP-80"),
8573+
},
8574+
},
8575+
},
82948576
}
82958577
for _, tt := range tests {
82968578
t.Run(tt.name, func(t *testing.T) {

pkg/cloudprovider/providers/oci/load_balancer_util_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,22 @@ func TestHasListenerChanged(t *testing.T) {
15551555

15561556
expected: false,
15571557
},
1558+
{
1559+
name: "GRPC protocol",
1560+
desired: client.GenericListener{
1561+
Name: common.String("TCP-443"),
1562+
DefaultBackendSetName: common.String("TCP-443"),
1563+
Port: common.Int(443),
1564+
Protocol: common.String("TCP"),
1565+
},
1566+
actual: client.GenericListener{
1567+
Name: common.String("GRPC-443"),
1568+
DefaultBackendSetName: common.String("TCP-443"),
1569+
Port: common.Int(443),
1570+
Protocol: common.String("GRPC"),
1571+
},
1572+
expected: true,
1573+
},
15581574
}
15591575

15601576
for _, tt := range testCases {

0 commit comments

Comments
 (0)