diff --git a/framework/helpers/docker.py b/framework/helpers/docker.py index 8f7b256a..86bdf9b6 100644 --- a/framework/helpers/docker.py +++ b/framework/helpers/docker.py @@ -1,3 +1,16 @@ +# Copyright 2024 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. from collections import defaultdict import datetime import logging @@ -14,7 +27,8 @@ from protos.grpc.testing import messages_pb2 from protos.grpc.testing import test_pb2_grpc -from protos.grpc.testing.xdsconfig import control_pb2, service_pb2_grpc +from protos.grpc.testing.xdsconfig import control_pb2 +from protos.grpc.testing.xdsconfig import service_pb2_grpc # bootstrap.json template BOOTSTRAP_JSON_TEMPLATE = "templates/bootstrap.json" @@ -294,6 +308,10 @@ def expect_running(self, timeout_s: int = 5): "Management server listening on", timeout_s ) + def set_resources(self, resources): + print([r.DebugString() for r in resources].join("\n\n")) + raise Exception("Stop!") + class Client(GrpcProcess): def __init__( diff --git a/framework/helpers/xds_resources.py b/framework/helpers/xds_resources.py new file mode 100644 index 00000000..1d67d97b --- /dev/null +++ b/framework/helpers/xds_resources.py @@ -0,0 +1,60 @@ +# Copyright 2024 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. +from envoy.config.listener.v3 import api_listener_pb2 +from envoy.config.listener.v3 import listener_pb2 +from envoy.config.route.v3 import route_components_pb2 +from envoy.config.route.v3 import route_pb2 +from envoy.extensions.filters.http.router.v3 import router_pb2 +from envoy.extensions.filters.network.http_connection_manager.v3 import ( + http_connection_manager_pb2, +) +from google.protobuf import any_pb2 +from google.protobuf import message + + +def wrap_in_any(message: message.Message) -> any_pb2.Any: + any_msg = any_pb2.Any() + any_msg.Pack(message) + return any_msg + + +def build_listener(listener_name: str, cluster_name: str): + hcm = http_connection_manager_pb2.HttpConnectionManager( + route_config=route_pb2.RouteConfiguration( + virtual_hosts=[ + route_components_pb2.VirtualHost( + domains=["*"], + routes=[ + route_components_pb2.Route( + match=route_components_pb2.RouteMatch(prefix=""), + route=route_components_pb2.RouteAction( + cluster=cluster_name + ), + ) + ], + ) + ] + ), + http_filters=[ + http_connection_manager_pb2.HttpFilter( + name="router", typed_config=wrap_in_any(router_pb2.Router()) + ) + ], + ) + return listener_pb2.Listener( + api_listener=api_listener_pb2.ApiListener( + api_listener=wrap_in_any(hcm) + ), + name=listener_name, + ) diff --git a/tests/fallback_test.py b/tests/fallback_test.py index 1741d65e..20fc56df 100644 --- a/tests/fallback_test.py +++ b/tests/fallback_test.py @@ -1,3 +1,16 @@ +# Copyright 2024 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. import logging import socket import unittest @@ -5,10 +18,12 @@ import absl from absl import flags from absl.testing import absltest +from google.protobuf.json_format import MessageToJson import framework import framework.helpers.docker import framework.helpers.logs +import framework.helpers.xds_resources import framework.xds_flags import framework.xds_k8s_testcase @@ -85,6 +100,17 @@ def start_server(self, name: str, port: int = None): command=[], ) + def test_dummy_to_see(self): + print( + MessageToJson( + framework.helpers.xds_resources.build_listener( + listener_name="listener0", cluster_name="cluster_cluster" + ) + ) + ) + # self.fail("Not implemented") + + @unittest.skip("Ignore for now") def test_fallback_on_startup(self): with ( self.start_server(name="server1") as server1, @@ -100,7 +126,8 @@ def test_fallback_on_startup(self): # Fallback control plane start, send traffic to server2 with self.start_control_plane( "fallback_xds_config", 1, server2.port - ): + ) as fallback: + fallback.set_resources(build_xds_resources()) stats = client.get_stats(5) self.assertGreater(stats.rpcs_by_peer["server2"], 0) self.assertNotIn("server1", stats.rpcs_by_peer) @@ -128,6 +155,7 @@ def test_fallback_on_startup(self): self.assertEqual(stats.num_failures, 0) self.assertEqual(stats.rpcs_by_peer["server1"], 5) + @unittest.skip("Disable for now") def test_fallback_mid_startup(self): # Run the mesh, excluding the client with ( @@ -165,6 +193,7 @@ def test_fallback_mid_startup(self): self.assertIn("server1", stats.rpcs_by_peer) self.assertGreater(stats.rpcs_by_peer["server1"], 0) + @unittest.skip("Disable for now") def test_fallback_mid_update(self): with ( self.start_server(name="server1") as server1,