From d5a878a10b899332639a46d83ce1e56356575baa Mon Sep 17 00:00:00 2001 From: Qian Sun Date: Mon, 13 Feb 2017 16:27:14 -0800 Subject: [PATCH 1/8] Get attributes from envoy config. (#87) * Send all attributes. * Remove unused const strings. * Address comment. --- src/envoy/mixer/http_control.cc | 24 ++++++------------------ src/envoy/mixer/http_control.h | 9 ++++----- src/envoy/mixer/http_filter.cc | 10 +++++++++- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/envoy/mixer/http_control.cc b/src/envoy/mixer/http_control.cc index 6ae266ef088..870d70956fb 100644 --- a/src/envoy/mixer/http_control.cc +++ b/src/envoy/mixer/http_control.cc @@ -38,12 +38,6 @@ const std::string kAttrNameResponseTime = "response.time"; const std::string kAttrNameOriginIp = "origin.ip"; const std::string kAttrNameOriginHost = "origin.host"; -const std::string kEnvNameSourceService = "SOURCE_SERVICE"; -const std::string kEnvNameTargetService = "TARGET_SERVICE"; - -const std::string kAttrNameSourceService = "source.service"; -const std::string kAttrNameTargetService = "target.service"; - Attributes::Value StringValue(const std::string& str) { Attributes::Value v; v.type = Attributes::Value::STRING; @@ -134,27 +128,21 @@ void FillRequestInfoAttributes(const AccessLog::RequestInfo& info, } // namespace -HttpControl::HttpControl(const std::string& mixer_server) { +HttpControl::HttpControl(const std::string& mixer_server, + std::map&& attributes) + : config_attributes_(std::move(attributes)) { ::istio::mixer_client::MixerClientOptions options; options.mixer_server = mixer_server; mixer_client_ = ::istio::mixer_client::CreateMixerClient(options); - - auto source_service = getenv(kEnvNameSourceService.c_str()); - if (source_service) { - source_service_ = source_service; - } - auto target_service = getenv(kEnvNameTargetService.c_str()); - if (target_service) { - target_service_ = target_service; - } } void HttpControl::FillCheckAttributes(const HeaderMap& header_map, Attributes* attr) { FillRequestHeaderAttributes(header_map, attr); - SetStringAttribute(kAttrNameSourceService, source_service_, attr); - SetStringAttribute(kAttrNameTargetService, target_service_, attr); + for (const auto& attribute : config_attributes_) { + SetStringAttribute(attribute.first, attribute.second, attr); + } } void HttpControl::Check(HttpRequestDataPtr request_data, HeaderMap& headers, diff --git a/src/envoy/mixer/http_control.h b/src/envoy/mixer/http_control.h index 312016e419c..bf52e49a81a 100644 --- a/src/envoy/mixer/http_control.h +++ b/src/envoy/mixer/http_control.h @@ -37,7 +37,8 @@ typedef std::shared_ptr HttpRequestDataPtr; class HttpControl final : public Logger::Loggable { public: // The constructor. - HttpControl(const std::string& mixer_server); + HttpControl(const std::string& mixer_server, + std::map&& attributes); // Make mixer check call. void Check(HttpRequestDataPtr request_data, HeaderMap& headers, @@ -55,10 +56,8 @@ class HttpControl final : public Logger::Loggable { // The mixer client std::unique_ptr<::istio::mixer_client::MixerClient> mixer_client_; - // Source service - std::string source_service_; - // Target service - std::string target_service_; + // The attributes read from the config file. + std::map config_attributes_; }; } // namespace Mixer diff --git a/src/envoy/mixer/http_filter.cc b/src/envoy/mixer/http_filter.cc index ec209b1ff98..a37ac032ee1 100644 --- a/src/envoy/mixer/http_filter.cc +++ b/src/envoy/mixer/http_filter.cc @@ -96,7 +96,15 @@ class Config : public Logger::Loggable { __func__); } - http_control_ = std::make_shared(mixer_server); + std::map attributes; + if (config.hasObject("attributes")) { + for (const std::string& attr : config.getStringArray("attributes")) { + attributes[attr] = config.getString(attr); + } + } + + http_control_ = + std::make_shared(mixer_server, std::move(attributes)); log().debug("Called Mixer::Config contructor with mixer_server: ", mixer_server); } From e1d500bdc154800dc5c672d39600ba5f845539cf Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 10:47:15 -0800 Subject: [PATCH 2/8] Added quota contoll without service control client library --- contrib/endpoints/src/api_manager/BUILD | 2 + .../src/api_manager/check_workflow.cc | 3 + .../api_manager/context/request_context.cc | 18 ++ .../src/api_manager/context/request_context.h | 10 + .../src/api_manager/proto/server_config.proto | 19 ++ .../src/api_manager/quota_control.cc | 77 ++++++++ .../endpoints/src/api_manager/quota_control.h | 19 ++ .../api_manager/service_control/aggregated.cc | 148 ++++++++++++-- .../api_manager/service_control/aggregated.h | 13 +- .../src/api_manager/service_control/info.h | 48 ++++- .../api_manager/service_control/interface.h | 11 ++ .../src/api_manager/service_control/proto.cc | 185 ++++++++++++++++++ .../src/api_manager/service_control/proto.h | 9 + .../src/api_manager/service_control/url.cc | 2 + .../src/api_manager/service_control/url.h | 2 + 15 files changed, 551 insertions(+), 15 deletions(-) create mode 100644 contrib/endpoints/src/api_manager/quota_control.cc create mode 100644 contrib/endpoints/src/api_manager/quota_control.h diff --git a/contrib/endpoints/src/api_manager/BUILD b/contrib/endpoints/src/api_manager/BUILD index e3d54b46eac..76416aea90e 100644 --- a/contrib/endpoints/src/api_manager/BUILD +++ b/contrib/endpoints/src/api_manager/BUILD @@ -81,6 +81,8 @@ cc_library( "method_impl.cc", "path_matcher.cc", "path_matcher_node.cc", + "quota_control.cc", + "quota_control.h", "request_handler.cc", ], linkopts = select({ diff --git a/contrib/endpoints/src/api_manager/check_workflow.cc b/contrib/endpoints/src/api_manager/check_workflow.cc index 8335d779142..27b9fba60da 100644 --- a/contrib/endpoints/src/api_manager/check_workflow.cc +++ b/contrib/endpoints/src/api_manager/check_workflow.cc @@ -18,6 +18,7 @@ #include "contrib/endpoints/src/api_manager/check_auth.h" #include "contrib/endpoints/src/api_manager/check_service_control.h" #include "contrib/endpoints/src/api_manager/fetch_metadata.h" +#include "contrib/endpoints/src/api_manager/quota_control.h" using ::google::api_manager::utils::Status; @@ -33,6 +34,8 @@ void CheckWorkflow::RegisterAll() { Register(CheckAuth); // Checks service control. Register(CheckServiceControl); + // Quota control + Register(QuotaControl); } void CheckWorkflow::Register(CheckHandler handler) { diff --git a/contrib/endpoints/src/api_manager/context/request_context.cc b/contrib/endpoints/src/api_manager/context/request_context.cc index 59cc7c3d53f..f4b18ea80a9 100644 --- a/contrib/endpoints/src/api_manager/context/request_context.cc +++ b/contrib/endpoints/src/api_manager/context/request_context.cc @@ -226,6 +226,24 @@ void RequestContext::FillCheckRequestInfo( info->allow_unregistered_calls = method()->allow_unregistered_calls(); } +void RequestContext::FillAllocateQuotaRequestInfo( + service_control::QuotaRequestInfo *info) { + + FillOperationInfo(info); + + info->client_ip = request_->GetClientIP(); + info->method_name = this->method_call_.method_info->name(); + + info->labels["servicecontrol.googleapis.com/caller_ip"] = + request_->GetClientIP(); + info->labels["servicecontrol.googleapis.com/referer"] = this->http_referer_; + info->labels["servicecontrol.googleapis.com/user"] = "integration_test_user"; + + // TODO(jaebong) need to set quota rule and metric rule + info->quota_rule_ = nullptr; + info->metric_rule_= nullptr; +} + void RequestContext::FillReportRequestInfo( Response *response, service_control::ReportRequestInfo *info) { FillOperationInfo(info); diff --git a/contrib/endpoints/src/api_manager/context/request_context.h b/contrib/endpoints/src/api_manager/context/request_context.h index 5b29c271aad..d6edf79b9aa 100644 --- a/contrib/endpoints/src/api_manager/context/request_context.h +++ b/contrib/endpoints/src/api_manager/context/request_context.h @@ -63,9 +63,17 @@ class RequestContext { check_response_info_ = check_response_info; } + // TODO(jaebong): set quota_response_info + void set_quota_response_info(const service_control::QuotaResponseInfo "a_response_info) { + quota_response_info_ = quota_response_info; + } + // Fill CheckRequestInfo void FillCheckRequestInfo(service_control::CheckRequestInfo *info); + // Fill AllocateQuotaRequestInfo + void FillAllocateQuotaRequestInfo(service_control::QuotaRequestInfo *info); + // Fill ReportRequestInfo void FillReportRequestInfo(Response *response, service_control::ReportRequestInfo *info); @@ -150,6 +158,8 @@ class RequestContext { // Pass check response data to Report call. service_control::CheckResponseInfo check_response_info_; + service_control::QuotaResponseInfo quota_response_info_; + // Needed by both Check() and Report, extract it once and store it here. std::string http_referer_; diff --git a/contrib/endpoints/src/api_manager/proto/server_config.proto b/contrib/endpoints/src/api_manager/proto/server_config.proto index 1fe04af6d07..35f1dd20e84 100644 --- a/contrib/endpoints/src/api_manager/proto/server_config.proto +++ b/contrib/endpoints/src/api_manager/proto/server_config.proto @@ -66,6 +66,14 @@ message ServiceControlConfig { // The intermediate reports for streaming calls should not be more frequent // than this value (in seconds) int32 intermediate_report_min_interval = 7; + + // Quota aggregator config + QuotaAggregatorConfig quota_aggregator_config = 8; + + // Timeout in milliseconds on service control allocate quota requests. + // If the value is <= 0, default timeout is 5000 milliseconds. + int32 quota_timeout_ms = 9; + } // Check aggregator config @@ -82,6 +90,17 @@ message CheckAggregatorConfig { int32 response_expiration_ms = 3; } +// Quota aggregator config +message QuotaAggregatorConfig { + // The maximum number of cache entries that can be kept in the aggregation + // cache. Cache is disabled when entries <= 0. + int32 cache_entries = 1; + + // The maximum milliseconds before aggregated quota requests are refreshed to + // the server. + int32 refresh_interval_ms = 2; +} + // Report aggregator config message ReportAggregatorConfig { // The maximum number of cache entries that can be kept in the aggregation diff --git a/contrib/endpoints/src/api_manager/quota_control.cc b/contrib/endpoints/src/api_manager/quota_control.cc new file mode 100644 index 00000000000..84897137a27 --- /dev/null +++ b/contrib/endpoints/src/api_manager/quota_control.cc @@ -0,0 +1,77 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// +// includes should be ordered. This seems like a bug in clang-format? +#include + +#include "contrib/endpoints/src/api_manager/cloud_trace/cloud_trace.h" +#include "contrib/endpoints/src/api_manager/quota_control.h" +#include "google/protobuf/stubs/status.h" + +using ::google::api_manager::utils::Status; +using ::google::protobuf::util::error::Code; + +namespace google { +namespace api_manager { + +void QuotaControl(std::shared_ptr context, + std::function continuation) { + std::shared_ptr trace_span( + CreateSpan(context->cloud_trace(), "QuotaControl")); + + if (!context->service_context()->service_control()) { + TRACE(trace_span) << "Service control check is not needed"; + continuation(Status::OK); + return; + } + + if (context->api_key().empty()) { + if (context->method()->allow_unregistered_calls()) { + // Not need to call Check. + TRACE(trace_span) << "Service control check is not needed"; + continuation(Status::OK); + return; + } + + TRACE(trace_span) << "Failed at checking caller identity."; + continuation( + Status(Code::UNAUTHENTICATED, + "Method doesn't allow unregistered callers (callers without " + "established identity). Please use API Key or other form of " + "API consumer identity to call this API.", + Status::SERVICE_CONTROL)); + return; + } + + + service_control::QuotaRequestInfo info; + context->FillAllocateQuotaRequestInfo(&info); + context->service_context()->service_control()->Quota( + info, trace_span.get(), + [context, continuation, trace_span]( + utils::Status status, + const service_control::QuotaResponseInfo &info) { + + TRACE(trace_span) << "Quota service control request returned with " + << "status " << status.ToString(); + + // info is valid regardless status. + context->set_quota_response_info(info); + continuation(status); + }); +} + +} // namespace service_control_client +} // namespace google diff --git a/contrib/endpoints/src/api_manager/quota_control.h b/contrib/endpoints/src/api_manager/quota_control.h new file mode 100644 index 00000000000..cd6d7b2b359 --- /dev/null +++ b/contrib/endpoints/src/api_manager/quota_control.h @@ -0,0 +1,19 @@ +// TODO: Insert description here. (generated by jaebong) + +#ifndef BAZEL_ESP_EXTERNAL_ISTIO_PROXY_GIT_CONTRIB_ENDPOINTS_SRC_API_MANAGER_QUOTA_CONTROL_H_ +#define BAZEL_ESP_EXTERNAL_ISTIO_PROXY_GIT_CONTRIB_ENDPOINTS_SRC_API_MANAGER_QUOTA_CONTROL_H_ + +#include "contrib/endpoints/include/api_manager/utils/status.h" +#include "contrib/endpoints/src/api_manager/context/request_context.h" + +namespace google { +namespace api_manager { + +// Call service control quota. +void QuotaControl(std::shared_ptr, + std::function); + +} // namespace api_manager +} // namespace google + +#endif // BAZEL_ESP_EXTERNAL_ISTIO_PROXY_GIT_CONTRIB_ENDPOINTS_SRC_API_MANAGER_QUOTA_CONTROL_H_ diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index d2754d69dbd..2960b201524 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -22,6 +22,8 @@ using ::google::api::servicecontrol::v1::CheckRequest; using ::google::api::servicecontrol::v1::CheckResponse; +using ::google::api::servicecontrol::v1::AllocateQuotaRequest; +using ::google::api::servicecontrol::v1::AllocateQuotaResponse; using ::google::api::servicecontrol::v1::ReportRequest; using ::google::api::servicecontrol::v1::ReportResponse; using ::google::api_manager::proto::ServerConfig; @@ -29,6 +31,7 @@ using ::google::api_manager::utils::Status; using ::google::protobuf::util::error::Code; using ::google::service_control_client::CheckAggregationOptions; +using ::google::service_control_client::QuotaAggregationOptions; using ::google::service_control_client::ReportAggregationOptions; using ::google::service_control_client::ServiceControlClient; using ::google::service_control_client::ServiceControlClientOptions; @@ -40,6 +43,9 @@ namespace service_control { namespace { +const int kQuotaAggregationEntries = 10000; +const int kQuotaAggregationRefreshMs = 1000; + // Default config for check aggregator const int kCheckAggregationEntries = 10000; // Check doesn't support quota yet. It is safe to increase @@ -54,6 +60,8 @@ const int kReportAggregationFlushIntervalMs = 1000; // The default connection timeout for check requests. const int kCheckDefaultTimeoutInMs = 5000; +// The default connection timeout for allocate quota requests. +const int kAllocateQuotaDefaultTimeoutInMs = 5000; // The default connection timeout for report requests. const int kReportDefaultTimeoutInMs = 15000; @@ -69,6 +77,10 @@ const char application_proto[] = "application/x-protobuf"; const char servicecontrol_service[] = "/google.api.servicecontrol.v1.ServiceController"; +// The quota_control service name. used for as audience to generate JWT token. +const char quotacontrol_service[] = + "/google.api.servicecontrol.v1.QuotaController"; + // Generates CheckAggregationOptions. CheckAggregationOptions GetCheckAggregationOptions( const ServerConfig* server_config) { @@ -85,6 +97,26 @@ CheckAggregationOptions GetCheckAggregationOptions( kCheckAggregationExpirationMs); } +// TODO(jaebong): - need to add quota configuration +// Generate QuotaAggregationOptions +QuotaAggregationOptions GetQuotaAggregationOptions( + const ServerConfig* server_config, + const ::google::api::Service* service_config) { + QuotaAggregationOptions option = QuotaAggregationOptions( + kQuotaAggregationEntries, kQuotaAggregationRefreshMs); + + if (server_config && server_config->has_service_control_config() && + server_config->service_control_config().has_quota_aggregator_config()) { + const auto& quota_config = + server_config->service_control_config().quota_aggregator_config(); + + option.num_entries = quota_config.cache_entries(); + option.refresh_interval_ms = quota_config.refresh_interval_ms(); + } + + return option; +} + // Generates ReportAggregationOptions. ReportAggregationOptions GetReportAggregationOptions( const ServerConfig* server_config) { @@ -133,6 +165,7 @@ Aggregated::Aggregated(const ::google::api::Service& service, server_config_(server_config), env_(env), sa_token_(sa_token), + sa_token_quota_(nullptr), service_control_proto_(logs, metrics, labels, service.name(), service.id()), url_(service_, server_config), @@ -144,6 +177,13 @@ Aggregated::Aggregated(const ::google::api::Service& service, auth::ServiceAccountToken::JWT_TOKEN_FOR_SERVICE_CONTROL, url_.service_control() + servicecontrol_service); } + + sa_token_quota_ = new auth::ServiceAccountToken(env); + sa_token_quota_->SetClientAuthSecret( + server_config->google_authentication_secret()); + sa_token_quota_->SetAudience( + auth::ServiceAccountToken::JWT_TOKEN_FOR_SERVICE_CONTROL, + url_.service_control() + quotacontrol_service); } Aggregated::Aggregated(const std::set& logs, @@ -153,12 +193,13 @@ Aggregated::Aggregated(const std::set& logs, server_config_(nullptr), env_(env), sa_token_(nullptr), + sa_token_quota_(nullptr), service_control_proto_(logs, "", ""), url_(service_, server_config_), client_(std::move(client)), max_report_size_(0) {} -Aggregated::~Aggregated() {} +Aggregated::~Aggregated() { delete sa_token_quota_; } Status Aggregated::Init() { // Init() can be called repeatedly. @@ -171,6 +212,7 @@ Status Aggregated::Init() { // env->StartPeriodicTimer doens't work at constructor. ServiceControlClientOptions options( GetCheckAggregationOptions(server_config_), + GetQuotaAggregationOptions(server_config_, service_), GetReportAggregationOptions(server_config_)); std::stringstream ss; @@ -186,6 +228,11 @@ Status Aggregated::Init() { options.check_transport = [this]( const CheckRequest& request, CheckResponse* response, TransportDoneFunc on_done) { Call(request, response, on_done, nullptr); }; + + options.quota_transport = [this]( + const AllocateQuotaRequest& request, AllocateQuotaResponse* response, + TransportDoneFunc on_done) { Call(request, response, on_done, nullptr); }; + options.report_transport = [this]( const ReportRequest& request, ReportResponse* response, TransportDoneFunc on_done) { Call(request, response, on_done, nullptr); }; @@ -317,6 +364,63 @@ void Aggregated::Check( check_pool_.Free(std::move(request)); } +void Aggregated::Quota( + const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, + std::function on_done) { + std::shared_ptr trace_span( + CreateChildSpan(parent_span, "QuotaServiceControlCache")); + + QuotaResponseInfo dummy_response_info; + if (!client_) { + on_done(Status(Code::INTERNAL, "Missing service control client"), + dummy_response_info); + return; + } + + auto request = quota_pool_.Alloc(); + + Status status = + service_control_proto_.FillAllocateQuotaRequest(info, request.get()); + if (!status.ok()) { + on_done(status, dummy_response_info); + quota_pool_.Free(std::move(request)); + return; + } + + AllocateQuotaResponse* response = new AllocateQuotaResponse(); + + auto check_on_done = [this, response, on_done, trace_span]( + const ::google::protobuf::util::Status& status) { + QuotaResponseInfo response_info; + + if (status.ok()) { + utils::Status status = Proto::ConvertAllocateQuotaResponse( + *response, service_control_proto_.service_name(), &response_info); + on_done(utils::Status::OK, response_info); + } else { + on_done(Status(status.error_code(), status.error_message(), + Status::SERVICE_CONTROL), + response_info); + } + + delete response; + }; + + AllocateQuotaRequest* quota_request_copy = new AllocateQuotaRequest(*request); + + Call(*request, response, + [this, quota_request_copy, response, + check_on_done](::google::protobuf::util::Status status) { + delete quota_request_copy; + check_on_done(status); + }, + trace_span.get()); + + // There is no reference to request anymore at this point and it is safe to + // free request now. + quota_pool_.Free(std::move(request)); +} + Status Aggregated::GetStatistics(Statistics* esp_stat) const { if (!client_) { return Status(Code::INTERNAL, "Missing service control client"); @@ -358,9 +462,11 @@ void Aggregated::Call(const RequestType& request, ResponseType* response, Status(Code::INVALID_ARGUMENT, std::string("Invalid response")); } } else { - const std::string& url = typeid(RequestType) == typeid(CheckRequest) - ? url_.check_url() - : url_.report_url(); + const std::string& url = + typeid(RequestType) == typeid(CheckRequest) + ? url_.check_url() + : typeid(RequestType) == typeid(ReportRequest) ? url_.report_url() + : url_.quota_url(); env_->LogError(std::string("Failed to call ") + url + ", Error: " + status.ToString() + ", Response body: " + body); @@ -378,36 +484,52 @@ void Aggregated::Call(const RequestType& request, ResponseType* response, on_done(status.ToProto()); })); - bool is_check = (typeid(RequestType) == typeid(CheckRequest)); - const std::string& url = is_check ? url_.check_url() : url_.report_url(); + const std::string& url = (typeid(RequestType) == typeid(CheckRequest)) + ? url_.check_url() + : typeid(RequestType) == typeid(ReportRequest) + ? url_.report_url() + : url_.quota_url(); + TRACE(trace_span) << "Http request URL: " << url; std::string request_body; request.SerializeToString(&request_body); - if (!is_check && (request_body.size() > max_report_size_)) { + if ((typeid(RequestType) == typeid(ReportRequest)) && + (request_body.size() > max_report_size_)) { max_report_size_ = request_body.size(); } + auto token_ = (typeid(RequestType) == typeid(AllocateQuotaRequest)) + ? sa_token_quota_ + : sa_token_; + http_request->set_url(url) .set_method("POST") - .set_auth_token(GetAuthToken()) + .set_auth_token(GetAuthToken(token_)) .set_header("Content-Type", application_proto) .set_body(request_body); // Set timeout on the request if it was so configured. - if (is_check) { + if (typeid(RequestType) == typeid(CheckRequest)) { http_request->set_timeout_ms(kCheckDefaultTimeoutInMs); + } else if (typeid(RequestType) == typeid(AllocateQuotaRequest)) { + http_request->set_timeout_ms(kAllocateQuotaDefaultTimeoutInMs); } else { http_request->set_timeout_ms(kReportDefaultTimeoutInMs); } + if (server_config_ != nullptr && server_config_->has_service_control_config()) { const auto& config = server_config_->service_control_config(); - if (is_check) { + if (typeid(RequestType) == typeid(CheckRequest)) { if (config.check_timeout_ms() > 0) { http_request->set_timeout_ms(config.check_timeout_ms()); } + } else if (typeid(RequestType) == typeid(AllocateQuotaRequest)) { + if (config.quota_timeout_ms() > 0) { + http_request->set_timeout_ms(config.quota_timeout_ms()); + } } else { if (config.report_timeout_ms() > 0) { http_request->set_timeout_ms(config.report_timeout_ms()); @@ -418,9 +540,9 @@ void Aggregated::Call(const RequestType& request, ResponseType* response, env_->RunHTTPRequest(std::move(http_request)); } -const std::string& Aggregated::GetAuthToken() { - if (sa_token_) { - return sa_token_->GetAuthToken( +const std::string& Aggregated::GetAuthToken(auth::ServiceAccountToken* token_) { + if (token_) { + return token_->GetAuthToken( auth::ServiceAccountToken::JWT_TOKEN_FOR_SERVICE_CONTROL); } else { static std::string empty; diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.h b/contrib/endpoints/src/api_manager/service_control/aggregated.h index 27e42833dbe..d3b8c1882ae 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.h +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.h @@ -49,6 +49,10 @@ class Aggregated : public Interface { const CheckRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, std::function on_done); + virtual void Quota( + const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, + std::function on_done); + virtual utils::Status Init(); virtual utils::Status Close(); @@ -112,7 +116,7 @@ class Aggregated : public Interface { cloud_trace::CloudTraceSpan* parent_span); // Gets the auth token to access service control server. - const std::string& GetAuthToken(); + const std::string& GetAuthToken(auth::ServiceAccountToken* token_); // the sevice config. const ::google::api::Service* service_; @@ -125,6 +129,9 @@ class Aggregated : public Interface { // service account token. auth::ServiceAccountToken* sa_token_; + // quota service account token. + auth::ServiceAccountToken* sa_token_quota_; + // The object to fill service control Check and Report protobuf. Proto service_control_proto_; @@ -134,6 +141,10 @@ class Aggregated : public Interface { // The service control client instance. std::unique_ptr<::google::service_control_client::ServiceControlClient> client_; + + // The protobuf pool to reuse CheckRequest protobuf. + ProtoPool<::google::api::servicecontrol::v1::AllocateQuotaRequest> quota_pool_; + // The protobuf pool to reuse CheckRequest protobuf. ProtoPool<::google::api::servicecontrol::v1::CheckRequest> check_pool_; // The protobuf pool to reuse ReportRequest protobuf. diff --git a/contrib/endpoints/src/api_manager/service_control/info.h b/contrib/endpoints/src/api_manager/service_control/info.h index f203057cc9e..d4ffc6fe236 100644 --- a/contrib/endpoints/src/api_manager/service_control/info.h +++ b/contrib/endpoints/src/api_manager/service_control/info.h @@ -17,7 +17,8 @@ #include "google/protobuf/stubs/stringpiece.h" -#include +#include "google/api/quota.pb.h" + #include #include #include @@ -71,6 +72,8 @@ struct OperationInfo { // Information to fill Check request protobuf. struct CheckRequestInfo : public OperationInfo { + // The client IP address. + std::string client_ip; // Whether the method allow unregistered calls. bool allow_unregistered_calls; @@ -89,6 +92,49 @@ struct CheckResponseInfo { CheckResponseInfo() : is_api_key_valid(true), service_is_activated(true) {} }; +struct MetricValueInfo { + std::string metric_name; + int64_t metric_value; + + std::unordered_map labels; + std::chrono::system_clock::time_point start_time; + std::chrono::system_clock::time_point end_time; + + MetricValueInfo(std::string name, int64_t value) + : metric_name(name), metric_value(value) {} +}; + +struct QuotaRequestInfo : public OperationInfo { + std::string method_name; + // The client IP address. + std::string client_ip; + + std::unordered_map labels; + + ::google::api::QuotaRule* quota_rule_; + ::google::api::MetricRule* metric_rule_; +}; + +enum QuotaResponseCacheStatus { WAITING, CACHED }; + +struct QuotaResponseInfo { + bool is_api_key_valid; + bool service_is_activated; + bool is_quota_allocated; + bool is_accept_request; + QuotaResponseCacheStatus status; + + std::vector quota_metrics; + std::unordered_map quota_aggregation; + + QuotaResponseInfo() + : is_api_key_valid(true), + service_is_activated(true), + is_quota_allocated(true), + is_accept_request(true), + status(QuotaResponseCacheStatus::WAITING) {} +}; + // Information to fill Report request protobuf. struct ReportRequestInfo : public OperationInfo { // The HTTP response code. diff --git a/contrib/endpoints/src/api_manager/service_control/interface.h b/contrib/endpoints/src/api_manager/service_control/interface.h index 708acc56a88..2e64994ed61 100644 --- a/contrib/endpoints/src/api_manager/service_control/interface.h +++ b/contrib/endpoints/src/api_manager/service_control/interface.h @@ -70,6 +70,17 @@ class Interface { const CheckRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, std::function on_done) = 0; + // on_done() function will be called once it is completed. + // utils::Status in the on_done callback: + // If status.code is more than 100, it is the HTTP response status + // from the service control server. + // If status code is less than 20, within the ranges defined by + // google/protobuf/stubs/status.h, is from parsing error response + // body. + virtual void Quota( + const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, + std::function on_done) = 0; + // Get statistics of ServiceControl library. virtual utils::Status GetStatistics(Statistics* stat) const = 0; }; diff --git a/contrib/endpoints/src/api_manager/service_control/proto.cc b/contrib/endpoints/src/api_manager/service_control/proto.cc index 3e7eba64d21..45dd07c2de2 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.cc +++ b/contrib/endpoints/src/api_manager/service_control/proto.cc @@ -30,6 +30,7 @@ #include "utils/distribution_helper.h" using ::google::api::servicecontrol::v1::CheckError; +using ::google::api::servicecontrol::v1::QuotaError; using ::google::api::servicecontrol::v1::CheckRequest; using ::google::api::servicecontrol::v1::CheckResponse; using ::google::api::servicecontrol::v1::Distribution; @@ -49,6 +50,11 @@ namespace google { namespace api_manager { namespace service_control { +const char kConsumerQuotaUsedCount[] = + "serviceruntime.googleapis.com/api/consumer/quota_used_count"; + +const char kQuotaName[] = "/quota_name"; + struct SupportedMetric { const char* name; ::google::api::MetricDescriptor_MetricKind metric_kind; @@ -905,6 +911,94 @@ Proto::Proto(const std::set& logs, service_name_(service_name), service_config_id_(service_config_id) {} +utils::Status Proto::FillAllocateQuotaRequest(const QuotaRequestInfo& info, ::google::api::servicecontrol::v1::AllocateQuotaRequest* request) { + + ::google::api::servicecontrol::v1::QuotaOperation* operation = request->mutable_allocate_operation(); + + // service_name + request->set_service_name(service_name_); + // service_config_id + request->set_service_config_id(service_config_id_); + + // allocate_operation.operation_id + if (!info.operation_id.empty()) { + operation->set_operation_id(info.operation_id); + } + // allocate_operation.method_name + if (!info.method_name.empty()) { + operation->set_method_name(info.method_name); + } + // allocate_operation.consumer_id + if (!info.api_key.empty()) { + operation->set_consumer_id(std::string(kConsumerIdApiKey) + + std::string(info.api_key)); + } + + // TODO(jaebong) - Read from service conf? + // allocate_operation.quota_mode + operation->set_quota_mode( + ::google::api::servicecontrol::v1::QuotaOperation_QuotaMode:: + QuotaOperation_QuotaMode_NORMAL); + + + // allocate_operation.labels + auto* labels = operation->mutable_labels(); + if (!info.client_ip.empty()) { + (*labels)[kServiceControlCallerIp] = info.client_ip; + } + + if (!info.referer.empty()) { + (*labels)[kServiceControlReferer] = info.referer; + } + (*labels)[kServiceControlUserAgent] = kUserAgent; + (*labels)[kServiceControlServiceAgent] = + kServiceAgentPrefix + utils::Version::instance().get(); + + + + // allocate_operation.quota_metrics + + // handle group rules + if (info.quota_rule_ != nullptr) { + MetricValueSet* value_set = operation->add_quota_metrics(); + value_set->set_metric_name(kConsumerQuotaUsedCount); + + for (const auto& group : info.quota_rule_->groups()) { + MetricValue* value = value_set->add_metric_values(); + (*value->mutable_labels())[kQuotaName] = group.group(); + // Quota cost should be always larger than 0. Default to 1 if not. + // When super quota (go/pollux-detailed-design) is ready, negative value + // should not happen due to validation. + value->set_int64_value(group.cost() <= 0 ? 1 : group.cost()); + } + + return Status::OK; + } + + // handle metric rules + if (info.metric_rule_ != nullptr) { + for (const auto& metric_and_cost : info.metric_rule_->metric_costs()) { + MetricValueSet* value_set = operation->add_quota_metrics(); + value_set->set_metric_name(metric_and_cost.first); + MetricValue* value = value_set->add_metric_values(); + const auto& cost = metric_and_cost.second; + value->set_int64_value(cost <= 0 ? 1 : cost); + } + } + + /* + for (auto it : info.quota_metrics) { + auto set = operation->add_quota_metrics(); + set->set_metric_name(it.metric_name); + + auto value = set->add_metric_values(); + value->set_int64_value(it.metric_value); + } + */ + + return Status::OK; +} + Status Proto::FillCheckRequest(const CheckRequestInfo& info, CheckRequest* request) { Status status = VerifyRequiredCheckFields(info); @@ -993,6 +1087,97 @@ Status Proto::FillReportRequest(const ReportRequestInfo& info, return Status::OK; } +Status Proto::ConvertAllocateQuotaResponse( + const ::google::api::servicecontrol::v1::AllocateQuotaResponse& response, + const std::string& service_name, QuotaResponseInfo* quota_response_info) { + // response.operation_id() + if (response.allocate_errors().size() == 0) { + return Status::OK; + } + + const ::google::api::servicecontrol::v1::QuotaError& error = + response.allocate_errors().Get(0); + + switch (error.code()) { + case ::google::api::servicecontrol::v1::QuotaError::UNSPECIFIED: + // This is never used. + break; + + case ::google::api::servicecontrol::v1::QuotaError::RESOURCE_EXHAUSTED: + // Quota allocation failed. + // Same as [google.rpc.Code.RESOURCE_EXHAUSTED][]. + return Status(Code::PERMISSION_DENIED, "Quota allocation failed."); + + case ::google::api::servicecontrol::v1::QuotaError::PROJECT_SUSPENDED: + // Consumer project has been suspended. + return Status(Code::PERMISSION_DENIED, "Project suspended."); + + case ::google::api::servicecontrol::v1::QuotaError::SERVICE_NOT_ENABLED: + // Consumer has not enabled the service. + return Status(Code::PERMISSION_DENIED, + std::string("API ") + service_name + + " is not enabled for the project."); + + case ::google::api::servicecontrol::v1::QuotaError::BILLING_NOT_ACTIVE: + // Consumer cannot access the service because billing is disabled. + return Status(Code::PERMISSION_DENIED, + std::string("API ") + service_name + + " has billing disabled. Please enable it."); + + case ::google::api::servicecontrol::v1::QuotaError::PROJECT_DELETED: + // Consumer's project has been marked as deleted (soft deletion). + case ::google::api::servicecontrol::v1::QuotaError::PROJECT_INVALID: + // Consumer's project number or ID does not represent a valid project. + return Status(Code::INVALID_ARGUMENT, + "Client project not valid. Please pass a valid project."); + + case ::google::api::servicecontrol::v1::QuotaError::IP_ADDRESS_BLOCKED: + // IP address of the consumer is invalid for the specific consumer + // project. + return Status(Code::PERMISSION_DENIED, "IP address blocked."); + + case ::google::api::servicecontrol::v1::QuotaError::REFERER_BLOCKED: + // Referer address of the consumer request is invalid for the specific + // consumer project. + return Status(Code::PERMISSION_DENIED, "Referer blocked."); + + case ::google::api::servicecontrol::v1::QuotaError::CLIENT_APP_BLOCKED: + // Client application of the consumer request is invalid for the + // specific consumer project. + return Status(Code::PERMISSION_DENIED, "Client app blocked."); + + case ::google::api::servicecontrol::v1::QuotaError::API_KEY_INVALID: + // Specified API key is invalid. + return Status(Code::INVALID_ARGUMENT, + "API key not valid. Please pass a valid API key."); + + case ::google::api::servicecontrol::v1::QuotaError::API_KEY_EXPIRED: + // Specified API Key has expired. + return Status(Code::INVALID_ARGUMENT, + "API key expired. Please renew the API key."); + + case ::google::api::servicecontrol::v1::QuotaError:: + PROJECT_STATUS_UNVAILABLE: + // The backend server for looking up project id/number is unavailable. + case ::google::api::servicecontrol::v1::QuotaError:: + SERVICE_STATUS_UNAVAILABLE: + // The backend server for checking service status is unavailable. + case ::google::api::servicecontrol::v1::QuotaError:: + BILLING_STATUS_UNAVAILABLE: + // The backend server for checking billing status is unavailable. + // Fail open for internal server errors per recommendation + return Status::OK; + + default: + return Status( + Code::INTERNAL, + std::string("Request blocked due to unsupported error code: ") + + std::to_string(error.code())); + } + + return Status::OK; +} + Status Proto::ConvertCheckResponse(const CheckResponse& check_response, const std::string& service_name, CheckResponseInfo* check_response_info) { diff --git a/contrib/endpoints/src/api_manager/service_control/proto.h b/contrib/endpoints/src/api_manager/service_control/proto.h index bea2a948b63..10e273e205f 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.h +++ b/contrib/endpoints/src/api_manager/service_control/proto.h @@ -20,6 +20,7 @@ #include "google/api/label.pb.h" #include "google/api/metric.pb.h" #include "google/api/servicecontrol/v1/service_controller.pb.h" +#include "google/api/servicecontrol/v1/quota_controller.pb.h" namespace google { namespace api_manager { @@ -48,6 +49,10 @@ class Proto final { const CheckRequestInfo& info, ::google::api::servicecontrol::v1::CheckRequest* request); + utils::Status FillAllocateQuotaRequest( + const QuotaRequestInfo& info, + ::google::api::servicecontrol::v1::AllocateQuotaRequest* request); + // Fills the CheckRequest protobuf from info. // FillReportRequest function should copy the strings pointed by info. // These buffers may be freed after the FillReportRequest call. @@ -64,6 +69,10 @@ class Proto final { const ::google::api::servicecontrol::v1::CheckResponse& response, const std::string& service_name, CheckResponseInfo* check_response_info); + static utils::Status ConvertAllocateQuotaResponse( + const ::google::api::servicecontrol::v1::AllocateQuotaResponse& response, + const std::string& service_name, QuotaResponseInfo* quota_response_info); + static bool IsMetricSupported(const ::google::api::MetricDescriptor& metric); static bool IsLabelSupported(const ::google::api::LabelDescriptor& label); const std::string& service_name() const { return service_name_; } diff --git a/contrib/endpoints/src/api_manager/service_control/url.cc b/contrib/endpoints/src/api_manager/service_control/url.cc index d113d402d1f..f106ccd40fa 100644 --- a/contrib/endpoints/src/api_manager/service_control/url.cc +++ b/contrib/endpoints/src/api_manager/service_control/url.cc @@ -27,6 +27,7 @@ namespace { // /v1/services/{service}:report const char v1_services_path[] = "/v1/services/"; const char check_verb[] = ":check"; +const char quota_verb[] = ":allocateQuota"; const char report_verb[] = ":report"; const char http[] = "http://"; const char https[] = "https://"; @@ -66,6 +67,7 @@ Url::Url(const ::google::api::Service* service, std::string path = service_control_ + v1_services_path + service->name(); check_url_ = path + check_verb; report_url_ = path + report_verb; + quota_url_ = path + quota_verb; } } diff --git a/contrib/endpoints/src/api_manager/service_control/url.h b/contrib/endpoints/src/api_manager/service_control/url.h index 4615864bbdd..fb17aa5e006 100644 --- a/contrib/endpoints/src/api_manager/service_control/url.h +++ b/contrib/endpoints/src/api_manager/service_control/url.h @@ -31,12 +31,14 @@ class Url { // Pre-computed url for service control. const std::string& service_control() const { return service_control_; } const std::string& check_url() const { return check_url_; } + const std::string& quota_url() const { return quota_url_; } const std::string& report_url() const { return report_url_; } private: // Pre-computed url for service control methods. std::string service_control_; std::string check_url_; + std::string quota_url_; std::string report_url_; }; From d4af8efbee47a5defefe04853d0a18ac4e7e45c5 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 11:02:11 -0800 Subject: [PATCH 3/8] Removed unnecessary QuotaResponseInfo class --- .../src/api_manager/context/request_context.h | 6 ------ .../endpoints/src/api_manager/quota_control.cc | 5 +---- .../api_manager/service_control/aggregated.cc | 17 ++++++----------- .../api_manager/service_control/aggregated.h | 2 +- .../src/api_manager/service_control/info.h | 18 ------------------ .../api_manager/service_control/interface.h | 2 +- .../src/api_manager/service_control/proto.cc | 2 +- .../src/api_manager/service_control/proto.h | 2 +- 8 files changed, 11 insertions(+), 43 deletions(-) diff --git a/contrib/endpoints/src/api_manager/context/request_context.h b/contrib/endpoints/src/api_manager/context/request_context.h index d6edf79b9aa..8ad894bf335 100644 --- a/contrib/endpoints/src/api_manager/context/request_context.h +++ b/contrib/endpoints/src/api_manager/context/request_context.h @@ -63,10 +63,6 @@ class RequestContext { check_response_info_ = check_response_info; } - // TODO(jaebong): set quota_response_info - void set_quota_response_info(const service_control::QuotaResponseInfo "a_response_info) { - quota_response_info_ = quota_response_info; - } // Fill CheckRequestInfo void FillCheckRequestInfo(service_control::CheckRequestInfo *info); @@ -158,8 +154,6 @@ class RequestContext { // Pass check response data to Report call. service_control::CheckResponseInfo check_response_info_; - service_control::QuotaResponseInfo quota_response_info_; - // Needed by both Check() and Report, extract it once and store it here. std::string http_referer_; diff --git a/contrib/endpoints/src/api_manager/quota_control.cc b/contrib/endpoints/src/api_manager/quota_control.cc index 84897137a27..cabaaa2ce99 100644 --- a/contrib/endpoints/src/api_manager/quota_control.cc +++ b/contrib/endpoints/src/api_manager/quota_control.cc @@ -61,14 +61,11 @@ void QuotaControl(std::shared_ptr context, context->service_context()->service_control()->Quota( info, trace_span.get(), [context, continuation, trace_span]( - utils::Status status, - const service_control::QuotaResponseInfo &info) { + utils::Status status) { TRACE(trace_span) << "Quota service control request returned with " << "status " << status.ToString(); - // info is valid regardless status. - context->set_quota_response_info(info); continuation(status); }); } diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index 2960b201524..c252837ebca 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -366,14 +366,12 @@ void Aggregated::Check( void Aggregated::Quota( const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, - std::function on_done) { + std::function on_done) { std::shared_ptr trace_span( CreateChildSpan(parent_span, "QuotaServiceControlCache")); - QuotaResponseInfo dummy_response_info; if (!client_) { - on_done(Status(Code::INTERNAL, "Missing service control client"), - dummy_response_info); + on_done(Status(Code::INTERNAL, "Missing service control client")); return; } @@ -382,7 +380,7 @@ void Aggregated::Quota( Status status = service_control_proto_.FillAllocateQuotaRequest(info, request.get()); if (!status.ok()) { - on_done(status, dummy_response_info); + on_done(status); quota_pool_.Free(std::move(request)); return; } @@ -391,16 +389,13 @@ void Aggregated::Quota( auto check_on_done = [this, response, on_done, trace_span]( const ::google::protobuf::util::Status& status) { - QuotaResponseInfo response_info; - if (status.ok()) { utils::Status status = Proto::ConvertAllocateQuotaResponse( - *response, service_control_proto_.service_name(), &response_info); - on_done(utils::Status::OK, response_info); + *response, service_control_proto_.service_name()); + on_done(utils::Status::OK); } else { on_done(Status(status.error_code(), status.error_message(), - Status::SERVICE_CONTROL), - response_info); + Status::SERVICE_CONTROL)); } delete response; diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.h b/contrib/endpoints/src/api_manager/service_control/aggregated.h index d3b8c1882ae..703cd18f51b 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.h +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.h @@ -51,7 +51,7 @@ class Aggregated : public Interface { virtual void Quota( const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, - std::function on_done); + std::function on_done); virtual utils::Status Init(); virtual utils::Status Close(); diff --git a/contrib/endpoints/src/api_manager/service_control/info.h b/contrib/endpoints/src/api_manager/service_control/info.h index d4ffc6fe236..81a8951f227 100644 --- a/contrib/endpoints/src/api_manager/service_control/info.h +++ b/contrib/endpoints/src/api_manager/service_control/info.h @@ -117,24 +117,6 @@ struct QuotaRequestInfo : public OperationInfo { enum QuotaResponseCacheStatus { WAITING, CACHED }; -struct QuotaResponseInfo { - bool is_api_key_valid; - bool service_is_activated; - bool is_quota_allocated; - bool is_accept_request; - QuotaResponseCacheStatus status; - - std::vector quota_metrics; - std::unordered_map quota_aggregation; - - QuotaResponseInfo() - : is_api_key_valid(true), - service_is_activated(true), - is_quota_allocated(true), - is_accept_request(true), - status(QuotaResponseCacheStatus::WAITING) {} -}; - // Information to fill Report request protobuf. struct ReportRequestInfo : public OperationInfo { // The HTTP response code. diff --git a/contrib/endpoints/src/api_manager/service_control/interface.h b/contrib/endpoints/src/api_manager/service_control/interface.h index 2e64994ed61..60ea2ae7c64 100644 --- a/contrib/endpoints/src/api_manager/service_control/interface.h +++ b/contrib/endpoints/src/api_manager/service_control/interface.h @@ -79,7 +79,7 @@ class Interface { // body. virtual void Quota( const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, - std::function on_done) = 0; + std::function on_done) = 0; // Get statistics of ServiceControl library. virtual utils::Status GetStatistics(Statistics* stat) const = 0; diff --git a/contrib/endpoints/src/api_manager/service_control/proto.cc b/contrib/endpoints/src/api_manager/service_control/proto.cc index 45dd07c2de2..ccfdc4f8c1a 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.cc +++ b/contrib/endpoints/src/api_manager/service_control/proto.cc @@ -1089,7 +1089,7 @@ Status Proto::FillReportRequest(const ReportRequestInfo& info, Status Proto::ConvertAllocateQuotaResponse( const ::google::api::servicecontrol::v1::AllocateQuotaResponse& response, - const std::string& service_name, QuotaResponseInfo* quota_response_info) { + const std::string& service_name) { // response.operation_id() if (response.allocate_errors().size() == 0) { return Status::OK; diff --git a/contrib/endpoints/src/api_manager/service_control/proto.h b/contrib/endpoints/src/api_manager/service_control/proto.h index 10e273e205f..433702b11b6 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.h +++ b/contrib/endpoints/src/api_manager/service_control/proto.h @@ -71,7 +71,7 @@ class Proto final { static utils::Status ConvertAllocateQuotaResponse( const ::google::api::servicecontrol::v1::AllocateQuotaResponse& response, - const std::string& service_name, QuotaResponseInfo* quota_response_info); + const std::string& service_name); static bool IsMetricSupported(const ::google::api::MetricDescriptor& metric); static bool IsLabelSupported(const ::google::api::LabelDescriptor& label); From 998904ff585e4ab9a7362ce16f82f10b1d514ba3 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 11:15:56 -0800 Subject: [PATCH 4/8] Code format fix --- .../api_manager/context/request_context.cc | 3 +-- .../src/api_manager/context/request_context.h | 1 - .../src/api_manager/quota_control.cc | 8 +++--- .../endpoints/src/api_manager/quota_control.h | 26 ++++++++++++++----- .../api_manager/service_control/aggregated.cc | 16 ++++++------ .../api_manager/service_control/aggregated.h | 9 ++++--- .../api_manager/service_control/interface.h | 6 ++--- .../src/api_manager/service_control/proto.cc | 13 +++++----- .../src/api_manager/service_control/proto.h | 2 +- 9 files changed, 47 insertions(+), 37 deletions(-) diff --git a/contrib/endpoints/src/api_manager/context/request_context.cc b/contrib/endpoints/src/api_manager/context/request_context.cc index f4b18ea80a9..0e31e24f2fd 100644 --- a/contrib/endpoints/src/api_manager/context/request_context.cc +++ b/contrib/endpoints/src/api_manager/context/request_context.cc @@ -228,7 +228,6 @@ void RequestContext::FillCheckRequestInfo( void RequestContext::FillAllocateQuotaRequestInfo( service_control::QuotaRequestInfo *info) { - FillOperationInfo(info); info->client_ip = request_->GetClientIP(); @@ -241,7 +240,7 @@ void RequestContext::FillAllocateQuotaRequestInfo( // TODO(jaebong) need to set quota rule and metric rule info->quota_rule_ = nullptr; - info->metric_rule_= nullptr; + info->metric_rule_ = nullptr; } void RequestContext::FillReportRequestInfo( diff --git a/contrib/endpoints/src/api_manager/context/request_context.h b/contrib/endpoints/src/api_manager/context/request_context.h index 8ad894bf335..09cca879159 100644 --- a/contrib/endpoints/src/api_manager/context/request_context.h +++ b/contrib/endpoints/src/api_manager/context/request_context.h @@ -63,7 +63,6 @@ class RequestContext { check_response_info_ = check_response_info; } - // Fill CheckRequestInfo void FillCheckRequestInfo(service_control::CheckRequestInfo *info); diff --git a/contrib/endpoints/src/api_manager/quota_control.cc b/contrib/endpoints/src/api_manager/quota_control.cc index cabaaa2ce99..04e2f974aef 100644 --- a/contrib/endpoints/src/api_manager/quota_control.cc +++ b/contrib/endpoints/src/api_manager/quota_control.cc @@ -13,7 +13,7 @@ // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// -// includes should be ordered. This seems like a bug in clang-format? +// #include #include "contrib/endpoints/src/api_manager/cloud_trace/cloud_trace.h" @@ -55,15 +55,13 @@ void QuotaControl(std::shared_ptr context, return; } - service_control::QuotaRequestInfo info; context->FillAllocateQuotaRequestInfo(&info); context->service_context()->service_control()->Quota( info, trace_span.get(), - [context, continuation, trace_span]( - utils::Status status) { + [context, continuation, trace_span](utils::Status status) { - TRACE(trace_span) << "Quota service control request returned with " + TRACE(trace_span) << "Quota service control request returned with " << "status " << status.ToString(); continuation(status); diff --git a/contrib/endpoints/src/api_manager/quota_control.h b/contrib/endpoints/src/api_manager/quota_control.h index cd6d7b2b359..e4f94d6ac93 100644 --- a/contrib/endpoints/src/api_manager/quota_control.h +++ b/contrib/endpoints/src/api_manager/quota_control.h @@ -1,7 +1,21 @@ -// TODO: Insert description here. (generated by jaebong) - -#ifndef BAZEL_ESP_EXTERNAL_ISTIO_PROXY_GIT_CONTRIB_ENDPOINTS_SRC_API_MANAGER_QUOTA_CONTROL_H_ -#define BAZEL_ESP_EXTERNAL_ISTIO_PROXY_GIT_CONTRIB_ENDPOINTS_SRC_API_MANAGER_QUOTA_CONTROL_H_ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// +// +#ifndef API_MANAGER_QUOTA_CONTROL_H_ +#define API_MANAGER_QUOTA_CONTROL_H_ #include "contrib/endpoints/include/api_manager/utils/status.h" #include "contrib/endpoints/src/api_manager/context/request_context.h" @@ -11,9 +25,9 @@ namespace api_manager { // Call service control quota. void QuotaControl(std::shared_ptr, - std::function); + std::function); } // namespace api_manager } // namespace google -#endif // BAZEL_ESP_EXTERNAL_ISTIO_PROXY_GIT_CONTRIB_ENDPOINTS_SRC_API_MANAGER_QUOTA_CONTROL_H_ +#endif // API_MANAGER_QUOTA_CONTROL_H_ diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index c252837ebca..8cc77773044 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -240,10 +240,10 @@ Status Aggregated::Init() { options.periodic_timer = [this](int interval_ms, std::function callback) -> std::unique_ptr<::google::service_control_client::PeriodicTimer> { - return std::unique_ptr<::google::service_control_client::PeriodicTimer>( - new ApiManagerPeriodicTimer(env_->StartPeriodicTimer( - std::chrono::milliseconds(interval_ms), callback))); - }; + return std::unique_ptr<::google::service_control_client::PeriodicTimer>( + new ApiManagerPeriodicTimer(env_->StartPeriodicTimer( + std::chrono::milliseconds(interval_ms), callback))); + }; client_ = ::google::service_control_client::CreateServiceControlClient( service_->name(), service_->id(), options); return Status::OK; @@ -364,9 +364,9 @@ void Aggregated::Check( check_pool_.Free(std::move(request)); } -void Aggregated::Quota( - const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, - std::function on_done) { +void Aggregated::Quota(const QuotaRequestInfo& info, + cloud_trace::CloudTraceSpan* parent_span, + std::function on_done) { std::shared_ptr trace_span( CreateChildSpan(parent_span, "QuotaServiceControlCache")); @@ -402,7 +402,7 @@ void Aggregated::Quota( }; AllocateQuotaRequest* quota_request_copy = new AllocateQuotaRequest(*request); - + Call(*request, response, [this, quota_request_copy, response, check_on_done](::google::protobuf::util::Status status) { diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.h b/contrib/endpoints/src/api_manager/service_control/aggregated.h index 703cd18f51b..e78f66cbea7 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.h +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.h @@ -49,9 +49,9 @@ class Aggregated : public Interface { const CheckRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, std::function on_done); - virtual void Quota( - const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, - std::function on_done); + virtual void Quota(const QuotaRequestInfo& info, + cloud_trace::CloudTraceSpan* parent_span, + std::function on_done); virtual utils::Status Init(); virtual utils::Status Close(); @@ -143,7 +143,8 @@ class Aggregated : public Interface { client_; // The protobuf pool to reuse CheckRequest protobuf. - ProtoPool<::google::api::servicecontrol::v1::AllocateQuotaRequest> quota_pool_; + ProtoPool<::google::api::servicecontrol::v1::AllocateQuotaRequest> + quota_pool_; // The protobuf pool to reuse CheckRequest protobuf. ProtoPool<::google::api::servicecontrol::v1::CheckRequest> check_pool_; diff --git a/contrib/endpoints/src/api_manager/service_control/interface.h b/contrib/endpoints/src/api_manager/service_control/interface.h index 60ea2ae7c64..a6188e0f73b 100644 --- a/contrib/endpoints/src/api_manager/service_control/interface.h +++ b/contrib/endpoints/src/api_manager/service_control/interface.h @@ -77,9 +77,9 @@ class Interface { // If status code is less than 20, within the ranges defined by // google/protobuf/stubs/status.h, is from parsing error response // body. - virtual void Quota( - const QuotaRequestInfo& info, cloud_trace::CloudTraceSpan* parent_span, - std::function on_done) = 0; + virtual void Quota(const QuotaRequestInfo& info, + cloud_trace::CloudTraceSpan* parent_span, + std::function on_done) = 0; // Get statistics of ServiceControl library. virtual utils::Status GetStatistics(Statistics* stat) const = 0; diff --git a/contrib/endpoints/src/api_manager/service_control/proto.cc b/contrib/endpoints/src/api_manager/service_control/proto.cc index ccfdc4f8c1a..7ff44810a1b 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.cc +++ b/contrib/endpoints/src/api_manager/service_control/proto.cc @@ -911,9 +911,11 @@ Proto::Proto(const std::set& logs, service_name_(service_name), service_config_id_(service_config_id) {} -utils::Status Proto::FillAllocateQuotaRequest(const QuotaRequestInfo& info, ::google::api::servicecontrol::v1::AllocateQuotaRequest* request) { - - ::google::api::servicecontrol::v1::QuotaOperation* operation = request->mutable_allocate_operation(); +utils::Status Proto::FillAllocateQuotaRequest( + const QuotaRequestInfo& info, + ::google::api::servicecontrol::v1::AllocateQuotaRequest* request) { + ::google::api::servicecontrol::v1::QuotaOperation* operation = + request->mutable_allocate_operation(); // service_name request->set_service_name(service_name_); @@ -931,7 +933,7 @@ utils::Status Proto::FillAllocateQuotaRequest(const QuotaRequestInfo& info, ::go // allocate_operation.consumer_id if (!info.api_key.empty()) { operation->set_consumer_id(std::string(kConsumerIdApiKey) + - std::string(info.api_key)); + std::string(info.api_key)); } // TODO(jaebong) - Read from service conf? @@ -940,7 +942,6 @@ utils::Status Proto::FillAllocateQuotaRequest(const QuotaRequestInfo& info, ::go ::google::api::servicecontrol::v1::QuotaOperation_QuotaMode:: QuotaOperation_QuotaMode_NORMAL); - // allocate_operation.labels auto* labels = operation->mutable_labels(); if (!info.client_ip.empty()) { @@ -954,8 +955,6 @@ utils::Status Proto::FillAllocateQuotaRequest(const QuotaRequestInfo& info, ::go (*labels)[kServiceControlServiceAgent] = kServiceAgentPrefix + utils::Version::instance().get(); - - // allocate_operation.quota_metrics // handle group rules diff --git a/contrib/endpoints/src/api_manager/service_control/proto.h b/contrib/endpoints/src/api_manager/service_control/proto.h index 433702b11b6..d4fa09592c9 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.h +++ b/contrib/endpoints/src/api_manager/service_control/proto.h @@ -19,8 +19,8 @@ #include "contrib/endpoints/src/api_manager/service_control/info.h" #include "google/api/label.pb.h" #include "google/api/metric.pb.h" -#include "google/api/servicecontrol/v1/service_controller.pb.h" #include "google/api/servicecontrol/v1/quota_controller.pb.h" +#include "google/api/servicecontrol/v1/service_controller.pb.h" namespace google { namespace api_manager { From 2f0d75927589a1dadd23f1f21982ca8451b2f13a Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 11:27:12 -0800 Subject: [PATCH 5/8] Removed uncessary class, enum, and comment --- .../api_manager/service_control/aggregated.cc | 10 +++++----- .../src/api_manager/service_control/aggregated.h | 6 +++--- .../src/api_manager/service_control/info.h | 16 ---------------- .../src/api_manager/service_control/proto.cc | 12 +----------- 4 files changed, 9 insertions(+), 35 deletions(-) diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index 8cc77773044..cb2e0f78de4 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -495,13 +495,13 @@ void Aggregated::Call(const RequestType& request, ResponseType* response, max_report_size_ = request_body.size(); } - auto token_ = (typeid(RequestType) == typeid(AllocateQuotaRequest)) + auto token = (typeid(RequestType) == typeid(AllocateQuotaRequest)) ? sa_token_quota_ : sa_token_; http_request->set_url(url) .set_method("POST") - .set_auth_token(GetAuthToken(token_)) + .set_auth_token(GetAuthToken(token)) .set_header("Content-Type", application_proto) .set_body(request_body); @@ -535,9 +535,9 @@ void Aggregated::Call(const RequestType& request, ResponseType* response, env_->RunHTTPRequest(std::move(http_request)); } -const std::string& Aggregated::GetAuthToken(auth::ServiceAccountToken* token_) { - if (token_) { - return token_->GetAuthToken( +const std::string& Aggregated::GetAuthToken(auth::ServiceAccountToken* token) { + if (token) { + return token->GetAuthToken( auth::ServiceAccountToken::JWT_TOKEN_FOR_SERVICE_CONTROL); } else { static std::string empty; diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.h b/contrib/endpoints/src/api_manager/service_control/aggregated.h index e78f66cbea7..1113f84a129 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.h +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.h @@ -116,7 +116,7 @@ class Aggregated : public Interface { cloud_trace::CloudTraceSpan* parent_span); // Gets the auth token to access service control server. - const std::string& GetAuthToken(auth::ServiceAccountToken* token_); + const std::string& GetAuthToken(auth::ServiceAccountToken* token); // the sevice config. const ::google::api::Service* service_; @@ -129,7 +129,7 @@ class Aggregated : public Interface { // service account token. auth::ServiceAccountToken* sa_token_; - // quota service account token. + // TODO(jaebong) quota service account token. auth::ServiceAccountToken* sa_token_quota_; // The object to fill service control Check and Report protobuf. @@ -142,7 +142,7 @@ class Aggregated : public Interface { std::unique_ptr<::google::service_control_client::ServiceControlClient> client_; - // The protobuf pool to reuse CheckRequest protobuf. + // The protobuf pool to reuse AllocateQuotaRequest protobuf. ProtoPool<::google::api::servicecontrol::v1::AllocateQuotaRequest> quota_pool_; diff --git a/contrib/endpoints/src/api_manager/service_control/info.h b/contrib/endpoints/src/api_manager/service_control/info.h index 81a8951f227..50000a264fb 100644 --- a/contrib/endpoints/src/api_manager/service_control/info.h +++ b/contrib/endpoints/src/api_manager/service_control/info.h @@ -72,8 +72,6 @@ struct OperationInfo { // Information to fill Check request protobuf. struct CheckRequestInfo : public OperationInfo { - // The client IP address. - std::string client_ip; // Whether the method allow unregistered calls. bool allow_unregistered_calls; @@ -92,18 +90,6 @@ struct CheckResponseInfo { CheckResponseInfo() : is_api_key_valid(true), service_is_activated(true) {} }; -struct MetricValueInfo { - std::string metric_name; - int64_t metric_value; - - std::unordered_map labels; - std::chrono::system_clock::time_point start_time; - std::chrono::system_clock::time_point end_time; - - MetricValueInfo(std::string name, int64_t value) - : metric_name(name), metric_value(value) {} -}; - struct QuotaRequestInfo : public OperationInfo { std::string method_name; // The client IP address. @@ -115,8 +101,6 @@ struct QuotaRequestInfo : public OperationInfo { ::google::api::MetricRule* metric_rule_; }; -enum QuotaResponseCacheStatus { WAITING, CACHED }; - // Information to fill Report request protobuf. struct ReportRequestInfo : public OperationInfo { // The HTTP response code. diff --git a/contrib/endpoints/src/api_manager/service_control/proto.cc b/contrib/endpoints/src/api_manager/service_control/proto.cc index 7ff44810a1b..4e8fbd5c306 100644 --- a/contrib/endpoints/src/api_manager/service_control/proto.cc +++ b/contrib/endpoints/src/api_manager/service_control/proto.cc @@ -956,7 +956,7 @@ utils::Status Proto::FillAllocateQuotaRequest( kServiceAgentPrefix + utils::Version::instance().get(); // allocate_operation.quota_metrics - + // TODO(jaebong) need to update after the configuration module change // handle group rules if (info.quota_rule_ != nullptr) { MetricValueSet* value_set = operation->add_quota_metrics(); @@ -985,16 +985,6 @@ utils::Status Proto::FillAllocateQuotaRequest( } } - /* - for (auto it : info.quota_metrics) { - auto set = operation->add_quota_metrics(); - set->set_metric_name(it.metric_name); - - auto value = set->add_metric_values(); - value->set_int64_value(it.metric_value); - } - */ - return Status::OK; } From f5577b2fadd0eec6fa1b15384b59bf4f78ada104 Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 11:30:51 -0800 Subject: [PATCH 6/8] Added comment --- contrib/endpoints/src/api_manager/service_control/aggregated.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index cb2e0f78de4..9acac4fb11d 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -403,6 +403,7 @@ void Aggregated::Quota(const QuotaRequestInfo& info, AllocateQuotaRequest* quota_request_copy = new AllocateQuotaRequest(*request); + // TODO(jaebong) Temporarily call Chemist directly instead of using service control client library Call(*request, response, [this, quota_request_copy, response, check_on_done](::google::protobuf::util::Status status) { From b2b3c4a3c1e5b95754f1a6cfdc5184b3d4933efb Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 11:30:51 -0800 Subject: [PATCH 7/8] Added comment --- contrib/endpoints/src/api_manager/service_control/aggregated.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index cb2e0f78de4..9acac4fb11d 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -403,6 +403,7 @@ void Aggregated::Quota(const QuotaRequestInfo& info, AllocateQuotaRequest* quota_request_copy = new AllocateQuotaRequest(*request); + // TODO(jaebong) Temporarily call Chemist directly instead of using service control client library Call(*request, response, [this, quota_request_copy, response, check_on_done](::google::protobuf::util::Status status) { From 8a1cc4edb0cd706ff40520e491c69caf4d4dc77b Mon Sep 17 00:00:00 2001 From: Jae Kim Date: Tue, 14 Feb 2017 11:49:58 -0800 Subject: [PATCH 8/8] Fixed file formatting error --- .../src/api_manager/service_control/aggregated.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contrib/endpoints/src/api_manager/service_control/aggregated.cc b/contrib/endpoints/src/api_manager/service_control/aggregated.cc index 9acac4fb11d..05ac5c7a49a 100644 --- a/contrib/endpoints/src/api_manager/service_control/aggregated.cc +++ b/contrib/endpoints/src/api_manager/service_control/aggregated.cc @@ -403,7 +403,8 @@ void Aggregated::Quota(const QuotaRequestInfo& info, AllocateQuotaRequest* quota_request_copy = new AllocateQuotaRequest(*request); - // TODO(jaebong) Temporarily call Chemist directly instead of using service control client library + // TODO(jaebong) Temporarily call Chemist directly instead of using service + // control client library Call(*request, response, [this, quota_request_copy, response, check_on_done](::google::protobuf::util::Status status) { @@ -497,8 +498,8 @@ void Aggregated::Call(const RequestType& request, ResponseType* response, } auto token = (typeid(RequestType) == typeid(AllocateQuotaRequest)) - ? sa_token_quota_ - : sa_token_; + ? sa_token_quota_ + : sa_token_; http_request->set_url(url) .set_method("POST")