Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support in route checker tool for runtimes in routes #7418

Merged
merged 8 commits into from
Jul 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 43 additions & 70 deletions docs/root/configuration/tools/router_check.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,90 +32,63 @@ Validate
A simple tool configuration json has one test case and is written as follows. The test
expects a cluster name match of "instant-server".::

[
{
"test_name: "Cluster_name_test",
"input":
{
":authority":"api.lyft.com",
":path": "/api/locations"
},
"validate":
{
"cluster_name": "instant-server"
}
}
]

.. code-block:: json

[
{
"test_name": "...",
"input":
{
":authority": "...",
":path": "...",
":method": "...",
"internal" : "...",
"random_value" : "...",
"ssl" : "...",
"additional_headers": [
{
"field": "...",
"value": "..."
},
{
"..."
}
]
},
"validate": {
"cluster_name": "...",
"virtual_cluster_name": "...",
"virtual_host_name": "...",
"host_rewrite": "...",
"path_rewrite": "...",
"path_redirect": "...",
"header_fields" : [
{
"field": "...",
"value": "..."
},
{
"..."
}
]
}
},
{
"..."
}
]
tests
- test_name: Cluster_name_test,
input:
authority: api.lyft.com,
path: /api/locations
validate:
cluster_name: instant-server

.. code-block:: yaml

tests
- test_name: ...,
input:
authority: ...,
path": ...,
method": ...,
internal" : ...,
random_value" : ...,
ssl" : ...,
- additional_headers:
key: ...,
value: ...
validate:
cluster_name: ...,
virtual_cluster_name: ...,
virtual_host_name: ...,
host_rewrite: ...,
path_rewrite: ...,
path_redirect: ...,
- header_fields:
key: ...,
value: ...

test_name
*(required, string)* The name of a test object.

input
*(required, object)* Input values sent to the router that determine the returned route.

:authority
authority
*(required, string)* The url authority. This value along with the path parameter define
the url to be matched. An example authority value is "api.lyft.com".

:path
path
*(required, string)* The url path. An example path value is "/foo".

:method
*(optional, string)* The request method. If not specified, the default method is GET. The options
method
*(required, string)* The request method. If not specified, the default method is GET. The options
are GET, PUT, or POST.

internal
*(optional, boolean)* A flag that determines whether to set x-envoy-internal to "true".
If not specified, or if internal is equal to false, x-envoy-internal is not set.

random_value
*(optional, integer)* An integer used to identify the target for weighted cluster selection.
*(optional, integer)* An integer used to identify the target for weighted cluster selection
and as a factor for the routing engine to decide whether a runtime based route takes effect.
The default value of random_value is 0.

ssl
Expand All @@ -125,11 +98,11 @@ input
x-forwarded-proto set to http.

additional_headers
*(optional, array)* Additional headers to be added as input for route determination. The ":authority",
":path", ":method", "x-forwarded-proto", and "x-envoy-internal" fields are specified by the other config
*(optional, array)* Additional headers to be added as input for route determination. The "authority",
"path", "method", "x-forwarded-proto", and "x-envoy-internal" fields are specified by the other config
options and should not be set here.

field
key
*(required, string)* The name of the header field to add.

value
Expand Down Expand Up @@ -159,11 +132,11 @@ validate
*(optional, string)* Match the returned redirect path.

header_fields
*(optional, array)* Match the listed header fields. Examples header fields include the ":path", "cookie",
*(optional, array)* Match the listed header fields. Examples header fields include the "path", "cookie",
and "date" fields. The header fields are checked after all other test cases. Thus, the header fields checked
will be those of the redirected or rewritten routes when applicable.

field
key
*(required, string)* The name of the header field to match.

value
Expand Down
3 changes: 0 additions & 3 deletions docs/root/install/tools/route_table_check_tool.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ Output
locations ats cluster_name
Test_6

Testing with valid :ref:`runtime values <envoy_api_field_route.RouteMatch.runtime_fraction>` is not currently supported,
this may be added in future work.

Building
The tool can be built locally using Bazel. ::

Expand Down
17 changes: 16 additions & 1 deletion test/tools/router_check/router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ RouterCheckTool::RouterCheckTool(
std::unique_ptr<Router::ConfigImpl> config, std::unique_ptr<Stats::IsolatedStoreImpl> stats,
Api::ApiPtr api)
: factory_context_(std::move(factory_context)), config_(std::move(config)),
stats_(std::move(stats)), api_(std::move(api)) {}
stats_(std::move(stats)), api_(std::move(api)) {
ON_CALL(factory_context_->runtime_loader_.snapshot_,
featureEnabled(_, testing::An<const envoy::type::FractionalPercent&>(),
testing::An<uint64_t>()))
.WillByDefault(testing::Invoke(this, &RouterCheckTool::runtimeMock));
}

// TODO(jyotima): Remove this code path once the json schema code path is deprecated.
bool RouterCheckTool::compareEntriesInJson(const std::string& expected_route_json) {
Expand Down Expand Up @@ -165,6 +170,7 @@ bool RouterCheckTool::compareEntries(const std::string& expected_routes) {
bool no_failures = true;
for (const envoy::RouterCheckToolSchema::ValidationItem& check_config :
validation_config.tests()) {
active_runtime = check_config.input().runtime();
headers_finalized_ = false;
ToolConfig tool_config = ToolConfig::create(check_config);
tool_config.route_ = config_->route(*tool_config.headers_, tool_config.random_value_);
Expand Down Expand Up @@ -396,6 +402,15 @@ bool RouterCheckTool::compareResults(const std::string& actual, const std::strin
return false;
}

// The Mock for runtime value checks.
// This is a simple implementation to mimic the actual runtime checks in Snapshot.featureEnabled
bool RouterCheckTool::runtimeMock(const std::string& key,
const envoy::type::FractionalPercent& default_value,
uint64_t random_value) {
return !active_runtime.empty() && active_runtime.compare(key) == 0 &&
ProtobufPercentHelper::evaluateFractionalPercent(default_value, random_value);
}

Options::Options(int argc, char** argv) {
TCLAP::CmdLine cmd("router_check_tool", ' ', "none", true);
TCLAP::SwitchArg is_proto("p", "useproto", "Use Proto test file schema", cmd, false);
Expand Down
6 changes: 5 additions & 1 deletion test/tools/router_check/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class RouterCheckTool : Logger::Loggable<Logger::Id::testing> {
bool compareCustomHeaderField(ToolConfig& tool_config, const std::string& field,
const std::string& expected);
bool compareCustomHeaderField(ToolConfig& tool_config,
const envoy::RouterCheckToolSchema::ValidationAssert& expecte);
const envoy::RouterCheckToolSchema::ValidationAssert& expected);
/**
* Compare the expected and actual route parameter values. Print out match details if details_
* flag is set.
Expand All @@ -130,6 +130,9 @@ class RouterCheckTool : Logger::Loggable<Logger::Id::testing> {
bool compareResults(const std::string& actual, const std::string& expected,
const std::string& test_type);

bool runtimeMock(const std::string& key, const envoy::type::FractionalPercent& default_value,
uint64_t random_value);

bool headers_finalized_{false};

bool details_{false};
Expand All @@ -139,6 +142,7 @@ class RouterCheckTool : Logger::Loggable<Logger::Id::testing> {
std::unique_ptr<Router::ConfigImpl> config_;
std::unique_ptr<Stats::IsolatedStoreImpl> stats_;
Api::ApiPtr api_;
std::string active_runtime;
};

/**
Expand Down
47 changes: 47 additions & 0 deletions test/tools/router_check/test/config/Runtime.golden.proto.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"tests": [
{
"test_name": "Test_1",
"input": {
"authority": "www.lyft.com",
"path": "/",
"method": "GET",
"ssl": true,
"internal": true
},
"validate": {
"cluster_name": "www3"
}
},
{
"test_name": "Test_2",
"input": {
"authority": "www.lyft.com",
"path": "/",
"method": "GET",
"ssl": true,
"internal": true,
"runtime": "runtime.key",
"random_value": 70
},
"validate": {
"cluster_name": "www3"
}
},
{
"test_name": "Test_3",
"input": {
"authority": "www.lyft.com",
"path": "/",
"method": "GET",
"ssl": true,
"internal": true,
"runtime": "runtime.key",
"random_value": 20
},
"validate": {
"cluster_name": "www2"
}
}
]
}
18 changes: 18 additions & 0 deletions test/tools/router_check/test/config/Runtime.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
virtual_hosts:
- name: www2
domains:
- www.lyft.com
routes:
- match:
prefix: /
runtime_fraction:
runtime_key: runtime.key
default_value:
numerator: 30
denominator: HUNDRED
route:
cluster: www2
- match:
prefix: /
route:
cluster: www3
1 change: 1 addition & 0 deletions test/tools/router_check/test/route_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ done

# Testing expected matches using --useproto
# --useproto needs the test schema as a validation.proto message.
TESTS+=("Runtime")
for t in "${TESTS[@]}"
do
TEST_OUTPUT=$("${PATH_BIN}" "-c" "${PATH_CONFIG}/${t}.yaml" "-t" "${PATH_CONFIG}/${t}.golden.proto.json" "--details" "--useproto")
Expand Down
5 changes: 5 additions & 0 deletions test/tools/router_check/validation.proto
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ message ValidationInput {
// The “:authority”, “:path”, “:method”, “x-forwarded-proto”, and “x-envoy-internal” fields are
// specified by the other config options and should not be set here.
repeated envoy.api.v2.core.HeaderValue additional_headers = 8;

// Runtime setting key to enable for the test case.
// If a route depends on the runtime, the route will be enabled based on the random_value defined
// in the test. Only a random_value less than the fractional percentage will enable the route.
string runtime = 9;
}

// The validate object specifies the returned route parameters to match.
Expand Down