Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

xds: implement fault injection HTTP filter (A33) #4236

Merged
merged 4 commits into from Mar 12, 2021

Conversation

dfawley
Copy link
Member

@dfawley dfawley commented Mar 2, 2021

also contains all of #4235

@dfawley dfawley added the Type: Feature New features or improvements in behavior label Mar 2, 2021
@dfawley dfawley added this to the 1.37 Release milestone Mar 2, 2021
@dfawley dfawley requested a review from menghanl March 2, 2021 22:19

func (builder) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
// Parsing is the same for the override config.
return builder{}.ParseFilterConfig(override)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name the receiver and use it, instead of create a new one.
Or just make a local function, and call it in both Parse() methods.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (latter).

md, _ := metadata.FromOutgoingContext(ctx)
if v := md[headerDelayDuration]; v != nil {
if ms, ok := parseIntFromMD(v); ok {
delay = time.Duration(time.Duration(ms) * time.Millisecond)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The outer time.Duration conversion is redundant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

} else {
return nil
}
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about

v := md[headerDelayDuration]
if v == nil {
  return nil
}
ms, ok := parseIntFromMD(v)
if! ok {
  return nil
}
delay = time.Duration(time.Duration(ms) * time.Millisecond)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, done. All the elses can be confusing.

code, okCode = sanitizeGRPCCode(codes.Code(errType.GrpcStatus)), true
case *fpb.FaultAbort_HeaderAbort_:
md, _ := metadata.FromOutgoingContext(ctx)
if v := md[headerAbortHTTPStatus]; v != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it by design that http status has higher priority than gRPC status?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/fault_filter#controlling-fault-injection-via-http-headers:

If both x-envoy-fault-abort-request and x-envoy-fault-abort-grpc-request headers are set then x-envoy-fault-abort-grpc-request header will be ignored and fault response http status code will be set to x-envoy-fault-abort-request header value.

}

// For overriding in tests
var intn = grpcrand.Intn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this to randIntn? I at first thought this is a type conversion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


func (*okStream) Header() (metadata.MD, error) { return nil, nil }
func (*okStream) Trailer() metadata.MD { return nil }
func (*okStream) CloseSend() error { return nil }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CloseSend should also return io.EOF, it's a special send.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's right. We never return an error from CloseSend:

grpc-go/stream.go

Lines 831 to 834 in 930c791

// Always return nil; io.EOF is the only error that might make sense
// instead, but there is no need to signal the client to call RecvMsg
// as the only use left for the stream after CloseSend is to call
// RecvMsg. This also matches historical behavior.

Copy link
Member Author

@dfawley dfawley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a test failure that was/is concerning, but I've re-run locally for hundreds of runs without encountering them. Also the failing test run on GA included a non-FI test failure that I've never seen before, so maybe solar flares are to blame?


func (builder) ParseFilterConfigOverride(override proto.Message) (httpfilter.FilterConfig, error) {
// Parsing is the same for the override config.
return builder{}.ParseFilterConfig(override)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (latter).

}

// For overriding in tests
var intn = grpcrand.Intn
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

md, _ := metadata.FromOutgoingContext(ctx)
if v := md[headerDelayDuration]; v != nil {
if ms, ok := parseIntFromMD(v); ok {
delay = time.Duration(time.Duration(ms) * time.Millisecond)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

} else {
return nil
}
} else {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, done. All the elses can be confusing.

code, okCode = sanitizeGRPCCode(codes.Code(errType.GrpcStatus)), true
case *fpb.FaultAbort_HeaderAbort_:
md, _ := metadata.FromOutgoingContext(ctx)
if v := md[headerAbortHTTPStatus]; v != nil {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/fault_filter#controlling-fault-injection-via-http-headers:

If both x-envoy-fault-abort-request and x-envoy-fault-abort-grpc-request headers are set then x-envoy-fault-abort-grpc-request header will be ignored and fault response http status code will be set to x-envoy-fault-abort-request header value.


func (*okStream) Header() (metadata.MD, error) { return nil, nil }
func (*okStream) Trailer() metadata.MD { return nil }
func (*okStream) CloseSend() error { return nil }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's right. We never return an error from CloseSend:

grpc-go/stream.go

Lines 831 to 834 in 930c791

// Always return nil; io.EOF is the only error that might make sense
// instead, but there is no need to signal the client to call RecvMsg
// as the only use left for the stream after CloseSend is to call
// RecvMsg. This also matches historical behavior.

@menghanl
Copy link
Contributor

menghanl commented Mar 8, 2021

Can you rebase this onto master? To fix the conflicts, and also then this PR will show only the new diffs.

@dfawley
Copy link
Member Author

dfawley commented Mar 9, 2021

Can you rebase this onto master? To fix the conflicts, and also then this PR will show only the new diffs.

Done!

@@ -0,0 +1,646 @@
// +build !386
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Type: Feature New features or improvements in behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants