Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expose GRPC conformance client as in interface #3095

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conformance/tests/grpcroute-exact-method-matching.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ var GRPCExactMethodMatching = suite.ConformanceTest{
tc := testCases[i]
t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
t.Parallel()
grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.TimeoutConfig, gwAddr, tc)
grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.GRPCClient, suite.TimeoutConfig, gwAddr, tc)
})
}
},
Expand Down
2 changes: 1 addition & 1 deletion conformance/tests/grpcroute-header-matching.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ var GRPCRouteHeaderMatching = suite.ConformanceTest{
tc := testCases[i]
t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
t.Parallel()
grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.TimeoutConfig, gwAddr, tc)
grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.GRPCClient, suite.TimeoutConfig, gwAddr, tc)
})
}
},
Expand Down
2 changes: 1 addition & 1 deletion conformance/tests/grpcroute-listener-hostname-matching.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ var GRPCRouteListenerHostnameMatching = suite.ConformanceTest{
tc := testCases[i]
t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
t.Parallel()
grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.TimeoutConfig, gwAddr, tc)
grpc.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.GRPCClient, suite.TimeoutConfig, gwAddr, tc)
})
}
},
Expand Down
45 changes: 26 additions & 19 deletions conformance/utils/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ const (
echoServerService = "GrpcEcho"
)

// Client is an interface used to make requests within conformance tests for grpc scenarios.
// This can be overridden with custom implementations whenever necessary.
type Client interface {
SendRPC(t *testing.T, address string, expected ExpectedResponse, timeout time.Duration) (*Response, error)
Close()
}

// DefaultClient is the default implementation of Client. It will
// be used if a custom implementation is not specified.
type DefaultClient struct {
Conn *grpc.ClientConn
}

type Response struct {
Code codes.Code
Headers *metadata.MD
Expand Down Expand Up @@ -136,19 +149,14 @@ func (er *ExpectedResponse) GetTestCaseName(i int) string {
return fmt.Sprintf("%s should receive a %s (%d)", reqStr, er.Response.Code.String(), er.Response.Code)
}

type client struct {
Conn *grpc.ClientConn
RequestMetadata *RequestMetadata
}

func (c *client) ensureConnection(address string) error {
func (c *DefaultClient) ensureConnection(address string, req *RequestMetadata) error {
if c.Conn != nil {
return nil
}
var err error
dialOpts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
if c.RequestMetadata != nil && c.RequestMetadata.Authority != "" {
dialOpts = append(dialOpts, grpc.WithAuthority(c.RequestMetadata.Authority))
if req != nil && req.Authority != "" {
dialOpts = append(dialOpts, grpc.WithAuthority(req.Authority))
}

c.Conn, err = grpc.Dial(address, dialOpts...)
Expand All @@ -159,17 +167,20 @@ func (c *client) ensureConnection(address string) error {
return nil
}

func (c *client) resetConnection() {
func (c *DefaultClient) resetConnection() {
if c.Conn == nil {
return
}
c.Conn.Close()
c.Conn = nil
}

func (c *client) SendRPC(t *testing.T, address string, expected ExpectedResponse, timeout time.Duration) (*Response, error) {
// SendRPC sends a gRPC request to the given address with the expected response.
// An error will be returned if there is an error running the function but not if an HTTP error status code
// is received.
func (c *DefaultClient) SendRPC(t *testing.T, address string, expected ExpectedResponse, timeout time.Duration) (*Response, error) {
t.Helper()
if err := c.ensureConnection(address); err != nil {
if err := c.ensureConnection(address, expected.RequestMetadata); err != nil {
return &Response{}, err
}

Expand All @@ -179,8 +190,8 @@ func (c *client) SendRPC(t *testing.T, address string, expected ExpectedResponse
}
ctx, cancel := context.WithTimeout(context.Background(), timeout)

if c.RequestMetadata != nil && len(c.RequestMetadata.Metadata) > 0 {
ctx = metadata.NewOutgoingContext(ctx, metadata.New(c.RequestMetadata.Metadata))
if expected.RequestMetadata != nil && len(expected.RequestMetadata.Metadata) > 0 {
ctx = metadata.NewOutgoingContext(ctx, metadata.New(expected.RequestMetadata.Metadata))
}

defer cancel()
Expand Down Expand Up @@ -215,7 +226,7 @@ func (c *client) SendRPC(t *testing.T, address string, expected ExpectedResponse
return resp, nil
}

func (c *client) Close() {
func (c *DefaultClient) Close() {
if c.Conn != nil {
c.Conn.Close()
}
Expand Down Expand Up @@ -256,13 +267,9 @@ func validateExpectedResponse(t *testing.T, expected ExpectedResponse) {
require.Equal(t, 1, requestTypeCount, "expected only one request type to be set, but found %d: %v", requestTypeCount, expected)
}

func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, timeoutConfig config.TimeoutConfig, gwAddr string, expected ExpectedResponse) {
func MakeRequestAndExpectEventuallyConsistentResponse(t *testing.T, c Client, timeoutConfig config.TimeoutConfig, gwAddr string, expected ExpectedResponse) {
t.Helper()
validateExpectedResponse(t, expected)
c := &client{
Conn: nil,
RequestMetadata: expected.RequestMetadata,
}
defer c.Close()
sendRPC := func(elapsed time.Duration) bool {
resp, err := c.SendRPC(t, gwAddr, expected, timeoutConfig.MaxTimeToConsistency-elapsed)
Expand Down
9 changes: 9 additions & 0 deletions conformance/utils/suite/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
confv1 "sigs.k8s.io/gateway-api/conformance/apis/v1"
"sigs.k8s.io/gateway-api/conformance/utils/config"
"sigs.k8s.io/gateway-api/conformance/utils/flags"
"sigs.k8s.io/gateway-api/conformance/utils/grpc"
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
"sigs.k8s.io/gateway-api/conformance/utils/roundtripper"
"sigs.k8s.io/gateway-api/conformance/utils/tlog"
Expand All @@ -59,6 +60,7 @@ type ConformanceTestSuite struct {
RESTClient *rest.RESTClient
RestConfig *rest.Config
RoundTripper roundtripper.RoundTripper
GRPCClient grpc.Client
GatewayClassName string
ControllerName string
Debug bool
Expand Down Expand Up @@ -125,6 +127,7 @@ type ConformanceOptions struct {
GatewayClassName string
Debug bool
RoundTripper roundtripper.RoundTripper
GRPCClient grpc.Client
BaseManifests string
MeshManifests string
NamespaceLabels map[string]string
Expand Down Expand Up @@ -189,6 +192,11 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite,
roundTripper = &roundtripper.DefaultRoundTripper{Debug: options.Debug, TimeoutConfig: options.TimeoutConfig}
}

grpcClient := options.GRPCClient
if grpcClient == nil {
grpcClient = &grpc.DefaultClient{Conn: nil}
}

installedCRDs := &apiextensionsv1.CustomResourceDefinitionList{}
err := options.Client.List(context.TODO(), installedCRDs)
if err != nil {
Expand Down Expand Up @@ -229,6 +237,7 @@ func NewConformanceTestSuite(options ConformanceOptions) (*ConformanceTestSuite,
Clientset: options.Clientset,
RestConfig: options.RestConfig,
RoundTripper: roundTripper,
GRPCClient: grpcClient,
GatewayClassName: options.GatewayClassName,
Debug: options.Debug,
Cleanup: options.CleanupBaseResources,
Expand Down