summaryrefslogtreecommitdiff
path: root/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'grpc/src/core/ext/filters/fault_injection/service_config_parser.cc')
-rw-r--r--grpc/src/core/ext/filters/fault_injection/service_config_parser.cc189
1 files changed, 189 insertions, 0 deletions
diff --git a/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc b/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc
new file mode 100644
index 00000000..e8c23e19
--- /dev/null
+++ b/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc
@@ -0,0 +1,189 @@
+//
+// Copyright 2021 gRPC authors.
+//
+// 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.
+//
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/fault_injection/service_config_parser.h"
+
+#include <vector>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "src/core/ext/filters/client_channel/service_config.h"
+#include "src/core/ext/filters/fault_injection/fault_injection_filter.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/channel/status_util.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/json/json_util.h"
+
+namespace grpc_core {
+
+namespace {
+
+size_t g_fault_injection_parser_index;
+
+std::vector<FaultInjectionMethodParsedConfig::FaultInjectionPolicy>
+ParseFaultInjectionPolicy(const Json::Array& policies_json_array,
+ std::vector<grpc_error_handle>* error_list) {
+ std::vector<FaultInjectionMethodParsedConfig::FaultInjectionPolicy> policies;
+ for (size_t i = 0; i < policies_json_array.size(); i++) {
+ FaultInjectionMethodParsedConfig::FaultInjectionPolicy
+ fault_injection_policy;
+ std::vector<grpc_error_handle> sub_error_list;
+ if (policies_json_array[i].type() != Json::Type::OBJECT) {
+ error_list->push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("faultInjectionPolicy index ", i,
+ " is not a JSON object")
+ .c_str()));
+ continue;
+ }
+ const Json::Object& json_object = policies_json_array[i].object_value();
+ // Parse abort_code
+ std::string abort_code_string;
+ if (ParseJsonObjectField(json_object, "abortCode", &abort_code_string,
+ &sub_error_list, false)) {
+ if (!grpc_status_code_from_string(abort_code_string.c_str(),
+ &(fault_injection_policy.abort_code))) {
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "field:abortCode error:failed to parse status code"));
+ }
+ }
+ // Parse abort_message
+ if (!ParseJsonObjectField(json_object, "abortMessage",
+ &fault_injection_policy.abort_message,
+ &sub_error_list, false)) {
+ fault_injection_policy.abort_message = "Fault injected";
+ }
+ // Parse abort_code_header
+ ParseJsonObjectField(json_object, "abortCodeHeader",
+ &fault_injection_policy.abort_code_header,
+ &sub_error_list, false);
+ // Parse abort_percentage_header
+ ParseJsonObjectField(json_object, "abortPercentageHeader",
+ &fault_injection_policy.abort_percentage_header,
+ &sub_error_list, false);
+ // Parse abort_percentage_numerator
+ ParseJsonObjectField(json_object, "abortPercentageNumerator",
+ &fault_injection_policy.abort_percentage_numerator,
+ &sub_error_list, false);
+ // Parse abort_percentage_denominator
+ if (ParseJsonObjectField(
+ json_object, "abortPercentageDenominator",
+ &fault_injection_policy.abort_percentage_denominator,
+ &sub_error_list, false)) {
+ if (fault_injection_policy.abort_percentage_denominator != 100 &&
+ fault_injection_policy.abort_percentage_denominator != 10000 &&
+ fault_injection_policy.abort_percentage_denominator != 1000000) {
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "field:abortPercentageDenominator error:Denominator can only be "
+ "one of "
+ "100, 10000, 1000000"));
+ }
+ }
+ // Parse delay
+ ParseJsonObjectFieldAsDuration(json_object, "delay",
+ &fault_injection_policy.delay,
+ &sub_error_list, false);
+ // Parse delay_header
+ ParseJsonObjectField(json_object, "delayHeader",
+ &fault_injection_policy.delay_header, &sub_error_list,
+ false);
+ // Parse delay_percentage_header
+ ParseJsonObjectField(json_object, "delayPercentageHeader",
+ &fault_injection_policy.delay_percentage_header,
+ &sub_error_list, false);
+ // Parse delay_percentage_numerator
+ ParseJsonObjectField(json_object, "delayPercentageNumerator",
+ &fault_injection_policy.delay_percentage_numerator,
+ &sub_error_list, false);
+ // Parse delay_percentage_denominator
+ if (ParseJsonObjectField(
+ json_object, "delayPercentageDenominator",
+ &fault_injection_policy.delay_percentage_denominator,
+ &sub_error_list, false)) {
+ if (fault_injection_policy.delay_percentage_denominator != 100 &&
+ fault_injection_policy.delay_percentage_denominator != 10000 &&
+ fault_injection_policy.delay_percentage_denominator != 1000000) {
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "field:delayPercentageDenominator error:Denominator can only be "
+ "one of "
+ "100, 10000, 1000000"));
+ }
+ }
+ // Parse max_faults
+ if (ParseJsonObjectField(json_object, "maxFaults",
+ &fault_injection_policy.max_faults,
+ &sub_error_list, false)) {
+ if (fault_injection_policy.max_faults < 0) {
+ sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+ "field:maxFaults error:should be zero or positive"));
+ }
+ }
+ if (!sub_error_list.empty()) {
+ // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error
+ // string is not static in this case.
+ grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
+ absl::StrCat("failed to parse faultInjectionPolicy index ", i)
+ .c_str());
+ for (size_t i = 0; i < sub_error_list.size(); ++i) {
+ error = grpc_error_add_child(error, sub_error_list[i]);
+ }
+ error_list->push_back(error);
+ }
+ policies.push_back(std::move(fault_injection_policy));
+ }
+ return policies;
+}
+
+} // namespace
+
+std::unique_ptr<ServiceConfigParser::ParsedConfig>
+FaultInjectionServiceConfigParser::ParsePerMethodParams(
+ const grpc_channel_args* args, const Json& json, grpc_error_handle* error) {
+ GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
+ // Only parse fault injection policy if the following channel arg is present.
+ if (!grpc_channel_args_find_bool(
+ args, GRPC_ARG_PARSE_FAULT_INJECTION_METHOD_CONFIG, false)) {
+ return nullptr;
+ }
+ // Parse fault injection policy from given Json
+ std::vector<FaultInjectionMethodParsedConfig::FaultInjectionPolicy>
+ fault_injection_policies;
+ std::vector<grpc_error_handle> error_list;
+ const Json::Array* policies_json_array;
+ if (ParseJsonObjectField(json.object_value(), "faultInjectionPolicy",
+ &policies_json_array, &error_list)) {
+ fault_injection_policies =
+ ParseFaultInjectionPolicy(*policies_json_array, &error_list);
+ }
+ *error = GRPC_ERROR_CREATE_FROM_VECTOR("Fault injection parser", &error_list);
+ if (*error != GRPC_ERROR_NONE || fault_injection_policies.empty()) {
+ return nullptr;
+ }
+ return absl::make_unique<FaultInjectionMethodParsedConfig>(
+ std::move(fault_injection_policies));
+}
+
+void FaultInjectionServiceConfigParser::Register() {
+ g_fault_injection_parser_index = ServiceConfigParser::RegisterParser(
+ absl::make_unique<FaultInjectionServiceConfigParser>());
+}
+
+size_t FaultInjectionServiceConfigParser::ParserIndex() {
+ return g_fault_injection_parser_index;
+}
+
+} // namespace grpc_core