def test_loading_sources_t1(discovery_request, sources): expected = { 'scopes': { 'listeners': [{ 'name': 'ssh', 'port': 22, 'tcp': True, 'target': 'httpbin-proxy', 'service_clusters': ['T1'] }], 'default': [ { 'name': 'httpbin-proxy', 'service_clusters': ['T1'], 'domains': ['example.local'], 'endpoints': [{ 'address': 'httpbin.org', 'port': 443 }], }, ] } } instances = match_node(node_value=extract_node_key(discovery_request.node)) assert instances.dict() == expected
async def deep_check(): template = random.choice( list(XDS_TEMPLATES['default'].keys()) ) await discovery.response( mock_discovery_request(), xds_type=template ) node = mock_discovery_request().node match_node(node_value=extract_node_key(node)) return PlainTextResponse(f'Rendered {template} OK')
def instances( service_cluster: str = Query( '*', title='The clients service cluster to emulate in this XDS request' ), modified: str = Query( 'yes', title= 'Whether the sources should run Modifiers/Global Modifiers prior to being returned' )): node = mock_discovery_request(service_cluster=service_cluster).node args = { 'modify': yaml.safe_load(modified), 'node_value': extract_node_key(node) } ret = match_node(**args) safe_response = jsonable_encoder(ret) return json_response_class(content=safe_response)
def test_loading_sources_wildcard(discovery_request, sources): expected = { 'scopes': { 'listeners': [{ 'name': 'ssh', 'port': 22, 'tcp': True, 'target': 'httpbin-proxy', 'service_clusters': ['T1'] }], 'default': [{ 'name': 'google-proxy', 'service_clusters': ['X1'], 'domains': ['google.local'], 'endpoints': [{ 'address': 'google.com.au', 'port': 443, 'region': 'ap-southeast-2' }, { 'address': 'google.com', 'port': 443, 'region': 'us-west-1' }], }, { 'name': 'httpbin-proxy', 'service_clusters': ['T1'], 'domains': ['example.local'], 'endpoints': [{ 'address': 'httpbin.org', 'port': 443 }], }] } } discovery_request.node.cluster = '*' instances = match_node(node_value=extract_node_key(discovery_request.node)) assert instances.dict() == expected
def test_loading_sources_x1(discovery_request, sources): expected = { 'scopes': { 'default': [{ 'name': 'google-proxy', 'service_clusters': ['X1'], 'domains': ['google.local'], 'endpoints': [{ 'address': 'google.com.au', 'port': 443, 'region': 'ap-southeast-2' }, { 'address': 'google.com', 'port': 443, 'region': 'us-west-1' }], }] } } discovery_request.node.cluster = 'X1' instances = match_node(node_value=extract_node_key(discovery_request.node)) assert instances.dict() == expected
async def response(request: DiscoveryRequest, xds_type: DiscoveryTypes, host: str = 'none'): """ A Discovery **Request** typically looks something like: .. code-block:: json { "version_info": "0", "node": { "cluster": "T1", "build_version": "<revision hash>/<version>/Clean/RELEASE", "metadata": { "auth": "..." } } } When we receive this, we give the client the latest configuration via a Discovery **Response** that looks something like this: .. code-block:: json { "version_info": "abcdef1234567890", "resources": [] } The version_info is derived from :func:`sovereign.discovery.version_hash` :param request: An envoy Discovery Request :param xds_type: what type of XDS template to use when rendering :param host: the host header that was received from the envoy client :return: An envoy Discovery Response """ template: XdsTemplate = XDS_TEMPLATES.get(request.envoy_version, default_templates)[xds_type] context = make_context( node_value=extract_node_key(request.node), template=template, ) # If the discovery request came from a mock, it will # typically contain this metadata key. # This means we should prevent any decryptable data # from ending up in the response. if request.node.metadata.get('hide_private_keys'): context['crypto'] = disabled_suite config_version = '0' if config.cache_strategy == 'context': config_version = version_hash(context, template.checksum, request.node.common, request.resources) if config_version == request.version_info: return {'version_info': config_version} kwargs = dict( discovery_request=request, host_header=host, resource_names=request.resources, **context ) if template.is_python_source: content = {'resources': list(template.code.call(**kwargs))} else: content = await template.content.render_async(**kwargs) if config.cache_strategy == 'content': config_version = version_hash(content) if config_version == request.version_info: return {'version_info': config_version} # This is the most expensive operation, I think, so it's performed as late as possible. if not template.is_python_source: content = deserialize_config(content) content['version_info'] = config_version return remove_unwanted_resources(content, request.resources)