From 0f387653d833c12cf4db15c574859a75450a05fb Mon Sep 17 00:00:00 2001 From: Kuat Date: Thu, 7 Jun 2018 15:00:58 -0700 Subject: [PATCH] Route directive (#1797) * wire through route directive Signed-off-by: Kuat Yessenov * fix format Signed-off-by: Kuat Yessenov * propagate info Signed-off-by: Kuat Yessenov * review Signed-off-by: Kuat Yessenov * implement the API Signed-off-by: Kuat Yessenov * manual test Signed-off-by: Kuat Yessenov * review Signed-off-by: Kuat Yessenov * fix upstream api change Signed-off-by: Kuat Yessenov * add a test case Signed-off-by: Kuat Yessenov * review, handle direct response headers Signed-off-by: Kuat Yessenov --- include/istio/control/http/request_handler.h | 2 +- include/istio/control/tcp/request_handler.h | 2 +- include/istio/mixerclient/BUILD | 1 + include/istio/mixerclient/check_response.h | 5 ++ istio.deps | 2 +- repositories.bzl | 2 +- src/envoy/BUILD | 1 + src/envoy/http/mixer/filter.cc | 73 ++++++++++++++++++- src/envoy/http/mixer/filter.h | 24 +++++- src/envoy/http/mixer/filter_factory.cc | 3 +- src/envoy/tcp/mixer/filter.cc | 6 +- src/istio/control/client_context_base.cc | 6 +- src/istio/control/client_context_base.h | 2 +- .../control/http/request_handler_impl.cc | 9 ++- src/istio/control/http/request_handler_impl.h | 2 +- .../control/http/request_handler_impl_test.cc | 13 +++- src/istio/control/tcp/request_handler_impl.cc | 10 ++- src/istio/control/tcp/request_handler_impl.h | 3 +- .../control/tcp/request_handler_impl_test.cc | 6 +- src/istio/mixerclient/check_cache.cc | 9 ++- src/istio/mixerclient/check_cache.h | 20 ++++- src/istio/mixerclient/check_cache_test.cc | 12 ++- src/istio/mixerclient/client_impl.cc | 3 + test/backend/echo/echo.go | 1 + tools/deb/BUILD | 1 + 25 files changed, 180 insertions(+), 38 deletions(-) diff --git a/include/istio/control/http/request_handler.h b/include/istio/control/http/request_handler.h index 7974a8054a41..ed863c7f4681 100644 --- a/include/istio/control/http/request_handler.h +++ b/include/istio/control/http/request_handler.h @@ -38,7 +38,7 @@ class RequestHandler { virtual ::istio::mixerclient::CancelFunc Check( CheckData* check_data, HeaderUpdate* header_update, ::istio::mixerclient::TransportCheckFunc transport, - ::istio::mixerclient::DoneFunc on_done) = 0; + ::istio::mixerclient::CheckDoneFunc on_done) = 0; // Make a Report call. It will: // * check service config to see if Report is required diff --git a/include/istio/control/tcp/request_handler.h b/include/istio/control/tcp/request_handler.h index acebfd67a363..493af0d940d8 100644 --- a/include/istio/control/tcp/request_handler.h +++ b/include/istio/control/tcp/request_handler.h @@ -33,7 +33,7 @@ class RequestHandler { // * extract downstream tcp connection attributes // * check config, make a Check call if necessary. virtual ::istio::mixerclient::CancelFunc Check( - CheckData* check_data, ::istio::mixerclient::DoneFunc on_done) = 0; + CheckData* check_data, ::istio::mixerclient::CheckDoneFunc on_done) = 0; // Make report call. // This can be called multiple times for long connection. diff --git a/include/istio/mixerclient/BUILD b/include/istio/mixerclient/BUILD index ed5183384a77..721e5546c9d7 100644 --- a/include/istio/mixerclient/BUILD +++ b/include/istio/mixerclient/BUILD @@ -25,6 +25,7 @@ cc_library( ], visibility = ["//visibility:public"], deps = [ + "//external:mixer_api_cc_proto", "//include/istio/quota_config:requirement_header", ], ) diff --git a/include/istio/mixerclient/check_response.h b/include/istio/mixerclient/check_response.h index 20a661c4a26a..bd9690533af2 100644 --- a/include/istio/mixerclient/check_response.h +++ b/include/istio/mixerclient/check_response.h @@ -17,6 +17,7 @@ #define ISTIO_MIXERCLIENT_CHECK_RESPONSE_H #include "google/protobuf/stubs/status.h" +#include "mixer/v1/check.pb.h" namespace istio { namespace mixerclient { @@ -32,6 +33,10 @@ struct CheckResponseInfo { // The check and quota response status. ::google::protobuf::util::Status response_status{ ::google::protobuf::util::Status::UNKNOWN}; + + // Routing directive (applicable if the status is OK) + ::istio::mixer::v1::RouteDirective route_directive{ + ::istio::mixer::v1::RouteDirective::default_instance()}; }; } // namespace mixerclient diff --git a/istio.deps b/istio.deps index 7d9168cf4652..9069de6b6233 100644 --- a/istio.deps +++ b/istio.deps @@ -4,7 +4,7 @@ "name": "ISTIO_API", "repoName": "api", "file": "repositories.bzl", - "lastStableSHA": "ecef45ec0f0ef17c4b383ee84dcbcdba4fcc0c8d" + "lastStableSHA": "f403f2ff3a7ee656a1bfbf23e66966a633160300", }, { "_comment": "", diff --git a/repositories.bzl b/repositories.bzl index 9493129f32a1..e1395e2447f3 100644 --- a/repositories.bzl +++ b/repositories.bzl @@ -113,7 +113,7 @@ cc_library( actual = "@googletest_git//:googletest_prod", ) -ISTIO_API = "c747495e9419606fa1febe210a7626e177b1935c" +ISTIO_API = "f403f2ff3a7ee656a1bfbf23e66966a633160300" def mixerapi_repositories(bind=True): BUILD = """ diff --git a/src/envoy/BUILD b/src/envoy/BUILD index 45e3251dcb68..43abb6b554f2 100644 --- a/src/envoy/BUILD +++ b/src/envoy/BUILD @@ -40,4 +40,5 @@ pkg_tar( files = [":envoy"], mode = "0755", package_dir = "/usr/local/bin/", + tags = ["manual"], ) diff --git a/src/envoy/http/mixer/filter.cc b/src/envoy/http/mixer/filter.cc index 41f8841ad56a..73cde1addcbe 100644 --- a/src/envoy/http/mixer/filter.cc +++ b/src/envoy/http/mixer/filter.cc @@ -24,6 +24,7 @@ using ::google::protobuf::util::Status; using ::istio::mixer::v1::config::client::ServiceConfig; +using ::istio::mixerclient::CheckResponseInfo; namespace Envoy { namespace Http { @@ -135,7 +136,7 @@ FilterHeadersStatus Filter::decodeHeaders(HeaderMap& headers, bool) { cancel_check_ = handler_->Check( &check_data, &header_update, control_.GetCheckTransport(decoder_callbacks_->activeSpan()), - [this](const Status& status) { completeCheck(status); }); + [this](const CheckResponseInfo& info) { completeCheck(info); }); initiating_call_ = false; if (state_ == Complete) { @@ -164,26 +165,70 @@ FilterTrailersStatus Filter::decodeTrailers(HeaderMap& trailers) { return FilterTrailersStatus::Continue; } +void Filter::UpdateHeaders( + HeaderMap& headers, const ::google::protobuf::RepeatedPtrField< + ::istio::mixer::v1::HeaderOperation>& operations) { + for (auto const iter : operations) { + switch (iter.operation()) { + case ::istio::mixer::v1::HeaderOperation_Operation_REPLACE: + headers.remove(LowerCaseString(iter.name())); + headers.addCopy(LowerCaseString(iter.name()), iter.value()); + break; + case ::istio::mixer::v1::HeaderOperation_Operation_REMOVE: + headers.remove(LowerCaseString(iter.name())); + break; + case ::istio::mixer::v1::HeaderOperation_Operation_APPEND: + headers.addCopy(LowerCaseString(iter.name()), iter.value()); + break; + default: + PANIC("unreachable header operation"); + } + } +} + +FilterHeadersStatus Filter::encodeHeaders(HeaderMap& headers, bool) { + ENVOY_LOG(debug, "Called Mixer::Filter : {} {}", __func__, state_); + ASSERT(state_ == Complete || state_ == Responded); + if (state_ == Complete) { + // handle response header operations + UpdateHeaders(headers, route_directive_.response_header_operations()); + } + return FilterHeadersStatus::Continue; +} + +FilterDataStatus Filter::encodeData(Buffer::Instance&, bool) { + ENVOY_LOG(debug, "Called Mixer::Filter : {}", __func__); + ASSERT(state_ == Complete || state_ == Responded); + return FilterDataStatus::Continue; +} + +FilterTrailersStatus Filter::encodeTrailers(HeaderMap&) { + ENVOY_LOG(debug, "Called Mixer::Filter : {}", __func__); + ASSERT(state_ == Complete || state_ == Responded); + return FilterTrailersStatus::Continue; +} + void Filter::setDecoderFilterCallbacks( StreamDecoderFilterCallbacks& callbacks) { ENVOY_LOG(debug, "Called Mixer::Filter : {}", __func__); decoder_callbacks_ = &callbacks; } -void Filter::completeCheck(const Status& status) { +void Filter::completeCheck(const CheckResponseInfo& info) { + auto status = info.response_status; ENVOY_LOG(debug, "Called Mixer::Filter : check complete {}", status.ToString()); // Remove Istio authentication header after Check() is completed if (nullptr != headers_) { Envoy::Utils::Authentication::ClearResultInHeader(headers_); - headers_ = nullptr; } // This stream has been reset, abort the callback. if (state_ == Responded) { return; } - if (!status.ok() && state_ != Responded) { + + if (!status.ok()) { state_ = Responded; int status_code = ::istio::utils::StatusHttpCode(status.error_code()); decoder_callbacks_->sendLocalReply(Code(status_code), status.ToString(), @@ -192,6 +237,26 @@ void Filter::completeCheck(const Status& status) { } state_ = Complete; + route_directive_ = info.route_directive; + + // handle direct response from the route directive + if (status.ok() && route_directive_.direct_response_code() != 0) { + ENVOY_LOG(debug, "Mixer::Filter direct response"); + state_ = Responded; + decoder_callbacks_->sendLocalReply( + Code(route_directive_.direct_response_code()), + route_directive_.direct_response_body(), [this](HeaderMap& headers) { + UpdateHeaders(headers, route_directive_.response_header_operations()); + }); + return; + } + + // handle request header operations + if (nullptr != headers_) { + UpdateHeaders(*headers_, route_directive_.request_header_operations()); + headers_ = nullptr; + } + if (!initiating_call_) { decoder_callbacks_->continueDecoding(); } diff --git a/src/envoy/http/mixer/filter.h b/src/envoy/http/mixer/filter.h index 6c31add39939..26b2d7266e4c 100644 --- a/src/envoy/http/mixer/filter.h +++ b/src/envoy/http/mixer/filter.h @@ -33,13 +33,13 @@ struct PerRouteServiceConfig : public Router::RouteSpecificFilterConfig { std::string hash; }; -class Filter : public Http::StreamDecoderFilter, +class Filter : public StreamFilter, public AccessLog::Instance, public Logger::Loggable { public: Filter(Control& control); - // Implementing virtual functions for StreamDecoderFilter + // Http::StreamDecoderFilter FilterHeadersStatus decodeHeaders(HeaderMap& headers, bool) override; FilterDataStatus decodeData(Buffer::Instance& data, bool end_stream) override; FilterTrailersStatus decodeTrailers(HeaderMap& trailers) override; @@ -49,8 +49,17 @@ class Filter : public Http::StreamDecoderFilter, // Http::StreamFilterBase void onDestroy() override; + // Http::StreamEncoderFilter + FilterHeadersStatus encode100ContinueHeaders(HeaderMap&) override { + return FilterHeadersStatus::Continue; + } + FilterHeadersStatus encodeHeaders(HeaderMap& headers, bool) override; + FilterDataStatus encodeData(Buffer::Instance&, bool) override; + FilterTrailersStatus encodeTrailers(HeaderMap&) override; + void setEncoderFilterCallbacks(StreamEncoderFilterCallbacks&) override {} + // This is the callback function when Check is done. - void completeCheck(const ::google::protobuf::util::Status& status); + void completeCheck(const ::istio::mixerclient::CheckResponseInfo& info); // Called when the request is completed. virtual void log(const HeaderMap* request_headers, @@ -64,6 +73,11 @@ class Filter : public Http::StreamDecoderFilter, const Router::RouteEntry* entry, ::istio::control::http::Controller::PerRouteConfig* config); + // Update header maps + void UpdateHeaders(HeaderMap& headers, + const ::google::protobuf::RepeatedPtrField< + ::istio::mixer::v1::HeaderOperation>& operations); + // The control object. Control& control_; // The request handler. @@ -85,6 +99,10 @@ class Filter : public Http::StreamDecoderFilter, // The stream decoder filter callback. StreamDecoderFilterCallbacks* decoder_callbacks_{nullptr}; + + // Returned directive + ::istio::mixer::v1::RouteDirective route_directive_{ + ::istio::mixer::v1::RouteDirective::default_instance()}; }; } // namespace Mixer diff --git a/src/envoy/http/mixer/filter_factory.cc b/src/envoy/http/mixer/filter_factory.cc index 4f045d479ba0..c46c97d65771 100644 --- a/src/envoy/http/mixer/filter_factory.cc +++ b/src/envoy/http/mixer/filter_factory.cc @@ -83,8 +83,7 @@ class MixerConfigFactory : public NamedHttpFilterConfigFactory { Http::FilterChainFactoryCallbacks& callbacks) -> void { std::shared_ptr instance = std::make_shared(control_factory->control()); - callbacks.addStreamDecoderFilter( - Http::StreamDecoderFilterSharedPtr(instance)); + callbacks.addStreamFilter(Http::StreamFilterSharedPtr(instance)); callbacks.addAccessLogHandler(AccessLog::InstanceSharedPtr(instance)); }; } diff --git a/src/envoy/tcp/mixer/filter.cc b/src/envoy/tcp/mixer/filter.cc index 218558b35d0d..128e06ef7157 100644 --- a/src/envoy/tcp/mixer/filter.cc +++ b/src/envoy/tcp/mixer/filter.cc @@ -18,6 +18,7 @@ #include "src/envoy/utils/utils.h" using ::google::protobuf::util::Status; +using ::istio::mixerclient::CheckResponseInfo; namespace Envoy { namespace Tcp { @@ -59,8 +60,9 @@ void Filter::callCheck() { state_ = State::Calling; filter_callbacks_->connection().readDisable(true); calling_check_ = true; - cancel_check_ = handler_->Check( - this, [this](const Status& status) { completeCheck(status); }); + cancel_check_ = handler_->Check(this, [this](const CheckResponseInfo& info) { + completeCheck(info.response_status); + }); calling_check_ = false; } diff --git a/src/istio/control/client_context_base.cc b/src/istio/control/client_context_base.cc index 73a5cdad6fc4..2188ebfa77a2 100644 --- a/src/istio/control/client_context_base.cc +++ b/src/istio/control/client_context_base.cc @@ -22,9 +22,9 @@ using ::google::protobuf::util::Status; using ::istio::mixer::v1::config::client::NetworkFailPolicy; using ::istio::mixer::v1::config::client::TransportConfig; using ::istio::mixerclient::CancelFunc; +using ::istio::mixerclient::CheckDoneFunc; using ::istio::mixerclient::CheckOptions; using ::istio::mixerclient::CheckResponseInfo; -using ::istio::mixerclient::DoneFunc; using ::istio::mixerclient::Environment; using ::istio::mixerclient::MixerClientOptions; using ::istio::mixerclient::QuotaOptions; @@ -77,7 +77,7 @@ ClientContextBase::ClientContextBase(const TransportConfig& config, } CancelFunc ClientContextBase::SendCheck(TransportCheckFunc transport, - DoneFunc on_done, + CheckDoneFunc on_done, RequestContext* request) { // Intercept the callback to save check status in request_context auto local_on_done = [request, @@ -90,7 +90,7 @@ CancelFunc ClientContextBase::SendCheck(TransportCheckFunc transport, check_response_info.is_check_cache_hit); builder.AddBool(AttributeName::kQuotaCacheHit, check_response_info.is_quota_cache_hit); - on_done(check_response_info.response_status); + on_done(check_response_info); }; // TODO: add debug message diff --git a/src/istio/control/client_context_base.h b/src/istio/control/client_context_base.h index d767265d38c6..54a6a89ace49 100644 --- a/src/istio/control/client_context_base.h +++ b/src/istio/control/client_context_base.h @@ -41,7 +41,7 @@ class ClientContextBase { // Use mixer client object to make a Check call. ::istio::mixerclient::CancelFunc SendCheck( ::istio::mixerclient::TransportCheckFunc transport, - ::istio::mixerclient::DoneFunc on_done, RequestContext* request); + ::istio::mixerclient::CheckDoneFunc on_done, RequestContext* request); // Use mixer client object to make a Report call. void SendReport(const RequestContext& request); diff --git a/src/istio/control/http/request_handler_impl.cc b/src/istio/control/http/request_handler_impl.cc index cbcb6e73a9fb..9b9ca09d9241 100644 --- a/src/istio/control/http/request_handler_impl.cc +++ b/src/istio/control/http/request_handler_impl.cc @@ -18,7 +18,8 @@ using ::google::protobuf::util::Status; using ::istio::mixerclient::CancelFunc; -using ::istio::mixerclient::DoneFunc; +using ::istio::mixerclient::CheckDoneFunc; +using ::istio::mixerclient::CheckResponseInfo; using ::istio::mixerclient::TransportCheckFunc; using ::istio::quota_config::Requirement; @@ -46,13 +47,15 @@ void RequestHandlerImpl::ExtractRequestAttributes(CheckData* check_data) { CancelFunc RequestHandlerImpl::Check(CheckData* check_data, HeaderUpdate* header_update, TransportCheckFunc transport, - DoneFunc on_done) { + CheckDoneFunc on_done) { ExtractRequestAttributes(check_data); header_update->RemoveIstioAttributes(); service_context_->InjectForwardedAttributes(header_update); if (!service_context_->enable_mixer_check()) { - on_done(Status::OK); + CheckResponseInfo check_response_info; + check_response_info.response_status = Status::OK; + on_done(check_response_info); return nullptr; } diff --git a/src/istio/control/http/request_handler_impl.h b/src/istio/control/http/request_handler_impl.h index 3cdc9c9ff5b9..e858094a7241 100644 --- a/src/istio/control/http/request_handler_impl.h +++ b/src/istio/control/http/request_handler_impl.h @@ -34,7 +34,7 @@ class RequestHandlerImpl : public RequestHandler { ::istio::mixerclient::CancelFunc Check( CheckData* check_data, HeaderUpdate* header_update, ::istio::mixerclient::TransportCheckFunc transport, - ::istio::mixerclient::DoneFunc on_done) override; + ::istio::mixerclient::CheckDoneFunc on_done) override; // Make a Report call. void Report(ReportData* report_data) override; diff --git a/src/istio/control/http/request_handler_impl_test.cc b/src/istio/control/http/request_handler_impl_test.cc index 9dd57e3e6ebf..1bdfc2b0a3c5 100644 --- a/src/istio/control/http/request_handler_impl_test.cc +++ b/src/istio/control/http/request_handler_impl_test.cc @@ -29,6 +29,7 @@ using ::istio::mixer::v1::config::client::HttpClientConfig; using ::istio::mixer::v1::config::client::ServiceConfig; using ::istio::mixerclient::CancelFunc; using ::istio::mixerclient::CheckDoneFunc; +using ::istio::mixerclient::CheckResponseInfo; using ::istio::mixerclient::DoneFunc; using ::istio::mixerclient::MixerClient; using ::istio::mixerclient::TransportCheckFunc; @@ -162,7 +163,9 @@ TEST_F(RequestHandlerImplTest, TestHandlerDisabledCheckReport) { auto handler = controller_->CreateRequestHandler(per_route); handler->Check(&mock_data, &mock_header, nullptr, - [](const Status& status) { EXPECT_TRUE(status.ok()); }); + [](const CheckResponseInfo& info) { + EXPECT_TRUE(info.response_status.ok()); + }); } TEST_F(RequestHandlerImplTest, TestHandlerDisabledCheck) { @@ -182,7 +185,9 @@ TEST_F(RequestHandlerImplTest, TestHandlerDisabledCheck) { auto handler = controller_->CreateRequestHandler(per_route); handler->Check(&mock_data, &mock_header, nullptr, - [](const Status& status) { EXPECT_TRUE(status.ok()); }); + [](const CheckResponseInfo& info) { + EXPECT_TRUE(info.response_status.ok()); + }); } TEST_F(RequestHandlerImplTest, TestPerRouteAttributes) { @@ -473,7 +478,9 @@ TEST_F(RequestHandlerImplTest, TestEmptyConfig) { Controller::PerRouteConfig config; auto handler = controller_->CreateRequestHandler(config); handler->Check(&mock_check, &mock_header, nullptr, - [](const Status& status) { EXPECT_TRUE(status.ok()); }); + [](const CheckResponseInfo& info) { + EXPECT_TRUE(info.response_status.ok()); + }); handler->Report(&mock_report); } diff --git a/src/istio/control/tcp/request_handler_impl.cc b/src/istio/control/tcp/request_handler_impl.cc index 5930beba54ac..168f0ca19193 100644 --- a/src/istio/control/tcp/request_handler_impl.cc +++ b/src/istio/control/tcp/request_handler_impl.cc @@ -18,7 +18,8 @@ using ::google::protobuf::util::Status; using ::istio::mixerclient::CancelFunc; -using ::istio::mixerclient::DoneFunc; +using ::istio::mixerclient::CheckDoneFunc; +using ::istio::mixerclient::CheckResponseInfo; using ::istio::quota_config::Requirement; namespace istio { @@ -30,7 +31,8 @@ RequestHandlerImpl::RequestHandlerImpl( : client_context_(client_context), last_report_info_{0ULL, 0ULL, std::chrono::nanoseconds::zero()} {} -CancelFunc RequestHandlerImpl::Check(CheckData* check_data, DoneFunc on_done) { +CancelFunc RequestHandlerImpl::Check(CheckData* check_data, + CheckDoneFunc on_done) { if (client_context_->enable_mixer_check() || client_context_->enable_mixer_report()) { client_context_->AddStaticAttributes(&request_context_); @@ -40,7 +42,9 @@ CancelFunc RequestHandlerImpl::Check(CheckData* check_data, DoneFunc on_done) { } if (!client_context_->enable_mixer_check()) { - on_done(Status::OK); + CheckResponseInfo check_response_info; + check_response_info.response_status = Status::OK; + on_done(check_response_info); return nullptr; } diff --git a/src/istio/control/tcp/request_handler_impl.h b/src/istio/control/tcp/request_handler_impl.h index c0ab04c17e97..3d4fa6ee693e 100644 --- a/src/istio/control/tcp/request_handler_impl.h +++ b/src/istio/control/tcp/request_handler_impl.h @@ -31,7 +31,8 @@ class RequestHandlerImpl : public RequestHandler { // Make a Check call. ::istio::mixerclient::CancelFunc Check( - CheckData* check_data, ::istio::mixerclient::DoneFunc on_done) override; + CheckData* check_data, + ::istio::mixerclient::CheckDoneFunc on_done) override; // Make a Report call. // TODO(JimmyCYJ): Let TCP filter use diff --git a/src/istio/control/tcp/request_handler_impl_test.cc b/src/istio/control/tcp/request_handler_impl_test.cc index 902478c68292..e6fe3b3425c1 100644 --- a/src/istio/control/tcp/request_handler_impl_test.cc +++ b/src/istio/control/tcp/request_handler_impl_test.cc @@ -25,6 +25,7 @@ using ::istio::mixer::v1::Attributes; using ::istio::mixer::v1::config::client::TcpClientConfig; using ::istio::mixerclient::CancelFunc; using ::istio::mixerclient::CheckDoneFunc; +using ::istio::mixerclient::CheckResponseInfo; using ::istio::mixerclient::DoneFunc; using ::istio::mixerclient::MixerClient; using ::istio::mixerclient::TransportCheckFunc; @@ -72,8 +73,9 @@ TEST_F(RequestHandlerImplTest, TestHandlerDisabledCheck) { client_config_.set_disable_check_calls(true); auto handler = controller_->CreateRequestHandler(); - handler->Check(&mock_data, - [](const Status& status) { EXPECT_TRUE(status.ok()); }); + handler->Check(&mock_data, [](const CheckResponseInfo& info) { + EXPECT_TRUE(info.response_status.ok()); + }); } TEST_F(RequestHandlerImplTest, TestHandlerCheck) { diff --git a/src/istio/mixerclient/check_cache.cc b/src/istio/mixerclient/check_cache.cc index 0b0160535e3b..0e3407fc58e6 100644 --- a/src/istio/mixerclient/check_cache.cc +++ b/src/istio/mixerclient/check_cache.cc @@ -38,6 +38,7 @@ void CheckCache::CacheElem::CacheElem::SetResponse( expire_time_ = time_point::max(); } use_count_ = response.precondition().valid_use_count(); + route_directive_ = response.precondition().route_directive(); } else { status_ = Status(Code::INVALID_ARGUMENT, "CheckResponse doesn't have PreconditionResult"); @@ -75,7 +76,7 @@ CheckCache::~CheckCache() { } void CheckCache::Check(const Attributes &attributes, CheckResult *result) { - Status status = Check(attributes, system_clock::now()); + Status status = Check(attributes, system_clock::now(), result); if (status.error_code() != Code::NOT_FOUND) { result->status_ = status; } @@ -95,7 +96,8 @@ void CheckCache::Check(const Attributes &attributes, CheckResult *result) { }; } -Status CheckCache::Check(const Attributes &attributes, Tick time_now) { +Status CheckCache::Check(const Attributes &attributes, Tick time_now, + CheckResult *result) { if (!cache_) { // By returning NOT_FOUND, caller will send request to server. return Status(Code::NOT_FOUND, ""); @@ -116,6 +118,9 @@ Status CheckCache::Check(const Attributes &attributes, Tick time_now) { cache_->Remove(signature); return Status(Code::NOT_FOUND, ""); } + if (result) { + result->route_directive_ = elem->route_directive(); + } return elem->status(); } } diff --git a/src/istio/mixerclient/check_cache.h b/src/istio/mixerclient/check_cache.h index 865972fb716e..36e9080f5cd4 100644 --- a/src/istio/mixerclient/check_cache.h +++ b/src/istio/mixerclient/check_cache.h @@ -56,12 +56,19 @@ class CheckCache { ::google::protobuf::util::Status status() const { return status_; } + ::istio::mixer::v1::RouteDirective route_directive() const { + return route_directive_; + } + void SetResponse(const ::google::protobuf::util::Status& status, const ::istio::mixer::v1::Attributes& attributes, const ::istio::mixer::v1::CheckResponse& response) { if (on_response_) { status_ = on_response_(status, attributes, response); } + if (response.has_precondition()) { + route_directive_ = response.precondition().route_directive(); + } } private: @@ -69,6 +76,9 @@ class CheckCache { // Check status. ::google::protobuf::util::Status status_; + // Route directive (if status is OK). + ::istio::mixer::v1::RouteDirective route_directive_; + // The function to set check response. using OnResponseFunc = std::function<::google::protobuf::util::Status( const ::google::protobuf::util::Status&, @@ -87,7 +97,8 @@ class CheckCache { // If the check could not be handled by the cache, returns NOT_FOUND, // caller has to send the request to mixer. ::google::protobuf::util::Status Check( - const ::istio::mixer::v1::Attributes& request, Tick time_now); + const ::istio::mixer::v1::Attributes& request, Tick time_now, + CheckResult* result); // Caches a response from a remote mixer call. // Return the converted status from response. @@ -121,11 +132,18 @@ class CheckCache { // getter for converted status from response. ::google::protobuf::util::Status status() const { return status_; } + // getter for the route directive + ::istio::mixer::v1::RouteDirective route_directive() const { + return route_directive_; + } + private: // To the parent cache object. const CheckCache& parent_; // The check status for the last check request. ::google::protobuf::util::Status status_; + // Route directive + ::istio::mixer::v1::RouteDirective route_directive_; // Cache item should not be used after it is expired. std::chrono::time_point expire_time_; // if -1, not to check use_count. diff --git a/src/istio/mixerclient/check_cache_test.cc b/src/istio/mixerclient/check_cache_test.cc index e35cac0bccd2..0b43309d63e3 100644 --- a/src/istio/mixerclient/check_cache_test.cc +++ b/src/istio/mixerclient/check_cache_test.cc @@ -49,16 +49,18 @@ class CheckCacheTest : public ::testing::Test { CheckResponse ok_response; ok_response.mutable_precondition()->set_valid_use_count(1000); // Just to calculate signature - EXPECT_ERROR_CODE(Code::NOT_FOUND, cache_->Check(attributes_, FakeTime(0))); + EXPECT_ERROR_CODE(Code::NOT_FOUND, + cache_->Check(attributes_, FakeTime(0), nullptr)); // set to the cache EXPECT_OK(cache_->CacheResponse(attributes_, ok_response, FakeTime(0))); // Still not_found, so cache is disabled. - EXPECT_ERROR_CODE(Code::NOT_FOUND, cache_->Check(attributes_, FakeTime(0))); + EXPECT_ERROR_CODE(Code::NOT_FOUND, + cache_->Check(attributes_, FakeTime(0), nullptr)); } Status Check(const Attributes& request, time_point time_now) { - return cache_->Check(request, time_now); + return cache_->Check(request, time_now, nullptr); } Status CacheResponse(const Attributes& attributes, const ::istio::mixer::v1::CheckResponse& response, @@ -131,6 +133,9 @@ TEST_F(CheckCacheTest, TestCheckResult) { CheckResponse ok_response; ok_response.mutable_precondition()->set_valid_use_count(1000); + ok_response.mutable_precondition() + ->mutable_route_directive() + ->set_direct_response_code(302); result.SetResponse(Status::OK, attributes_, ok_response); EXPECT_OK(result.status()); @@ -139,6 +144,7 @@ TEST_F(CheckCacheTest, TestCheckResult) { cache_->Check(attributes_, &result); EXPECT_TRUE(result.IsCacheHit()); EXPECT_OK(result.status()); + EXPECT_EQ(result.route_directive().direct_response_code(), 302); } } diff --git a/src/istio/mixerclient/client_impl.cc b/src/istio/mixerclient/client_impl.cc index 2fb11d0d09de..b80ce6a8c834 100644 --- a/src/istio/mixerclient/client_impl.cc +++ b/src/istio/mixerclient/client_impl.cc @@ -64,6 +64,7 @@ CancelFunc MixerClientImpl::Check( CheckResponseInfo check_response_info; check_response_info.is_check_cache_hit = check_result->IsCacheHit(); check_response_info.response_status = check_result->status(); + check_response_info.route_directive = check_result->route_directive(); if (check_result->IsCacheHit() && !check_result->status().ok()) { on_done(check_response_info); @@ -132,6 +133,8 @@ CancelFunc MixerClientImpl::Check( } else { check_response_info.response_status = raw_quota_result->status(); } + check_response_info.route_directive = + raw_check_result->route_directive(); on_done(check_response_info); } delete raw_check_result; diff --git a/test/backend/echo/echo.go b/test/backend/echo/echo.go index 34802ea10743..5fae42c89914 100644 --- a/test/backend/echo/echo.go +++ b/test/backend/echo/echo.go @@ -118,6 +118,7 @@ func handler(w http.ResponseWriter, r *http.Request) { fmt.Printf("%v: %v\n", name, h) } } + fmt.Printf("Host: %v\n", r.Host) body, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/tools/deb/BUILD b/tools/deb/BUILD index 1dc63c246fc2..125d4f0db55d 100644 --- a/tools/deb/BUILD +++ b/tools/deb/BUILD @@ -45,6 +45,7 @@ pkg_tar( ":envoy-bin", ":istio-conf", ], + tags = ["manual"], ) pkg_deb(