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

upstream: allow extension protocol options to be used with http filters #4165

Merged
merged 5 commits into from
Aug 20, 2018

Conversation

yuval-k
Copy link
Contributor

@yuval-k yuval-k commented Aug 15, 2018

#4098 Added protocol extensions for clusters and network filters. This PR expands this to http filters as well (this can be used for example in a filter that translates http to a different protocol, like our NATS Streaming filter)

Risk Level: low, ignored by existing protocols
Testing: unit tests
Docs Changes: inline
Release Notes: n/a

Few notes:

  • I've extracted createProtocolOptionsConfig, createEmptyProtocolOptionsProto to an interface called ProtocolOptionsConsumer as the factories that inherit from it are the ones that will eventually consume the configuration (via created filters). not sure if its the best name, suggestions are welcome.
  • when building the config map, for each filter name, I first check if there's a network filter and if there isn't, i check if there's an http filter. I did not handle the case of both existing as this should never happen (as filter names are namespaced by convention).
  • Updated existing unit tests to test both http and network filters.

@mattklein123
Copy link
Member

Make sense to me. @zuercher PTAL

Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

Nice! I have one minor change and a couple of things to thing about, bit it looks good otherwise.

@@ -311,6 +323,16 @@ class NamedHttpFilterConfigFactory {
return nullptr;
}

// ProtocolOptionsConsumer
Upstream::ProtocolOptionsConfigConstSharedPtr
createProtocolOptionsConfig(const Protobuf::Message& config) override {
Copy link
Member

Choose a reason for hiding this comment

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

What do you think about moving the default implementations (here and from the NamedNetworkFilterConfigFactory) to ProtocolOptionsConsumer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sounds good

class TestNetworkFilterConfigFactory
: public Server::Configuration::NamedNetworkFilterConfigFactory {
public:
TestNetworkFilterConfigFactory(TestFilterConfigFactoryBase& parent) : parent_(parent) {}
Copy link
Member

Choose a reason for hiding this comment

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

It's a little odd not to use inheritance here, but I guess the alternative is assigning the lambdas to variables in the tests and re-using them.

It's a bit dodgy, but I think you could combine the two factories into a single class as long as you overload all the methods that appear in both. 😬

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The catch is that i'm not sure how that will work with name() method that's shared on both, but doesn't come from a common interface. is there a way to express that in c++ ?

Copy link
Member

Choose a reason for hiding this comment

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

It's probably a bad idea. I'm fine for you to leave this as is.


if (factory == nullptr) {
throw EnvoyException(fmt::format(
"Didn't find a registered network or http implementation for name: '{}'", name));
Copy link
Member

Choose a reason for hiding this comment

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

Let's add "filter" between http and implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sounds good

Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

Looks great. Let's think about a better name for ProtocolOptionsConsumer and then I think it's good to go.

@@ -181,11 +181,35 @@ class NamedListenerFilterConfigFactory {
virtual std::string name() PURE;
};

class ProtocolOptionsConsumer {
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps this should be called ProtocolOptionsFactory? I'm sure what "consumer" means here.

Regardless, should add at least a brief class comment here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good to me - will fix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what about this comment for class doc:
Implemented by filter factories that require more options to process the protocol used by the upstream cluster.

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 16, 2018

@zuercher fixed 2 of the 3 comments, not sure if there's a good was to fix the suggestion on the the filter test class - see my response.

@zuercher
Copy link
Member

BTW I'm going to cancel your running builds for an older commit -- circle ci is running a backlog and I want to get master fix testing asap -- it shouldn't affect your builds for your latest (or any future) commits. Just FYI, in case you get an email.

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 16, 2018

ipv6 test failure seems unrelated as it results from the hds_integration_test:


[2018-08-16 21:05:42.680][9551][critical][assert] test/integration/fake_upstream.h:302] assert failure: parented_ || allow_unexpected_disconnects_. Details: An queued upstream connection was torn down without being associated with a fake connection. Either manage the connection via waitForRawConnection() or waitForHttpConnection(), or set_allow_unexpected_disconnects(true).

full stack trace from CI logs:




==================== Test output for //test/integration:hds_integration_test:
WARNING: Perftools heap leak checker is active -- Performance may suffer
[==========] Running 20 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 20 tests from IpVersions/HdsIntegrationTest
[ RUN      ] IpVersions/HdsIntegrationTest.SingleEndpointHealthyHttp/IPv4
[       OK ] IpVersions/HdsIntegrationTest.SingleEndpointHealthyHttp/IPv4 (1091 ms)
[ RUN      ] IpVersions/HdsIntegrationTest.SingleEndpointHealthyHttp/IPv6
[       OK ] IpVersions/HdsIntegrationTest.SingleEndpointHealthyHttp/IPv6 (1057 ms)
[ RUN      ] IpVersions/HdsIntegrationTest.SingleEndpointTimeoutHttp/IPv4
[2018-08-16 21:05:42.680][9551][critical][assert] test/integration/fake_upstream.h:302] assert failure: parented_ || allow_unexpected_disconnects_. Details: An queued upstream connection was torn down without being associated with a fake connection. Either manage the connection via waitForRawConnection() or waitForHttpConnection(), or set_allow_unexpected_disconnects(true).
 See https://github.com/envoyproxy/envoy/blob/master/test/integration/README.md#unparented-upstream-connections
[2018-08-16 21:05:42.680][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:125] Caught Aborted, suspect faulting address 0x2526
[2018-08-16 21:05:42.680][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:94] Backtrace thr<9551> obj</lib/x86_64-linux-gnu/libc.so.6> (If unsymbolized, use tools/stack_decode.py):
[2018-08-16 21:05:42.680][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:117] thr<9551> #0 0x7fd862b68428 (unknown)
[2018-08-16 21:05:42.680][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:117] thr<9551> #1 0x7fd862b6a029 (unknown)
[2018-08-16 21:05:42.680][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] thr<9551> obj</build/tmp/_bazel_bazel/436badd4919a15958fa3800a4e21074a/execroot/ci/bazel-out/k8-fastbuild/bin/test/integration/hds_integration_test.runfiles/ci/test/integration/hds_integration_test>
[2018-08-16 21:05:42.686][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #2 0x645011 Envoy::QueuedConnectionWrapper::QueuedConnectionWrapper()::{lambda()#1}::operator()()
[2018-08-16 21:05:42.691][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #3 0x644d6c std::_Function_handler<>::_M_invoke()
[2018-08-16 21:05:42.696][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #4 0x62e8fd std::function<>::operator()()
[2018-08-16 21:05:42.701][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #5 0x62e7b7 Envoy::Common::CallbackManager<>::runCallbacks()
[2018-08-16 21:05:42.705][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #6 0x62d674 Envoy::SharedConnectionWrapper::onEvent()
[2018-08-16 21:05:42.710][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #7 0x75ad15 Envoy::Network::ConnectionImpl::raiseEvent()
[2018-08-16 21:05:42.716][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #8 0x759b51 Envoy::Network::ConnectionImpl::closeSocket()
[2018-08-16 21:05:42.721][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #9 0x75c495 Envoy::Network::ConnectionImpl::onFileEvent()
[2018-08-16 21:05:42.726][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #10 0x75e63d Envoy::Network::ConnectionImpl::ConnectionImpl()::$_2::operator()()
[2018-08-16 21:05:42.731][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #11 0x75e4f0 std::_Function_handler<>::_M_invoke()
[2018-08-16 21:05:42.736][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #12 0x751779 std::function<>::operator()()
[2018-08-16 21:05:42.741][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #13 0x751308 Envoy::Event::FileEventImpl::assignEvents()::$_0::operator()()
[2018-08-16 21:05:42.746][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #14 0x751137 Envoy::Event::FileEventImpl::assignEvents()::$_0::__invoke()
[2018-08-16 21:05:42.751][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #15 0x1876ba4 event_process_active_single_queue.isra.29
[2018-08-16 21:05:42.756][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #16 0x18772ee event_process_active
[2018-08-16 21:05:42.761][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #17 0x187a077 event_base_loop
[2018-08-16 21:05:42.766][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #18 0x74bd9c Envoy::Event::DispatcherImpl::run()
[2018-08-16 21:05:42.771][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #19 0x639085 Envoy::FakeUpstream::threadRoutine()
[2018-08-16 21:05:42.776][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #20 0x63d147 Envoy::FakeUpstream::FakeUpstream()::$_9::operator()()
[2018-08-16 21:05:42.781][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #21 0x63cffc std::_Function_handler<>::_M_invoke()
[2018-08-16 21:05:42.782][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #22 0x62e8fd std::function<>::operator()()
[2018-08-16 21:05:42.787][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #23 0x156436b Envoy::Thread::Thread::Thread()::$_0::operator()()
[2018-08-16 21:05:42.792][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #24 0x1564347 Envoy::Thread::Thread::Thread()::$_0::__invoke()
[2018-08-16 21:05:42.792][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] thr<9551> obj</lib/x86_64-linux-gnu/libpthread.so.0>
[2018-08-16 21:05:42.792][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:114] thr<9551> #25 0x7fd8637a56b9 start_thread
[2018-08-16 21:05:42.793][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:104] thr<9551> obj</lib/x86_64-linux-gnu/libc.so.6>
[2018-08-16 21:05:42.793][9551][critical][backtrace] bazel-out/k8-fastbuild/bin/source/server/_virtual_includes/backtrace_lib/server/backtrace.h:117] thr<9551> #26 0x7fd862c3a41c (unknown)
[2,834 / 2,836] 32 / 38 tests, 1 failed; 2 actions running; last test: //test/\


integration:hds_integration_test


    Testing //test/integration:hotrestart_test; 36s local


    Testing //test/integration:hds_integration_test; 3s local

@zuercher
Copy link
Member

The hds integration test is being worked on in #4164.
Depending on when you branched, merging master may with the release build test (if you don't already have 07bc27c). You can create and push an empty commit to force another go (git commit --allow-empty -m 'bump ci' -s)

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 16, 2018

The release failure also seems unrelated and stems from rbac:integration_test:

test/extensions/filters/network/rbac/integration_test.cc:92: Failure
Expected equality of these values:
  1U
    Which is: 1
  test_server_->counter("tcp.rbac.allowed")->value()
    Which is: 0
test/extensions/filters/network/rbac/integration_test.cc:95: Failure
Expected equality of these values:
  1U
    Which is: 1
  test_server_->counter("tcp.rbac.shadow_denied")->value()
    Which is: 0
[  FAILED  ] IpVersions/RoleBasedAccessControlNetworkFilterIntegrationTest.Allowed/IPv4, where GetParam() = 4-byte object <00-00 00-00> (53 ms)

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 16, 2018

yes it seems like that flaky RBAC you mentioned, i'll kick CI to have another go.
Thanks for the insights!

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 16, 2018

Success! thanks @zuercher !

zuercher
zuercher previously approved these changes Aug 17, 2018
Copy link
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

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

Looks great. Thanks for taking this on.

@htuch do you want to have a look?

@htuch
Copy link
Member

htuch commented Aug 17, 2018

@yuval-k this seems reasonable, but I'd like to quickly double check on motivation here. Is it the case that your NATS streaming filter makes use of knowledge of the upstream picked cluster? Usually awareness of upstream cluster and host pick is more limited, to the router filter, earlier filters in the pipeline don't have this smarts. You can't action on this information until later in the request, post initial headers for example.

Anyway, if you can provide some insight into how this is consume by your HTTP filter I think that would help review. Thanks.

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 17, 2018

@htuch yes that's correct. In that sense the NATS filter replaces the router filter (i.e. the NATs filter doesn't let the request continue down the filter chain). The idea is to support a case when some requests are routed to http upstreams, and others are converted to NATS pub.

@htuch
Copy link
Member

htuch commented Aug 17, 2018

@yuval-k how do the cluster defined protocol options fit into that idea? If you're holding the request, you probably don't even have a cluster assignment yet for it, so how can you benefit from the protocol options there?

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 17, 2018

The cluster assignment happens in the HCM before the request reaches the NATS filter (which is an http filter, placed before the router filter).
If the NATS see that the request belongs to a NATS cluster, it prevents the request from continuing the chain and handles it. the protocol options is a way to express that per cluster vs on the filter config (otherwise I will need a map of cluster -> nats parameters in the filter config).

@htuch
Copy link
Member

htuch commented Aug 17, 2018

Right, yeah; we have the cached route entry, which indicates cluster (but no actual upstream host pick yet). Makes sense.

@@ -1625,14 +1685,27 @@ TEST_F(ClusterInfoImplTest, ExtensionProtocolOptionsForFilterWithOptions) {
envoy.test.filter: { option: "value" }
)EOF";

auto cluster = makeCluster(yaml);
std::vector<std::unique_ptr<StrictDnsClusterImpl>> clusters;
Copy link
Member

Choose a reason for hiding this comment

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

Can you add some comment explaining what you're testing here? It's unclear without reading deeply whether we're covering all the permutations of {no filter, network filter, http filter} for a given protocol options slot.

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 17, 2018

Not sure what happened with the DCO - I merged master to get the RBAC flake fix (did a regular git merge origin/master)

@htuch
Copy link
Member

htuch commented Aug 17, 2018

That's weird, this branch looks kind of crazy. Do you want to just get it into a sane state and force push?

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 17, 2018

sounds good, will do

Signed-off-by: Yuval Kohavi <yuval.kohavi@gmail.com>
Signed-off-by: Yuval Kohavi <yuval.kohavi@gmail.com>
Signed-off-by: Yuval Kohavi <yuval.kohavi@gmail.com>
Signed-off-by: Yuval Kohavi <yuval.kohavi@gmail.com>
Signed-off-by: Yuval Kohavi <yuval.kohavi@gmail.com>
@yuval-k yuval-k force-pushed the http-protocol-options branch from faad843 to b5a1a6d Compare August 17, 2018 18:23
@zuercher
Copy link
Member

@yuval-k make sure you get the clang-6 change as well

@yuval-k
Copy link
Contributor Author

yuval-k commented Aug 17, 2018

I used latest master from today and cherry picked my commits over it - so it should be good.

@htuch htuch merged commit de4e2f4 into envoyproxy:master Aug 20, 2018
snowp added a commit to snowp/envoy that referenced this pull request Aug 20, 2018
* origin/master: (34 commits)
  fuzz: fixes oss-fuzz: 9895 (envoyproxy#4189)
  docs: added developer docs for pprof/tcmalloc testing (envoyproxy#4194)
  fix sometimes returns response body to HEAD requests (envoyproxy#3985)
  admin: fix config dump order (envoyproxy#4197)
  thrift: allow translation between downstream and upstream protocols (envoyproxy#4136)
  Use local_info.node() instead of bootstrap.node() whenever possible (envoyproxy#4120)
  upstream: allow extension protocol options to be used with http filters (envoyproxy#4165)
  [thrift_proxy] Replace local HeaderMap with Http::HeaderMap[Impl] (envoyproxy#4169)
  docs: improve gRPC-JSON filter doc (envoyproxy#4184)
  stats: refactoring MetricImpl without strings (envoyproxy#4190)
  fuzz: coverage profile generation instructions. (envoyproxy#4193)
  upstream: rebuild cluster when health check config is changed (envoyproxy#4075)
  build: use clang-6.0. (envoyproxy#4168)
  thrift_proxy: introduce header transport (envoyproxy#4082)
  tcp: allow connection pool callers to store protocol state (envoyproxy#4131)
  configs: match latest API changes (envoyproxy#4185)
  Fix wrong mock function name. (envoyproxy#4187)
  Bump yaml-cpp so it builds with Visual Studio 15.8 (envoyproxy#4182)
  Converting envoy configs to V2 (envoyproxy#2957)
  Add timestamp to HealthCheckEvent definition (envoyproxy#4119)
  ...

Signed-off-by: Snow Pettersen <snowp@squareup.com>
yuval-k added a commit to solo-io/envoy-gloo that referenced this pull request Dec 6, 2018
temporary using my envoy fork until PR envoyproxy/envoy#4165 is merged.
also - remove envoy common from workspace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants