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

Add config for the header use by the general ingress #638

Merged
merged 6 commits into from
Jan 8, 2024

Conversation

nanassito
Copy link
Contributor

@nanassito nanassito commented Jan 5, 2024

💸 TL;DR

We now have a generic ingress for thrift traffic that routes the traffic based on a header. This means that looking at a service config we don't see what service the traffic is going to and that the application need to set the header manually unlike every other configuration bit.

So this PR adds a new configuration to set this header.

📜 Details

Design Doc

Jira

🧪 Testing Steps / Validation

✅ Checks

  • CI tests (if present) are passing
  • Adheres to code style for repo
  • Contributor License Agreement (CLA) completed if not a Reddit employee

@@ -429,6 +434,19 @@ func NewCustomClientPoolWithContext(
return newClientPool(ctx, cfg, genAddr, protoFactory, middlewares...)
}

const ThriftHostnameHeader = "thrift-hostname"
Copy link
Member

Choose a reason for hiding this comment

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

is this intentionally lower-case?

for THeaders we use Camel-Case (see https://github.com/reddit/baseplate.go/blob/master/transport/headers.go), it will be better to keep it consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that's the value the ingress expects sadly.

@davinci26 can comment on whether this can be changed or not

Copy link
Contributor

Choose a reason for hiding this comment

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

So according to the HTTP RFC header casing doesnt matter. @fishy does the same apply for thrift?

Each header field consists of a case-insensitive field name followed
by a colon (":"), optional leading whitespace, the field value, and
optional trailing whitespace.

In any case envoy will lower case the headers when parsing the thrift payload so it doesn't care but it would be nice if we took a dependency on a thrift spec definition rather than an envoy implementation detail.

https://github.com/envoyproxy/envoy/blob/12210e53db6cea79b58ee027f047faa356e1e392/source/extensions/filters/network/thrift_proxy/header_transport_impl.cc#L163

Copy link
Member

@fishy fishy Jan 5, 2024

Choose a reason for hiding this comment

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

well this is not http header, it's thrift header.

envoy lower case all headers was a bug and fixed in latest version of envoy: envoyproxy/envoy#20595, envoyproxy/envoy@53867ab

Copy link
Contributor

@davinci26 davinci26 Jan 5, 2024

Choose a reason for hiding this comment

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

well this is not http header, it's thrift header.

Now I am reading the issue

Copy link
Contributor

Choose a reason for hiding this comment

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

then in that case I think we should maintain the original casing so we follow the thrift protocol rather than the envoy implementation detail

Copy link
Contributor

Choose a reason for hiding this comment

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

even if this breaks the code pattern here. This is a header defined externally to baseplate.go so it should be fine to have different casing

@@ -505,6 +523,11 @@ func newClientPool(

slug: cfg.ServiceSlug,
}

if cfg.ThriftHostnameHeader != "" {
Copy link
Member

Choose a reason for hiding this comment

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

instead of conditionally add the middleware, it might be better to always add the middleware but the middleware itself conditionally add the header (don't add it if it's empty string)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure

Copy link
Contributor

@davinci26 davinci26 left a comment

Choose a reason for hiding this comment

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

overall looks pretty sane to me. Is there a way we could add tests?

Comment on lines 215 to 218
// The hostname to add as a "thrift-hostname" header.
//
// Optional. If empty, not "thrift-hostname" header will be sent.
ThriftHostnameHeader string `yaml:"thriftHostnameHeader"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// The hostname to add as a "thrift-hostname" header.
//
// Optional. If empty, not "thrift-hostname" header will be sent.
ThriftHostnameHeader string `yaml:"thriftHostnameHeader"`
// The hostname to add as a "Thrift-Hostname" header.
//
// Optional. If empty, no "Thrift-Hostname" header will be sent.
ThriftHostnameHeader string `yaml:"thriftHostnameHeader"`

Copy link
Contributor Author

Choose a reason for hiding this comment

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

well from the rest of the convo it looks like we'll keep the lower case in the end

Copy link
Member

Choose a reason for hiding this comment

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

but we still should s/not/no/ :)

@nanassito nanassito marked this pull request as ready for review January 5, 2024 23:22
@nanassito nanassito requested a review from a team as a code owner January 5, 2024 23:22
@nanassito nanassito requested review from fishy and pacejackson and removed request for a team January 5, 2024 23:22
@nanassito
Copy link
Contributor Author

Ideally I'd like to add tests but I'm not sure how. I haven't found a way to check the headers yet.

Copy link
Member

@fishy fishy left a comment

Choose a reason for hiding this comment

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

I still think if it's not too late we should change the header to Camel-Case, but that's not a blocking issue.

As for testing, the way to test headers is to:

  1. start a server from a loopback port
  2. create a client pool on the loopback port, with the header config
  3. send a request
  4. you can check the header on the server endpoint handler via thrift.GetHeader(ctx)

thriftbp/client_pool.go Outdated Show resolved Hide resolved
Comment on lines 215 to 218
// The hostname to add as a "thrift-hostname" header.
//
// Optional. If empty, not "thrift-hostname" header will be sent.
ThriftHostnameHeader string `yaml:"thriftHostnameHeader"`
Copy link
Member

Choose a reason for hiding this comment

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

but we still should s/not/no/ :)

@nanassito nanassito requested a review from fishy January 8, 2024 17:44
func (thriftHostnameHandler) IsHealthy(ctx context.Context, _ *baseplatethrift.IsHealthyRequest) (r bool, err error) {
value, ok := thrift.GetHeader(ctx, thriftbp.ThriftHostnameHeader)
if !ok {
return false, errors.New("did not find the thrift header")
Copy link
Member

Choose a reason for hiding this comment

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

I would slightly prefer to add tb testing.TB into thriftHostnameHandler struct and use tb.Error() instead, but this also works.

@nanassito nanassito merged commit f99bf0b into reddit:master Jan 8, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants