From b08845a69c70ded8b7cc57d54284a27cc5f47786 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Tue, 10 Dec 2024 14:10:18 +0000 Subject: [PATCH 01/35] Fix test cases and update code to latest branch --- rpc_util.go | 23 +++++++++++++- rpc_util_test.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/rpc_util.go b/rpc_util.go index 9fac2b08b48b..b9eb0bfee99b 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -874,14 +874,35 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes return nil, 0, err } - out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1), pool) + out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)), pool) if err != nil { out.Free() return nil, 0, err } + if err = checkReceiveMessageOverflow(int64(out.Len()), int64(maxReceiveMessageSize), dcReader); err != nil { + return nil, out.Len() + 1, err + } return out, out.Len(), nil } +// checkReceiveMessageOverflow checks if the number of bytes read from the stream exceeds +// the maximum receive message size allowed by the client. If the `readBytes` equals +// `maxReceiveMessageSize`, the function attempts to read one more byte from the `dcReader` +// to detect if there's an overflow. +// +// If additional data is read, or an error other than `io.EOF` is encountered, the function +// returns an error indicating that the message size has exceeded the permissible limit. +func checkReceiveMessageOverflow(readBytes, maxReceiveMessageSize int64, dcReader io.Reader) error { + if readBytes == maxReceiveMessageSize { + b := make([]byte, 1) + if n, err := dcReader.Read(b); n > 0 || err != io.EOF { + return fmt.Errorf("overflow: received message size is larger than the allowed maxReceiveMessageSize (%d bytes)", + maxReceiveMessageSize) + } + } + return nil +} + type recvCompressor interface { RecvCompress() string } diff --git a/rpc_util_test.go b/rpc_util_test.go index 94f50bc24ade..713d3f98dc13 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -21,12 +21,16 @@ package grpc import ( "bytes" "compress/gzip" + "errors" "io" "math" "reflect" "testing" + "github.com/google/go-cmp/cmp" "google.golang.org/grpc/codes" + "google.golang.org/grpc/encoding" + _ "google.golang.org/grpc/encoding/gzip" protoenc "google.golang.org/grpc/encoding/proto" "google.golang.org/grpc/internal/testutils" "google.golang.org/grpc/internal/transport" @@ -294,3 +298,81 @@ func BenchmarkGZIPCompressor512KiB(b *testing.B) { func BenchmarkGZIPCompressor1MiB(b *testing.B) { bmCompressor(b, 1024*1024, NewGZIPCompressor()) } + +// compressData compresses data using gzip and returns the compressed bytes. +func compressData(data []byte) []byte { + var buf bytes.Buffer + gz := gzip.NewWriter(&buf) + _, _ = gz.Write(data) + _ = gz.Close() + return buf.Bytes() +} + +// TestDecompress tests the decompress function with various scenarios, including +// successful decompression, error handling, and edge cases like overflow or +// premature data end. It ensures that the function behaves correctly with different +// inputs, buffer sizes, and error conditions, using the "gzip" compressor for testing. + +func TestDecompress(t *testing.T) { + c := encoding.GetCompressor("gzip") + + compressInput := func(input []byte) mem.BufferSlice { + compressedData := compressData(input) + return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} + } + + tests := []struct { + name string + compressor encoding.Compressor + input []byte + maxReceiveMessageSize int + want []byte + error error + }{ + { + name: "Decompresses successfully with sufficient buffer size", + compressor: c, + input: []byte("decompressed data"), + maxReceiveMessageSize: 50, + want: []byte("decompressed data"), + error: nil, + }, + { + name: "failure, empty receive message", + compressor: c, + input: []byte{}, + maxReceiveMessageSize: 10, + want: nil, + error: nil, + }, + { + name: "overflow failure, receive message exceeds maxReceiveMessageSize", + compressor: c, + input: []byte("small message"), + maxReceiveMessageSize: 5, + want: nil, + error: errors.New("overflow: received message size is larger than the allowed maxReceiveMessageSize (5 bytes)"), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + compressedMsg := compressInput(tt.input) + output, numSliceInBuf, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) + var wantMsg mem.BufferSlice + if tt.want != nil { + wantMsg = mem.BufferSlice{mem.NewBuffer(&tt.want, nil)} + } + if tt.error != nil && err == nil { + t.Fatalf("decompress() error, got err=%v, want err=%v", err, tt.error) + } + if tt.error == nil && numSliceInBuf != wantMsg.Len() { + t.Fatalf("decompress() number of slices mismatch, got = %d, want = %d", numSliceInBuf, wantMsg.Len()) + } + if diff := cmp.Diff(wantMsg.Materialize(), output.Materialize()); diff != "" { + t.Fatalf("Mismatch in output:\n%s", diff) + } + + }) + } +} From a02e58cf4ba0116770bf5ce88ad3e468368adce5 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Wed, 11 Dec 2024 11:34:34 +0000 Subject: [PATCH 02/35] small tweaks --- rpc_util_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rpc_util_test.go b/rpc_util_test.go index 713d3f98dc13..c96b258912d3 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -359,6 +359,7 @@ func TestDecompress(t *testing.T) { t.Run(tt.name, func(t *testing.T) { compressedMsg := compressInput(tt.input) output, numSliceInBuf, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) + var wantMsg mem.BufferSlice if tt.want != nil { wantMsg = mem.BufferSlice{mem.NewBuffer(&tt.want, nil)} From 54da70dcfe1b5cfd4929af4f3aff71a71fd2e4b5 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Thu, 12 Dec 2024 07:30:53 +0000 Subject: [PATCH 03/35] small tweaks --- rpc_util_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index c96b258912d3..713d3f98dc13 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -359,7 +359,6 @@ func TestDecompress(t *testing.T) { t.Run(tt.name, func(t *testing.T) { compressedMsg := compressInput(tt.input) output, numSliceInBuf, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) - var wantMsg mem.BufferSlice if tt.want != nil { wantMsg = mem.BufferSlice{mem.NewBuffer(&tt.want, nil)} From 4efd6fea37b5a16a68a78a331531b755f1bd56cc Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Thu, 12 Dec 2024 10:41:20 +0000 Subject: [PATCH 04/35] update code based on review feedback --- rpc_util.go | 30 +++++++++++++++++------------- rpc_util_test.go | 7 +++---- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index b9eb0bfee99b..bebc801f2297 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -22,6 +22,7 @@ import ( "compress/gzip" "context" "encoding/binary" + "errors" "fmt" "io" "math" @@ -808,6 +809,9 @@ func (p *payloadInfo) free() { } } +// Global error for message size exceeding the limit +var ErrMaxMessageSizeExceeded = errors.New("max message size exceeded") + // recvAndDecompress reads a message from the stream, decompressing it if necessary. // // Cancelling the returned cancel function releases the buffer back to the pool. So the caller should cancel as soon as @@ -828,7 +832,6 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM return nil, st.Err() } - var size int if pf.isCompressed() { defer compressed.Free() @@ -840,18 +843,18 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM if err == nil { out = mem.BufferSlice{mem.SliceBuffer(uncompressedBuf)} } - size = len(uncompressedBuf) } else { - out, size, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) + out, _, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) } if err != nil { return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) } - if size > maxReceiveMessageSize { + + if err == ErrMaxMessageSizeExceeded { out.Free() // TODO: Revisit the error code. Currently keep it consistent with java // implementation. - return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) + return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) } } else { out = compressed @@ -867,7 +870,7 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM } // Using compressor, decompress d, returning data and size. -// Optionally, if data will be over maxReceiveMessageSize, just return the size. +// If the decompressed data exceeds maxReceiveMessageSize, it returns nil, 0, and an error. func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, int, error) { dcReader, err := compressor.Decompress(d.Reader()) if err != nil { @@ -877,7 +880,7 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)), pool) if err != nil { out.Free() - return nil, 0, err + return nil, 0, ErrMaxMessageSizeExceeded } if err = checkReceiveMessageOverflow(int64(out.Len()), int64(maxReceiveMessageSize), dcReader); err != nil { return nil, out.Len() + 1, err @@ -893,12 +896,13 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes // If additional data is read, or an error other than `io.EOF` is encountered, the function // returns an error indicating that the message size has exceeded the permissible limit. func checkReceiveMessageOverflow(readBytes, maxReceiveMessageSize int64, dcReader io.Reader) error { - if readBytes == maxReceiveMessageSize { - b := make([]byte, 1) - if n, err := dcReader.Read(b); n > 0 || err != io.EOF { - return fmt.Errorf("overflow: received message size is larger than the allowed maxReceiveMessageSize (%d bytes)", - maxReceiveMessageSize) - } + if readBytes < maxReceiveMessageSize { + return nil + } + + b := make([]byte, 1) + if n, err := dcReader.Read(b); n > 0 || err != io.EOF { + return fmt.Errorf("overflow: received message size is larger than the allowed maxReceiveMessageSize (%d bytes)", maxReceiveMessageSize) } return nil } diff --git a/rpc_util_test.go b/rpc_util_test.go index 713d3f98dc13..457e6c0ea6ce 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -21,7 +21,6 @@ package grpc import ( "bytes" "compress/gzip" - "errors" "io" "math" "reflect" @@ -351,7 +350,7 @@ func TestDecompress(t *testing.T) { input: []byte("small message"), maxReceiveMessageSize: 5, want: nil, - error: errors.New("overflow: received message size is larger than the allowed maxReceiveMessageSize (5 bytes)"), + error: ErrMaxMessageSizeExceeded, }, } @@ -369,8 +368,8 @@ func TestDecompress(t *testing.T) { if tt.error == nil && numSliceInBuf != wantMsg.Len() { t.Fatalf("decompress() number of slices mismatch, got = %d, want = %d", numSliceInBuf, wantMsg.Len()) } - if diff := cmp.Diff(wantMsg.Materialize(), output.Materialize()); diff != "" { - t.Fatalf("Mismatch in output:\n%s", diff) + if diff := cmp.Diff(tt.want, output.Materialize()); diff != "" { + t.Fatalf("decompress() mismatch (-want +got):\n%s", diff) } }) From 851d13a0ebc511f77b1820a168bfc286fbb28f8c Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 13 Dec 2024 08:01:42 +0000 Subject: [PATCH 05/35] fixed the changes based on review feedback --- rpc_util.go | 42 ++++++++++++++++++++++-------------------- rpc_util_test.go | 44 +++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index bebc801f2297..d32e2f3d3bf6 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -809,8 +809,8 @@ func (p *payloadInfo) free() { } } -// Global error for message size exceeding the limit -var ErrMaxMessageSizeExceeded = errors.New("max message size exceeded") +// errMaxMessageSizeExceeded represents an error due to exceeding the maximum message size limit. +var errMaxMessageSizeExceeded = errors.New("max message size exceeded") // recvAndDecompress reads a message from the stream, decompressing it if necessary. // @@ -844,13 +844,13 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM out = mem.BufferSlice{mem.SliceBuffer(uncompressedBuf)} } } else { - out, _, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) + out, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) } if err != nil { return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) } - if err == ErrMaxMessageSizeExceeded { + if err == errMaxMessageSizeExceeded { out.Free() // TODO: Revisit the error code. Currently keep it consistent with java // implementation. @@ -870,41 +870,43 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM } // Using compressor, decompress d, returning data and size. -// If the decompressed data exceeds maxReceiveMessageSize, it returns nil, 0, and an error. -func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, int, error) { +// If the decompressed data exceeds maxReceiveMessageSize, it returns errMaxMessageSizeExceeded. +func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { dcReader, err := compressor.Decompress(d.Reader()) if err != nil { - return nil, 0, err + return nil, err } out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)), pool) if err != nil { out.Free() - return nil, 0, ErrMaxMessageSizeExceeded + return nil, err } - if err = checkReceiveMessageOverflow(int64(out.Len()), int64(maxReceiveMessageSize), dcReader); err != nil { - return nil, out.Len() + 1, err + + if doesReceiveMessageOverflow(int64(out.Len()), int64(maxReceiveMessageSize), dcReader) { + return nil, errMaxMessageSizeExceeded } - return out, out.Len(), nil + return out, nil } -// checkReceiveMessageOverflow checks if the number of bytes read from the stream exceeds -// the maximum receive message size allowed by the client. If the `readBytes` equals -// `maxReceiveMessageSize`, the function attempts to read one more byte from the `dcReader` -// to detect if there's an overflow. +// doesReceiveMessageOverflow checks if the number of bytes read from the stream +// exceeds the maximum receive message size allowed by the client. If the `readBytes` +// is greater than or equal to `maxReceiveMessageSize`, the function attempts to read +// one more byte from the `dcReader` to detect if there's an overflow. // // If additional data is read, or an error other than `io.EOF` is encountered, the function -// returns an error indicating that the message size has exceeded the permissible limit. -func checkReceiveMessageOverflow(readBytes, maxReceiveMessageSize int64, dcReader io.Reader) error { +// returns `true` to indicate that the message size has exceeded the permissible limit. +// Otherwise, it returns `false` indicating no overflow. +func doesReceiveMessageOverflow(readBytes, maxReceiveMessageSize int64, dcReader io.Reader) bool { if readBytes < maxReceiveMessageSize { - return nil + return false } b := make([]byte, 1) if n, err := dcReader.Read(b); n > 0 || err != io.EOF { - return fmt.Errorf("overflow: received message size is larger than the allowed maxReceiveMessageSize (%d bytes)", maxReceiveMessageSize) + return true } - return nil + return false } type recvCompressor interface { diff --git a/rpc_util_test.go b/rpc_util_test.go index 457e6c0ea6ce..9afd7292cde4 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -21,6 +21,7 @@ package grpc import ( "bytes" "compress/gzip" + "errors" "io" "math" "reflect" @@ -326,7 +327,7 @@ func TestDecompress(t *testing.T) { input []byte maxReceiveMessageSize int want []byte - error error + wantErr error }{ { name: "Decompresses successfully with sufficient buffer size", @@ -334,44 +335,45 @@ func TestDecompress(t *testing.T) { input: []byte("decompressed data"), maxReceiveMessageSize: 50, want: []byte("decompressed data"), - error: nil, + wantErr: nil, }, { - name: "failure, empty receive message", + name: "Fails due to exceeding maxReceiveMessageSize", compressor: c, - input: []byte{}, - maxReceiveMessageSize: 10, + input: []byte("small message that is too large"), + maxReceiveMessageSize: 5, want: nil, - error: nil, + wantErr: errMaxMessageSizeExceeded, }, { - name: "overflow failure, receive message exceeds maxReceiveMessageSize", + name: "Decompresses to exactly maxReceiveMessageSize", compressor: c, - input: []byte("small message"), - maxReceiveMessageSize: 5, - want: nil, - error: ErrMaxMessageSizeExceeded, + input: []byte("exact size message"), + maxReceiveMessageSize: len("exact size message"), + want: []byte("exact size message"), + wantErr: nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { compressedMsg := compressInput(tt.input) - output, numSliceInBuf, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) - var wantMsg mem.BufferSlice - if tt.want != nil { - wantMsg = mem.BufferSlice{mem.NewBuffer(&tt.want, nil)} - } - if tt.error != nil && err == nil { - t.Fatalf("decompress() error, got err=%v, want err=%v", err, tt.error) + output, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) + + if tt.wantErr != nil { + if !errors.Is(err, tt.wantErr) { + t.Fatalf("decompress() error = %v, wantErr = %v", err, tt.wantErr) + } + return } - if tt.error == nil && numSliceInBuf != wantMsg.Len() { - t.Fatalf("decompress() number of slices mismatch, got = %d, want = %d", numSliceInBuf, wantMsg.Len()) + + if err != nil { + t.Fatalf("decompress() unexpected error = %v", err) } + if diff := cmp.Diff(tt.want, output.Materialize()); diff != "" { t.Fatalf("decompress() mismatch (-want +got):\n%s", diff) } - }) } } From 26bf73101a8ab4c4fdb0717494dddf440dbfca11 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Tue, 17 Dec 2024 07:30:58 +0000 Subject: [PATCH 06/35] Added test cases for Handles maxReceiveMessageSize as MaxInt64 --- rpc_util_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rpc_util_test.go b/rpc_util_test.go index 9afd7292cde4..7c77f432f7dd 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -353,6 +353,14 @@ func TestDecompress(t *testing.T) { want: []byte("exact size message"), wantErr: nil, }, + { + name: "Handles maxReceiveMessageSize as MaxInt64", + compressor: c, + input: []byte("small message"), + maxReceiveMessageSize: math.MaxInt64, + want: []byte("small message"), + wantErr: nil, + }, } for _, tt := range tests { From 3cf9054f895cd112af5277c8d736648ae7b4d060 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Wed, 18 Dec 2024 07:39:47 +0000 Subject: [PATCH 07/35] Fixed the review changes --- rpc_util.go | 13 ++++++------- rpc_util_test.go | 41 ++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index d32e2f3d3bf6..7effcf1c65be 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -845,17 +845,16 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM } } else { out, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) + if err == errMaxMessageSizeExceeded { + out.Free() + // TODO: Revisit the error code. Currently keep it consistent with java + // implementation. + return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) + } } if err != nil { return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) } - - if err == errMaxMessageSizeExceeded { - out.Free() - // TODO: Revisit the error code. Currently keep it consistent with java - // implementation. - return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) - } } else { out = compressed } diff --git a/rpc_util_test.go b/rpc_util_test.go index 7c77f432f7dd..0c828008abaf 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -21,13 +21,13 @@ package grpc import ( "bytes" "compress/gzip" - "errors" "io" "math" "reflect" "testing" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/grpc/codes" "google.golang.org/grpc/encoding" _ "google.golang.org/grpc/encoding/gzip" @@ -300,27 +300,33 @@ func BenchmarkGZIPCompressor1MiB(b *testing.B) { } // compressData compresses data using gzip and returns the compressed bytes. -func compressData(data []byte) []byte { +// It now accepts *testing.T to handle errors during compression. +func compressData(t *testing.T, data []byte) []byte { var buf bytes.Buffer gz := gzip.NewWriter(&buf) - _, _ = gz.Write(data) - _ = gz.Close() + if _, err := gz.Write(data); err != nil { + t.Fatalf("compressData() failed to write data: %v", err) + } + + if err := gz.Close(); err != nil { + t.Fatalf("compressData() failed to close gzip writer: %v", err) + } return buf.Bytes() } +// compressInput compresses input data and returns a BufferSlice. +func compressInput(input []byte) mem.BufferSlice { + compressedData := compressData(nil, input) + return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} +} + // TestDecompress tests the decompress function with various scenarios, including // successful decompression, error handling, and edge cases like overflow or // premature data end. It ensures that the function behaves correctly with different // inputs, buffer sizes, and error conditions, using the "gzip" compressor for testing. - func TestDecompress(t *testing.T) { c := encoding.GetCompressor("gzip") - compressInput := func(input []byte) mem.BufferSlice { - compressedData := compressData(input) - return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} - } - tests := []struct { name string compressor encoding.Compressor @@ -354,10 +360,10 @@ func TestDecompress(t *testing.T) { wantErr: nil, }, { - name: "Handles maxReceiveMessageSize as MaxInt64", + name: "Handles maxReceiveMessageSize as MaxInt", compressor: c, input: []byte("small message"), - maxReceiveMessageSize: math.MaxInt64, + maxReceiveMessageSize: math.MaxInt, want: []byte("small message"), wantErr: nil, }, @@ -368,15 +374,8 @@ func TestDecompress(t *testing.T) { compressedMsg := compressInput(tt.input) output, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) - if tt.wantErr != nil { - if !errors.Is(err, tt.wantErr) { - t.Fatalf("decompress() error = %v, wantErr = %v", err, tt.wantErr) - } - return - } - - if err != nil { - t.Fatalf("decompress() unexpected error = %v", err) + if !cmp.Equal(err, tt.wantErr, cmpopts.EquateErrors()) { + t.Fatalf("decompress() error = %v, wantErr = %v", err, tt.wantErr) } if diff := cmp.Diff(tt.want, output.Materialize()); diff != "" { From 27a68a015720250b59736014ae2934dd2f2e4cfc Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Wed, 18 Dec 2024 12:46:31 +0000 Subject: [PATCH 08/35] Remove the casting for doesReceiveMessageOverflow --- rpc_util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index 7effcf1c65be..4ecd186d8570 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -882,7 +882,7 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes return nil, err } - if doesReceiveMessageOverflow(int64(out.Len()), int64(maxReceiveMessageSize), dcReader) { + if doesReceiveMessageOverflow(out.Len(), maxReceiveMessageSize, dcReader) { return nil, errMaxMessageSizeExceeded } return out, nil @@ -896,7 +896,7 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes // If additional data is read, or an error other than `io.EOF` is encountered, the function // returns `true` to indicate that the message size has exceeded the permissible limit. // Otherwise, it returns `false` indicating no overflow. -func doesReceiveMessageOverflow(readBytes, maxReceiveMessageSize int64, dcReader io.Reader) bool { +func doesReceiveMessageOverflow(readBytes, maxReceiveMessageSize int, dcReader io.Reader) bool { if readBytes < maxReceiveMessageSize { return false } From 3daef9b2bc8ef317c7237244b9aa12a117f15eb2 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Wed, 18 Dec 2024 13:27:10 +0000 Subject: [PATCH 09/35] Resolve all the issues --- rpc_util_test.go | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index 0c828008abaf..2aa1763b2af5 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -299,24 +299,19 @@ func BenchmarkGZIPCompressor1MiB(b *testing.B) { bmCompressor(b, 1024*1024, NewGZIPCompressor()) } -// compressData compresses data using gzip and returns the compressed bytes. -// It now accepts *testing.T to handle errors during compression. -func compressData(t *testing.T, data []byte) []byte { +// compressInput compresses the input data and returns a BufferSlice. +func compressInput(t *testing.T, input []byte) mem.BufferSlice { var buf bytes.Buffer gz := gzip.NewWriter(&buf) - if _, err := gz.Write(data); err != nil { - t.Fatalf("compressData() failed to write data: %v", err) + if _, err := gz.Write(input); err != nil { + t.Fatalf("compressInput() failed to write data: %v", err) } if err := gz.Close(); err != nil { - t.Fatalf("compressData() failed to close gzip writer: %v", err) + t.Fatalf("compressInput() failed to close gzip writer: %v", err) } - return buf.Bytes() -} -// compressInput compresses input data and returns a BufferSlice. -func compressInput(input []byte) mem.BufferSlice { - compressedData := compressData(nil, input) + compressedData := buf.Bytes() return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} } @@ -371,15 +366,15 @@ func TestDecompress(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - compressedMsg := compressInput(tt.input) + compressedMsg := compressInput(t, tt.input) output, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) if !cmp.Equal(err, tt.wantErr, cmpopts.EquateErrors()) { t.Fatalf("decompress() error = %v, wantErr = %v", err, tt.wantErr) } - if diff := cmp.Diff(tt.want, output.Materialize()); diff != "" { - t.Fatalf("decompress() mismatch (-want +got):\n%s", diff) + if !cmp.Equal(tt.want, output.Materialize()) { + t.Fatalf("decompress() mismatch (-want +got):\nwant = %v\ngot = %v", tt.want, output.Materialize()) } }) } From 8815cbda50231cf2e1b3a5f740910cee637e7260 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Wed, 18 Dec 2024 14:44:58 +0000 Subject: [PATCH 10/35] Refactored code changes done --- rpc_util_test.go | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index 2aa1763b2af5..4af861d14f29 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -299,8 +299,8 @@ func BenchmarkGZIPCompressor1MiB(b *testing.B) { bmCompressor(b, 1024*1024, NewGZIPCompressor()) } -// compressInput compresses the input data and returns a BufferSlice. -func compressInput(t *testing.T, input []byte) mem.BufferSlice { +// mustCompress compresses the input data and returns a BufferSlice. +func mustCompress(t *testing.T, input []byte) mem.BufferSlice { var buf bytes.Buffer gz := gzip.NewWriter(&buf) if _, err := gz.Write(input); err != nil { @@ -319,62 +319,56 @@ func compressInput(t *testing.T, input []byte) mem.BufferSlice { // successful decompression, error handling, and edge cases like overflow or // premature data end. It ensures that the function behaves correctly with different // inputs, buffer sizes, and error conditions, using the "gzip" compressor for testing. -func TestDecompress(t *testing.T) { +func (s) TestDecompress(t *testing.T) { c := encoding.GetCompressor("gzip") - tests := []struct { + testCases := []struct { name string - compressor encoding.Compressor - input []byte + input mem.BufferSlice maxReceiveMessageSize int want []byte wantErr error }{ { name: "Decompresses successfully with sufficient buffer size", - compressor: c, - input: []byte("decompressed data"), + input: mustCompress(t, []byte("decompressed data")), maxReceiveMessageSize: 50, want: []byte("decompressed data"), wantErr: nil, }, { name: "Fails due to exceeding maxReceiveMessageSize", - compressor: c, - input: []byte("small message that is too large"), - maxReceiveMessageSize: 5, + input: mustCompress(t, []byte("message that is too large")), + maxReceiveMessageSize: len("message that is too large") - 1, want: nil, wantErr: errMaxMessageSizeExceeded, }, { name: "Decompresses to exactly maxReceiveMessageSize", - compressor: c, - input: []byte("exact size message"), + input: mustCompress(t, []byte("exact size message")), maxReceiveMessageSize: len("exact size message"), want: []byte("exact size message"), wantErr: nil, }, { - name: "Handles maxReceiveMessageSize as MaxInt", - compressor: c, - input: []byte("small message"), + name: "Handles large buffer size (MaxInt)", + input: mustCompress(t, []byte("large message")), maxReceiveMessageSize: math.MaxInt, - want: []byte("small message"), + want: []byte("large message"), wantErr: nil, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - compressedMsg := compressInput(t, tt.input) - output, err := decompress(tt.compressor, compressedMsg, tt.maxReceiveMessageSize, mem.DefaultBufferPool()) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + output, err := decompress(c, tc.input, tc.maxReceiveMessageSize, mem.DefaultBufferPool()) - if !cmp.Equal(err, tt.wantErr, cmpopts.EquateErrors()) { - t.Fatalf("decompress() error = %v, wantErr = %v", err, tt.wantErr) + if !cmp.Equal(err, tc.wantErr, cmpopts.EquateErrors()) { + t.Fatalf("decompress() error = %v, wantErr = %v", err, tc.wantErr) } - if !cmp.Equal(tt.want, output.Materialize()) { - t.Fatalf("decompress() mismatch (-want +got):\nwant = %v\ngot = %v", tt.want, output.Materialize()) + if !cmp.Equal(tc.want, output.Materialize()) { + t.Fatalf("decompress() output mismatch: Got = %v, Want = %v", output.Materialize(), tc.want) } }) } From 5541486478d4c535c24e9e520536b66de3e1fcc3 Mon Sep 17 00:00:00 2001 From: pvsravani Date: Wed, 18 Dec 2024 18:14:42 +0000 Subject: [PATCH 11/35] test: switching to stubserver in tests instead of testservice (#7925) --- test/balancer_test.go | 52 ++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/test/balancer_test.go b/test/balancer_test.go index bb45e11d97c1..9cb41e5a6a2c 100644 --- a/test/balancer_test.go +++ b/test/balancer_test.go @@ -417,11 +417,15 @@ func (s) TestAddressAttributesInNewSubConn(t *testing.T) { if err != nil { t.Fatal(err) } - - s := grpc.NewServer() - testgrpc.RegisterTestServiceServer(s, &testServer{}) - go s.Serve(lis) - defer s.Stop() + stub := &stubserver.StubServer{ + Listener: lis, + EmptyCallF: func(_ context.Context, _ *testpb.Empty) (*testpb.Empty, error) { + return &testpb.Empty{}, nil + }, + S: grpc.NewServer(), + } + stubserver.StartTestService(t, stub) + defer stub.S.Stop() t.Logf("Started gRPC server at %s...", lis.Addr().String()) creds := &attrTransportCreds{} @@ -548,15 +552,16 @@ func (s) TestServersSwap(t *testing.T) { if err != nil { t.Fatalf("Error while listening. Err: %v", err) } - s := grpc.NewServer() - ts := &funcServer{ - unaryCall: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + + stub := &stubserver.StubServer{ + Listener: lis, + UnaryCallF: func(_ context.Context, _ *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { return &testpb.SimpleResponse{Username: username}, nil }, + S: grpc.NewServer(), } - testgrpc.RegisterTestServiceServer(s, ts) - go s.Serve(lis) - return lis.Addr().String(), s.Stop + stubserver.StartTestService(t, stub) + return lis.Addr().String(), stub.S.Stop } const one = "1" addr1, cleanup := reg(one) @@ -603,16 +608,16 @@ func (s) TestWaitForReady(t *testing.T) { if err != nil { t.Fatalf("Error while listening. Err: %v", err) } - s := grpc.NewServer() - defer s.Stop() const one = "1" - ts := &funcServer{ - unaryCall: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + stub := &stubserver.StubServer{ + Listener: lis, + UnaryCallF: func(_ context.Context, _ *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { return &testpb.SimpleResponse{Username: one}, nil }, + S: grpc.NewServer(), } - testgrpc.RegisterTestServiceServer(s, ts) - go s.Serve(lis) + stubserver.StartTestService(t, stub) + defer stub.S.Stop() // Initialize client r := manual.NewBuilderWithScheme("whatever") @@ -740,10 +745,15 @@ func (s) TestAuthorityInBuildOptions(t *testing.T) { t.Fatal(err) } - s := grpc.NewServer() - testgrpc.RegisterTestServiceServer(s, &testServer{}) - go s.Serve(lis) - defer s.Stop() + stub := &stubserver.StubServer{ + Listener: lis, + EmptyCallF: func(_ context.Context, _ *testpb.Empty) (*testpb.Empty, error) { + return &testpb.Empty{}, nil + }, + S: grpc.NewServer(), + } + stubserver.StartTestService(t, stub) + defer stub.S.Stop() t.Logf("Started gRPC server at %s...", lis.Addr().String()) r := manual.NewBuilderWithScheme("whatever") From a21e192176002a217aaa1ff2a026ad3316159130 Mon Sep 17 00:00:00 2001 From: janardhanvissa <47281167+janardhanvissa@users.noreply.github.com> Date: Thu, 19 Dec 2024 03:43:10 +0530 Subject: [PATCH 12/35] cleanup: replace dial with newclient (#7920) --- balancer/grpclb/grpclb_test.go | 39 ++++++++++++++++++---------------- balancer/rls/picker_test.go | 12 +++++------ resolver_balancer_ext_test.go | 10 +++++---- test/creds_test.go | 27 +++++++++++------------ test/end2end_test.go | 2 +- 5 files changed, 48 insertions(+), 42 deletions(-) diff --git a/balancer/grpclb/grpclb_test.go b/balancer/grpclb/grpclb_test.go index 62dc947e0ee5..e234ace6576f 100644 --- a/balancer/grpclb/grpclb_test.go +++ b/balancer/grpclb/grpclb_test.go @@ -460,7 +460,7 @@ func (s) TestGRPCLB_Basic(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() @@ -517,7 +517,7 @@ func (s) TestGRPCLB_Weighted(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() @@ -597,7 +597,7 @@ func (s) TestGRPCLB_DropRequest(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -769,7 +769,7 @@ func (s) TestGRPCLB_BalancerDisconnects(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -940,7 +940,7 @@ func (s) TestGRPCLB_ExplicitFallback(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -1008,11 +1008,12 @@ func (s) TestGRPCLB_FallBackWithNoServerAddress(t *testing.T) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), } - cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, dopts...) + cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() + cc.Connect() testC := testgrpc.NewTestServiceClient(cc) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -1102,10 +1103,11 @@ func (s) TestGRPCLB_PickFirst(t *testing.T) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), } - cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, dopts...) + cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend: %v", err) } + cc.Connect() defer cc.Close() // Push a service config with grpclb as the load balancing policy and @@ -1198,7 +1200,7 @@ func (s) TestGRPCLB_BackendConnectionErrorPropagation(t *testing.T) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer)) if err != nil { - t.Fatalf("Failed to create new client to the backend %v", err) + t.Fatalf("Failed to create a client for the backend: %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -1241,10 +1243,11 @@ func testGRPCLBEmptyServerList(t *testing.T, svcfg string) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), } - cc, err := grpc.DialContext(ctx, r.Scheme()+":///"+beServerName, dopts...) + cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } + cc.Connect() defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -1311,15 +1314,16 @@ func (s) TestGRPCLBWithTargetNameFieldInConfig(t *testing.T) { // Push the backend address to the remote balancer. tss.ls.sls <- sl - cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, + cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), grpc.WithUserAgent(testUserAgent)) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } defer cc.Close() + cc.Connect() testC := testgrpc.NewTestServiceClient(cc) // Push a resolver update with grpclb configuration which does not contain the @@ -1418,15 +1422,14 @@ func runAndCheckStats(t *testing.T, drop bool, statsChan chan *lbpb.ClientStats, tss.ls.statsDura = 100 * time.Millisecond creds := serverNameCheckCreds{} - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - cc, err := grpc.DialContext(ctx, r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), + cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), grpc.WithTransportCredentials(&creds), grpc.WithPerRPCCredentials(failPreRPCCred{}), grpc.WithContextDialer(fakeNameDialer)) if err != nil { - t.Fatalf("Failed to dial to the backend %v", err) + t.Fatalf("Failed to create a client for the backend %v", err) } + cc.Connect() defer cc.Close() rstate := resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)} diff --git a/balancer/rls/picker_test.go b/balancer/rls/picker_test.go index cb08c433f9e8..a0bdbc827921 100644 --- a/balancer/rls/picker_test.go +++ b/balancer/rls/picker_test.go @@ -267,9 +267,9 @@ func (s) Test_RLSDefaultTargetPicksMetric(t *testing.T) { r := startManualResolverWithConfig(t, rlsConfig) tmr := stats.NewTestMetricsRecorder() - cc, err := grpc.Dial(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) + cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) if err != nil { - t.Fatalf("grpc.Dial() failed: %v", err) + t.Fatalf("grpc.NewClient() failed: %v", err) } defer cc.Close() @@ -314,9 +314,9 @@ func (s) Test_RLSTargetPicksMetric(t *testing.T) { tmr := stats.NewTestMetricsRecorder() // Dial the backend. - cc, err := grpc.Dial(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) + cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) if err != nil { - t.Fatalf("grpc.Dial() failed: %v", err) + t.Fatalf("grpc.NewClient() failed: %v", err) } defer cc.Close() @@ -352,9 +352,9 @@ func (s) Test_RLSFailedPicksMetric(t *testing.T) { tmr := stats.NewTestMetricsRecorder() // Dial the backend. - cc, err := grpc.Dial(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) + cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) if err != nil { - t.Fatalf("grpc.Dial() failed: %v", err) + t.Fatalf("grpc.NewClient() failed: %v", err) } defer cc.Close() diff --git a/resolver_balancer_ext_test.go b/resolver_balancer_ext_test.go index 417a5781ef80..75fac51a66db 100644 --- a/resolver_balancer_ext_test.go +++ b/resolver_balancer_ext_test.go @@ -66,11 +66,12 @@ func (s) TestResolverBalancerInteraction(t *testing.T) { rb.ResolveNowCallback = func(resolver.ResolveNowOptions) { close(rnCh) } resolver.Register(rb) - cc, err := grpc.Dial(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) + cc, err := grpc.NewClient(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - t.Fatalf("grpc.Dial error: %v", err) + t.Fatalf("grpc.NewClient error: %v", err) } defer cc.Close() + cc.Connect() select { case <-rnCh: case <-time.After(defaultTestTimeout): @@ -109,11 +110,12 @@ func (s) TestResolverBuildFailure(t *testing.T) { resolver.Register(&resolverBuilderWithErr{errCh: resErrCh, scheme: name}) resErrCh <- nil - cc, err := grpc.Dial(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) + cc, err := grpc.NewClient(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - t.Fatalf("grpc.Dial error: %v", err) + t.Fatalf("grpc.NewClient error: %v", err) } defer cc.Close() + cc.Connect() enterIdle(cc) const errStr = "test error from resolver builder" t.Log("pushing res err") diff --git a/test/creds_test.go b/test/creds_test.go index ff3818e0ad54..c9b8862442db 100644 --- a/test/creds_test.go +++ b/test/creds_test.go @@ -236,9 +236,9 @@ func (s) TestFailFastRPCErrorOnBadCertificates(t *testing.T) { opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() - cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) + cc, err := grpc.NewClient(te.srvAddr, opts...) if err != nil { - t.Fatalf("Dial(_) = %v, want %v", err, nil) + t.Fatalf("NewClient(_) = %v, want %v", err, nil) } defer cc.Close() @@ -262,16 +262,14 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { defer te.tearDown() opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} - ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) - defer cancel() - cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) + cc, err := grpc.NewClient(te.srvAddr, opts...) if err != nil { - t.Fatalf("Dial(_) = %v, want %v", err, nil) + t.Fatalf("NewClient(_) = %v, want %v", err, nil) } defer cc.Close() tc := testgrpc.NewTestServiceClient(cc) - ctx, cancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) + ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) defer cancel() if _, err = tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); !strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want err.Error() contains %q", err, clientAlwaysFailCredErrorMsg) @@ -437,11 +435,12 @@ func (s) TestCredsHandshakeAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) } defer cc.Close() + cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String()}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -469,11 +468,12 @@ func (s) TestCredsHandshakeServerNameAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) } defer cc.Close() + cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String(), ServerName: testServerName}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -524,11 +524,12 @@ func (s) TestServerCredsDispatch(t *testing.T) { go s.Serve(lis) defer s.Stop() - cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(cred)) + cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(cred)) if err != nil { - t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) } defer cc.Close() + cc.Connect() rawConn := cred.getRawConn() // Give grpc a chance to see the error and potentially close the connection. diff --git a/test/end2end_test.go b/test/end2end_test.go index 2238f8f12422..19972ecebe17 100644 --- a/test/end2end_test.go +++ b/test/end2end_test.go @@ -609,7 +609,7 @@ func (te *test) listenAndServe(ts testgrpc.TestServiceServer, listen func(networ if te.serverInitialConnWindowSize > 0 { sopts = append(sopts, grpc.InitialConnWindowSize(te.serverInitialConnWindowSize)) } - la := "localhost:0" + la := ":0" switch te.e.network { case "unix": la = "/tmp/testsock" + fmt.Sprintf("%d", time.Now().UnixNano()) From 09132bfd8cd5158bc68bff9441308b7654a47dc9 Mon Sep 17 00:00:00 2001 From: TomerJLevy Date: Fri, 20 Dec 2024 07:45:50 +0200 Subject: [PATCH 13/35] deps: update crypto dependency to resolve CVE-2024-45337 (#7956) --- examples/go.mod | 2 +- examples/go.sum | 3 ++- gcp/observability/go.mod | 16 +++++++-------- gcp/observability/go.sum | 29 +++++++++++++++------------- interop/observability/go.mod | 16 +++++++-------- interop/observability/go.sum | 29 +++++++++++++++------------- security/advancedtls/examples/go.mod | 2 +- security/advancedtls/examples/go.sum | 4 ++-- security/advancedtls/go.mod | 2 +- security/advancedtls/go.sum | 4 ++-- 10 files changed, 57 insertions(+), 50 deletions(-) diff --git a/examples/go.mod b/examples/go.mod index 51c2f2b1ff83..d2d1f719d8c0 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -68,7 +68,7 @@ require ( go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/sdk v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.30.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect diff --git a/examples/go.sum b/examples/go.sum index 9cb58041e4ba..02577c25e514 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1159,8 +1159,9 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/gcp/observability/go.mod b/gcp/observability/go.mod index d85b4b73eed7..4053ed38880d 100644 --- a/gcp/observability/go.mod +++ b/gcp/observability/go.mod @@ -9,16 +9,16 @@ require ( github.com/google/uuid v1.6.0 go.opencensus.io v0.24.0 golang.org/x/oauth2 v0.24.0 - google.golang.org/api v0.201.0 + google.golang.org/api v0.213.0 google.golang.org/grpc v1.67.1 google.golang.org/grpc/stats/opencensus v1.0.0 ) require ( cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.9.8 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect - cloud.google.com/go/compute/metadata v0.5.2 // indirect + cloud.google.com/go/auth v0.13.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/longrunning v0.6.1 // indirect cloud.google.com/go/monitoring v1.21.1 // indirect cloud.google.com/go/trace v1.11.1 // indirect @@ -43,21 +43,21 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.30.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/time v0.8.0 // indirect google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/gcp/observability/go.sum b/gcp/observability/go.sum index 72588140a0e7..552da2bd29a8 100644 --- a/gcp/observability/go.sum +++ b/gcp/observability/go.sum @@ -118,10 +118,10 @@ cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEar cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= -cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= -cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= @@ -219,8 +219,9 @@ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1h cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -986,8 +987,8 @@ github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38 github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -1133,8 +1134,9 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1453,8 +1455,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1596,8 +1598,8 @@ google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZ google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.201.0 h1:+7AD9JNM3tREtawRMu8sOjSbb8VYcYXJG/2eEOmfDu0= -google.golang.org/api v0.201.0/go.mod h1:HVY0FCHVs89xIW9fzf/pBvOEm+OolHa86G/txFezyq4= +google.golang.org/api v0.213.0 h1:KmF6KaDyFqB417T68tMPbVmmwtIXs2VB60OJKIHB0xQ= +google.golang.org/api v0.213.0/go.mod h1:V0T5ZhNUUNpYAlL306gFZPFt5F5D/IeyLoktduYYnvQ= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1771,8 +1773,9 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/stats/opencensus v1.0.0 h1:evSYcRZaSToQp+borzWE52+03joezZeXcKJvZDfkUJA= google.golang.org/grpc/stats/opencensus v1.0.0/go.mod h1:FhdkeYvN43wLYUnapVuRJJ9JXkNwe403iLUW2LKSnjs= diff --git a/interop/observability/go.mod b/interop/observability/go.mod index 07bcfcee15bc..781ec330ac86 100644 --- a/interop/observability/go.mod +++ b/interop/observability/go.mod @@ -9,9 +9,9 @@ require ( require ( cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.9.8 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect - cloud.google.com/go/compute/metadata v0.5.2 // indirect + cloud.google.com/go/auth v0.13.0 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect + cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/logging v1.12.0 // indirect cloud.google.com/go/longrunning v0.6.1 // indirect cloud.google.com/go/monitoring v1.21.1 // indirect @@ -41,24 +41,24 @@ require ( github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.30.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.7.0 // indirect - google.golang.org/api v0.201.0 // indirect + golang.org/x/time v0.8.0 // indirect + google.golang.org/api v0.213.0 // indirect google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect google.golang.org/grpc/stats/opencensus v1.0.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/interop/observability/go.sum b/interop/observability/go.sum index 054a3377d46c..cc3c70245cf6 100644 --- a/interop/observability/go.sum +++ b/interop/observability/go.sum @@ -118,10 +118,10 @@ cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEar cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= -cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= -cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= +cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= +cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= +cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= @@ -219,8 +219,9 @@ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1h cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= +cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -989,8 +990,8 @@ github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38 github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -1136,8 +1137,9 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1456,8 +1458,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1599,8 +1601,8 @@ google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZ google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.201.0 h1:+7AD9JNM3tREtawRMu8sOjSbb8VYcYXJG/2eEOmfDu0= -google.golang.org/api v0.201.0/go.mod h1:HVY0FCHVs89xIW9fzf/pBvOEm+OolHa86G/txFezyq4= +google.golang.org/api v0.213.0 h1:KmF6KaDyFqB417T68tMPbVmmwtIXs2VB60OJKIHB0xQ= +google.golang.org/api v0.213.0/go.mod h1:V0T5ZhNUUNpYAlL306gFZPFt5F5D/IeyLoktduYYnvQ= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1774,8 +1776,9 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/security/advancedtls/examples/go.mod b/security/advancedtls/examples/go.mod index 43a16752b17c..3f9223147b30 100644 --- a/security/advancedtls/examples/go.mod +++ b/security/advancedtls/examples/go.mod @@ -9,7 +9,7 @@ require ( ) require ( - golang.org/x/crypto v0.30.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/security/advancedtls/examples/go.sum b/security/advancedtls/examples/go.sum index ec9f8e8372e7..cbf4886fe7f5 100644 --- a/security/advancedtls/examples/go.sum +++ b/security/advancedtls/examples/go.sum @@ -18,8 +18,8 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= diff --git a/security/advancedtls/go.mod b/security/advancedtls/go.mod index 5cc89cbb74d7..3e9e4f09168c 100644 --- a/security/advancedtls/go.mod +++ b/security/advancedtls/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/google/go-cmp v0.6.0 - golang.org/x/crypto v0.30.0 + golang.org/x/crypto v0.31.0 google.golang.org/grpc v1.68.1 google.golang.org/grpc/examples v0.0.0-20201112215255-90f1b3ee835b ) diff --git a/security/advancedtls/go.sum b/security/advancedtls/go.sum index ec9f8e8372e7..cbf4886fe7f5 100644 --- a/security/advancedtls/go.sum +++ b/security/advancedtls/go.sum @@ -18,8 +18,8 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= From 5181e7b9ef8e550a1cdb313241251343256bf6de Mon Sep 17 00:00:00 2001 From: Arjan Singh Bal <46515553+arjan-bal@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:29:13 +0530 Subject: [PATCH 14/35] test: Workaround slow SRV lookups in flaking test (#7957) --- test/creds_test.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/creds_test.go b/test/creds_test.go index c9b8862442db..fe8b552e719c 100644 --- a/test/creds_test.go +++ b/test/creds_test.go @@ -243,15 +243,8 @@ func (s) TestFailFastRPCErrorOnBadCertificates(t *testing.T) { defer cc.Close() tc := testgrpc.NewTestServiceClient(cc) - for i := 0; i < 1000; i++ { - // This loop runs for at most 1 second. The first several RPCs will fail - // with Unavailable because the connection hasn't started. When the - // first connection failed with creds error, the next RPC should also - // fail with the expected error. - if _, err = tc.EmptyCall(ctx, &testpb.Empty{}); strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { - return - } - time.Sleep(time.Millisecond) + if _, err = tc.EmptyCall(ctx, &testpb.Empty{}); strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { + return } te.t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want err.Error() contains %q", err, clientAlwaysFailCredErrorMsg) } @@ -268,8 +261,18 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { } defer cc.Close() + // The DNS resolver may take more than defaultTestShortTimeout, we let the + // channel enter TransientFailure signalling that the first resolver state + // has been produced. + cc.Connect() + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure) + tc := testgrpc.NewTestServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) + // Use a short context as WaitForReady waits for context expiration before + // failing the RPC. + ctx, cancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) defer cancel() if _, err = tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); !strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want err.Error() contains %q", err, clientAlwaysFailCredErrorMsg) From 46faf72fda5b68e7832024b2308c7e5f66a7d609 Mon Sep 17 00:00:00 2001 From: Easwar Swaminathan Date: Fri, 20 Dec 2024 09:49:25 -0800 Subject: [PATCH 15/35] envconfig: enable xDS client fallback by default (#7949) --- internal/envconfig/envconfig.go | 2 +- internal/xds/bootstrap/bootstrap_test.go | 10 +++------- xds/internal/xdsclient/tests/fallback_test.go | 16 ---------------- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/internal/envconfig/envconfig.go b/internal/envconfig/envconfig.go index 6e7dd6b77270..1e42b6fdc872 100644 --- a/internal/envconfig/envconfig.go +++ b/internal/envconfig/envconfig.go @@ -49,7 +49,7 @@ var ( // XDSFallbackSupport is the env variable that controls whether support for // xDS fallback is turned on. If this is unset or is false, only the first // xDS server in the list of server configs will be used. - XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", false) + XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true) // NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used // instead of the exiting pickfirst implementation. This can be enabled by // setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST" diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index 302e281405ee..d057197804d6 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -429,10 +429,6 @@ func (s) TestGetConfiguration_Success(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - origFallbackEnv := envconfig.XDSFallbackSupport - envconfig.XDSFallbackSupport = true - defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() - testGetConfigurationWithFileNameEnv(t, test.name, false, test.wantConfig) testGetConfigurationWithFileContentEnv(t, test.name, false, test.wantConfig) }) @@ -1202,9 +1198,9 @@ func (s) TestNode_ToProto(t *testing.T) { // Tests the case where the xDS fallback env var is set to false, and verifies // that only the first server from the list of server configurations is used. func (s) TestGetConfiguration_FallbackDisabled(t *testing.T) { - // TODO(easwars): Default value of "GRPC_EXPERIMENTAL_XDS_FALLBACK" - // env var is currently false. When the default is changed to true, - // explicitly set it to false here. + origFallbackEnv := envconfig.XDSFallbackSupport + envconfig.XDSFallbackSupport = false + defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() cancel := setupBootstrapOverride(map[string]string{ "multipleXDSServers": ` diff --git a/xds/internal/xdsclient/tests/fallback_test.go b/xds/internal/xdsclient/tests/fallback_test.go index 18c382dbd146..19f00de4426f 100644 --- a/xds/internal/xdsclient/tests/fallback_test.go +++ b/xds/internal/xdsclient/tests/fallback_test.go @@ -30,7 +30,6 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/internal" - "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/internal/testutils" "google.golang.org/grpc/internal/testutils/xds/e2e" @@ -79,11 +78,6 @@ func waitForRPCsToReachBackend(ctx context.Context, client testgrpc.TestServiceC // to it. The test also verifies that when all requested resources are cached // from the primary, fallback is not triggered when the connection goes down. func (s) TestFallback_OnStartup(t *testing.T) { - // Enable fallback env var. - origFallbackEnv := envconfig.XDSFallbackSupport - envconfig.XDSFallbackSupport = true - defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() - ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout) defer cancel() @@ -248,11 +242,6 @@ func (s) TestFallback_OnStartup(t *testing.T) { // Tests fallback when the primary management server fails during an update. func (s) TestFallback_MidUpdate(t *testing.T) { - // Enable fallback env var. - origFallbackEnv := envconfig.XDSFallbackSupport - envconfig.XDSFallbackSupport = true - defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() - ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout) defer cancel() @@ -454,11 +443,6 @@ func (s) TestFallback_MidUpdate(t *testing.T) { // Tests fallback when the primary management server fails during startup. func (s) TestFallback_MidStartup(t *testing.T) { - // Enable fallback env var. - origFallbackEnv := envconfig.XDSFallbackSupport - envconfig.XDSFallbackSupport = true - defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() - ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout) defer cancel() From bd4989a3473fd6f073d40123cbc1fa6668c4e35c Mon Sep 17 00:00:00 2001 From: Arjan Singh Bal <46515553+arjan-bal@users.noreply.github.com> Date: Mon, 23 Dec 2024 09:48:51 +0530 Subject: [PATCH 16/35] test: Add a test for decompression exceeding max receive message size (#7938) --- test/compressor_test.go | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test/compressor_test.go b/test/compressor_test.go index 0495a06f0968..0a629bcecdb5 100644 --- a/test/compressor_test.go +++ b/test/compressor_test.go @@ -785,3 +785,62 @@ func (s) TestGzipBadChecksum(t *testing.T) { t.Errorf("ss.Client.UnaryCall(_) = _, %v\n\twant: _, status(codes.Internal, contains %q)", err, gzip.ErrChecksum) } } + +// fakeCompressor returns a messages of a configured size, irrespective of the +// input. +type fakeCompressor struct { + decompressedMessageSize int +} + +func (f *fakeCompressor) Compress(w io.Writer) (io.WriteCloser, error) { + return nopWriteCloser{w}, nil +} + +func (f *fakeCompressor) Decompress(io.Reader) (io.Reader, error) { + return bytes.NewReader(make([]byte, f.decompressedMessageSize)), nil +} + +func (f *fakeCompressor) Name() string { + // Use the name of an existing compressor to avoid interactions with other + // tests since compressors can't be un-registered. + return "gzip" +} + +type nopWriteCloser struct { + io.Writer +} + +func (nopWriteCloser) Close() error { + return nil +} + +// TestDecompressionExceedsMaxMessageSize uses a fake compressor that produces +// messages of size 100 bytes on decompression. A server is started with the +// max receive message size restricted to 99 bytes. The test verifies that the +// client receives a ResourceExhausted response from the server. +func (s) TestDecompressionExceedsMaxMessageSize(t *testing.T) { + oldC := encoding.GetCompressor("gzip") + defer func() { + encoding.RegisterCompressor(oldC) + }() + const messageLen = 100 + encoding.RegisterCompressor(&fakeCompressor{decompressedMessageSize: messageLen}) + ss := &stubserver.StubServer{ + UnaryCallF: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + return &testpb.SimpleResponse{}, nil + }, + } + if err := ss.Start([]grpc.ServerOption{grpc.MaxRecvMsgSize(messageLen - 1)}); err != nil { + t.Fatalf("Error starting endpoint server: %v", err) + } + defer ss.Stop() + + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + + req := &testpb.SimpleRequest{Payload: &testpb.Payload{}} + _, err := ss.Client.UnaryCall(ctx, req, grpc.UseCompressor("gzip")) + if got, want := status.Code(err), codes.ResourceExhausted; got != want { + t.Errorf("Client.UnaryCall(%+v) returned status %v, want %v", req, got, want) + } +} From 985965a87952abce7a98723363c67a753c8a3c81 Mon Sep 17 00:00:00 2001 From: Arjan Singh Bal <46515553+arjan-bal@users.noreply.github.com> Date: Mon, 23 Dec 2024 10:38:35 +0530 Subject: [PATCH 17/35] outlierdetection: Support health listener for ejection updates (#7908) --- balancer/endpointsharding/endpointsharding.go | 8 +- .../pickfirst/pickfirstleaf/pickfirstleaf.go | 27 ++- .../pickfirstleaf/pickfirstleaf_ext_test.go | 52 +++--- balancer/weightedroundrobin/balancer.go | 8 +- .../balancer/outlierdetection/balancer.go | 146 ++++++++++------ .../outlierdetection/balancer_test.go | 96 ++++++++++ .../e2e_test/outlierdetection_test.go | 165 ++++++++++-------- .../outlierdetection/subconn_wrapper.go | 154 +++++++++++++++- 8 files changed, 487 insertions(+), 169 deletions(-) diff --git a/balancer/endpointsharding/endpointsharding.go b/balancer/endpointsharding/endpointsharding.go index 263c024a84c7..9b59bfc1d979 100644 --- a/balancer/endpointsharding/endpointsharding.go +++ b/balancer/endpointsharding/endpointsharding.go @@ -35,11 +35,9 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/base" - "google.golang.org/grpc/balancer/pickfirst" "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/balancer/gracefulswitch" - "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" ) @@ -48,11 +46,7 @@ import ( var PickFirstConfig string func init() { - name := pickfirst.Name - if !envconfig.NewPickFirstEnabled { - name = pickfirstleaf.Name - } - PickFirstConfig = fmt.Sprintf("[{%q: {}}]", name) + PickFirstConfig = fmt.Sprintf("[{%q: {}}]", pickfirstleaf.Name) } // ChildState is the balancer state of a child along with the endpoint which diff --git a/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go index 2fc0a71f9441..76fa5fea95f2 100644 --- a/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go +++ b/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go @@ -54,9 +54,18 @@ func init() { balancer.Register(pickfirstBuilder{}) } -// enableHealthListenerKeyType is a unique key type used in resolver attributes -// to indicate whether the health listener usage is enabled. -type enableHealthListenerKeyType struct{} +type ( + // enableHealthListenerKeyType is a unique key type used in resolver + // attributes to indicate whether the health listener usage is enabled. + enableHealthListenerKeyType struct{} + // managedByPickfirstKeyType is an attribute key type to inform Outlier + // Detection that the generic health listener is being used. + // TODO: https://github.com/grpc/grpc-go/issues/7915 - Remove this when + // implementing the dualstack design. This is a hack. Once Dualstack is + // completed, outlier detection will stop sending ejection updates through + // the connectivity listener. + managedByPickfirstKeyType struct{} +) var ( logger = grpclog.Component("pick-first-leaf-lb") @@ -140,6 +149,17 @@ func EnableHealthListener(state resolver.State) resolver.State { return state } +// IsManagedByPickfirst returns whether an address belongs to a SubConn +// managed by the pickfirst LB policy. +// TODO: https://github.com/grpc/grpc-go/issues/7915 - This is a hack to disable +// outlier_detection via the with connectivity listener when using pick_first. +// Once Dualstack changes are complete, all SubConns will be created by +// pick_first and outlier detection will only use the health listener for +// ejection. This hack can then be removed. +func IsManagedByPickfirst(addr resolver.Address) bool { + return addr.BalancerAttributes.Value(managedByPickfirstKeyType{}) != nil +} + type pfConfig struct { serviceconfig.LoadBalancingConfig `json:"-"` @@ -166,6 +186,7 @@ type scData struct { } func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) { + addr.BalancerAttributes = addr.BalancerAttributes.WithValue(managedByPickfirstKeyType{}, true) sd := &scData{ rawConnectivityState: connectivity.Idle, effectiveState: connectivity.Idle, diff --git a/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go b/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go index 9667c2b3db6b..2a87d6690f4c 100644 --- a/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go +++ b/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go @@ -58,7 +58,13 @@ const ( stateStoringBalancerName = "state_storing" ) -var stateStoringServiceConfig = fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, stateStoringBalancerName) +var ( + stateStoringServiceConfig = fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, stateStoringBalancerName) + ignoreBalAttributesOpt = cmp.Transformer("IgnoreBalancerAttributes", func(a resolver.Address) resolver.Address { + a.BalancerAttributes = nil + return a + }) +) type s struct { grpctest.Tester @@ -177,7 +183,7 @@ func (s) TestPickFirstLeaf_SimpleResolverUpdate_FirstServerReady(t *testing.T) { wantSCStates := []scState{ {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -219,7 +225,7 @@ func (s) TestPickFirstLeaf_SimpleResolverUpdate_FirstServerUnReady(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown}, {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -264,7 +270,7 @@ func (s) TestPickFirstLeaf_SimpleResolverUpdate_DuplicateAddrs(t *testing.T) { {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown}, {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -317,7 +323,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_DisjointLists(t *testing.T) { {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -334,7 +340,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_DisjointLists(t *testing.T) { {Addrs: []resolver.Address{addrs[3]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -378,7 +384,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_ActiveBackendInUpdatedList(t *testing {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -398,7 +404,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_ActiveBackendInUpdatedList(t *testing {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -440,7 +446,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_InActiveBackendInUpdatedList(t *testi {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -458,7 +464,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_InActiveBackendInUpdatedList(t *testi {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -502,7 +508,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_IdenticalLists(t *testing.T) { {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -521,7 +527,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_IdenticalLists(t *testing.T) { {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -576,7 +582,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerRestart(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -591,7 +597,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerRestart(t *testing.T) t.Fatal(err) } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -639,7 +645,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerRestart(t *testing.T) {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -660,7 +666,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerRestart(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -708,7 +714,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerToFirst(t *testing.T) {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -729,7 +735,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerToFirst(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -776,7 +782,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerToSecond(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -796,7 +802,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerToSecond(t *testing.T) {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -1130,7 +1136,7 @@ func (s) TestPickFirstLeaf_InterleavingIPV4Preffered(t *testing.T) { if err != nil { t.Fatalf("%v", err) } - if diff := cmp.Diff(wantAddrs, gotAddrs); diff != "" { + if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff) } } @@ -1174,7 +1180,7 @@ func (s) TestPickFirstLeaf_InterleavingIPv6Preffered(t *testing.T) { if err != nil { t.Fatalf("%v", err) } - if diff := cmp.Diff(wantAddrs, gotAddrs); diff != "" { + if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff) } } @@ -1220,7 +1226,7 @@ func (s) TestPickFirstLeaf_InterleavingUnknownPreffered(t *testing.T) { if err != nil { t.Fatalf("%v", err) } - if diff := cmp.Diff(wantAddrs, gotAddrs); diff != "" { + if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" { t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff) } } diff --git a/balancer/weightedroundrobin/balancer.go b/balancer/weightedroundrobin/balancer.go index c9c5b576bb0c..d7b9dc4666ee 100644 --- a/balancer/weightedroundrobin/balancer.go +++ b/balancer/weightedroundrobin/balancer.go @@ -29,6 +29,7 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/endpointsharding" + "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/balancer/weightedroundrobin/internal" "google.golang.org/grpc/balancer/weightedtarget" "google.golang.org/grpc/connectivity" @@ -218,7 +219,9 @@ type wrrBalancer struct { } func (b *wrrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error { - b.logger.Infof("UpdateCCS: %v", ccs) + if b.logger.V(2) { + b.logger.Infof("UpdateCCS: %v", ccs) + } cfg, ok := ccs.BalancerConfig.(*lbConfig) if !ok { return fmt.Errorf("wrr: received nil or illegal BalancerConfig (type %T): %v", ccs.BalancerConfig, ccs.BalancerConfig) @@ -232,6 +235,9 @@ func (b *wrrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error b.updateEndpointsLocked(ccs.ResolverState.Endpoints) b.mu.Unlock() + // Make pickfirst children use health listeners for outlier detection to + // work. + ccs.ResolverState = pickfirstleaf.EnableHealthListener(ccs.ResolverState) // This causes child to update picker inline and will thus cause inline // picker update. return b.child.UpdateClientConnState(balancer.ClientConnState{ diff --git a/xds/internal/balancer/outlierdetection/balancer.go b/xds/internal/balancer/outlierdetection/balancer.go index c9d496ce09b9..8f58c0030321 100644 --- a/xds/internal/balancer/outlierdetection/balancer.go +++ b/xds/internal/balancer/outlierdetection/balancer.go @@ -33,6 +33,7 @@ import ( "unsafe" "google.golang.org/grpc/balancer" + "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/balancer/gracefulswitch" "google.golang.org/grpc/internal/buffer" @@ -72,7 +73,7 @@ func (bb) Build(cc balancer.ClientConn, bOpts balancer.BuildOptions) balancer.Ba } b.logger = prefixLogger(b) b.logger.Infof("Created") - b.child = gracefulswitch.NewBalancer(b, bOpts) + b.child = synchronizingBalancerWrapper{lb: gracefulswitch.NewBalancer(b, bOpts)} go b.run() return b } @@ -152,6 +153,11 @@ type lbCfgUpdate struct { done chan struct{} } +type scHealthUpdate struct { + scw *subConnWrapper + state balancer.SubConnState +} + type outlierDetectionBalancer struct { // These fields are safe to be accessed without holding any mutex because // they are synchronized in run(), which makes these field accesses happen @@ -170,10 +176,7 @@ type outlierDetectionBalancer struct { logger *grpclog.PrefixLogger channelzParent channelz.Identifier - // childMu guards calls into child (to uphold the balancer.Balancer API - // guarantee of synchronous calls). - childMu sync.Mutex - child *gracefulswitch.Balancer + child synchronizingBalancerWrapper // mu guards access to the following fields. It also helps to synchronize // behaviors of the following events: config updates, firing of the interval @@ -190,8 +193,8 @@ type outlierDetectionBalancer struct { // which uses addrs. This balancer waits for the interval timer algorithm to // finish before making the update to the addrs map. // - // This mutex is never held at the same time as childMu (within the context - // of a single goroutine). + // This mutex is never held when calling methods on the child policy + // (within the context of a single goroutine). mu sync.Mutex addrs map[string]*addressInfo cfg *LBConfig @@ -276,13 +279,9 @@ func (b *outlierDetectionBalancer) UpdateClientConnState(s balancer.ClientConnSt // the balancer.Balancer API, so it is guaranteed to be called in a // synchronous manner, so it cannot race with this read. if b.cfg == nil || b.cfg.ChildPolicy.Name != lbCfg.ChildPolicy.Name { - b.childMu.Lock() - err := b.child.SwitchTo(bb) - if err != nil { - b.childMu.Unlock() + if err := b.child.switchTo(bb); err != nil { return fmt.Errorf("outlier detection: error switching to child of type %q: %v", lbCfg.ChildPolicy.Name, err) } - b.childMu.Unlock() } b.mu.Lock() @@ -319,12 +318,10 @@ func (b *outlierDetectionBalancer) UpdateClientConnState(s balancer.ClientConnSt } b.mu.Unlock() - b.childMu.Lock() - err := b.child.UpdateClientConnState(balancer.ClientConnState{ + err := b.child.updateClientConnState(balancer.ClientConnState{ ResolverState: s.ResolverState, BalancerConfig: b.cfg.ChildPolicy.Config, }) - b.childMu.Unlock() done := make(chan struct{}) b.pickerUpdateCh.Put(lbCfgUpdate{ @@ -337,9 +334,7 @@ func (b *outlierDetectionBalancer) UpdateClientConnState(s balancer.ClientConnSt } func (b *outlierDetectionBalancer) ResolverError(err error) { - b.childMu.Lock() - defer b.childMu.Unlock() - b.child.ResolverError(err) + b.child.resolverError(err) } func (b *outlierDetectionBalancer) updateSubConnState(sc balancer.SubConn, state balancer.SubConnState) { @@ -355,6 +350,7 @@ func (b *outlierDetectionBalancer) updateSubConnState(sc balancer.SubConn, state if state.ConnectivityState == connectivity.Shutdown { delete(b.scWrappers, scw.SubConn) } + scw.setLatestConnectivityState(state.ConnectivityState) b.scUpdateCh.Put(&scUpdate{ scw: scw, state: state, @@ -368,9 +364,7 @@ func (b *outlierDetectionBalancer) UpdateSubConnState(sc balancer.SubConn, state func (b *outlierDetectionBalancer) Close() { b.closed.Fire() <-b.done.Done() - b.childMu.Lock() - b.child.Close() - b.childMu.Unlock() + b.child.closeLB() b.scUpdateCh.Close() b.pickerUpdateCh.Close() @@ -383,9 +377,7 @@ func (b *outlierDetectionBalancer) Close() { } func (b *outlierDetectionBalancer) ExitIdle() { - b.childMu.Lock() - defer b.childMu.Unlock() - b.child.ExitIdle() + b.child.exitIdle() } // wrappedPicker delegates to the child policy's picker, and when the request @@ -475,10 +467,13 @@ func (b *outlierDetectionBalancer) NewSubConn(addrs []resolver.Address, opts bal return nil, err } scw := &subConnWrapper{ - SubConn: sc, - addresses: addrs, - scUpdateCh: b.scUpdateCh, - listener: oldListener, + SubConn: sc, + addresses: addrs, + scUpdateCh: b.scUpdateCh, + listener: oldListener, + latestRawConnectivityState: balancer.SubConnState{ConnectivityState: connectivity.Idle}, + latestHealthState: balancer.SubConnState{ConnectivityState: connectivity.Connecting}, + healthListenerEnabled: len(addrs) == 1 && pickfirstleaf.IsManagedByPickfirst(addrs[0]), } b.mu.Lock() defer b.mu.Unlock() @@ -596,34 +591,18 @@ func (b *outlierDetectionBalancer) Target() string { // if the SubConn is not ejected. func (b *outlierDetectionBalancer) handleSubConnUpdate(u *scUpdate) { scw := u.scw - scw.latestState = u.state - if !scw.ejected { - if scw.listener != nil { - b.childMu.Lock() - scw.listener(u.state) - b.childMu.Unlock() - } - } + scw.clearHealthListener() + b.child.updateSubConnState(scw, u.state) +} + +func (b *outlierDetectionBalancer) handleSubConnHealthUpdate(u *scHealthUpdate) { + b.child.updateSubConnHealthState(u.scw, u.state) } // handleEjectedUpdate handles any SubConns that get ejected/unejected, and // forwards the appropriate corresponding subConnState to the child policy. func (b *outlierDetectionBalancer) handleEjectedUpdate(u *ejectionUpdate) { - scw := u.scw - scw.ejected = u.isEjected - // If scw.latestState has never been written to will default to connectivity - // IDLE, which is fine. - stateToUpdate := scw.latestState - if u.isEjected { - stateToUpdate = balancer.SubConnState{ - ConnectivityState: connectivity.TransientFailure, - } - } - if scw.listener != nil { - b.childMu.Lock() - scw.listener(stateToUpdate) - b.childMu.Unlock() - } + b.child.handleEjectionUpdate(u) } // handleChildStateUpdate forwards the picker update wrapped in a wrapped picker @@ -696,6 +675,8 @@ func (b *outlierDetectionBalancer) run() { b.handleSubConnUpdate(u) case *ejectionUpdate: b.handleEjectedUpdate(u) + case *scHealthUpdate: + b.handleSubConnHealthUpdate(u) } case update, ok := <-b.pickerUpdateCh.Get(): if !ok { @@ -880,6 +861,69 @@ func (b *outlierDetectionBalancer) unejectAddress(addrInfo *addressInfo) { } } +// synchronizingBalancerWrapper serializes calls into balancer (to uphold the +// balancer.Balancer API guarantee of synchronous calls). It also ensures a +// consistent order of locking mutexes when using SubConn listeners to avoid +// deadlocks. +type synchronizingBalancerWrapper struct { + // mu should not be used directly from outside this struct, instead use + // methods defined on the struct. + mu sync.Mutex + lb *gracefulswitch.Balancer +} + +func (sbw *synchronizingBalancerWrapper) switchTo(builder balancer.Builder) error { + sbw.mu.Lock() + defer sbw.mu.Unlock() + return sbw.lb.SwitchTo(builder) +} + +func (sbw *synchronizingBalancerWrapper) updateClientConnState(state balancer.ClientConnState) error { + sbw.mu.Lock() + defer sbw.mu.Unlock() + return sbw.lb.UpdateClientConnState(state) +} + +func (sbw *synchronizingBalancerWrapper) resolverError(err error) { + sbw.mu.Lock() + defer sbw.mu.Unlock() + sbw.lb.ResolverError(err) +} + +func (sbw *synchronizingBalancerWrapper) closeLB() { + sbw.mu.Lock() + defer sbw.mu.Unlock() + sbw.lb.Close() +} + +func (sbw *synchronizingBalancerWrapper) exitIdle() { + sbw.mu.Lock() + defer sbw.mu.Unlock() + sbw.lb.ExitIdle() +} + +func (sbw *synchronizingBalancerWrapper) updateSubConnHealthState(scw *subConnWrapper, scs balancer.SubConnState) { + sbw.mu.Lock() + defer sbw.mu.Unlock() + scw.updateSubConnHealthState(scs) +} + +func (sbw *synchronizingBalancerWrapper) updateSubConnState(scw *subConnWrapper, scs balancer.SubConnState) { + sbw.mu.Lock() + defer sbw.mu.Unlock() + scw.updateSubConnConnectivityState(scs) +} + +func (sbw *synchronizingBalancerWrapper) handleEjectionUpdate(u *ejectionUpdate) { + sbw.mu.Lock() + defer sbw.mu.Unlock() + if u.isEjected { + u.scw.handleEjection() + } else { + u.scw.handleUnejection() + } +} + // addressInfo contains the runtime information about an address that pertains // to Outlier Detection. This struct and all of its fields is protected by // outlierDetectionBalancer.mu in the case where it is accessed through the diff --git a/xds/internal/balancer/outlierdetection/balancer_test.go b/xds/internal/balancer/outlierdetection/balancer_test.go index a80d4d9dee4f..ca07dcda0c88 100644 --- a/xds/internal/balancer/outlierdetection/balancer_test.go +++ b/xds/internal/balancer/outlierdetection/balancer_test.go @@ -31,17 +31,24 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "google.golang.org/grpc" "google.golang.org/grpc/balancer" + "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/internal/balancer/stub" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpctest" iserviceconfig "google.golang.org/grpc/internal/serviceconfig" + "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/internal/testutils" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" "google.golang.org/grpc/xds/internal/balancer/clusterimpl" + + testgrpc "google.golang.org/grpc/interop/grpc_testing" + testpb "google.golang.org/grpc/interop/grpc_testing" ) var ( @@ -1568,3 +1575,92 @@ func (s) TestConcurrentOperations(t *testing.T) { close(finished) wg.Wait() } + +// Test verifies that outlier detection doesn't eject subchannels created by +// the new pickfirst balancer when pickfirst is a non-leaf policy, i.e. not +// under a petiole policy. When pickfirst is not under a petiole policy, it will +// not register a health listener. pickfirst will still set the address +// attribute to disable ejection through the raw connectivity listener. When +// Outlier Detection processes a health update and sees the health listener is +// enabled but a health listener is not registered, it will drop the ejection +// update. +func (s) TestPickFirstHealthListenerDisabled(t *testing.T) { + backend := &stubserver.StubServer{ + EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { + return nil, errors.New("some error") + }, + } + if err := backend.StartServer(); err != nil { + t.Fatalf("Failed to start backend: %v", err) + } + defer backend.Stop() + t.Logf("Started bad TestService backend at: %q", backend.Address) + + // The interval is intentionally kept very large, the interval algorithm + // will be triggered manually. + odCfg := &LBConfig{ + Interval: iserviceconfig.Duration(300 * time.Second), + BaseEjectionTime: iserviceconfig.Duration(300 * time.Second), + MaxEjectionTime: iserviceconfig.Duration(500 * time.Second), + FailurePercentageEjection: &FailurePercentageEjection{ + Threshold: 50, + EnforcementPercentage: 100, + MinimumHosts: 0, + RequestVolume: 2, + }, + MaxEjectionPercent: 100, + ChildPolicy: &iserviceconfig.BalancerConfig{ + Name: pickfirstleaf.Name, + }, + } + + lbChan := make(chan *outlierDetectionBalancer, 1) + bf := stub.BalancerFuncs{ + Init: func(bd *stub.BalancerData) { + bd.Data = balancer.Get(Name).Build(bd.ClientConn, bd.BuildOptions) + lbChan <- bd.Data.(*outlierDetectionBalancer) + }, + Close: func(bd *stub.BalancerData) { + bd.Data.(balancer.Balancer).Close() + }, + UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { + ccs.BalancerConfig = odCfg + return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs) + }, + } + + stub.Register(t.Name(), bf) + + opts := []grpc.DialOption{ + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultServiceConfig(fmt.Sprintf(`{ "loadBalancingConfig": [{%q: {}}] }`, t.Name())), + } + cc, err := grpc.NewClient(backend.Address, opts...) + if err != nil { + t.Fatalf("grpc.NewClient() failed: %v", err) + } + defer cc.Close() + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + testServiceClient := testgrpc.NewTestServiceClient(cc) + testServiceClient.EmptyCall(ctx, &testpb.Empty{}) + testutils.AwaitState(ctx, t, cc, connectivity.Ready) + + // Failing request should not cause ejection. + testServiceClient.EmptyCall(ctx, &testpb.Empty{}) + testServiceClient.EmptyCall(ctx, &testpb.Empty{}) + testServiceClient.EmptyCall(ctx, &testpb.Empty{}) + testServiceClient.EmptyCall(ctx, &testpb.Empty{}) + + // Run the interval algorithm. + select { + case <-ctx.Done(): + t.Fatal("Timed out waiting for the outlier detection LB policy to be built.") + case od := <-lbChan: + od.intervalTimerAlgorithm() + } + + shortCtx, shortCancel := context.WithTimeout(ctx, defaultTestShortTimeout) + defer shortCancel() + testutils.AwaitNoStateChange(shortCtx, t, cc, connectivity.Ready) +} diff --git a/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go b/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go index 35c4d75301b3..ec087eb08b53 100644 --- a/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go +++ b/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go @@ -28,8 +28,10 @@ import ( "github.com/google/go-cmp/cmp" "google.golang.org/grpc" + "google.golang.org/grpc/balancer/weightedroundrobin" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpctest" "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/peer" @@ -43,7 +45,18 @@ import ( _ "google.golang.org/grpc/xds/internal/balancer/outlierdetection" // To register helper functions which register/unregister Outlier Detection LB Policy. ) -var defaultTestTimeout = 5 * time.Second +var ( + defaultTestTimeout = 5 * time.Second + leafPolicyName = "round_robin" +) + +func init() { + // Test the health listener code path for ejection when the experimental + // pickfirst is enabled. + if envconfig.NewPickFirstEnabled { + leafPolicyName = weightedroundrobin.Name + } +} type s struct { grpctest.Tester @@ -155,50 +168,50 @@ func (s) TestOutlierDetectionAlgorithmsE2E(t *testing.T) { }{ { name: "Success Rate Algorithm", - odscJSON: ` -{ - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "successRateEjection": { - "stdevFactor": 50, - "enforcementPercentage": 100, - "minimumHosts": 3, - "requestVolume": 5 - }, - "childPolicy": [{"round_robin": {}}] - } - } - ] -}`, + odscJSON: fmt.Sprintf(` + { + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "successRateEjection": { + "stdevFactor": 50, + "enforcementPercentage": 100, + "minimumHosts": 3, + "requestVolume": 5 + }, + "childPolicy": [{"%s": {}}] + } + } + ] + }`, leafPolicyName), }, { name: "Failure Percentage Algorithm", - odscJSON: ` -{ - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "failurePercentageEjection": { - "threshold": 50, - "enforcementPercentage": 100, - "minimumHosts": 3, - "requestVolume": 5 - }, - "childPolicy": [{"round_robin": {}} - ] - } - } - ] -}`, + odscJSON: fmt.Sprintf(` + { + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "failurePercentageEjection": { + "threshold": 50, + "enforcementPercentage": 100, + "minimumHosts": 3, + "requestVolume": 5 + }, + "childPolicy": [{"%s": {}} + ] + } + } + ] + }`, leafPolicyName), }, } for _, test := range tests { @@ -273,20 +286,20 @@ func (s) TestNoopConfiguration(t *testing.T) { mr := manual.NewBuilderWithScheme("od-e2e") defer mr.Close() - noopODServiceConfigJSON := ` -{ - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "childPolicy": [{"round_robin": {}}] - } - } - ] -}` + noopODServiceConfigJSON := fmt.Sprintf(` + { + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "childPolicy": [{"%s": {}}] + } + } + ] + }`, leafPolicyName) sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(noopODServiceConfigJSON) // The full list of addresses. fullAddresses := []resolver.Address{ @@ -321,26 +334,26 @@ func (s) TestNoopConfiguration(t *testing.T) { // specifies to count RPC's and eject upstreams. Due to the balancer no // longer being a noop, it should eject any unhealthy addresses as specified // by the failure percentage portion of the configuration. - countingODServiceConfigJSON := ` -{ - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "failurePercentageEjection": { - "threshold": 50, - "enforcementPercentage": 100, - "minimumHosts": 3, - "requestVolume": 5 - }, - "childPolicy": [{"round_robin": {}}] - } - } - ] -}` + countingODServiceConfigJSON := fmt.Sprintf(` + { + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "failurePercentageEjection": { + "threshold": 50, + "enforcementPercentage": 100, + "minimumHosts": 3, + "requestVolume": 5 + }, + "childPolicy": [{"%s": {}}] + } + } + ] + }`, leafPolicyName) sc = internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(countingODServiceConfigJSON) mr.UpdateState(resolver.State{ diff --git a/xds/internal/balancer/outlierdetection/subconn_wrapper.go b/xds/internal/balancer/outlierdetection/subconn_wrapper.go index 0fa422d8f262..7d710fde1b2a 100644 --- a/xds/internal/balancer/outlierdetection/subconn_wrapper.go +++ b/xds/internal/balancer/outlierdetection/subconn_wrapper.go @@ -19,9 +19,11 @@ package outlierdetection import ( "fmt" + "sync" "unsafe" "google.golang.org/grpc/balancer" + "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/buffer" "google.golang.org/grpc/resolver" ) @@ -31,23 +33,54 @@ import ( // whether or not this SubConn is ejected. type subConnWrapper struct { balancer.SubConn - listener func(balancer.SubConnState) - // addressInfo is a pointer to the subConnWrapper's corresponding address - // map entry, if the map entry exists. + // map entry, if the map entry exists. It is accessed atomically. addressInfo unsafe.Pointer // *addressInfo + // The following fields are set during object creation and read-only after + // that. + + listener func(balancer.SubConnState) + // healthListenerEnabled indicates whether the leaf LB policy is using a + // generic health listener. When enabled, ejection updates are sent via the + // health listener instead of the connectivity listener. Once Dualstack + // changes are complete, all SubConns will be created by pickfirst which + // uses the health listener. + // TODO: https://github.com/grpc/grpc-go/issues/7915 - Once Dualstack + // changes are complete, all SubConns will be created by pick_first and + // outlier detection will only use the health listener for ejection and + // this field can be removed. + healthListenerEnabled bool + + scUpdateCh *buffer.Unbounded + + // The following fields are only referenced in the context of a work + // serializing buffer and don't need to be protected by a mutex. + // These two pieces of state will reach eventual consistency due to sync in // run(), and child will always have the correctly updated SubConnState. - // latestState is the latest state update from the underlying SubConn. This - // is used whenever a SubConn gets unejected. - latestState balancer.SubConnState - ejected bool - scUpdateCh *buffer.Unbounded + ejected bool // addresses is the list of address(es) this SubConn was created with to // help support any change in address(es) addresses []resolver.Address + // latestHealthState is tracked to update the child policy during + // unejection. + latestHealthState balancer.SubConnState + // latestRawConnectivityState is tracked to update the child policy during + // unejection. + latestRawConnectivityState balancer.SubConnState + + // Access to the following fields are protected by a mutex. These fields + // should not be accessed from outside this file, instead use methods + // defined on the struct. + mu sync.Mutex + healthListener func(balancer.SubConnState) + // latestReceivedConnectivityState is the SubConn's most recent connectivity + // state received. It may not be delivered to the child balancer yet. It is + // used to ensure a health listener is registered with the SubConn only when + // the SubConn is READY. + latestReceivedConnectivityState connectivity.State } // eject causes the wrapper to report a state update with the TRANSIENT_FAILURE @@ -72,3 +105,108 @@ func (scw *subConnWrapper) uneject() { func (scw *subConnWrapper) String() string { return fmt.Sprintf("%+v", scw.addresses) } + +func (scw *subConnWrapper) RegisterHealthListener(listener func(balancer.SubConnState)) { + // gRPC currently supports two mechanisms that provide a health signal for + // a connection: client-side health checking and outlier detection. Earlier + // both these mechanisms signaled unhealthiness by setting the subchannel + // state to TRANSIENT_FAILURE. As part of the dualstack changes to make + // pick_first the universal leaf policy (see A61), both these mechanisms + // started using the new health listener to make health signal visible to + // the petiole policies without affecting the underlying connectivity + // management of the pick_first policy + if !scw.healthListenerEnabled { + logger.Errorf("Health listener unexpectedly registered on SubConn %v.", scw) + return + } + + scw.mu.Lock() + defer scw.mu.Unlock() + + if scw.latestReceivedConnectivityState != connectivity.Ready { + return + } + scw.healthListener = listener + if listener == nil { + scw.SubConn.RegisterHealthListener(nil) + return + } + + scw.SubConn.RegisterHealthListener(func(scs balancer.SubConnState) { + scw.scUpdateCh.Put(&scHealthUpdate{ + scw: scw, + state: scs, + }) + }) +} + +// updateSubConnHealthState stores the latest health state for unejection and +// sends updates the health listener. +func (scw *subConnWrapper) updateSubConnHealthState(scs balancer.SubConnState) { + scw.latestHealthState = scs + if scw.ejected { + return + } + scw.mu.Lock() + defer scw.mu.Unlock() + if scw.healthListener != nil { + scw.healthListener(scs) + } +} + +// updateSubConnConnectivityState stores the latest connectivity state for +// unejection and updates the raw connectivity listener. +func (scw *subConnWrapper) updateSubConnConnectivityState(scs balancer.SubConnState) { + scw.latestRawConnectivityState = scs + // If the raw connectivity listener is used for ejection, and the SubConn is + // ejected, don't send the update. + if scw.ejected && !scw.healthListenerEnabled { + return + } + if scw.listener != nil { + scw.listener(scs) + } +} + +func (scw *subConnWrapper) clearHealthListener() { + scw.mu.Lock() + defer scw.mu.Unlock() + scw.healthListener = nil +} + +func (scw *subConnWrapper) handleUnejection() { + scw.ejected = false + if !scw.healthListenerEnabled { + // If scw.latestRawConnectivityState has never been written to will + // default to connectivity IDLE, which is fine. + scw.updateSubConnConnectivityState(scw.latestRawConnectivityState) + return + } + // If scw.latestHealthState has never been written to will use the health + // state CONNECTING set during object creation. + scw.updateSubConnHealthState(scw.latestHealthState) +} + +func (scw *subConnWrapper) handleEjection() { + scw.ejected = true + stateToUpdate := balancer.SubConnState{ + ConnectivityState: connectivity.TransientFailure, + } + if !scw.healthListenerEnabled { + if scw.listener != nil { + scw.listener(stateToUpdate) + } + return + } + scw.mu.Lock() + defer scw.mu.Unlock() + if scw.healthListener != nil { + scw.healthListener(stateToUpdate) + } +} + +func (scw *subConnWrapper) setLatestConnectivityState(state connectivity.State) { + scw.mu.Lock() + defer scw.mu.Unlock() + scw.latestReceivedConnectivityState = state +} From 8a0db4c1d0d1d9ded83ad8dbde75a2c1ff7622c0 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:05:30 +0000 Subject: [PATCH 18/35] Revert "test: switching to stubserver in tests instead of testservice (#7925)" This reverts commit 5541486478d4c535c24e9e520536b66de3e1fcc3. --- test/balancer_test.go | 52 +++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/test/balancer_test.go b/test/balancer_test.go index 9cb41e5a6a2c..bb45e11d97c1 100644 --- a/test/balancer_test.go +++ b/test/balancer_test.go @@ -417,15 +417,11 @@ func (s) TestAddressAttributesInNewSubConn(t *testing.T) { if err != nil { t.Fatal(err) } - stub := &stubserver.StubServer{ - Listener: lis, - EmptyCallF: func(_ context.Context, _ *testpb.Empty) (*testpb.Empty, error) { - return &testpb.Empty{}, nil - }, - S: grpc.NewServer(), - } - stubserver.StartTestService(t, stub) - defer stub.S.Stop() + + s := grpc.NewServer() + testgrpc.RegisterTestServiceServer(s, &testServer{}) + go s.Serve(lis) + defer s.Stop() t.Logf("Started gRPC server at %s...", lis.Addr().String()) creds := &attrTransportCreds{} @@ -552,16 +548,15 @@ func (s) TestServersSwap(t *testing.T) { if err != nil { t.Fatalf("Error while listening. Err: %v", err) } - - stub := &stubserver.StubServer{ - Listener: lis, - UnaryCallF: func(_ context.Context, _ *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + s := grpc.NewServer() + ts := &funcServer{ + unaryCall: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { return &testpb.SimpleResponse{Username: username}, nil }, - S: grpc.NewServer(), } - stubserver.StartTestService(t, stub) - return lis.Addr().String(), stub.S.Stop + testgrpc.RegisterTestServiceServer(s, ts) + go s.Serve(lis) + return lis.Addr().String(), s.Stop } const one = "1" addr1, cleanup := reg(one) @@ -608,16 +603,16 @@ func (s) TestWaitForReady(t *testing.T) { if err != nil { t.Fatalf("Error while listening. Err: %v", err) } + s := grpc.NewServer() + defer s.Stop() const one = "1" - stub := &stubserver.StubServer{ - Listener: lis, - UnaryCallF: func(_ context.Context, _ *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { + ts := &funcServer{ + unaryCall: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { return &testpb.SimpleResponse{Username: one}, nil }, - S: grpc.NewServer(), } - stubserver.StartTestService(t, stub) - defer stub.S.Stop() + testgrpc.RegisterTestServiceServer(s, ts) + go s.Serve(lis) // Initialize client r := manual.NewBuilderWithScheme("whatever") @@ -745,15 +740,10 @@ func (s) TestAuthorityInBuildOptions(t *testing.T) { t.Fatal(err) } - stub := &stubserver.StubServer{ - Listener: lis, - EmptyCallF: func(_ context.Context, _ *testpb.Empty) (*testpb.Empty, error) { - return &testpb.Empty{}, nil - }, - S: grpc.NewServer(), - } - stubserver.StartTestService(t, stub) - defer stub.S.Stop() + s := grpc.NewServer() + testgrpc.RegisterTestServiceServer(s, &testServer{}) + go s.Serve(lis) + defer s.Stop() t.Logf("Started gRPC server at %s...", lis.Addr().String()) r := manual.NewBuilderWithScheme("whatever") From cf12acebee5906184e16a7691b0dc142ffc73516 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:13:24 +0000 Subject: [PATCH 19/35] Revert "cleanup: replace dial with newclient (#7920)" This reverts commit a21e192176002a217aaa1ff2a026ad3316159130. --- balancer/grpclb/grpclb_test.go | 39 ++++++++++++++++------------------ balancer/rls/picker_test.go | 12 +++++------ resolver_balancer_ext_test.go | 10 ++++----- test/creds_test.go | 29 ++++++++++++------------- test/end2end_test.go | 2 +- 5 files changed, 42 insertions(+), 50 deletions(-) diff --git a/balancer/grpclb/grpclb_test.go b/balancer/grpclb/grpclb_test.go index e234ace6576f..62dc947e0ee5 100644 --- a/balancer/grpclb/grpclb_test.go +++ b/balancer/grpclb/grpclb_test.go @@ -460,7 +460,7 @@ func (s) TestGRPCLB_Basic(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() @@ -517,7 +517,7 @@ func (s) TestGRPCLB_Weighted(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() @@ -597,7 +597,7 @@ func (s) TestGRPCLB_DropRequest(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -769,7 +769,7 @@ func (s) TestGRPCLB_BalancerDisconnects(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -940,7 +940,7 @@ func (s) TestGRPCLB_ExplicitFallback(t *testing.T) { } cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -1008,12 +1008,11 @@ func (s) TestGRPCLB_FallBackWithNoServerAddress(t *testing.T) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), } - cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) + cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() - cc.Connect() testC := testgrpc.NewTestServiceClient(cc) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -1103,11 +1102,10 @@ func (s) TestGRPCLB_PickFirst(t *testing.T) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), } - cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) + cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend: %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } - cc.Connect() defer cc.Close() // Push a service config with grpclb as the load balancing policy and @@ -1200,7 +1198,7 @@ func (s) TestGRPCLB_BackendConnectionErrorPropagation(t *testing.T) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer)) if err != nil { - t.Fatalf("Failed to create a client for the backend: %v", err) + t.Fatalf("Failed to create new client to the backend %v", err) } defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -1243,11 +1241,10 @@ func testGRPCLBEmptyServerList(t *testing.T, svcfg string) { grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), } - cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, dopts...) + cc, err := grpc.DialContext(ctx, r.Scheme()+":///"+beServerName, dopts...) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } - cc.Connect() defer cc.Close() testC := testgrpc.NewTestServiceClient(cc) @@ -1314,16 +1311,15 @@ func (s) TestGRPCLBWithTargetNameFieldInConfig(t *testing.T) { // Push the backend address to the remote balancer. tss.ls.sls <- sl - cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, + cc, err := grpc.Dial(r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), grpc.WithTransportCredentials(&serverNameCheckCreds{}), grpc.WithContextDialer(fakeNameDialer), grpc.WithUserAgent(testUserAgent)) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } defer cc.Close() - cc.Connect() testC := testgrpc.NewTestServiceClient(cc) // Push a resolver update with grpclb configuration which does not contain the @@ -1422,14 +1418,15 @@ func runAndCheckStats(t *testing.T, drop bool, statsChan chan *lbpb.ClientStats, tss.ls.statsDura = 100 * time.Millisecond creds := serverNameCheckCreds{} - cc, err := grpc.NewClient(r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + cc, err := grpc.DialContext(ctx, r.Scheme()+":///"+beServerName, grpc.WithResolvers(r), grpc.WithTransportCredentials(&creds), grpc.WithPerRPCCredentials(failPreRPCCred{}), grpc.WithContextDialer(fakeNameDialer)) if err != nil { - t.Fatalf("Failed to create a client for the backend %v", err) + t.Fatalf("Failed to dial to the backend %v", err) } - cc.Connect() defer cc.Close() rstate := resolver.State{ServiceConfig: r.CC.ParseServiceConfig(grpclbConfig)} diff --git a/balancer/rls/picker_test.go b/balancer/rls/picker_test.go index a0bdbc827921..cb08c433f9e8 100644 --- a/balancer/rls/picker_test.go +++ b/balancer/rls/picker_test.go @@ -267,9 +267,9 @@ func (s) Test_RLSDefaultTargetPicksMetric(t *testing.T) { r := startManualResolverWithConfig(t, rlsConfig) tmr := stats.NewTestMetricsRecorder() - cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) + cc, err := grpc.Dial(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) if err != nil { - t.Fatalf("grpc.NewClient() failed: %v", err) + t.Fatalf("grpc.Dial() failed: %v", err) } defer cc.Close() @@ -314,9 +314,9 @@ func (s) Test_RLSTargetPicksMetric(t *testing.T) { tmr := stats.NewTestMetricsRecorder() // Dial the backend. - cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) + cc, err := grpc.Dial(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) if err != nil { - t.Fatalf("grpc.NewClient() failed: %v", err) + t.Fatalf("grpc.Dial() failed: %v", err) } defer cc.Close() @@ -352,9 +352,9 @@ func (s) Test_RLSFailedPicksMetric(t *testing.T) { tmr := stats.NewTestMetricsRecorder() // Dial the backend. - cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) + cc, err := grpc.Dial(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithStatsHandler(tmr)) if err != nil { - t.Fatalf("grpc.NewClient() failed: %v", err) + t.Fatalf("grpc.Dial() failed: %v", err) } defer cc.Close() diff --git a/resolver_balancer_ext_test.go b/resolver_balancer_ext_test.go index 75fac51a66db..417a5781ef80 100644 --- a/resolver_balancer_ext_test.go +++ b/resolver_balancer_ext_test.go @@ -66,12 +66,11 @@ func (s) TestResolverBalancerInteraction(t *testing.T) { rb.ResolveNowCallback = func(resolver.ResolveNowOptions) { close(rnCh) } resolver.Register(rb) - cc, err := grpc.NewClient(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) + cc, err := grpc.Dial(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - t.Fatalf("grpc.NewClient error: %v", err) + t.Fatalf("grpc.Dial error: %v", err) } defer cc.Close() - cc.Connect() select { case <-rnCh: case <-time.After(defaultTestTimeout): @@ -110,12 +109,11 @@ func (s) TestResolverBuildFailure(t *testing.T) { resolver.Register(&resolverBuilderWithErr{errCh: resErrCh, scheme: name}) resErrCh <- nil - cc, err := grpc.NewClient(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) + cc, err := grpc.Dial(name+":///", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { - t.Fatalf("grpc.NewClient error: %v", err) + t.Fatalf("grpc.Dial error: %v", err) } defer cc.Close() - cc.Connect() enterIdle(cc) const errStr = "test error from resolver builder" t.Log("pushing res err") diff --git a/test/creds_test.go b/test/creds_test.go index fe8b552e719c..74ee24c02965 100644 --- a/test/creds_test.go +++ b/test/creds_test.go @@ -236,9 +236,9 @@ func (s) TestFailFastRPCErrorOnBadCertificates(t *testing.T) { opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() - cc, err := grpc.NewClient(te.srvAddr, opts...) + cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) if err != nil { - t.Fatalf("NewClient(_) = %v, want %v", err, nil) + t.Fatalf("Dial(_) = %v, want %v", err, nil) } defer cc.Close() @@ -255,9 +255,11 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { defer te.tearDown() opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} - cc, err := grpc.NewClient(te.srvAddr, opts...) + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) if err != nil { - t.Fatalf("NewClient(_) = %v, want %v", err, nil) + t.Fatalf("Dial(_) = %v, want %v", err, nil) } defer cc.Close() @@ -270,9 +272,7 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure) tc := testgrpc.NewTestServiceClient(cc) - // Use a short context as WaitForReady waits for context expiration before - // failing the RPC. - ctx, cancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) + ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) defer cancel() if _, err = tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); !strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want err.Error() contains %q", err, clientAlwaysFailCredErrorMsg) @@ -438,12 +438,11 @@ func (s) TestCredsHandshakeAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) } defer cc.Close() - cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String()}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -471,12 +470,11 @@ func (s) TestCredsHandshakeServerNameAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) } defer cc.Close() - cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String(), ServerName: testServerName}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -527,12 +525,11 @@ func (s) TestServerCredsDispatch(t *testing.T) { go s.Serve(lis) defer s.Stop() - cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(cred)) + cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(cred)) if err != nil { - t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) } defer cc.Close() - cc.Connect() rawConn := cred.getRawConn() // Give grpc a chance to see the error and potentially close the connection. diff --git a/test/end2end_test.go b/test/end2end_test.go index 19972ecebe17..2238f8f12422 100644 --- a/test/end2end_test.go +++ b/test/end2end_test.go @@ -609,7 +609,7 @@ func (te *test) listenAndServe(ts testgrpc.TestServiceServer, listen func(networ if te.serverInitialConnWindowSize > 0 { sopts = append(sopts, grpc.InitialConnWindowSize(te.serverInitialConnWindowSize)) } - la := ":0" + la := "localhost:0" switch te.e.network { case "unix": la = "/tmp/testsock" + fmt.Sprintf("%d", time.Now().UnixNano()) From 0e927fb4bd6906a63922f7dc7c68de2990f9d40a Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:13:41 +0000 Subject: [PATCH 20/35] Revert "deps: update crypto dependency to resolve CVE-2024-45337 (#7956)" This reverts commit 09132bfd8cd5158bc68bff9441308b7654a47dc9. --- examples/go.mod | 2 +- examples/go.sum | 3 +-- gcp/observability/go.mod | 16 +++++++-------- gcp/observability/go.sum | 29 +++++++++++++--------------- interop/observability/go.mod | 16 +++++++-------- interop/observability/go.sum | 29 +++++++++++++--------------- security/advancedtls/examples/go.mod | 2 +- security/advancedtls/examples/go.sum | 4 ++-- security/advancedtls/go.mod | 2 +- security/advancedtls/go.sum | 4 ++-- 10 files changed, 50 insertions(+), 57 deletions(-) diff --git a/examples/go.mod b/examples/go.mod index d2d1f719d8c0..51c2f2b1ff83 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -68,7 +68,7 @@ require ( go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/sdk v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.30.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect diff --git a/examples/go.sum b/examples/go.sum index 02577c25e514..9cb58041e4ba 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1159,9 +1159,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/gcp/observability/go.mod b/gcp/observability/go.mod index 4053ed38880d..d85b4b73eed7 100644 --- a/gcp/observability/go.mod +++ b/gcp/observability/go.mod @@ -9,16 +9,16 @@ require ( github.com/google/uuid v1.6.0 go.opencensus.io v0.24.0 golang.org/x/oauth2 v0.24.0 - google.golang.org/api v0.213.0 + google.golang.org/api v0.201.0 google.golang.org/grpc v1.67.1 google.golang.org/grpc/stats/opencensus v1.0.0 ) require ( cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.13.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/auth v0.9.8 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/compute/metadata v0.5.2 // indirect cloud.google.com/go/longrunning v0.6.1 // indirect cloud.google.com/go/monitoring v1.21.1 // indirect cloud.google.com/go/trace v1.11.1 // indirect @@ -43,21 +43,21 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.14.0 // indirect + github.com/googleapis/gax-go/v2 v2.13.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.30.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.8.0 // indirect + golang.org/x/time v0.7.0 // indirect google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/gcp/observability/go.sum b/gcp/observability/go.sum index 552da2bd29a8..72588140a0e7 100644 --- a/gcp/observability/go.sum +++ b/gcp/observability/go.sum @@ -118,10 +118,10 @@ cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEar cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= -cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= -cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= -cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= +cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= @@ -219,9 +219,8 @@ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1h cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -987,8 +986,8 @@ github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38 github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= -github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -1134,9 +1133,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1455,8 +1453,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1598,8 +1596,8 @@ google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZ google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.213.0 h1:KmF6KaDyFqB417T68tMPbVmmwtIXs2VB60OJKIHB0xQ= -google.golang.org/api v0.213.0/go.mod h1:V0T5ZhNUUNpYAlL306gFZPFt5F5D/IeyLoktduYYnvQ= +google.golang.org/api v0.201.0 h1:+7AD9JNM3tREtawRMu8sOjSbb8VYcYXJG/2eEOmfDu0= +google.golang.org/api v0.201.0/go.mod h1:HVY0FCHVs89xIW9fzf/pBvOEm+OolHa86G/txFezyq4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1773,9 +1771,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/stats/opencensus v1.0.0 h1:evSYcRZaSToQp+borzWE52+03joezZeXcKJvZDfkUJA= google.golang.org/grpc/stats/opencensus v1.0.0/go.mod h1:FhdkeYvN43wLYUnapVuRJJ9JXkNwe403iLUW2LKSnjs= diff --git a/interop/observability/go.mod b/interop/observability/go.mod index 781ec330ac86..07bcfcee15bc 100644 --- a/interop/observability/go.mod +++ b/interop/observability/go.mod @@ -9,9 +9,9 @@ require ( require ( cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.13.0 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect - cloud.google.com/go/compute/metadata v0.6.0 // indirect + cloud.google.com/go/auth v0.9.8 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/compute/metadata v0.5.2 // indirect cloud.google.com/go/logging v1.12.0 // indirect cloud.google.com/go/longrunning v0.6.1 // indirect cloud.google.com/go/monitoring v1.21.1 // indirect @@ -41,24 +41,24 @@ require ( github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.14.0 // indirect + github.com/googleapis/gax-go/v2 v2.13.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.32.0 // indirect go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.30.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.8.0 // indirect - google.golang.org/api v0.213.0 // indirect + golang.org/x/time v0.7.0 // indirect + google.golang.org/api v0.201.0 // indirect google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect google.golang.org/grpc/stats/opencensus v1.0.0 // indirect google.golang.org/protobuf v1.35.2 // indirect ) diff --git a/interop/observability/go.sum b/interop/observability/go.sum index cc3c70245cf6..054a3377d46c 100644 --- a/interop/observability/go.sum +++ b/interop/observability/go.sum @@ -118,10 +118,10 @@ cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEar cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs= -cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q= -cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU= -cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/auth v0.9.8 h1:+CSJ0Gw9iVeSENVCKJoLHhdUykDgXSc4Qn+gu2BRtR8= +cloud.google.com/go/auth v0.9.8/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= @@ -219,9 +219,8 @@ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1h cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= -cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I= -cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -990,8 +989,8 @@ github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38 github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= -github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= @@ -1137,9 +1136,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1458,8 +1456,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1601,8 +1599,8 @@ google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZ google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.213.0 h1:KmF6KaDyFqB417T68tMPbVmmwtIXs2VB60OJKIHB0xQ= -google.golang.org/api v0.213.0/go.mod h1:V0T5ZhNUUNpYAlL306gFZPFt5F5D/IeyLoktduYYnvQ= +google.golang.org/api v0.201.0 h1:+7AD9JNM3tREtawRMu8sOjSbb8VYcYXJG/2eEOmfDu0= +google.golang.org/api v0.201.0/go.mod h1:HVY0FCHVs89xIW9fzf/pBvOEm+OolHa86G/txFezyq4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1776,9 +1774,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240521202816-d264139d666e/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/security/advancedtls/examples/go.mod b/security/advancedtls/examples/go.mod index 3f9223147b30..43a16752b17c 100644 --- a/security/advancedtls/examples/go.mod +++ b/security/advancedtls/examples/go.mod @@ -9,7 +9,7 @@ require ( ) require ( - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.30.0 // indirect golang.org/x/net v0.32.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/security/advancedtls/examples/go.sum b/security/advancedtls/examples/go.sum index cbf4886fe7f5..ec9f8e8372e7 100644 --- a/security/advancedtls/examples/go.sum +++ b/security/advancedtls/examples/go.sum @@ -18,8 +18,8 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= diff --git a/security/advancedtls/go.mod b/security/advancedtls/go.mod index 3e9e4f09168c..5cc89cbb74d7 100644 --- a/security/advancedtls/go.mod +++ b/security/advancedtls/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/google/go-cmp v0.6.0 - golang.org/x/crypto v0.31.0 + golang.org/x/crypto v0.30.0 google.golang.org/grpc v1.68.1 google.golang.org/grpc/examples v0.0.0-20201112215255-90f1b3ee835b ) diff --git a/security/advancedtls/go.sum b/security/advancedtls/go.sum index cbf4886fe7f5..ec9f8e8372e7 100644 --- a/security/advancedtls/go.sum +++ b/security/advancedtls/go.sum @@ -18,8 +18,8 @@ go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiy go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= From ee88fc03ecb3d55be6cf78c793f79cafd724c6a4 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:15:50 +0000 Subject: [PATCH 21/35] Revert "envconfig: enable xDS client fallback by default (#7949)" This reverts commit 46faf72fda5b68e7832024b2308c7e5f66a7d609. --- internal/envconfig/envconfig.go | 2 +- internal/xds/bootstrap/bootstrap_test.go | 10 +++++++--- xds/internal/xdsclient/tests/fallback_test.go | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/internal/envconfig/envconfig.go b/internal/envconfig/envconfig.go index 1e42b6fdc872..6e7dd6b77270 100644 --- a/internal/envconfig/envconfig.go +++ b/internal/envconfig/envconfig.go @@ -49,7 +49,7 @@ var ( // XDSFallbackSupport is the env variable that controls whether support for // xDS fallback is turned on. If this is unset or is false, only the first // xDS server in the list of server configs will be used. - XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", true) + XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", false) // NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used // instead of the exiting pickfirst implementation. This can be enabled by // setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST" diff --git a/internal/xds/bootstrap/bootstrap_test.go b/internal/xds/bootstrap/bootstrap_test.go index d057197804d6..302e281405ee 100644 --- a/internal/xds/bootstrap/bootstrap_test.go +++ b/internal/xds/bootstrap/bootstrap_test.go @@ -429,6 +429,10 @@ func (s) TestGetConfiguration_Success(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { + origFallbackEnv := envconfig.XDSFallbackSupport + envconfig.XDSFallbackSupport = true + defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() + testGetConfigurationWithFileNameEnv(t, test.name, false, test.wantConfig) testGetConfigurationWithFileContentEnv(t, test.name, false, test.wantConfig) }) @@ -1198,9 +1202,9 @@ func (s) TestNode_ToProto(t *testing.T) { // Tests the case where the xDS fallback env var is set to false, and verifies // that only the first server from the list of server configurations is used. func (s) TestGetConfiguration_FallbackDisabled(t *testing.T) { - origFallbackEnv := envconfig.XDSFallbackSupport - envconfig.XDSFallbackSupport = false - defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() + // TODO(easwars): Default value of "GRPC_EXPERIMENTAL_XDS_FALLBACK" + // env var is currently false. When the default is changed to true, + // explicitly set it to false here. cancel := setupBootstrapOverride(map[string]string{ "multipleXDSServers": ` diff --git a/xds/internal/xdsclient/tests/fallback_test.go b/xds/internal/xdsclient/tests/fallback_test.go index 19f00de4426f..18c382dbd146 100644 --- a/xds/internal/xdsclient/tests/fallback_test.go +++ b/xds/internal/xdsclient/tests/fallback_test.go @@ -30,6 +30,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/internal/testutils" "google.golang.org/grpc/internal/testutils/xds/e2e" @@ -78,6 +79,11 @@ func waitForRPCsToReachBackend(ctx context.Context, client testgrpc.TestServiceC // to it. The test also verifies that when all requested resources are cached // from the primary, fallback is not triggered when the connection goes down. func (s) TestFallback_OnStartup(t *testing.T) { + // Enable fallback env var. + origFallbackEnv := envconfig.XDSFallbackSupport + envconfig.XDSFallbackSupport = true + defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() + ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout) defer cancel() @@ -242,6 +248,11 @@ func (s) TestFallback_OnStartup(t *testing.T) { // Tests fallback when the primary management server fails during an update. func (s) TestFallback_MidUpdate(t *testing.T) { + // Enable fallback env var. + origFallbackEnv := envconfig.XDSFallbackSupport + envconfig.XDSFallbackSupport = true + defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() + ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout) defer cancel() @@ -443,6 +454,11 @@ func (s) TestFallback_MidUpdate(t *testing.T) { // Tests fallback when the primary management server fails during startup. func (s) TestFallback_MidStartup(t *testing.T) { + // Enable fallback env var. + origFallbackEnv := envconfig.XDSFallbackSupport + envconfig.XDSFallbackSupport = true + defer func() { envconfig.XDSFallbackSupport = origFallbackEnv }() + ctx, cancel := context.WithTimeout(context.Background(), defaultFallbackTestTimeout) defer cancel() From 4ef6aab76e76dd924bba63564cd555b94fae8f74 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:15:55 +0000 Subject: [PATCH 22/35] Revert "test: Add a test for decompression exceeding max receive message size (#7938)" This reverts commit bd4989a3473fd6f073d40123cbc1fa6668c4e35c. --- test/compressor_test.go | 59 ----------------------------------------- 1 file changed, 59 deletions(-) diff --git a/test/compressor_test.go b/test/compressor_test.go index 0a629bcecdb5..0495a06f0968 100644 --- a/test/compressor_test.go +++ b/test/compressor_test.go @@ -785,62 +785,3 @@ func (s) TestGzipBadChecksum(t *testing.T) { t.Errorf("ss.Client.UnaryCall(_) = _, %v\n\twant: _, status(codes.Internal, contains %q)", err, gzip.ErrChecksum) } } - -// fakeCompressor returns a messages of a configured size, irrespective of the -// input. -type fakeCompressor struct { - decompressedMessageSize int -} - -func (f *fakeCompressor) Compress(w io.Writer) (io.WriteCloser, error) { - return nopWriteCloser{w}, nil -} - -func (f *fakeCompressor) Decompress(io.Reader) (io.Reader, error) { - return bytes.NewReader(make([]byte, f.decompressedMessageSize)), nil -} - -func (f *fakeCompressor) Name() string { - // Use the name of an existing compressor to avoid interactions with other - // tests since compressors can't be un-registered. - return "gzip" -} - -type nopWriteCloser struct { - io.Writer -} - -func (nopWriteCloser) Close() error { - return nil -} - -// TestDecompressionExceedsMaxMessageSize uses a fake compressor that produces -// messages of size 100 bytes on decompression. A server is started with the -// max receive message size restricted to 99 bytes. The test verifies that the -// client receives a ResourceExhausted response from the server. -func (s) TestDecompressionExceedsMaxMessageSize(t *testing.T) { - oldC := encoding.GetCompressor("gzip") - defer func() { - encoding.RegisterCompressor(oldC) - }() - const messageLen = 100 - encoding.RegisterCompressor(&fakeCompressor{decompressedMessageSize: messageLen}) - ss := &stubserver.StubServer{ - UnaryCallF: func(context.Context, *testpb.SimpleRequest) (*testpb.SimpleResponse, error) { - return &testpb.SimpleResponse{}, nil - }, - } - if err := ss.Start([]grpc.ServerOption{grpc.MaxRecvMsgSize(messageLen - 1)}); err != nil { - t.Fatalf("Error starting endpoint server: %v", err) - } - defer ss.Stop() - - ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) - defer cancel() - - req := &testpb.SimpleRequest{Payload: &testpb.Payload{}} - _, err := ss.Client.UnaryCall(ctx, req, grpc.UseCompressor("gzip")) - if got, want := status.Code(err), codes.ResourceExhausted; got != want { - t.Errorf("Client.UnaryCall(%+v) returned status %v, want %v", req, got, want) - } -} From 7ef57fd60b974ed147007fd013a63623018b7b65 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:15:59 +0000 Subject: [PATCH 23/35] Revert "outlierdetection: Support health listener for ejection updates (#7908)" This reverts commit 985965a87952abce7a98723363c67a753c8a3c81. --- balancer/endpointsharding/endpointsharding.go | 8 +- .../pickfirst/pickfirstleaf/pickfirstleaf.go | 27 +-- .../pickfirstleaf/pickfirstleaf_ext_test.go | 52 +++--- balancer/weightedroundrobin/balancer.go | 8 +- .../balancer/outlierdetection/balancer.go | 146 ++++++---------- .../outlierdetection/balancer_test.go | 96 ---------- .../e2e_test/outlierdetection_test.go | 165 ++++++++---------- .../outlierdetection/subconn_wrapper.go | 154 +--------------- 8 files changed, 169 insertions(+), 487 deletions(-) diff --git a/balancer/endpointsharding/endpointsharding.go b/balancer/endpointsharding/endpointsharding.go index 9b59bfc1d979..263c024a84c7 100644 --- a/balancer/endpointsharding/endpointsharding.go +++ b/balancer/endpointsharding/endpointsharding.go @@ -35,9 +35,11 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/base" + "google.golang.org/grpc/balancer/pickfirst" "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/balancer/gracefulswitch" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" ) @@ -46,7 +48,11 @@ import ( var PickFirstConfig string func init() { - PickFirstConfig = fmt.Sprintf("[{%q: {}}]", pickfirstleaf.Name) + name := pickfirst.Name + if !envconfig.NewPickFirstEnabled { + name = pickfirstleaf.Name + } + PickFirstConfig = fmt.Sprintf("[{%q: {}}]", name) } // ChildState is the balancer state of a child along with the endpoint which diff --git a/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go index 76fa5fea95f2..2fc0a71f9441 100644 --- a/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go +++ b/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go @@ -54,18 +54,9 @@ func init() { balancer.Register(pickfirstBuilder{}) } -type ( - // enableHealthListenerKeyType is a unique key type used in resolver - // attributes to indicate whether the health listener usage is enabled. - enableHealthListenerKeyType struct{} - // managedByPickfirstKeyType is an attribute key type to inform Outlier - // Detection that the generic health listener is being used. - // TODO: https://github.com/grpc/grpc-go/issues/7915 - Remove this when - // implementing the dualstack design. This is a hack. Once Dualstack is - // completed, outlier detection will stop sending ejection updates through - // the connectivity listener. - managedByPickfirstKeyType struct{} -) +// enableHealthListenerKeyType is a unique key type used in resolver attributes +// to indicate whether the health listener usage is enabled. +type enableHealthListenerKeyType struct{} var ( logger = grpclog.Component("pick-first-leaf-lb") @@ -149,17 +140,6 @@ func EnableHealthListener(state resolver.State) resolver.State { return state } -// IsManagedByPickfirst returns whether an address belongs to a SubConn -// managed by the pickfirst LB policy. -// TODO: https://github.com/grpc/grpc-go/issues/7915 - This is a hack to disable -// outlier_detection via the with connectivity listener when using pick_first. -// Once Dualstack changes are complete, all SubConns will be created by -// pick_first and outlier detection will only use the health listener for -// ejection. This hack can then be removed. -func IsManagedByPickfirst(addr resolver.Address) bool { - return addr.BalancerAttributes.Value(managedByPickfirstKeyType{}) != nil -} - type pfConfig struct { serviceconfig.LoadBalancingConfig `json:"-"` @@ -186,7 +166,6 @@ type scData struct { } func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) { - addr.BalancerAttributes = addr.BalancerAttributes.WithValue(managedByPickfirstKeyType{}, true) sd := &scData{ rawConnectivityState: connectivity.Idle, effectiveState: connectivity.Idle, diff --git a/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go b/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go index 2a87d6690f4c..9667c2b3db6b 100644 --- a/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go +++ b/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go @@ -58,13 +58,7 @@ const ( stateStoringBalancerName = "state_storing" ) -var ( - stateStoringServiceConfig = fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, stateStoringBalancerName) - ignoreBalAttributesOpt = cmp.Transformer("IgnoreBalancerAttributes", func(a resolver.Address) resolver.Address { - a.BalancerAttributes = nil - return a - }) -) +var stateStoringServiceConfig = fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, stateStoringBalancerName) type s struct { grpctest.Tester @@ -183,7 +177,7 @@ func (s) TestPickFirstLeaf_SimpleResolverUpdate_FirstServerReady(t *testing.T) { wantSCStates := []scState{ {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -225,7 +219,7 @@ func (s) TestPickFirstLeaf_SimpleResolverUpdate_FirstServerUnReady(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown}, {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -270,7 +264,7 @@ func (s) TestPickFirstLeaf_SimpleResolverUpdate_DuplicateAddrs(t *testing.T) { {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown}, {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -323,7 +317,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_DisjointLists(t *testing.T) { {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -340,7 +334,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_DisjointLists(t *testing.T) { {Addrs: []resolver.Address{addrs[3]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -384,7 +378,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_ActiveBackendInUpdatedList(t *testing {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -404,7 +398,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_ActiveBackendInUpdatedList(t *testing {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -446,7 +440,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_InActiveBackendInUpdatedList(t *testi {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -464,7 +458,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_InActiveBackendInUpdatedList(t *testi {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -508,7 +502,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_IdenticalLists(t *testing.T) { {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -527,7 +521,7 @@ func (s) TestPickFirstLeaf_ResolverUpdates_IdenticalLists(t *testing.T) { {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -582,7 +576,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerRestart(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -597,7 +591,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerRestart(t *testing.T) t.Fatal(err) } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -645,7 +639,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerRestart(t *testing.T) {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -666,7 +660,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerRestart(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -714,7 +708,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerToFirst(t *testing.T) {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -735,7 +729,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerToFirst(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -782,7 +776,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerToSecond(t *testing.T) {Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -802,7 +796,7 @@ func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerToSecond(t *testing.T) {Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready}, } - if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantSCStates, bal.subConnStates()); diff != "" { t.Errorf("SubConn states mismatch (-want +got):\n%s", diff) } @@ -1136,7 +1130,7 @@ func (s) TestPickFirstLeaf_InterleavingIPV4Preffered(t *testing.T) { if err != nil { t.Fatalf("%v", err) } - if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantAddrs, gotAddrs); diff != "" { t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff) } } @@ -1180,7 +1174,7 @@ func (s) TestPickFirstLeaf_InterleavingIPv6Preffered(t *testing.T) { if err != nil { t.Fatalf("%v", err) } - if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantAddrs, gotAddrs); diff != "" { t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff) } } @@ -1226,7 +1220,7 @@ func (s) TestPickFirstLeaf_InterleavingUnknownPreffered(t *testing.T) { if err != nil { t.Fatalf("%v", err) } - if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" { + if diff := cmp.Diff(wantAddrs, gotAddrs); diff != "" { t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff) } } diff --git a/balancer/weightedroundrobin/balancer.go b/balancer/weightedroundrobin/balancer.go index d7b9dc4666ee..c9c5b576bb0c 100644 --- a/balancer/weightedroundrobin/balancer.go +++ b/balancer/weightedroundrobin/balancer.go @@ -29,7 +29,6 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/endpointsharding" - "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/balancer/weightedroundrobin/internal" "google.golang.org/grpc/balancer/weightedtarget" "google.golang.org/grpc/connectivity" @@ -219,9 +218,7 @@ type wrrBalancer struct { } func (b *wrrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error { - if b.logger.V(2) { - b.logger.Infof("UpdateCCS: %v", ccs) - } + b.logger.Infof("UpdateCCS: %v", ccs) cfg, ok := ccs.BalancerConfig.(*lbConfig) if !ok { return fmt.Errorf("wrr: received nil or illegal BalancerConfig (type %T): %v", ccs.BalancerConfig, ccs.BalancerConfig) @@ -235,9 +232,6 @@ func (b *wrrBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error b.updateEndpointsLocked(ccs.ResolverState.Endpoints) b.mu.Unlock() - // Make pickfirst children use health listeners for outlier detection to - // work. - ccs.ResolverState = pickfirstleaf.EnableHealthListener(ccs.ResolverState) // This causes child to update picker inline and will thus cause inline // picker update. return b.child.UpdateClientConnState(balancer.ClientConnState{ diff --git a/xds/internal/balancer/outlierdetection/balancer.go b/xds/internal/balancer/outlierdetection/balancer.go index 8f58c0030321..c9d496ce09b9 100644 --- a/xds/internal/balancer/outlierdetection/balancer.go +++ b/xds/internal/balancer/outlierdetection/balancer.go @@ -33,7 +33,6 @@ import ( "unsafe" "google.golang.org/grpc/balancer" - "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/balancer/gracefulswitch" "google.golang.org/grpc/internal/buffer" @@ -73,7 +72,7 @@ func (bb) Build(cc balancer.ClientConn, bOpts balancer.BuildOptions) balancer.Ba } b.logger = prefixLogger(b) b.logger.Infof("Created") - b.child = synchronizingBalancerWrapper{lb: gracefulswitch.NewBalancer(b, bOpts)} + b.child = gracefulswitch.NewBalancer(b, bOpts) go b.run() return b } @@ -153,11 +152,6 @@ type lbCfgUpdate struct { done chan struct{} } -type scHealthUpdate struct { - scw *subConnWrapper - state balancer.SubConnState -} - type outlierDetectionBalancer struct { // These fields are safe to be accessed without holding any mutex because // they are synchronized in run(), which makes these field accesses happen @@ -176,7 +170,10 @@ type outlierDetectionBalancer struct { logger *grpclog.PrefixLogger channelzParent channelz.Identifier - child synchronizingBalancerWrapper + // childMu guards calls into child (to uphold the balancer.Balancer API + // guarantee of synchronous calls). + childMu sync.Mutex + child *gracefulswitch.Balancer // mu guards access to the following fields. It also helps to synchronize // behaviors of the following events: config updates, firing of the interval @@ -193,8 +190,8 @@ type outlierDetectionBalancer struct { // which uses addrs. This balancer waits for the interval timer algorithm to // finish before making the update to the addrs map. // - // This mutex is never held when calling methods on the child policy - // (within the context of a single goroutine). + // This mutex is never held at the same time as childMu (within the context + // of a single goroutine). mu sync.Mutex addrs map[string]*addressInfo cfg *LBConfig @@ -279,9 +276,13 @@ func (b *outlierDetectionBalancer) UpdateClientConnState(s balancer.ClientConnSt // the balancer.Balancer API, so it is guaranteed to be called in a // synchronous manner, so it cannot race with this read. if b.cfg == nil || b.cfg.ChildPolicy.Name != lbCfg.ChildPolicy.Name { - if err := b.child.switchTo(bb); err != nil { + b.childMu.Lock() + err := b.child.SwitchTo(bb) + if err != nil { + b.childMu.Unlock() return fmt.Errorf("outlier detection: error switching to child of type %q: %v", lbCfg.ChildPolicy.Name, err) } + b.childMu.Unlock() } b.mu.Lock() @@ -318,10 +319,12 @@ func (b *outlierDetectionBalancer) UpdateClientConnState(s balancer.ClientConnSt } b.mu.Unlock() - err := b.child.updateClientConnState(balancer.ClientConnState{ + b.childMu.Lock() + err := b.child.UpdateClientConnState(balancer.ClientConnState{ ResolverState: s.ResolverState, BalancerConfig: b.cfg.ChildPolicy.Config, }) + b.childMu.Unlock() done := make(chan struct{}) b.pickerUpdateCh.Put(lbCfgUpdate{ @@ -334,7 +337,9 @@ func (b *outlierDetectionBalancer) UpdateClientConnState(s balancer.ClientConnSt } func (b *outlierDetectionBalancer) ResolverError(err error) { - b.child.resolverError(err) + b.childMu.Lock() + defer b.childMu.Unlock() + b.child.ResolverError(err) } func (b *outlierDetectionBalancer) updateSubConnState(sc balancer.SubConn, state balancer.SubConnState) { @@ -350,7 +355,6 @@ func (b *outlierDetectionBalancer) updateSubConnState(sc balancer.SubConn, state if state.ConnectivityState == connectivity.Shutdown { delete(b.scWrappers, scw.SubConn) } - scw.setLatestConnectivityState(state.ConnectivityState) b.scUpdateCh.Put(&scUpdate{ scw: scw, state: state, @@ -364,7 +368,9 @@ func (b *outlierDetectionBalancer) UpdateSubConnState(sc balancer.SubConn, state func (b *outlierDetectionBalancer) Close() { b.closed.Fire() <-b.done.Done() - b.child.closeLB() + b.childMu.Lock() + b.child.Close() + b.childMu.Unlock() b.scUpdateCh.Close() b.pickerUpdateCh.Close() @@ -377,7 +383,9 @@ func (b *outlierDetectionBalancer) Close() { } func (b *outlierDetectionBalancer) ExitIdle() { - b.child.exitIdle() + b.childMu.Lock() + defer b.childMu.Unlock() + b.child.ExitIdle() } // wrappedPicker delegates to the child policy's picker, and when the request @@ -467,13 +475,10 @@ func (b *outlierDetectionBalancer) NewSubConn(addrs []resolver.Address, opts bal return nil, err } scw := &subConnWrapper{ - SubConn: sc, - addresses: addrs, - scUpdateCh: b.scUpdateCh, - listener: oldListener, - latestRawConnectivityState: balancer.SubConnState{ConnectivityState: connectivity.Idle}, - latestHealthState: balancer.SubConnState{ConnectivityState: connectivity.Connecting}, - healthListenerEnabled: len(addrs) == 1 && pickfirstleaf.IsManagedByPickfirst(addrs[0]), + SubConn: sc, + addresses: addrs, + scUpdateCh: b.scUpdateCh, + listener: oldListener, } b.mu.Lock() defer b.mu.Unlock() @@ -591,18 +596,34 @@ func (b *outlierDetectionBalancer) Target() string { // if the SubConn is not ejected. func (b *outlierDetectionBalancer) handleSubConnUpdate(u *scUpdate) { scw := u.scw - scw.clearHealthListener() - b.child.updateSubConnState(scw, u.state) -} - -func (b *outlierDetectionBalancer) handleSubConnHealthUpdate(u *scHealthUpdate) { - b.child.updateSubConnHealthState(u.scw, u.state) + scw.latestState = u.state + if !scw.ejected { + if scw.listener != nil { + b.childMu.Lock() + scw.listener(u.state) + b.childMu.Unlock() + } + } } // handleEjectedUpdate handles any SubConns that get ejected/unejected, and // forwards the appropriate corresponding subConnState to the child policy. func (b *outlierDetectionBalancer) handleEjectedUpdate(u *ejectionUpdate) { - b.child.handleEjectionUpdate(u) + scw := u.scw + scw.ejected = u.isEjected + // If scw.latestState has never been written to will default to connectivity + // IDLE, which is fine. + stateToUpdate := scw.latestState + if u.isEjected { + stateToUpdate = balancer.SubConnState{ + ConnectivityState: connectivity.TransientFailure, + } + } + if scw.listener != nil { + b.childMu.Lock() + scw.listener(stateToUpdate) + b.childMu.Unlock() + } } // handleChildStateUpdate forwards the picker update wrapped in a wrapped picker @@ -675,8 +696,6 @@ func (b *outlierDetectionBalancer) run() { b.handleSubConnUpdate(u) case *ejectionUpdate: b.handleEjectedUpdate(u) - case *scHealthUpdate: - b.handleSubConnHealthUpdate(u) } case update, ok := <-b.pickerUpdateCh.Get(): if !ok { @@ -861,69 +880,6 @@ func (b *outlierDetectionBalancer) unejectAddress(addrInfo *addressInfo) { } } -// synchronizingBalancerWrapper serializes calls into balancer (to uphold the -// balancer.Balancer API guarantee of synchronous calls). It also ensures a -// consistent order of locking mutexes when using SubConn listeners to avoid -// deadlocks. -type synchronizingBalancerWrapper struct { - // mu should not be used directly from outside this struct, instead use - // methods defined on the struct. - mu sync.Mutex - lb *gracefulswitch.Balancer -} - -func (sbw *synchronizingBalancerWrapper) switchTo(builder balancer.Builder) error { - sbw.mu.Lock() - defer sbw.mu.Unlock() - return sbw.lb.SwitchTo(builder) -} - -func (sbw *synchronizingBalancerWrapper) updateClientConnState(state balancer.ClientConnState) error { - sbw.mu.Lock() - defer sbw.mu.Unlock() - return sbw.lb.UpdateClientConnState(state) -} - -func (sbw *synchronizingBalancerWrapper) resolverError(err error) { - sbw.mu.Lock() - defer sbw.mu.Unlock() - sbw.lb.ResolverError(err) -} - -func (sbw *synchronizingBalancerWrapper) closeLB() { - sbw.mu.Lock() - defer sbw.mu.Unlock() - sbw.lb.Close() -} - -func (sbw *synchronizingBalancerWrapper) exitIdle() { - sbw.mu.Lock() - defer sbw.mu.Unlock() - sbw.lb.ExitIdle() -} - -func (sbw *synchronizingBalancerWrapper) updateSubConnHealthState(scw *subConnWrapper, scs balancer.SubConnState) { - sbw.mu.Lock() - defer sbw.mu.Unlock() - scw.updateSubConnHealthState(scs) -} - -func (sbw *synchronizingBalancerWrapper) updateSubConnState(scw *subConnWrapper, scs balancer.SubConnState) { - sbw.mu.Lock() - defer sbw.mu.Unlock() - scw.updateSubConnConnectivityState(scs) -} - -func (sbw *synchronizingBalancerWrapper) handleEjectionUpdate(u *ejectionUpdate) { - sbw.mu.Lock() - defer sbw.mu.Unlock() - if u.isEjected { - u.scw.handleEjection() - } else { - u.scw.handleUnejection() - } -} - // addressInfo contains the runtime information about an address that pertains // to Outlier Detection. This struct and all of its fields is protected by // outlierDetectionBalancer.mu in the case where it is accessed through the diff --git a/xds/internal/balancer/outlierdetection/balancer_test.go b/xds/internal/balancer/outlierdetection/balancer_test.go index ca07dcda0c88..a80d4d9dee4f 100644 --- a/xds/internal/balancer/outlierdetection/balancer_test.go +++ b/xds/internal/balancer/outlierdetection/balancer_test.go @@ -31,24 +31,17 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "google.golang.org/grpc" "google.golang.org/grpc/balancer" - "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" "google.golang.org/grpc/connectivity" - "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/internal/balancer/stub" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpctest" iserviceconfig "google.golang.org/grpc/internal/serviceconfig" - "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/internal/testutils" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" "google.golang.org/grpc/xds/internal/balancer/clusterimpl" - - testgrpc "google.golang.org/grpc/interop/grpc_testing" - testpb "google.golang.org/grpc/interop/grpc_testing" ) var ( @@ -1575,92 +1568,3 @@ func (s) TestConcurrentOperations(t *testing.T) { close(finished) wg.Wait() } - -// Test verifies that outlier detection doesn't eject subchannels created by -// the new pickfirst balancer when pickfirst is a non-leaf policy, i.e. not -// under a petiole policy. When pickfirst is not under a petiole policy, it will -// not register a health listener. pickfirst will still set the address -// attribute to disable ejection through the raw connectivity listener. When -// Outlier Detection processes a health update and sees the health listener is -// enabled but a health listener is not registered, it will drop the ejection -// update. -func (s) TestPickFirstHealthListenerDisabled(t *testing.T) { - backend := &stubserver.StubServer{ - EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { - return nil, errors.New("some error") - }, - } - if err := backend.StartServer(); err != nil { - t.Fatalf("Failed to start backend: %v", err) - } - defer backend.Stop() - t.Logf("Started bad TestService backend at: %q", backend.Address) - - // The interval is intentionally kept very large, the interval algorithm - // will be triggered manually. - odCfg := &LBConfig{ - Interval: iserviceconfig.Duration(300 * time.Second), - BaseEjectionTime: iserviceconfig.Duration(300 * time.Second), - MaxEjectionTime: iserviceconfig.Duration(500 * time.Second), - FailurePercentageEjection: &FailurePercentageEjection{ - Threshold: 50, - EnforcementPercentage: 100, - MinimumHosts: 0, - RequestVolume: 2, - }, - MaxEjectionPercent: 100, - ChildPolicy: &iserviceconfig.BalancerConfig{ - Name: pickfirstleaf.Name, - }, - } - - lbChan := make(chan *outlierDetectionBalancer, 1) - bf := stub.BalancerFuncs{ - Init: func(bd *stub.BalancerData) { - bd.Data = balancer.Get(Name).Build(bd.ClientConn, bd.BuildOptions) - lbChan <- bd.Data.(*outlierDetectionBalancer) - }, - Close: func(bd *stub.BalancerData) { - bd.Data.(balancer.Balancer).Close() - }, - UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { - ccs.BalancerConfig = odCfg - return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs) - }, - } - - stub.Register(t.Name(), bf) - - opts := []grpc.DialOption{ - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithDefaultServiceConfig(fmt.Sprintf(`{ "loadBalancingConfig": [{%q: {}}] }`, t.Name())), - } - cc, err := grpc.NewClient(backend.Address, opts...) - if err != nil { - t.Fatalf("grpc.NewClient() failed: %v", err) - } - defer cc.Close() - ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) - defer cancel() - testServiceClient := testgrpc.NewTestServiceClient(cc) - testServiceClient.EmptyCall(ctx, &testpb.Empty{}) - testutils.AwaitState(ctx, t, cc, connectivity.Ready) - - // Failing request should not cause ejection. - testServiceClient.EmptyCall(ctx, &testpb.Empty{}) - testServiceClient.EmptyCall(ctx, &testpb.Empty{}) - testServiceClient.EmptyCall(ctx, &testpb.Empty{}) - testServiceClient.EmptyCall(ctx, &testpb.Empty{}) - - // Run the interval algorithm. - select { - case <-ctx.Done(): - t.Fatal("Timed out waiting for the outlier detection LB policy to be built.") - case od := <-lbChan: - od.intervalTimerAlgorithm() - } - - shortCtx, shortCancel := context.WithTimeout(ctx, defaultTestShortTimeout) - defer shortCancel() - testutils.AwaitNoStateChange(shortCtx, t, cc, connectivity.Ready) -} diff --git a/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go b/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go index ec087eb08b53..35c4d75301b3 100644 --- a/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go +++ b/xds/internal/balancer/outlierdetection/e2e_test/outlierdetection_test.go @@ -28,10 +28,8 @@ import ( "github.com/google/go-cmp/cmp" "google.golang.org/grpc" - "google.golang.org/grpc/balancer/weightedroundrobin" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/internal" - "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpctest" "google.golang.org/grpc/internal/stubserver" "google.golang.org/grpc/peer" @@ -45,18 +43,7 @@ import ( _ "google.golang.org/grpc/xds/internal/balancer/outlierdetection" // To register helper functions which register/unregister Outlier Detection LB Policy. ) -var ( - defaultTestTimeout = 5 * time.Second - leafPolicyName = "round_robin" -) - -func init() { - // Test the health listener code path for ejection when the experimental - // pickfirst is enabled. - if envconfig.NewPickFirstEnabled { - leafPolicyName = weightedroundrobin.Name - } -} +var defaultTestTimeout = 5 * time.Second type s struct { grpctest.Tester @@ -168,50 +155,50 @@ func (s) TestOutlierDetectionAlgorithmsE2E(t *testing.T) { }{ { name: "Success Rate Algorithm", - odscJSON: fmt.Sprintf(` - { - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "successRateEjection": { - "stdevFactor": 50, - "enforcementPercentage": 100, - "minimumHosts": 3, - "requestVolume": 5 - }, - "childPolicy": [{"%s": {}}] - } - } - ] - }`, leafPolicyName), + odscJSON: ` +{ + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "successRateEjection": { + "stdevFactor": 50, + "enforcementPercentage": 100, + "minimumHosts": 3, + "requestVolume": 5 + }, + "childPolicy": [{"round_robin": {}}] + } + } + ] +}`, }, { name: "Failure Percentage Algorithm", - odscJSON: fmt.Sprintf(` - { - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "failurePercentageEjection": { - "threshold": 50, - "enforcementPercentage": 100, - "minimumHosts": 3, - "requestVolume": 5 - }, - "childPolicy": [{"%s": {}} - ] - } - } - ] - }`, leafPolicyName), + odscJSON: ` +{ + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "failurePercentageEjection": { + "threshold": 50, + "enforcementPercentage": 100, + "minimumHosts": 3, + "requestVolume": 5 + }, + "childPolicy": [{"round_robin": {}} + ] + } + } + ] +}`, }, } for _, test := range tests { @@ -286,20 +273,20 @@ func (s) TestNoopConfiguration(t *testing.T) { mr := manual.NewBuilderWithScheme("od-e2e") defer mr.Close() - noopODServiceConfigJSON := fmt.Sprintf(` - { - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "childPolicy": [{"%s": {}}] - } - } - ] - }`, leafPolicyName) + noopODServiceConfigJSON := ` +{ + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "childPolicy": [{"round_robin": {}}] + } + } + ] +}` sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(noopODServiceConfigJSON) // The full list of addresses. fullAddresses := []resolver.Address{ @@ -334,26 +321,26 @@ func (s) TestNoopConfiguration(t *testing.T) { // specifies to count RPC's and eject upstreams. Due to the balancer no // longer being a noop, it should eject any unhealthy addresses as specified // by the failure percentage portion of the configuration. - countingODServiceConfigJSON := fmt.Sprintf(` - { - "loadBalancingConfig": [ - { - "outlier_detection_experimental": { - "interval": "0.050s", - "baseEjectionTime": "0.100s", - "maxEjectionTime": "300s", - "maxEjectionPercent": 33, - "failurePercentageEjection": { - "threshold": 50, - "enforcementPercentage": 100, - "minimumHosts": 3, - "requestVolume": 5 - }, - "childPolicy": [{"%s": {}}] - } - } - ] - }`, leafPolicyName) + countingODServiceConfigJSON := ` +{ + "loadBalancingConfig": [ + { + "outlier_detection_experimental": { + "interval": "0.050s", + "baseEjectionTime": "0.100s", + "maxEjectionTime": "300s", + "maxEjectionPercent": 33, + "failurePercentageEjection": { + "threshold": 50, + "enforcementPercentage": 100, + "minimumHosts": 3, + "requestVolume": 5 + }, + "childPolicy": [{"round_robin": {}}] + } + } + ] +}` sc = internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(countingODServiceConfigJSON) mr.UpdateState(resolver.State{ diff --git a/xds/internal/balancer/outlierdetection/subconn_wrapper.go b/xds/internal/balancer/outlierdetection/subconn_wrapper.go index 7d710fde1b2a..0fa422d8f262 100644 --- a/xds/internal/balancer/outlierdetection/subconn_wrapper.go +++ b/xds/internal/balancer/outlierdetection/subconn_wrapper.go @@ -19,11 +19,9 @@ package outlierdetection import ( "fmt" - "sync" "unsafe" "google.golang.org/grpc/balancer" - "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal/buffer" "google.golang.org/grpc/resolver" ) @@ -33,54 +31,23 @@ import ( // whether or not this SubConn is ejected. type subConnWrapper struct { balancer.SubConn - // addressInfo is a pointer to the subConnWrapper's corresponding address - // map entry, if the map entry exists. It is accessed atomically. - addressInfo unsafe.Pointer // *addressInfo - // The following fields are set during object creation and read-only after - // that. - listener func(balancer.SubConnState) - // healthListenerEnabled indicates whether the leaf LB policy is using a - // generic health listener. When enabled, ejection updates are sent via the - // health listener instead of the connectivity listener. Once Dualstack - // changes are complete, all SubConns will be created by pickfirst which - // uses the health listener. - // TODO: https://github.com/grpc/grpc-go/issues/7915 - Once Dualstack - // changes are complete, all SubConns will be created by pick_first and - // outlier detection will only use the health listener for ejection and - // this field can be removed. - healthListenerEnabled bool - - scUpdateCh *buffer.Unbounded - - // The following fields are only referenced in the context of a work - // serializing buffer and don't need to be protected by a mutex. + // addressInfo is a pointer to the subConnWrapper's corresponding address + // map entry, if the map entry exists. + addressInfo unsafe.Pointer // *addressInfo // These two pieces of state will reach eventual consistency due to sync in // run(), and child will always have the correctly updated SubConnState. + // latestState is the latest state update from the underlying SubConn. This + // is used whenever a SubConn gets unejected. + latestState balancer.SubConnState + ejected bool - ejected bool + scUpdateCh *buffer.Unbounded // addresses is the list of address(es) this SubConn was created with to // help support any change in address(es) addresses []resolver.Address - // latestHealthState is tracked to update the child policy during - // unejection. - latestHealthState balancer.SubConnState - // latestRawConnectivityState is tracked to update the child policy during - // unejection. - latestRawConnectivityState balancer.SubConnState - - // Access to the following fields are protected by a mutex. These fields - // should not be accessed from outside this file, instead use methods - // defined on the struct. - mu sync.Mutex - healthListener func(balancer.SubConnState) - // latestReceivedConnectivityState is the SubConn's most recent connectivity - // state received. It may not be delivered to the child balancer yet. It is - // used to ensure a health listener is registered with the SubConn only when - // the SubConn is READY. - latestReceivedConnectivityState connectivity.State } // eject causes the wrapper to report a state update with the TRANSIENT_FAILURE @@ -105,108 +72,3 @@ func (scw *subConnWrapper) uneject() { func (scw *subConnWrapper) String() string { return fmt.Sprintf("%+v", scw.addresses) } - -func (scw *subConnWrapper) RegisterHealthListener(listener func(balancer.SubConnState)) { - // gRPC currently supports two mechanisms that provide a health signal for - // a connection: client-side health checking and outlier detection. Earlier - // both these mechanisms signaled unhealthiness by setting the subchannel - // state to TRANSIENT_FAILURE. As part of the dualstack changes to make - // pick_first the universal leaf policy (see A61), both these mechanisms - // started using the new health listener to make health signal visible to - // the petiole policies without affecting the underlying connectivity - // management of the pick_first policy - if !scw.healthListenerEnabled { - logger.Errorf("Health listener unexpectedly registered on SubConn %v.", scw) - return - } - - scw.mu.Lock() - defer scw.mu.Unlock() - - if scw.latestReceivedConnectivityState != connectivity.Ready { - return - } - scw.healthListener = listener - if listener == nil { - scw.SubConn.RegisterHealthListener(nil) - return - } - - scw.SubConn.RegisterHealthListener(func(scs balancer.SubConnState) { - scw.scUpdateCh.Put(&scHealthUpdate{ - scw: scw, - state: scs, - }) - }) -} - -// updateSubConnHealthState stores the latest health state for unejection and -// sends updates the health listener. -func (scw *subConnWrapper) updateSubConnHealthState(scs balancer.SubConnState) { - scw.latestHealthState = scs - if scw.ejected { - return - } - scw.mu.Lock() - defer scw.mu.Unlock() - if scw.healthListener != nil { - scw.healthListener(scs) - } -} - -// updateSubConnConnectivityState stores the latest connectivity state for -// unejection and updates the raw connectivity listener. -func (scw *subConnWrapper) updateSubConnConnectivityState(scs balancer.SubConnState) { - scw.latestRawConnectivityState = scs - // If the raw connectivity listener is used for ejection, and the SubConn is - // ejected, don't send the update. - if scw.ejected && !scw.healthListenerEnabled { - return - } - if scw.listener != nil { - scw.listener(scs) - } -} - -func (scw *subConnWrapper) clearHealthListener() { - scw.mu.Lock() - defer scw.mu.Unlock() - scw.healthListener = nil -} - -func (scw *subConnWrapper) handleUnejection() { - scw.ejected = false - if !scw.healthListenerEnabled { - // If scw.latestRawConnectivityState has never been written to will - // default to connectivity IDLE, which is fine. - scw.updateSubConnConnectivityState(scw.latestRawConnectivityState) - return - } - // If scw.latestHealthState has never been written to will use the health - // state CONNECTING set during object creation. - scw.updateSubConnHealthState(scw.latestHealthState) -} - -func (scw *subConnWrapper) handleEjection() { - scw.ejected = true - stateToUpdate := balancer.SubConnState{ - ConnectivityState: connectivity.TransientFailure, - } - if !scw.healthListenerEnabled { - if scw.listener != nil { - scw.listener(stateToUpdate) - } - return - } - scw.mu.Lock() - defer scw.mu.Unlock() - if scw.healthListener != nil { - scw.healthListener(stateToUpdate) - } -} - -func (scw *subConnWrapper) setLatestConnectivityState(state connectivity.State) { - scw.mu.Lock() - defer scw.mu.Unlock() - scw.latestReceivedConnectivityState = state -} From 20d4dc654271c8999408242e1312e1ff45a92280 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:23:53 +0000 Subject: [PATCH 24/35] Revert the changes --- test/creds_test.go | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/creds_test.go b/test/creds_test.go index 74ee24c02965..fe8b552e719c 100644 --- a/test/creds_test.go +++ b/test/creds_test.go @@ -236,9 +236,9 @@ func (s) TestFailFastRPCErrorOnBadCertificates(t *testing.T) { opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() - cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) + cc, err := grpc.NewClient(te.srvAddr, opts...) if err != nil { - t.Fatalf("Dial(_) = %v, want %v", err, nil) + t.Fatalf("NewClient(_) = %v, want %v", err, nil) } defer cc.Close() @@ -255,11 +255,9 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { defer te.tearDown() opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} - ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) - defer cancel() - cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) + cc, err := grpc.NewClient(te.srvAddr, opts...) if err != nil { - t.Fatalf("Dial(_) = %v, want %v", err, nil) + t.Fatalf("NewClient(_) = %v, want %v", err, nil) } defer cc.Close() @@ -272,7 +270,9 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure) tc := testgrpc.NewTestServiceClient(cc) - ctx, cancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) + // Use a short context as WaitForReady waits for context expiration before + // failing the RPC. + ctx, cancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) defer cancel() if _, err = tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); !strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want err.Error() contains %q", err, clientAlwaysFailCredErrorMsg) @@ -438,11 +438,12 @@ func (s) TestCredsHandshakeAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) } defer cc.Close() + cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String()}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -470,11 +471,12 @@ func (s) TestCredsHandshakeServerNameAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) } defer cc.Close() + cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String(), ServerName: testServerName}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -525,11 +527,12 @@ func (s) TestServerCredsDispatch(t *testing.T) { go s.Serve(lis) defer s.Stop() - cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(cred)) + cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(cred)) if err != nil { - t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) } defer cc.Close() + cc.Connect() rawConn := cred.getRawConn() // Give grpc a chance to see the error and potentially close the connection. From 0907f9d1e6ebff3ede47488865c63d2e09833094 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 06:35:25 +0000 Subject: [PATCH 25/35] Revert the changes for test cases --- test/creds_test.go | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/test/creds_test.go b/test/creds_test.go index fe8b552e719c..ff3818e0ad54 100644 --- a/test/creds_test.go +++ b/test/creds_test.go @@ -236,15 +236,22 @@ func (s) TestFailFastRPCErrorOnBadCertificates(t *testing.T) { opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) defer cancel() - cc, err := grpc.NewClient(te.srvAddr, opts...) + cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) if err != nil { - t.Fatalf("NewClient(_) = %v, want %v", err, nil) + t.Fatalf("Dial(_) = %v, want %v", err, nil) } defer cc.Close() tc := testgrpc.NewTestServiceClient(cc) - if _, err = tc.EmptyCall(ctx, &testpb.Empty{}); strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { - return + for i := 0; i < 1000; i++ { + // This loop runs for at most 1 second. The first several RPCs will fail + // with Unavailable because the connection hasn't started. When the + // first connection failed with creds error, the next RPC should also + // fail with the expected error. + if _, err = tc.EmptyCall(ctx, &testpb.Empty{}); strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { + return + } + time.Sleep(time.Millisecond) } te.t.Fatalf("TestService/EmptyCall(_, _) = _, %v, want err.Error() contains %q", err, clientAlwaysFailCredErrorMsg) } @@ -255,23 +262,15 @@ func (s) TestWaitForReadyRPCErrorOnBadCertificates(t *testing.T) { defer te.tearDown() opts := []grpc.DialOption{grpc.WithTransportCredentials(clientAlwaysFailCred{})} - cc, err := grpc.NewClient(te.srvAddr, opts...) + ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) + defer cancel() + cc, err := grpc.DialContext(ctx, te.srvAddr, opts...) if err != nil { - t.Fatalf("NewClient(_) = %v, want %v", err, nil) + t.Fatalf("Dial(_) = %v, want %v", err, nil) } defer cc.Close() - // The DNS resolver may take more than defaultTestShortTimeout, we let the - // channel enter TransientFailure signalling that the first resolver state - // has been produced. - cc.Connect() - ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) - defer cancel() - testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure) - tc := testgrpc.NewTestServiceClient(cc) - // Use a short context as WaitForReady waits for context expiration before - // failing the RPC. ctx, cancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) defer cancel() if _, err = tc.EmptyCall(ctx, &testpb.Empty{}, grpc.WaitForReady(true)); !strings.Contains(err.Error(), clientAlwaysFailCredErrorMsg) { @@ -438,12 +437,11 @@ func (s) TestCredsHandshakeAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) } defer cc.Close() - cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String()}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -471,12 +469,11 @@ func (s) TestCredsHandshakeServerNameAuthority(t *testing.T) { r := manual.NewBuilderWithScheme("whatever") - cc, err := grpc.NewClient(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) + cc, err := grpc.Dial(r.Scheme()+":///"+testAuthority, grpc.WithTransportCredentials(cred), grpc.WithResolvers(r)) if err != nil { - t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) } defer cc.Close() - cc.Connect() r.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: lis.Addr().String(), ServerName: testServerName}}}) ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) @@ -527,12 +524,11 @@ func (s) TestServerCredsDispatch(t *testing.T) { go s.Serve(lis) defer s.Stop() - cc, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(cred)) + cc, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(cred)) if err != nil { - t.Fatalf("grpc.NewClient(%q) = %v", lis.Addr().String(), err) + t.Fatalf("grpc.Dial(%q) = %v", lis.Addr().String(), err) } defer cc.Close() - cc.Connect() rawConn := cred.getRawConn() // Give grpc a chance to see the error and potentially close the connection. From 84e8a4f1fe45336aa896e531cb4aef18dfd15c0c Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Mon, 23 Dec 2024 11:58:21 +0000 Subject: [PATCH 26/35] Fix decompression size check and refactor based on review feedback --- rpc_util.go | 9 ++++++++- rpc_util_test.go | 9 +++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index 4ecd186d8570..b522830dfc8b 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -841,8 +841,15 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM var uncompressedBuf []byte uncompressedBuf, err = dc.Do(compressed.Reader()) if err == nil { + if size := len(uncompressedBuf); size > maxReceiveMessageSize { + out.Free() + // TODO: Revisit the error code. Currently keep it consistent with java + // implementation. + return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) + } out = mem.BufferSlice{mem.SliceBuffer(uncompressedBuf)} } + } else { out, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) if err == errMaxMessageSizeExceeded { @@ -889,7 +896,7 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes } // doesReceiveMessageOverflow checks if the number of bytes read from the stream -// exceeds the maximum receive message size allowed by the client. If the `readBytes` +// exceed the maximum receive message size allowed by the receiver. If the `readBytes` // is greater than or equal to `maxReceiveMessageSize`, the function attempts to read // one more byte from the `dcReader` to detect if there's an overflow. // diff --git a/rpc_util_test.go b/rpc_util_test.go index 4af861d14f29..c5bbe3111a96 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -301,6 +301,7 @@ func BenchmarkGZIPCompressor1MiB(b *testing.B) { // mustCompress compresses the input data and returns a BufferSlice. func mustCompress(t *testing.T, input []byte) mem.BufferSlice { + t.Helper() var buf bytes.Buffer gz := gzip.NewWriter(&buf) if _, err := gz.Write(input); err != nil { @@ -320,7 +321,7 @@ func mustCompress(t *testing.T, input []byte) mem.BufferSlice { // premature data end. It ensures that the function behaves correctly with different // inputs, buffer sizes, and error conditions, using the "gzip" compressor for testing. func (s) TestDecompress(t *testing.T) { - c := encoding.GetCompressor("gzip") + compressor := encoding.GetCompressor("gzip") testCases := []struct { name string @@ -351,7 +352,7 @@ func (s) TestDecompress(t *testing.T) { wantErr: nil, }, { - name: "Handles large buffer size (MaxInt)", + name: "Handles large buffer size MaxInt", input: mustCompress(t, []byte("large message")), maxReceiveMessageSize: math.MaxInt, want: []byte("large message"), @@ -361,14 +362,14 @@ func (s) TestDecompress(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - output, err := decompress(c, tc.input, tc.maxReceiveMessageSize, mem.DefaultBufferPool()) + output, err := decompress(compressor, tc.input, tc.maxReceiveMessageSize, mem.DefaultBufferPool()) if !cmp.Equal(err, tc.wantErr, cmpopts.EquateErrors()) { t.Fatalf("decompress() error = %v, wantErr = %v", err, tc.wantErr) } if !cmp.Equal(tc.want, output.Materialize()) { - t.Fatalf("decompress() output mismatch: Got = %v, Want = %v", output.Materialize(), tc.want) + t.Fatalf("decompress() output mismatch: got = %v, want = %v", output.Materialize(), tc.want) } }) } From 77ea2307ecfe38af28f7ce24a64beb7146fb4465 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Tue, 24 Dec 2024 06:58:59 +0000 Subject: [PATCH 27/35] small tweaks --- rpc_util_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index c5bbe3111a96..fab5f8066502 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -363,11 +363,9 @@ func (s) TestDecompress(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { output, err := decompress(compressor, tc.input, tc.maxReceiveMessageSize, mem.DefaultBufferPool()) - if !cmp.Equal(err, tc.wantErr, cmpopts.EquateErrors()) { - t.Fatalf("decompress() error = %v, wantErr = %v", err, tc.wantErr) + t.Fatalf("decompress() err = %v, wantErr = %v", err, tc.wantErr) } - if !cmp.Equal(tc.want, output.Materialize()) { t.Fatalf("decompress() output mismatch: got = %v, want = %v", output.Materialize(), tc.want) } From 6ff93219139d2db79efd44bb566d776d9844cf40 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Tue, 24 Dec 2024 07:15:46 +0000 Subject: [PATCH 28/35] Fixed the space formatting issues --- rpc_util_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index fab5f8066502..902a88631edf 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -307,11 +307,9 @@ func mustCompress(t *testing.T, input []byte) mem.BufferSlice { if _, err := gz.Write(input); err != nil { t.Fatalf("compressInput() failed to write data: %v", err) } - if err := gz.Close(); err != nil { t.Fatalf("compressInput() failed to close gzip writer: %v", err) } - compressedData := buf.Bytes() return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} } From 82124a4950417b08eb5aca52002dc93489569617 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Tue, 24 Dec 2024 11:28:45 +0000 Subject: [PATCH 29/35] Rename the test cases and refactor some of them --- rpc_util.go | 1 + rpc_util_test.go | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index b522830dfc8b..3671559b3899 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -890,6 +890,7 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMes } if doesReceiveMessageOverflow(out.Len(), maxReceiveMessageSize, dcReader) { + out.Free() return nil, errMaxMessageSizeExceeded } return out, nil diff --git a/rpc_util_test.go b/rpc_util_test.go index 902a88631edf..8a27e8a2d739 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -299,8 +299,8 @@ func BenchmarkGZIPCompressor1MiB(b *testing.B) { bmCompressor(b, 1024*1024, NewGZIPCompressor()) } -// mustCompress compresses the input data and returns a BufferSlice. -func mustCompress(t *testing.T, input []byte) mem.BufferSlice { +// compressWithDeterministicError compresses the input data and returns a BufferSlice. +func compressWithDeterministicError(t *testing.T, input []byte) mem.BufferSlice { t.Helper() var buf bytes.Buffer gz := gzip.NewWriter(&buf) @@ -314,10 +314,10 @@ func mustCompress(t *testing.T, input []byte) mem.BufferSlice { return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} } -// TestDecompress tests the decompress function with various scenarios, including -// successful decompression, error handling, and edge cases like overflow or -// premature data end. It ensures that the function behaves correctly with different -// inputs, buffer sizes, and error conditions, using the "gzip" compressor for testing. +// TestDecompress tests the decompress function behaves correctly for following scenarios +// decompress successfully when message is <= maxReceiveMessageSize +// errors when message > maxReceiveMessageSize +// decompress successfully when maxReceiveMessageSize is MaxInt. func (s) TestDecompress(t *testing.T) { compressor := encoding.GetCompressor("gzip") @@ -330,28 +330,28 @@ func (s) TestDecompress(t *testing.T) { }{ { name: "Decompresses successfully with sufficient buffer size", - input: mustCompress(t, []byte("decompressed data")), + input: compressWithDeterministicError(t, []byte("decompressed data")), maxReceiveMessageSize: 50, want: []byte("decompressed data"), wantErr: nil, }, { name: "Fails due to exceeding maxReceiveMessageSize", - input: mustCompress(t, []byte("message that is too large")), + input: compressWithDeterministicError(t, []byte("message that is too large")), maxReceiveMessageSize: len("message that is too large") - 1, want: nil, wantErr: errMaxMessageSizeExceeded, }, { name: "Decompresses to exactly maxReceiveMessageSize", - input: mustCompress(t, []byte("exact size message")), + input: compressWithDeterministicError(t, []byte("exact size message")), maxReceiveMessageSize: len("exact size message"), want: []byte("exact size message"), wantErr: nil, }, { - name: "Handles large buffer size MaxInt", - input: mustCompress(t, []byte("large message")), + name: "Decompresses successfully with maxReceiveMessageSize MaxInt", + input: compressWithDeterministicError(t, []byte("large message")), maxReceiveMessageSize: math.MaxInt, want: []byte("large message"), wantErr: nil, From 4e9c665e9a53e44e670f79919632f7c08049f9b3 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 10 Jan 2025 12:42:07 +0000 Subject: [PATCH 30/35] Fix reviewed changes --- rpc_util.go | 67 +++++++++++++++++++++--------------------------- rpc_util_test.go | 9 +++++-- 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index 3671559b3899..6d8acee2ebf6 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -809,7 +809,6 @@ func (p *payloadInfo) free() { } } -// errMaxMessageSizeExceeded represents an error due to exceeding the maximum message size limit. var errMaxMessageSizeExceeded = errors.New("max message size exceeded") // recvAndDecompress reads a message from the stream, decompressing it if necessary. @@ -834,33 +833,11 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM if pf.isCompressed() { defer compressed.Free() - // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, // use this decompressor as the default. - if dc != nil { - var uncompressedBuf []byte - uncompressedBuf, err = dc.Do(compressed.Reader()) - if err == nil { - if size := len(uncompressedBuf); size > maxReceiveMessageSize { - out.Free() - // TODO: Revisit the error code. Currently keep it consistent with java - // implementation. - return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) - } - out = mem.BufferSlice{mem.SliceBuffer(uncompressedBuf)} - } - - } else { - out, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) - if err == errMaxMessageSizeExceeded { - out.Free() - // TODO: Revisit the error code. Currently keep it consistent with java - // implementation. - return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) - } - } + out, err = decompress(compressor, compressed, dc, maxReceiveMessageSize, p.bufferPool) if err != nil { - return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) + return nil, err } } else { out = compressed @@ -877,23 +854,37 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM // Using compressor, decompress d, returning data and size. // If the decompressed data exceeds maxReceiveMessageSize, it returns errMaxMessageSizeExceeded. -func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { - dcReader, err := compressor.Decompress(d.Reader()) - if err != nil { - return nil, err +func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { + if dc != nil { + uncompressed, err := dc.Do(d.Reader()) + if err != nil { + return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) + } + if len(uncompressed) > maxReceiveMessageSize { + return nil, status.Errorf(codes.ResourceExhausted, "grpc: message after decompression larger than max (%d vs. %d)", len(uncompressed), maxReceiveMessageSize) + } + return mem.BufferSlice{mem.SliceBuffer(uncompressed)}, nil } + if compressor != nil { + dcReader, err := compressor.Decompress(d.Reader()) + if err != nil { + return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the message: %v", err) + } - out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)), pool) - if err != nil { - out.Free() - return nil, err - } + out, err := mem.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)), pool) + if err != nil { + out.Free() + return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err) - if doesReceiveMessageOverflow(out.Len(), maxReceiveMessageSize, dcReader) { - out.Free() - return nil, errMaxMessageSizeExceeded + } + + if doesReceiveMessageOverflow(out.Len(), maxReceiveMessageSize, dcReader) { + out.Free() + return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) + } + return out, nil } - return out, nil + return d, nil } // doesReceiveMessageOverflow checks if the number of bytes read from the stream diff --git a/rpc_util_test.go b/rpc_util_test.go index 8a27e8a2d739..fd284e66b720 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -324,6 +324,7 @@ func (s) TestDecompress(t *testing.T) { testCases := []struct { name string input mem.BufferSlice + dc Decompressor maxReceiveMessageSize int want []byte wantErr error @@ -331,6 +332,7 @@ func (s) TestDecompress(t *testing.T) { { name: "Decompresses successfully with sufficient buffer size", input: compressWithDeterministicError(t, []byte("decompressed data")), + dc: nil, maxReceiveMessageSize: 50, want: []byte("decompressed data"), wantErr: nil, @@ -338,13 +340,15 @@ func (s) TestDecompress(t *testing.T) { { name: "Fails due to exceeding maxReceiveMessageSize", input: compressWithDeterministicError(t, []byte("message that is too large")), + dc: nil, maxReceiveMessageSize: len("message that is too large") - 1, want: nil, - wantErr: errMaxMessageSizeExceeded, + wantErr: status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", len("message that is too large")-1), }, { name: "Decompresses to exactly maxReceiveMessageSize", input: compressWithDeterministicError(t, []byte("exact size message")), + dc: nil, maxReceiveMessageSize: len("exact size message"), want: []byte("exact size message"), wantErr: nil, @@ -352,6 +356,7 @@ func (s) TestDecompress(t *testing.T) { { name: "Decompresses successfully with maxReceiveMessageSize MaxInt", input: compressWithDeterministicError(t, []byte("large message")), + dc: nil, maxReceiveMessageSize: math.MaxInt, want: []byte("large message"), wantErr: nil, @@ -360,7 +365,7 @@ func (s) TestDecompress(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - output, err := decompress(compressor, tc.input, tc.maxReceiveMessageSize, mem.DefaultBufferPool()) + output, err := decompress(compressor, tc.input, tc.dc, tc.maxReceiveMessageSize, mem.DefaultBufferPool()) if !cmp.Equal(err, tc.wantErr, cmpopts.EquateErrors()) { t.Fatalf("decompress() err = %v, wantErr = %v", err, tc.wantErr) } From da82d307535222a9c374a7e13a847654364f1e15 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 10 Jan 2025 12:49:38 +0000 Subject: [PATCH 31/35] small tweaks --- rpc_util.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index 6d8acee2ebf6..55743a84afde 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -22,7 +22,6 @@ import ( "compress/gzip" "context" "encoding/binary" - "errors" "fmt" "io" "math" @@ -809,8 +808,6 @@ func (p *payloadInfo) free() { } } -var errMaxMessageSizeExceeded = errors.New("max message size exceeded") - // recvAndDecompress reads a message from the stream, decompressing it if necessary. // // Cancelling the returned cancel function releases the buffer back to the pool. So the caller should cancel as soon as @@ -852,8 +849,9 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM return out, nil } -// Using compressor, decompress d, returning data and size. -// If the decompressed data exceeds maxReceiveMessageSize, it returns errMaxMessageSizeExceeded. +// decompress decompresses the given data `d` using either a custom decompressor `dc` +// or a provided `compressor`. It checks if the decompressed data exceeds the +// `maxReceiveMessageSize` and returns an error if so. func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { if dc != nil { uncompressed, err := dc.Do(d.Reader()) From 33962c27c90bdd75da11c4a797c4bfa6f9697549 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 10 Jan 2025 16:49:13 +0000 Subject: [PATCH 32/35] Fixed test cases for decompress function --- rpc_util.go | 8 ++++---- rpc_util_test.go | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index 55743a84afde..ec60fb599be8 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -849,9 +849,10 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM return out, nil } -// decompress decompresses the given data `d` using either a custom decompressor `dc` -// or a provided `compressor`. It checks if the decompressed data exceeds the -// `maxReceiveMessageSize` and returns an error if so. +// decompress processes the given data by decompressing it using either a custom decompressor or a standard compressor. +// If a custom decompressor is provided, it takes precedence. The function validates that the decompressed data +// does not exceed the specified maximum size and returns an error if this limit is exceeded. +// On success, it returns the decompressed data. Otherwise, it returns an error if decompression fails or the data exceeds the size limit. func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { if dc != nil { uncompressed, err := dc.Do(d.Reader()) @@ -873,7 +874,6 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompress if err != nil { out.Free() return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err) - } if doesReceiveMessageOverflow(out.Len(), maxReceiveMessageSize, dcReader) { diff --git a/rpc_util_test.go b/rpc_util_test.go index fd284e66b720..bc63aaeb6e7b 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -21,6 +21,7 @@ package grpc import ( "bytes" "compress/gzip" + "errors" "io" "math" "reflect" @@ -40,6 +41,11 @@ import ( "google.golang.org/protobuf/proto" ) +const ( + defaultDecompressedData = "default decompressed data" + decompressionErrorMsg = "invalid compression format" +) + type fullReader struct { data []byte } @@ -314,12 +320,33 @@ func compressWithDeterministicError(t *testing.T, input []byte) mem.BufferSlice return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} } +// MockDecompressor is a mock decompressor that always returns an error +type MockDecompressor struct { + ShouldError bool +} + +// Do simulates decompression. If ShouldError is true, it returns an error, else it returns decompressed data. +func (m *MockDecompressor) Do(reader io.Reader) ([]byte, error) { + if m.ShouldError { + return nil, errors.New(decompressionErrorMsg) + } + return []byte(defaultDecompressedData), nil +} + +func (m *MockDecompressor) Type() string { + return "mock" +} + // TestDecompress tests the decompress function behaves correctly for following scenarios // decompress successfully when message is <= maxReceiveMessageSize // errors when message > maxReceiveMessageSize -// decompress successfully when maxReceiveMessageSize is MaxInt. +// decompress successfully when maxReceiveMessageSize is MaxInt +// errors when the decompressed message has an invalid format +// errors when the decompressed message exceeds the maxReceiveMessageSize. func (s) TestDecompress(t *testing.T) { compressor := encoding.GetCompressor("gzip") + validDecompressor := &MockDecompressor{ShouldError: false} + invalidFormatDecompressor := &MockDecompressor{ShouldError: true} testCases := []struct { name string @@ -361,6 +388,22 @@ func (s) TestDecompress(t *testing.T) { want: []byte("large message"), wantErr: nil, }, + { + name: "Fails with decompression error due to invalid format", + input: compressWithDeterministicError(t, []byte("invalid compressed data")), + dc: invalidFormatDecompressor, + maxReceiveMessageSize: 50, + want: nil, + wantErr: status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", errors.New(decompressionErrorMsg)), + }, + { + name: "Fails with resourceExhausted error when decompressed message exceeds maxReceiveMessageSize", + input: compressWithDeterministicError(t, []byte("large compressed data")), + dc: validDecompressor, + maxReceiveMessageSize: 20, + want: nil, + wantErr: status.Errorf(codes.ResourceExhausted, "grpc: message after decompression larger than max (%d vs. %d)", 25, 20), + }, } for _, tc := range testCases { From 23baa5398d1f4f32ca7bf834344f4cbc8a1cc6e1 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 10 Jan 2025 17:04:48 +0000 Subject: [PATCH 33/35] Fixed test cases for dock block --- rpc_util_test.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index bc63aaeb6e7b..13ab903b954a 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -320,24 +320,27 @@ func compressWithDeterministicError(t *testing.T, input []byte) mem.BufferSlice return mem.BufferSlice{mem.NewBuffer(&compressedData, nil)} } -// MockDecompressor is a mock decompressor that always returns an error +// MockDecompressor is a mock implementation of a decompressor used for testing purposes. +// It simulates decompression behavior, returning either decompressed data or an error based on the ShouldError flag. type MockDecompressor struct { - ShouldError bool + ShouldError bool // Flag to control whether the decompression should simulate an error. } -// Do simulates decompression. If ShouldError is true, it returns an error, else it returns decompressed data. -func (m *MockDecompressor) Do(reader io.Reader) ([]byte, error) { +// Do simulates decompression. It returns a predefined error if ShouldError is true, +// or a fixed set of decompressed data if ShouldError is false. +func (m *MockDecompressor) Do(_ io.Reader) ([]byte, error) { if m.ShouldError { return nil, errors.New(decompressionErrorMsg) } return []byte(defaultDecompressedData), nil } +// Type returns the identifier for the MockDecompressor, which is "mock". func (m *MockDecompressor) Type() string { - return "mock" + return "MockDecompressor" } -// TestDecompress tests the decompress function behaves correctly for following scenarios +// TestDecompress// fails with resourceExhausted error when the decompressed message exceeds maxReceiveMessageSize. tests the decompress function behaves correctly for following scenarios // decompress successfully when message is <= maxReceiveMessageSize // errors when message > maxReceiveMessageSize // decompress successfully when maxReceiveMessageSize is MaxInt From 7664e754bd8aab4c8ce72e0db7fa0af2911a3509 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 10 Jan 2025 17:24:27 +0000 Subject: [PATCH 34/35] small tweaks --- rpc_util_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc_util_test.go b/rpc_util_test.go index 13ab903b954a..608cc1002471 100644 --- a/rpc_util_test.go +++ b/rpc_util_test.go @@ -335,12 +335,12 @@ func (m *MockDecompressor) Do(_ io.Reader) ([]byte, error) { return []byte(defaultDecompressedData), nil } -// Type returns the identifier for the MockDecompressor, which is "mock". +// Type returns the string identifier for the MockDecompressor. func (m *MockDecompressor) Type() string { return "MockDecompressor" } -// TestDecompress// fails with resourceExhausted error when the decompressed message exceeds maxReceiveMessageSize. tests the decompress function behaves correctly for following scenarios +// TestDecompress tests the decompress function behaves correctly for following scenarios // decompress successfully when message is <= maxReceiveMessageSize // errors when message > maxReceiveMessageSize // decompress successfully when maxReceiveMessageSize is MaxInt From 6fb580c20b66d358b6790d63f73ea8748512ca00 Mon Sep 17 00:00:00 2001 From: Vinothkumar Date: Fri, 17 Jan 2025 07:50:27 +0000 Subject: [PATCH 35/35] Fixed review changes for the decompress function --- rpc_util.go | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/rpc_util.go b/rpc_util.go index ec60fb599be8..94160b130897 100644 --- a/rpc_util.go +++ b/rpc_util.go @@ -876,33 +876,19 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompress return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err) } - if doesReceiveMessageOverflow(out.Len(), maxReceiveMessageSize, dcReader) { + if out.Len() == maxReceiveMessageSize && !atEOF(dcReader) { out.Free() return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) } return out, nil } - return d, nil + return nil, status.Errorf(codes.Internal, "grpc: no decompressor available for compressed payload") } -// doesReceiveMessageOverflow checks if the number of bytes read from the stream -// exceed the maximum receive message size allowed by the receiver. If the `readBytes` -// is greater than or equal to `maxReceiveMessageSize`, the function attempts to read -// one more byte from the `dcReader` to detect if there's an overflow. -// -// If additional data is read, or an error other than `io.EOF` is encountered, the function -// returns `true` to indicate that the message size has exceeded the permissible limit. -// Otherwise, it returns `false` indicating no overflow. -func doesReceiveMessageOverflow(readBytes, maxReceiveMessageSize int, dcReader io.Reader) bool { - if readBytes < maxReceiveMessageSize { - return false - } - - b := make([]byte, 1) - if n, err := dcReader.Read(b); n > 0 || err != io.EOF { - return true - } - return false +// atEOF reads data from r and returns true if zero bytes could be read and r.Read returns EOF. +func atEOF(dcReader io.Reader) bool { + n, err := dcReader.Read(make([]byte, 1)) + return n == 0 && err == io.EOF } type recvCompressor interface {