1import logging
2from typing import TYPE_CHECKING, Optional
3
4import pytest
5
6from tests.selfsigned import TLSCerts
7from tests.utils import (
8 assert_valid_envoy_config,
9 econf_foreach_cluster,
10 module_and_mapping_manifests,
11)
12
13logging.basicConfig(
14 level=logging.INFO,
15 format="%(asctime)s test %(levelname)s: %(message)s",
16 datefmt="%Y-%m-%d %H:%M:%S",
17)
18
19logger = logging.getLogger("ambassador")
20
21from ambassador import IR, Config
22from ambassador.envoy import EnvoyConfig
23from ambassador.fetch import ResourceFetcher
24from ambassador.utils import NullSecretHandler, SecretHandler, SecretInfo
25from tests.utils import default_listener_manifests
26
27if TYPE_CHECKING:
28 from ambassador.ir.irresource import IRResource # pragma: no cover
29
30
31class MockSecretHandler(SecretHandler):
32 def load_secret(
33 self, resource: "IRResource", secret_name: str, namespace: str
34 ) -> Optional[SecretInfo]:
35 return SecretInfo(
36 "fallback-self-signed-cert",
37 "ambassador",
38 "mocked-fallback-secret",
39 TLSCerts["acook"].pubcert,
40 TLSCerts["acook"].privkey,
41 decode_b64=False,
42 )
43
44
45def _get_envoy_config(yaml, version="V2"):
46
47 aconf = Config()
48 fetcher = ResourceFetcher(logger, aconf)
49 fetcher.parse_yaml(default_listener_manifests() + yaml, k8s=True)
50
51 aconf.load_all(fetcher.sorted())
52
53 secret_handler = NullSecretHandler(logger, None, None, "0")
54
55 ir = IR(aconf, file_checker=lambda path: True, secret_handler=secret_handler)
56
57 assert ir
58 return EnvoyConfig.generate(ir, version)
59
60
61def lightstep_tracing_service_manifest():
62 return """
63---
64apiVersion: getambassador.io/v3alpha1
65kind: TracingService
66metadata:
67 name: tracing
68 namespace: ambassador
69spec:
70 service: lightstep:80
71 driver: lightstep
72 config:
73 access_token_file: /lightstep-credentials/access-token
74 propagation_modes: ["ENVOY", "TRACE_CONTEXT"]
75"""
76
77
78@pytest.mark.compilertest
79def test_tracing_config_v3():
80 aconf = Config()
81
82 yaml = module_and_mapping_manifests(None, []) + "\n" + lightstep_tracing_service_manifest()
83 fetcher = ResourceFetcher(logger, aconf)
84 fetcher.parse_yaml(yaml, k8s=True)
85
86 aconf.load_all(fetcher.sorted())
87
88 secret_handler = MockSecretHandler(logger, "mockery", "/tmp/ambassador/snapshots", "v1")
89 ir = IR(aconf, file_checker=lambda path: True, secret_handler=secret_handler)
90
91 assert ir
92
93 econf = EnvoyConfig.generate(ir, "V3")
94
95 bootstrap_config, ads_config, _ = econf.split_config()
96 assert "tracing" in bootstrap_config
97 assert bootstrap_config["tracing"] == {
98 "http": {
99 "name": "envoy.lightstep",
100 "typed_config": {
101 "@type": "type.googleapis.com/envoy.config.trace.v3.LightstepConfig",
102 "access_token_file": "/lightstep-credentials/access-token",
103 "collector_cluster": "cluster_tracing_lightstep_80_ambassador",
104 "propagation_modes": ["ENVOY", "TRACE_CONTEXT"],
105 },
106 }
107 }
108
109 ads_config.pop("@type", None)
110 assert_valid_envoy_config(ads_config)
111 assert_valid_envoy_config(bootstrap_config)
112
113
114@pytest.mark.compilertest
115def test_tracing_config_v2():
116 aconf = Config()
117
118 yaml = module_and_mapping_manifests(None, []) + "\n" + lightstep_tracing_service_manifest()
119 fetcher = ResourceFetcher(logger, aconf)
120 fetcher.parse_yaml(yaml, k8s=True)
121
122 aconf.load_all(fetcher.sorted())
123
124 secret_handler = MockSecretHandler(logger, "mockery", "/tmp/ambassador/snapshots", "v1")
125 ir = IR(aconf, file_checker=lambda path: True, secret_handler=secret_handler)
126
127 assert ir
128
129 econf = EnvoyConfig.generate(ir, "V2")
130
131 bootstrap_config, ads_config, _ = econf.split_config()
132 assert "tracing" in bootstrap_config
133 assert bootstrap_config["tracing"] == {
134 "http": {
135 "name": "envoy.lightstep",
136 "typed_config": {
137 "@type": "type.googleapis.com/envoy.config.trace.v2.LightstepConfig",
138 "access_token_file": "/lightstep-credentials/access-token",
139 "collector_cluster": "cluster_tracing_lightstep_80_ambassador",
140 "propagation_modes": ["ENVOY", "TRACE_CONTEXT"],
141 },
142 }
143 }
144
145 ads_config.pop("@type", None)
146 assert_valid_envoy_config(ads_config, v2=True)
147 assert_valid_envoy_config(bootstrap_config, v2=True)
148
149
150@pytest.mark.compilertest
151def test_tracing_zipkin_defaults_v3_config():
152
153 yaml = """
154---
155apiVersion: getambassador.io/v3alpha1
156kind: TracingService
157metadata:
158 name: myts
159 namespace: default
160spec:
161 service: zipkin-test:9411
162 driver: zipkin
163"""
164
165 econf = _get_envoy_config(yaml, version="V3")
166
167 bootstrap_config, _, _ = econf.split_config()
168 assert "tracing" in bootstrap_config
169
170 assert bootstrap_config["tracing"] == {
171 "http": {
172 "name": "envoy.zipkin",
173 "typed_config": {
174 "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
175 "collector_endpoint": "/api/v2/spans",
176 "collector_endpoint_version": "HTTP_JSON",
177 "trace_id_128bit": True,
178 "collector_cluster": "cluster_tracing_zipkin_test_9411_default",
179 },
180 }
181 }
182
183
184def test_tracing_zipkin_defaults_v2_config():
185
186 yaml = """
187---
188apiVersion: getambassador.io/v3alpha1
189kind: TracingService
190metadata:
191 name: myts
192 namespace: default
193spec:
194 service: zipkin-test:9411
195 driver: zipkin
196"""
197
198 econf = _get_envoy_config(yaml, version="V2")
199
200 bootstrap_config, _, _ = econf.split_config()
201 assert "tracing" in bootstrap_config
202
203 assert bootstrap_config["tracing"] == {
204 "http": {
205 "name": "envoy.zipkin",
206 "typed_config": {
207 "@type": "type.googleapis.com/envoy.config.trace.v2.ZipkinConfig",
208 "collector_endpoint": "/api/v2/spans",
209 "collector_endpoint_version": "HTTP_JSON",
210 "trace_id_128bit": True,
211 "collector_cluster": "cluster_tracing_zipkin_test_9411_default",
212 },
213 }
214 }
215
216
217@pytest.mark.compilertest
218def test_tracing_cluster_fields_v2_config():
219
220 yaml = """
221---
222apiVersion: getambassador.io/v3alpha1
223kind: TracingService
224metadata:
225 name: myts
226 namespace: default
227spec:
228 service: zipkin-test:9411
229 driver: zipkin
230 stats_name: tracingservice
231"""
232
233 econf = _get_envoy_config(yaml, version="V2")
234
235 bootstrap_config, _, _ = econf.split_config()
236 assert "tracing" in bootstrap_config
237
238 cluster_name = "cluster_tracing_zipkin_test_9411_default"
239 assert bootstrap_config["tracing"] == {
240 "http": {
241 "name": "envoy.zipkin",
242 "typed_config": {
243 "@type": "type.googleapis.com/envoy.config.trace.v2.ZipkinConfig",
244 "collector_endpoint": "/api/v2/spans",
245 "collector_endpoint_version": "HTTP_JSON",
246 "trace_id_128bit": True,
247 "collector_cluster": cluster_name,
248 },
249 }
250 }
251
252 def check_fields(cluster):
253 assert cluster["alt_stat_name"] == "tracingservice"
254
255 econf_foreach_cluster(econf.as_dict(), check_fields, name=cluster_name)
256
257
258@pytest.mark.compilertest
259def test_tracing_cluster_fields_v3_config():
260
261 yaml = """
262---
263apiVersion: getambassador.io/v3alpha1
264kind: TracingService
265metadata:
266 name: myts
267 namespace: default
268spec:
269 service: zipkin-test:9411
270 driver: zipkin
271 stats_name: tracingservice
272"""
273
274 econf = _get_envoy_config(yaml, version="V3")
275
276 bootstrap_config, _, _ = econf.split_config()
277 assert "tracing" in bootstrap_config
278
279 cluster_name = "cluster_tracing_zipkin_test_9411_default"
280 assert bootstrap_config["tracing"] == {
281 "http": {
282 "name": "envoy.zipkin",
283 "typed_config": {
284 "@type": "type.googleapis.com/envoy.config.trace.v3.ZipkinConfig",
285 "collector_endpoint": "/api/v2/spans",
286 "collector_endpoint_version": "HTTP_JSON",
287 "trace_id_128bit": True,
288 "collector_cluster": cluster_name,
289 },
290 }
291 }
292
293 def check_fields(cluster):
294 assert cluster["alt_stat_name"] == "tracingservice"
295
296 econf_foreach_cluster(econf.as_dict(), check_fields, name=cluster_name)
View as plain text