From f54957d810cddffd63123b52776416748518eded Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 26 Aug 2022 11:10:47 -0600 Subject: [PATCH 01/18] .golangci.yml: Temporarily disable depguard Signed-off-by: Luke Shumaker (cherry picked from commit 95dd1ac45b5ddfd379e3733a02f016297c959e7a) --- .golangci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 021579fe96..a39b418282 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,7 +5,7 @@ linters: enable: - gofmt - govet - - depguard + #- depguard # there's a bug in depguard with (or just exacerbated by?) Go 1.19 that causes it to have false positives - unused - errcheck linters-settings: From 352ebcd9e9d28ff73d6db03336cb1473f5a88c67 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 8 Sep 2022 22:52:28 -0600 Subject: [PATCH 02/18] build-sys: Add a missing dependency on the kubectl binary I'm not sure why this doesn't trip up in CI, but harness.py needs to call out to tools/bin/kubectl for `is_ingress_class_compatible()` and `is_knative_compatible()`, which it calls when initializing the test objects for enumeration. Signed-off-by: Luke Shumaker --- builder/builder.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/builder.mk b/builder/builder.mk index 5179bd7b35..06c556dabf 100644 --- a/builder/builder.mk +++ b/builder/builder.mk @@ -320,7 +320,7 @@ pytest-kat-local: push-pytest-images pytest-kat-envoy3: push-pytest-images # doing this all at once is too much for CI... $(MAKE) pytest KAT_RUN_MODE=envoy PYTEST_ARGS="$$PYTEST_ARGS python/tests/kat" # ... so we have a separate rule to run things split up -build-aux/.pytest-kat.txt.stamp: $(OSS_HOME)/venv push-pytest-images FORCE +build-aux/.pytest-kat.txt.stamp: $(OSS_HOME)/venv push-pytest-images $(tools/kubectl) FORCE . venv/bin/activate && set -o pipefail && pytest --collect-only python/tests/kat 2>&1 | sed -En 's/.*/\1/p' | sed 's/[].].*//' | sort -u > $@ build-aux/pytest-kat.txt: build-aux/%: build-aux/.%.stamp $(tools/copy-ifchanged) $(tools/copy-ifchanged) $< $@ From cc3e2c30d1bff1755e70f30270c36b0ecf4ab65a Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 27 Jun 2022 13:15:30 -0600 Subject: [PATCH 03/18] python/tests/unit: Consolidate testdata files That's just too many differently-named directories for me to exclude from `git grep`. Also, fixup how test_envoy_stats.py determines the test directory. Signed-off-by: Luke Shumaker --- python/tests/unit/test_acme_privatekey_secrets.py | 4 ++-- python/tests/unit/test_cache.py | 2 +- python/tests/unit/test_envoy_stats.py | 7 ++----- .../unit/{test_cache_data => testdata}/cache_delta_1.yaml | 0 .../unit/{test_cache_data => testdata}/cache_delta_2.yaml | 0 .../unit/{test_cache_data => testdata}/cache_delta_3.yaml | 0 .../unit/{test_cache_data => testdata}/cache_random_1.yaml | 0 .../unit/{test_cache_data => testdata}/cache_random_2.yaml | 0 .../unit/{test_cache_data => testdata}/cache_random_3.yaml | 0 .../unit/{test_cache_data => testdata}/cache_random_4.yaml | 0 .../unit/{test_cache_data => testdata}/cache_random_5.yaml | 0 .../unit/{test_cache_data => testdata}/cache_result_1.yaml | 0 .../unit/{test_cache_data => testdata}/cache_result_2.yaml | 0 .../unit/{test_cache_data => testdata}/cache_result_3.yaml | 0 .../unit/{test_cache_data => testdata}/cache_result_4.yaml | 0 .../unit/{test_cache_data => testdata}/cache_test_1.yaml | 0 .../unit/{test_cache_data => testdata}/cache_test_2.yaml | 0 .../unit/{test_cache_data => testdata}/cache_test_3.yaml | 0 .../unit/{test_cache_data => testdata}/cache_test_4.yaml | 0 .../unit/{test_cache_data => testdata}/cache_test_5.yaml | 0 .../unit/{test_envoy_stats_data => testdata}/logging-1.txt | 0 .../unit/{test_envoy_stats_data => testdata}/logging-2.txt | 0 .../unit/{test_envoy_stats_data => testdata}/stats-1.txt | 0 .../unit/{test_envoy_stats_data => testdata}/stats-2.txt | 0 .../test-acme-private-key-snapshot-bad.json | 0 .../test-acme-private-key-snapshot.json | 0 26 files changed, 5 insertions(+), 8 deletions(-) rename python/tests/unit/{test_cache_data => testdata}/cache_delta_1.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_delta_2.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_delta_3.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_random_1.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_random_2.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_random_3.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_random_4.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_random_5.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_result_1.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_result_2.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_result_3.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_result_4.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_test_1.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_test_2.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_test_3.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_test_4.yaml (100%) rename python/tests/unit/{test_cache_data => testdata}/cache_test_5.yaml (100%) rename python/tests/unit/{test_envoy_stats_data => testdata}/logging-1.txt (100%) rename python/tests/unit/{test_envoy_stats_data => testdata}/logging-2.txt (100%) rename python/tests/unit/{test_envoy_stats_data => testdata}/stats-1.txt (100%) rename python/tests/unit/{test_envoy_stats_data => testdata}/stats-2.txt (100%) rename python/tests/unit/{test_general_data => testdata}/test-acme-private-key-snapshot-bad.json (100%) rename python/tests/unit/{test_general_data => testdata}/test-acme-private-key-snapshot.json (100%) diff --git a/python/tests/unit/test_acme_privatekey_secrets.py b/python/tests/unit/test_acme_privatekey_secrets.py index c3cee13ca2..d4ea315daf 100644 --- a/python/tests/unit/test_acme_privatekey_secrets.py +++ b/python/tests/unit/test_acme_privatekey_secrets.py @@ -121,7 +121,7 @@ def test_acme_privatekey_secrets(caplog: pytest.LogCaptureFixture): "test_acme_privatekey_secrets-bad", os.path.join( os.path.dirname(os.path.abspath(__file__)), - "test_general_data", + "testdata", "test-acme-private-key-snapshot-bad.json", ), ) @@ -135,7 +135,7 @@ def test_acme_privatekey_secrets(caplog: pytest.LogCaptureFixture): "test_acme_privatekey_secrets", os.path.join( os.path.dirname(os.path.abspath(__file__)), - "test_general_data", + "testdata", "test-acme-private-key-snapshot.json", ), ) diff --git a/python/tests/unit/test_cache.py b/python/tests/unit/test_cache.py index 5176765da0..6966e948f2 100644 --- a/python/tests/unit/test_cache.py +++ b/python/tests/unit/test_cache.py @@ -32,7 +32,7 @@ def __init__( ) -> None: self.logger = logger - self.test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_cache_data") + self.test_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testdata") self.cache: Optional[Cache] = None diff --git a/python/tests/unit/test_envoy_stats.py b/python/tests/unit/test_envoy_stats.py index bae737768f..3237f8d2f4 100644 --- a/python/tests/unit/test_envoy_stats.py +++ b/python/tests/unit/test_envoy_stats.py @@ -20,12 +20,9 @@ class EnvoyStatsMocker: def __init__(self) -> None: - current_test = os.environ.get("PYTEST_CURRENT_TEST") - - assert current_test is not None, "PYTEST_CURRENT_TEST is not set??" - self.test_dir = os.path.join( - os.path.dirname(current_test.split("::")[0]), "test_envoy_stats_data" + os.path.dirname(os.path.abspath(__file__)), + "testdata", ) self.log_idx = 0 diff --git a/python/tests/unit/test_cache_data/cache_delta_1.yaml b/python/tests/unit/testdata/cache_delta_1.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_delta_1.yaml rename to python/tests/unit/testdata/cache_delta_1.yaml diff --git a/python/tests/unit/test_cache_data/cache_delta_2.yaml b/python/tests/unit/testdata/cache_delta_2.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_delta_2.yaml rename to python/tests/unit/testdata/cache_delta_2.yaml diff --git a/python/tests/unit/test_cache_data/cache_delta_3.yaml b/python/tests/unit/testdata/cache_delta_3.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_delta_3.yaml rename to python/tests/unit/testdata/cache_delta_3.yaml diff --git a/python/tests/unit/test_cache_data/cache_random_1.yaml b/python/tests/unit/testdata/cache_random_1.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_random_1.yaml rename to python/tests/unit/testdata/cache_random_1.yaml diff --git a/python/tests/unit/test_cache_data/cache_random_2.yaml b/python/tests/unit/testdata/cache_random_2.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_random_2.yaml rename to python/tests/unit/testdata/cache_random_2.yaml diff --git a/python/tests/unit/test_cache_data/cache_random_3.yaml b/python/tests/unit/testdata/cache_random_3.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_random_3.yaml rename to python/tests/unit/testdata/cache_random_3.yaml diff --git a/python/tests/unit/test_cache_data/cache_random_4.yaml b/python/tests/unit/testdata/cache_random_4.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_random_4.yaml rename to python/tests/unit/testdata/cache_random_4.yaml diff --git a/python/tests/unit/test_cache_data/cache_random_5.yaml b/python/tests/unit/testdata/cache_random_5.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_random_5.yaml rename to python/tests/unit/testdata/cache_random_5.yaml diff --git a/python/tests/unit/test_cache_data/cache_result_1.yaml b/python/tests/unit/testdata/cache_result_1.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_result_1.yaml rename to python/tests/unit/testdata/cache_result_1.yaml diff --git a/python/tests/unit/test_cache_data/cache_result_2.yaml b/python/tests/unit/testdata/cache_result_2.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_result_2.yaml rename to python/tests/unit/testdata/cache_result_2.yaml diff --git a/python/tests/unit/test_cache_data/cache_result_3.yaml b/python/tests/unit/testdata/cache_result_3.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_result_3.yaml rename to python/tests/unit/testdata/cache_result_3.yaml diff --git a/python/tests/unit/test_cache_data/cache_result_4.yaml b/python/tests/unit/testdata/cache_result_4.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_result_4.yaml rename to python/tests/unit/testdata/cache_result_4.yaml diff --git a/python/tests/unit/test_cache_data/cache_test_1.yaml b/python/tests/unit/testdata/cache_test_1.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_test_1.yaml rename to python/tests/unit/testdata/cache_test_1.yaml diff --git a/python/tests/unit/test_cache_data/cache_test_2.yaml b/python/tests/unit/testdata/cache_test_2.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_test_2.yaml rename to python/tests/unit/testdata/cache_test_2.yaml diff --git a/python/tests/unit/test_cache_data/cache_test_3.yaml b/python/tests/unit/testdata/cache_test_3.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_test_3.yaml rename to python/tests/unit/testdata/cache_test_3.yaml diff --git a/python/tests/unit/test_cache_data/cache_test_4.yaml b/python/tests/unit/testdata/cache_test_4.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_test_4.yaml rename to python/tests/unit/testdata/cache_test_4.yaml diff --git a/python/tests/unit/test_cache_data/cache_test_5.yaml b/python/tests/unit/testdata/cache_test_5.yaml similarity index 100% rename from python/tests/unit/test_cache_data/cache_test_5.yaml rename to python/tests/unit/testdata/cache_test_5.yaml diff --git a/python/tests/unit/test_envoy_stats_data/logging-1.txt b/python/tests/unit/testdata/logging-1.txt similarity index 100% rename from python/tests/unit/test_envoy_stats_data/logging-1.txt rename to python/tests/unit/testdata/logging-1.txt diff --git a/python/tests/unit/test_envoy_stats_data/logging-2.txt b/python/tests/unit/testdata/logging-2.txt similarity index 100% rename from python/tests/unit/test_envoy_stats_data/logging-2.txt rename to python/tests/unit/testdata/logging-2.txt diff --git a/python/tests/unit/test_envoy_stats_data/stats-1.txt b/python/tests/unit/testdata/stats-1.txt similarity index 100% rename from python/tests/unit/test_envoy_stats_data/stats-1.txt rename to python/tests/unit/testdata/stats-1.txt diff --git a/python/tests/unit/test_envoy_stats_data/stats-2.txt b/python/tests/unit/testdata/stats-2.txt similarity index 100% rename from python/tests/unit/test_envoy_stats_data/stats-2.txt rename to python/tests/unit/testdata/stats-2.txt diff --git a/python/tests/unit/test_general_data/test-acme-private-key-snapshot-bad.json b/python/tests/unit/testdata/test-acme-private-key-snapshot-bad.json similarity index 100% rename from python/tests/unit/test_general_data/test-acme-private-key-snapshot-bad.json rename to python/tests/unit/testdata/test-acme-private-key-snapshot-bad.json diff --git a/python/tests/unit/test_general_data/test-acme-private-key-snapshot.json b/python/tests/unit/testdata/test-acme-private-key-snapshot.json similarity index 100% rename from python/tests/unit/test_general_data/test-acme-private-key-snapshot.json rename to python/tests/unit/testdata/test-acme-private-key-snapshot.json From 67279ecd94c32bac8b480f80b760af1bed0d3997 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 9 Sep 2022 12:31:55 -0600 Subject: [PATCH 04/18] pytest-kat: Fix splitting the tests among jobs When splitting KAT tests among multiple jobs, we need a listing of all of the KAT tests; we'll assign each entry in this list to a different job. The problem with that right now is that the expressions in that listing are sometimes ambiguous. For example, "AuthenticationTest" shows up as `kat[AuthenticationTest`. Notice that it doesn't include a trailing `]`; this causes it to also match the "AuthenticationTestV1". If both of those tests were going to be scheduled on the same job, that's fine; but if they were going to be scheduled on different jobs, then that "AuthenticationTestV1" test will run in *both* jobs, potentially overloading the one where it wasn't supposed to run. This is probably less of a problem for that one test, and a bigger problem for common prefixes like "TLS". Here is a listing of all such ambiguities: $ grep -f <( --- builder/builder.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/builder.mk b/builder/builder.mk index 06c556dabf..cc0d9f45e1 100644 --- a/builder/builder.mk +++ b/builder/builder.mk @@ -321,7 +321,7 @@ pytest-kat-envoy3: push-pytest-images # doing this all at once is too much for C $(MAKE) pytest KAT_RUN_MODE=envoy PYTEST_ARGS="$$PYTEST_ARGS python/tests/kat" # ... so we have a separate rule to run things split up build-aux/.pytest-kat.txt.stamp: $(OSS_HOME)/venv push-pytest-images $(tools/kubectl) FORCE - . venv/bin/activate && set -o pipefail && pytest --collect-only python/tests/kat 2>&1 | sed -En 's/.*/\1/p' | sed 's/[].].*//' | sort -u > $@ + . venv/bin/activate && set -o pipefail && pytest --collect-only python/tests/kat 2>&1 | sed -En 's/.*/\1/p' | cut -d. -f1 | sort -u > $@ build-aux/pytest-kat.txt: build-aux/%: build-aux/.%.stamp $(tools/copy-ifchanged) $(tools/copy-ifchanged) $< $@ clean: build-aux/.pytest-kat.txt.stamp.rm build-aux/pytest-kat.txt.rm From d4ffcbd231fd14f6ae828442e2648daba7a564fc Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 11 Sep 2022 13:45:01 -0600 Subject: [PATCH 05/18] KAT: Do a better job of showing YAML errors Signed-off-by: Luke Shumaker --- python/kat/harness.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/kat/harness.py b/python/kat/harness.py index b0d8c6f917..99dc2ce9cc 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -18,6 +18,7 @@ import pytest import yaml as pyyaml from packaging import version +from yaml.parser import ParserError as YAMLParseError from yaml.scanner import ScannerError as YAMLScanError import tests.integration.manifests as integration_manifests @@ -1429,7 +1430,7 @@ def _setup_k8s(self, selected): try: for o in load(n.path, cfg, Tag.MAPPING): parent_config.merge(o) - except YAMLScanError as e: + except (YAMLScanError, YAMLParseError) as e: raise Exception("Parse Error: %s, input text:\n%s" % (e, cfg)) else: target = cfg[0] @@ -1443,7 +1444,7 @@ def _setup_k8s(self, selected): obj["ambassador_id"] = [n.ambassador_id] configs[n].append((target, yaml_view)) - except YAMLScanError as e: + except (YAMLScanError, YAMLParseError) as e: raise Exception("Parse Error: %s, input text:\n%s" % (e, cfg[1])) for tgt_cfgs in configs.values(): From 4b590b638b6a289eeda05a8600f7de7a25bb4e1a Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 11 Sep 2022 13:01:39 -0600 Subject: [PATCH 06/18] KAT: t_tracing.py: Have the Zipkin backend be a KAT node This shouldn't be changing reliability at all, but is helping with DRY for a change I'm about to make. Signed-off-by: Luke Shumaker --- python/tests/kat/t_tracing.py | 398 ++++++---------------------------- 1 file changed, 70 insertions(+), 328 deletions(-) diff --git a/python/tests/kat/t_tracing.py b/python/tests/kat/t_tracing.py index 1c2745b2d8..fe2a76db82 100644 --- a/python/tests/kat/t_tracing.py +++ b/python/tests/kat/t_tracing.py @@ -1,7 +1,7 @@ import json -from typing import Generator, Tuple, Union +from typing import ClassVar, Generator, Tuple, Union -from abstract_tests import AHTTP, HTTP, AmbassadorTest, Node +from abstract_tests import AHTTP, HTTP, AmbassadorTest, Node, ServiceType from ambassador import Config from kat.harness import EDGE_STACK, Query @@ -14,21 +14,21 @@ check_phase = 3 -class TracingTest(AmbassadorTest): - def init(self): - self.target = HTTP() +class Zipkin(ServiceType): + skip_variant: ClassVar[bool] = True - def manifests(self) -> str: - return ( - """ + def __init__(self, *args, **kwargs) -> None: + kwargs[ + "service_manifests" + ] = """ --- apiVersion: v1 kind: Service metadata: - name: zipkin + name: {self.path.k8s} spec: selector: - app: zipkin + backend: {self.path.k8s} ports: - port: 9411 name: http @@ -38,18 +38,18 @@ def manifests(self) -> str: apiVersion: apps/v1 kind: Deployment metadata: - name: zipkin + name: {self.path.k8s} spec: selector: matchLabels: - app: zipkin + backend: {self.path.k8s} replicas: 1 strategy: type: RollingUpdate template: metadata: labels: - app: zipkin + backend: {self.path.k8s} spec: containers: - name: zipkin @@ -58,8 +58,16 @@ def manifests(self) -> str: - name: http containerPort: 9411 """ - + super().manifests() - ) + super().__init__(*args, **kwargs) + + def requirements(self): + yield ("url", Query(f"http://{self.path.fqdn}:9411/api/v2/services")) + + +class TracingTest(AmbassadorTest): + def init(self): + self.target = HTTP() + self.zipkin = Zipkin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: # Use self.target here, because we want this mapping to be annotated @@ -84,17 +92,13 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing -service: zipkin:9411 +service: {self.zipkin.path.fqdn}:9411 driver: zipkin tag_headers: - "x-watsup" """ ) - def requirements(self): - yield from super().requirements() - yield ("url", Query("http://zipkin:9411/api/v2/services")) - def queries(self): # Speak through each Ambassador to the traced service... @@ -103,12 +107,14 @@ def queries(self): # ...then ask the Zipkin for services and spans. Including debug=True in these queries # is particularly helpful. - yield Query("http://zipkin:9411/api/v2/services", phase=check_phase) + yield Query(f"http://{self.zipkin.path.fqdn}:9411/api/v2/services", phase=check_phase) yield Query( - "http://zipkin:9411/api/v2/spans?serviceName=tracingtest-default", phase=check_phase + f"http://{self.zipkin.path.fqdn}:9411/api/v2/spans?serviceName=tracingtest-default", + phase=check_phase, ) yield Query( - "http://zipkin:9411/api/v2/traces?serviceName=tracingtest-default", phase=check_phase + f"http://{self.zipkin.path.fqdn}:9411/api/v2/traces?serviceName=tracingtest-default", + phase=check_phase, ) # The diagnostics page should load properly @@ -152,49 +158,11 @@ def check(self): class TracingTestLongClusterName(AmbassadorTest): def init(self): self.target = HTTP() - - def manifests(self) -> str: - return ( - """ ---- -apiVersion: v1 -kind: Service -metadata: - name: zipkinservicenamewithoversixtycharacterstoforcenamecompression -spec: - selector: - app: zipkin-longclustername - ports: - - port: 9411 - name: http - targetPort: http - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: zipkin-longclustername -spec: - selector: - matchLabels: - app: zipkin-longclustername - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: zipkin-longclustername - spec: - containers: - - name: zipkin - image: openzipkin/zipkin:2.17 - ports: - - name: http - containerPort: 9411 -""" - + super().manifests() - ) + # The full name ends up being `{testname}-{zipkin}-{name}`; so the name we pass in doesn't + # need to be as long as you'd think. Down in check() we'll do some asserts on + # self.zipkin.path.fqdn to make sure we got the desired length correct (we can't do those + # checks here because .path isn't populated yet during init()). + self.zipkin = Zipkin(name="longnamethatforcescompression") def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: # Use self.target here, because we want this mapping to be annotated @@ -219,20 +187,11 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing-longclustername -service: zipkinservicenamewithoversixtycharacterstoforcenamecompression:9411 +service: {self.zipkin.path.fqdn}:9411 driver: zipkin """ ) - def requirements(self): - yield from super().requirements() - yield ( - "url", - Query( - "http://zipkinservicenamewithoversixtycharacterstoforcenamecompression:9411/api/v2/services" - ), - ) - def queries(self): # Speak through each Ambassador to the traced service... @@ -242,15 +201,15 @@ def queries(self): # ...then ask the Zipkin for services and spans. Including debug=True in these queries # is particularly helpful. yield Query( - "http://zipkinservicenamewithoversixtycharacterstoforcenamecompression:9411/api/v2/services", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/services", phase=check_phase, ) yield Query( - "http://zipkinservicenamewithoversixtycharacterstoforcenamecompression:9411/api/v2/spans?serviceName=tracingtestlongclustername-default", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/spans?serviceName=tracingtestlongclustername-default", phase=check_phase, ) yield Query( - "http://zipkinservicenamewithoversixtycharacterstoforcenamecompression:9411/api/v2/traces?serviceName=tracingtestlongclustername-default", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/traces?serviceName=tracingtestlongclustername-default", phase=check_phase, ) @@ -259,6 +218,9 @@ def queries(self): yield Query(self.url("ambassador/v0/diag/"), phase=check_phase) def check(self): + assert len(self.zipkin.path.fqdn.split(".")[0]) > 60 + assert len(self.zipkin.path.fqdn.split(".")[0]) < 64 + for i in range(100): result = self.results[i] assert result.backend @@ -292,49 +254,7 @@ def check(self): class TracingTestShortTraceId(AmbassadorTest): def init(self): self.target = HTTP() - - def manifests(self) -> str: - return ( - """ ---- -apiVersion: v1 -kind: Service -metadata: - name: zipkin-64 -spec: - selector: - app: zipkin-64 - ports: - - port: 9411 - name: http - targetPort: http - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: zipkin-64 -spec: - selector: - matchLabels: - app: zipkin-64 - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: zipkin-64 - spec: - containers: - - name: zipkin - image: openzipkin/zipkin:2.17 - ports: - - name: http - containerPort: 9411 -""" - + super().manifests() - ) + self.zipkin = Zipkin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: # Use self.target here, because we want this mapping to be annotated @@ -353,20 +273,18 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: ) # Configure the TracingService. - yield self, """ + yield self, self.format( + """ --- apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing-64 -service: zipkin-64:9411 +service: {self.zipkin.path.fqdn}:9411 driver: zipkin config: trace_id_128bit: false """ - - def requirements(self): - yield from super().requirements() - yield ("url", Query("http://zipkin-64:9411/api/v2/services")) + ) def queries(self): # Speak through each Ambassador to the traced service... @@ -374,7 +292,7 @@ def queries(self): # ...then ask the Zipkin for services and spans. Including debug=True in these queries # is particularly helpful. - yield Query("http://zipkin-64:9411/api/v2/traces", phase=check_phase) + yield Query(f"http://{self.zipkin.path.fqdn}:9411/api/v2/traces", phase=check_phase) # The diagnostics page should load properly yield Query(self.url("ambassador/v0/diag/"), phase=check_phase) @@ -394,49 +312,7 @@ def init(self): self.xfail = "XFailing for now, custom AuthServices not supported in Edge Stack" self.target = HTTP() self.auth = AHTTP(name="auth") - - def manifests(self) -> str: - return ( - """ ---- -apiVersion: v1 -kind: Service -metadata: - name: zipkin-auth -spec: - selector: - app: zipkin-auth - ports: - - port: 9411 - name: http - targetPort: http - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: zipkin-auth -spec: - selector: - matchLabels: - app: zipkin-auth - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: zipkin-auth - spec: - containers: - - name: zipkin-auth - image: openzipkin/zipkin:2.17 - ports: - - name: http - containerPort: 9411 -""" - + super().manifests() - ) + self.zipkin = Zipkin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self.target, self.format( @@ -457,7 +333,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing-auth -service: zipkin-auth:9411 +service: {self.zipkin.path.k8s}:9411 driver: zipkin """ ) @@ -476,10 +352,6 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: """ ) - def requirements(self): - yield from super().requirements() - yield ("url", Query("http://zipkin-auth:9411/api/v2/services")) - def queries(self): yield Query( self.url("target/"), headers={"Kat-Req-Extuath-Requested-Status": "200"}, expected=200 @@ -510,49 +382,7 @@ class TracingTestSampling(AmbassadorTest): def init(self): self.target = HTTP() - - def manifests(self) -> str: - return ( - """ ---- -apiVersion: v1 -kind: Service -metadata: - name: zipkin-65 -spec: - selector: - app: zipkin-65 - ports: - - port: 9411 - name: http - targetPort: http - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: zipkin-65 -spec: - selector: - matchLabels: - app: zipkin-65 - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: zipkin-65 - spec: - containers: - - name: zipkin - image: openzipkin/zipkin:2.17 - ports: - - name: http - containerPort: 9411 -""" - + super().manifests() - ) + self.zipkin = Zipkin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: # Use self.target here, because we want this mapping to be annotated @@ -571,20 +401,18 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: ) # Configure the TracingService. - yield self, """ + yield self, self.format( + """ --- apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing-65 -service: zipkin-65:9411 +service: {self.zipkin.path.fqdn}:9411 driver: zipkin sampling: overall: 10 """ - - def requirements(self): - yield from super().requirements() - yield ("url", Query("http://zipkin-65:9411/api/v2/services")) + ) def queries(self): # Speak through each Ambassador to the traced service... @@ -593,7 +421,9 @@ def queries(self): # ...then ask the Zipkin for services and spans. Including debug=True in these queries # is particularly helpful. - yield Query("http://zipkin-65:9411/api/v2/traces?limit=10000", phase=check_phase) + yield Query( + f"http://{self.zipkin.path.fqdn}:9411/api/v2/traces?limit=10000", phase=check_phase + ) # The diagnostics page should load properly yield Query(self.url("ambassador/v0/diag/"), phase=check_phase) @@ -619,49 +449,7 @@ class TracingTestZipkinV2(AmbassadorTest): def init(self): self.target = HTTP() - - def manifests(self) -> str: - return ( - """ ---- -apiVersion: v1 -kind: Service -metadata: - name: zipkin-v2 -spec: - selector: - app: zipkin-v2 - ports: - - port: 9411 - name: http - targetPort: http - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: zipkin-v2 -spec: - selector: - matchLabels: - app: zipkin-v2 - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: zipkin-v2 - spec: - containers: - - name: zipkin - image: openzipkin/zipkin:2.17 - ports: - - name: http - containerPort: 9411 -""" - + super().manifests() - ) + self.zipkin = Zipkin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: # Use self.target here, because we want this mapping to be annotated @@ -685,18 +473,18 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing -service: zipkin-v2:9411 +service: {self.zipkin.path.fqdn}:9411 driver: zipkin config: collector_endpoint: /api/v2/spans collector_endpoint_version: HTTP_JSON - collector_hostname: zipkin-v2 + collector_hostname: {self.zipkin.path.fqdn} """ ) def requirements(self): yield from super().requirements() - yield ("url", Query("http://zipkin-v2:9411/api/v2/services")) + yield ("url", Query(f"http://{self.zipkin.path.fqdn}:9411/api/v2/services")) def queries(self): # Speak through each Ambassador to the traced service... @@ -706,13 +494,13 @@ def queries(self): # ...then ask the Zipkin for services and spans. Including debug=True in these queries # is particularly helpful. - yield Query("http://zipkin-v2:9411/api/v2/services", phase=check_phase) + yield Query(f"http://{self.zipkin.path.fqdn}:9411/api/v2/services", phase=check_phase) yield Query( - "http://zipkin-v2:9411/api/v2/spans?serviceName=tracingtestzipkinv2-default", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/spans?serviceName=tracingtestzipkinv2-default", phase=check_phase, ) yield Query( - "http://zipkin-v2:9411/api/v2/traces?serviceName=tracingtestzipkinv2-default", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/traces?serviceName=tracingtestzipkinv2-default", phase=check_phase, ) @@ -757,49 +545,7 @@ class TracingTestZipkinV1(AmbassadorTest): def init(self): self.target = HTTP() - - def manifests(self) -> str: - return ( - """ ---- -apiVersion: v1 -kind: Service -metadata: - name: zipkin-v1 -spec: - selector: - app: zipkin-v1 - ports: - - port: 9411 - name: http - targetPort: http - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: zipkin-v1 -spec: - selector: - matchLabels: - app: zipkin-v1 - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - app: zipkin-v1 - spec: - containers: - - name: zipkin - image: openzipkin/zipkin:2.17 - ports: - - name: http - containerPort: 9411 -""" - + super().manifests() - ) + self.zipkin = Zipkin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: # Use self.target here, because we want this mapping to be annotated @@ -824,19 +570,15 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: apiVersion: getambassador.io/v3alpha1 kind: TracingService name: tracing -service: zipkin-v1:9411 +service: {self.zipkin.path.fqdn}:9411 driver: zipkin config: collector_endpoint: /api/v1/spans collector_endpoint_version: HTTP_JSON_V1 - collector_hostname: zipkin-v1 + collector_hostname: {self.zipkin.path.fqdn} """ ) - def requirements(self): - yield from super().requirements() - yield ("url", Query("http://zipkin-v1:9411/api/v2/services")) - def queries(self): # Speak through each Ambassador to the traced service... @@ -844,15 +586,15 @@ def queries(self): yield Query(self.url("target/"), phase=1) # result 100 - yield Query("http://zipkin-v1:9411/api/v2/services", phase=check_phase) + yield Query(f"http://{self.zipkin.path.fqdn}:9411/api/v2/services", phase=check_phase) # result 101 yield Query( - "http://zipkin-v1:9411/api/v2/spans?serviceName=tracingtestzipkinv1-default", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/spans?serviceName=tracingtestzipkinv1-default", phase=check_phase, ) # result 102 yield Query( - "http://zipkin-v1:9411/api/v2/traces?serviceName=tracingtestzipkinv1-default", + f"http://{self.zipkin.path.fqdn}:9411/api/v2/traces?serviceName=tracingtestzipkinv1-default", phase=check_phase, ) From eb8843cc320d09ecba3863d8acfe49307f49ec77 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 11 Sep 2022 14:08:32 -0600 Subject: [PATCH 07/18] KAT: t_tracing.py: Reset Zipkin between runs Signed-off-by: Luke Shumaker --- python/tests/kat/t_tracing.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/python/tests/kat/t_tracing.py b/python/tests/kat/t_tracing.py index fe2a76db82..0044e1e596 100644 --- a/python/tests/kat/t_tracing.py +++ b/python/tests/kat/t_tracing.py @@ -1,4 +1,5 @@ import json +from random import random from typing import ClassVar, Generator, Tuple, Union from abstract_tests import AHTTP, HTTP, AmbassadorTest, Node, ServiceType @@ -18,6 +19,10 @@ class Zipkin(ServiceType): skip_variant: ClassVar[bool] = True def __init__(self, *args, **kwargs) -> None: + # We want to reset Zipkin between test runs. StatsD has a handy "reset" call that can do + # this... but the only way to reset Zipkin is to roll over the Pod. So, 'nonce' is a + # horrible hack to get the Pod to roll over each invocation. + self.nonce = random() kwargs[ "service_manifests" ] = """ @@ -45,7 +50,7 @@ def __init__(self, *args, **kwargs) -> None: backend: {self.path.k8s} replicas: 1 strategy: - type: RollingUpdate + type: Recreate # rolling would be bad with the nonce hack template: metadata: labels: @@ -57,6 +62,9 @@ def __init__(self, *args, **kwargs) -> None: ports: - name: http containerPort: 9411 + env: + - name: _nonce + value: '{self.nonce}' """ super().__init__(*args, **kwargs) From 5e9e13b03ae30e160878c9f87b0a205da5b3775c Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 11 Sep 2022 14:36:51 -0600 Subject: [PATCH 08/18] KAT: t_tracing.py: Improve debuggability Signed-off-by: Luke Shumaker --- python/tests/kat/t_tracing.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/tests/kat/t_tracing.py b/python/tests/kat/t_tracing.py index 0044e1e596..8dcb62e6c6 100644 --- a/python/tests/kat/t_tracing.py +++ b/python/tests/kat/t_tracing.py @@ -144,8 +144,8 @@ def check(self): assert self.results[101].backend assert self.results[101].backend.name == "raw" - tracelist = {x: True for x in self.results[101].backend.response} - + tracelist = set(x for x in self.results[101].backend.response) + print(f"tracelist = {tracelist}") assert "router cluster_tracingtest_http_default egress" in tracelist # Look for the host that we actually queried, since that's what appears in the spans. @@ -244,8 +244,8 @@ def check(self): assert self.results[101].backend assert self.results[101].backend.name == "raw" - tracelist = {x: True for x in self.results[101].backend.response} - + tracelist = set(x for x in self.results[101].backend.response) + print(f"tracelist = {tracelist}") assert "router cluster_tracingtestlongclustername_http_default egress" in tracelist # Look for the host that we actually queried, since that's what appears in the spans. @@ -531,8 +531,8 @@ def check(self): assert self.results[101].backend assert self.results[101].backend.name == "raw" - tracelist = {x: True for x in self.results[101].backend.response} - + tracelist = set(x for x in self.results[101].backend.response) + print(f"tracelist = {tracelist}") assert "router cluster_tracingtestzipkinv2_http_default egress" in tracelist # Look for the host that we actually queried, since that's what appears in the spans. From 38bb5916dbcf0e32b8c7d0473414af7581cdb255 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 9 Sep 2022 01:11:34 -0600 Subject: [PATCH 09/18] KAT: Node(): Have a helpful signature ... instead of opaque (*args, **args) Signed-off-by: Luke Shumaker --- python/kat/harness.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/python/kat/harness.py b/python/kat/harness.py index 99dc2ce9cc..8cff8eaaa8 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -342,22 +342,22 @@ class Node(ABC): children: List["Node"] name: Name ambassador_id: str - namespace: str = None # type: ignore + namespace: str is_ambassador = False local_result: Optional[Dict[str, str]] = None - def __init__(self, *args, **kwargs) -> None: + def __init__( + self, + *args, + name: Optional[str] = None, + namespace: Optional[str] = None, + _clone: Optional["Node"] = None, + **kwargs, + ) -> None: # If self.skip is set to true, this node is skipped self.skip_node = False self.xfail: Optional[str] = None - name = kwargs.pop("name", None) - - if "namespace" in kwargs: - self.namespace = kwargs.pop("namespace", None) - - _clone: Node = kwargs.pop("_clone", None) - if _clone: args = _clone._args # type: ignore kwargs = _clone._kwargs # type: ignore @@ -378,7 +378,11 @@ def __init__(self, *args, **kwargs) -> None: saved = _local.current self.parent = _local.current - if not self.namespace: + if namespace: + self.namespace = namespace + if not getattr(self, "namespace", ""): + # We do the above `getattr` instead of just an `else` because subclasses might set a + # default namespace; so `self.namespace` might already be set before calling __init__(). if self.parent and self.parent.namespace: # We have no namespace assigned, but our parent does have a namespace # defined. Copy the namespace down from our parent. From 1ed88c7bbe891c84e116a1c1113dfd67ed58d945 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 9 Sep 2022 01:38:25 -0600 Subject: [PATCH 10/18] KAT: Don't have Name be a subclass of str This type of magic is just confusing; both to humans and to mypy. Signed-off-by: Luke Shumaker --- python/kat/harness.py | 60 ++++++++++++++++------------- python/tests/kat/abstract_tests.py | 14 +------ python/tests/kat/t_hosts.py | 36 ++++++++--------- python/tests/kat/t_ingress.py | 36 ++++++++--------- python/tests/kat/t_ip_allow_deny.py | 4 +- python/tests/kat/t_tls.py | 8 ++-- 6 files changed, 76 insertions(+), 82 deletions(-) diff --git a/python/kat/harness.py b/python/kat/harness.py index 8cff8eaaa8..c90c910cad 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -13,7 +13,19 @@ from collections import OrderedDict from functools import singledispatch from hashlib import sha256 -from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union, cast +from typing import ( + Any, + Callable, + Dict, + List, + NamedTuple, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) import pytest import yaml as pyyaml @@ -291,20 +303,16 @@ def variants(cls, *args, **kwargs) -> Tuple[Any]: return tuple(a for n in get_nodes(cls) for a in n.variants(*args, **kwargs)) # type: ignore -class Name(str): +class Name(NamedTuple): + name: str namespace: Optional[str] - def __new__(cls, value, namespace: Optional[str] = None): - s = super().__new__(cls, value) - s.namespace = namespace - return s - @property - def k8s(self): - return self.replace(".", "-").lower() + def k8s(self) -> str: + return self.name.replace(".", "-").lower() @property - def fqdn(self): + def fqdn(self) -> str: r = self.k8s if self.namespace and (self.namespace != "default"): @@ -340,7 +348,7 @@ class Node(ABC): parent: Optional["Node"] children: List["Node"] - name: Name + name: str ambassador_id: str namespace: str is_ambassador = False @@ -362,7 +370,7 @@ def __init__( args = _clone._args # type: ignore kwargs = _clone._kwargs # type: ignore if name: - name = Name("-".join((_clone.name, name))) + name = "-".join((_clone.name, name)) else: name = _clone.name self._args = _clone._args # type: ignore @@ -371,9 +379,9 @@ def __init__( self._args = args self._kwargs = kwargs if name: - name = Name("-".join((self.__class__.__name__, name))) + name = "-".join((self.__class__.__name__, name)) else: - name = Name(self.__class__.__name__) + name = self.__class__.__name__ saved = _local.current self.parent = _local.current @@ -400,7 +408,9 @@ def __init__( finally: _local.current = saved - self.name = Name(self.format(name or self.__class__.__name__)) + # This has to come after the above to init(), because the format-string might reference + # things that get set by init(). + self.name = self.format(name) names = {} # type: ignore for c in self.children: @@ -568,14 +578,10 @@ def variants(cls): @property def path(self) -> Name: - return self.relpath(None) - - def relpath(self, ancestor): - if self.parent is ancestor: - return Name(self.name, namespace=self.namespace) + if self.parent is None: + return Name(self.name, self.namespace) else: - assert self.parent - return Name(self.parent.relpath(ancestor) + "." + self.name, namespace=self.namespace) + return Name(self.parent.path.name + "." + self.name, self.namespace) @property def traversal(self): @@ -609,7 +615,7 @@ def get_fqdn(self, name: str) -> str: @functools.lru_cache() def matches(self, pattern): - if fnmatch.fnmatch(self.path, "*%s*" % pattern): + if fnmatch.fnmatch(self.path.name, "*%s*" % pattern): return True for c in self.children: if c.matches(pattern): @@ -700,7 +706,7 @@ def handle_local_result(self) -> bool: @property def ambassador_id(self): if self.parent is None: - return self.name.k8s + return self.path.k8s else: return self.parent.ambassador_id @@ -785,7 +791,7 @@ def __init__( def as_json(self): assert self.parent result = { - "test": self.parent.path, + "test": self.parent.path.name, "id": id(self), "url": self.url, "insecure": self.insecure, @@ -1184,7 +1190,7 @@ def __init__(self, *classes, scope=None): self.roots = tuple(v for c in classes for v in variants(c)) self.nodes = [n for r in self.roots for n in r.traversal if not n.skip_node] self.tests = [n for n in self.nodes if isinstance(n, Test)] - self.ids = [t.path for t in self.tests] + self.ids = [t.path.name for t in self.tests] self.done = False self.skip_nonlocal_tests = False self.ids_to_strip: Dict[str, bool] = {} @@ -1474,7 +1480,7 @@ def _setup_k8s(self, selected): continue break else: - assert False, "no service found for target: %s" % target.path + assert False, "no service found for target: %s" % target.path.name yaml = "" diff --git a/python/tests/kat/abstract_tests.py b/python/tests/kat/abstract_tests.py index 63bf92b0b4..e3c59c5c7d 100644 --- a/python/tests/kat/abstract_tests.py +++ b/python/tests/kat/abstract_tests.py @@ -92,7 +92,7 @@ class AmbassadorTest(Test): _ambassador_id: Optional[str] = None single_namespace: bool = False disable_endpoints: bool = False - name: Name + name: str path: Name extra_ports: Optional[List[int]] = None debug_diagd: bool = True @@ -180,18 +180,6 @@ def manifests(self) -> str: capabilities_block="", ) - # # Will tear this out of the harness shortly - # @property - # def ambassador_id(self) -> str: - # if self._ambassador_id is None: - # return self.name.k8s - # else: - # return typecast(str, self._ambassador_id) - - # @ambassador_id.setter - # def ambassador_id(self, val: str) -> None: - # self._ambassador_id = val - @property def index(self) -> int: if self._index is None: diff --git a/python/tests/kat/t_hosts.py b/python/tests/kat/t_hosts.py index 70058b543a..cc94a97528 100644 --- a/python/tests/kat/t_hosts.py +++ b/python/tests/kat/t_hosts.py @@ -42,7 +42,7 @@ def manifests(self) -> str: apiVersion: v1 kind: Secret metadata: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret labels: kat-ambassador-id: {self.ambassador_id} type: kubernetes.io/tls @@ -57,7 +57,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Host metadata: - name: {self.name.k8s}-host + name: {self.path.k8s}-host labels: kat-ambassador-id: {self.ambassador_id} spec: @@ -66,7 +66,7 @@ def manifests(self) -> str: acmeProvider: authority: none tlsSecret: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret mappingSelector: matchLabels: hostname: {self.path.fqdn} @@ -74,7 +74,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Mapping metadata: - name: {self.name.k8s}-target-mapping + name: {self.path.k8s}-target-mapping labels: hostname: {self.path.fqdn} spec: @@ -116,7 +116,7 @@ def manifests(self) -> str: apiVersion: v1 kind: Secret metadata: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret labels: kat-ambassador-id: {self.ambassador_id} type: kubernetes.io/tls @@ -131,7 +131,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Listener metadata: - name: {self.name.k8s}-listener + name: {self.path.k8s}-listener labels: kat-ambassador-id: {self.ambassador_id} spec: @@ -146,7 +146,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Host metadata: - name: {self.name.k8s}-host + name: {self.path.k8s}-host labels: kat-ambassador-id: {self.ambassador_id} spec: @@ -155,7 +155,7 @@ def manifests(self) -> str: acmeProvider: authority: none tlsSecret: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret mappingSelector: matchLabels: hostname: {self.path.fqdn} @@ -166,7 +166,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Mapping metadata: - name: {self.name.k8s}-target-mapping + name: {self.path.k8s}-target-mapping labels: hostname: {self.path.fqdn} spec: @@ -308,7 +308,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Listener metadata: - name: {self.name.k8s}-listener + name: {self.path.k8s}-listener labels: kat-ambassador-id: {self.ambassador_id} spec: @@ -451,7 +451,7 @@ def manifests(self) -> str: apiVersion: v1 kind: Secret metadata: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret labels: kat-ambassador-id: {self.ambassador_id} type: kubernetes.io/tls @@ -478,7 +478,7 @@ def manifests(self) -> str: matchLabels: hostname: {self.path.fqdn} tlsSecret: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret tlsContext: name: {self.path.k8s}-separate-tls-context --- @@ -490,7 +490,7 @@ def manifests(self) -> str: kat-ambassador-id: {self.ambassador_id} spec: ambassador_id: [ {self.ambassador_id} ] - secret: {self.name.k8s}-secret + secret: {self.path.k8s}-secret min_tls_version: v1.2 max_tls_version: v1.3 --- @@ -543,7 +543,7 @@ def manifests(self) -> str: apiVersion: v1 kind: Secret metadata: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret labels: kat-ambassador-id: {self.ambassador_id} type: kubernetes.io/tls @@ -570,7 +570,7 @@ def manifests(self) -> str: matchLabels: hostname: {self.path.fqdn} tlsSecret: - name: {self.name.k8s}-secret + name: {self.path.k8s}-secret tls: min_tls_version: v1.2 max_tls_version: v1.3 @@ -1985,7 +1985,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Mapping metadata: - name: {self.name.k8s}-target-mapping + name: {self.path.k8s}-target-mapping labels: hostname: {self.path.fqdn} spec: @@ -2083,7 +2083,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Mapping metadata: - name: {self.name.k8s}-target-mapping + name: {self.path.k8s}-target-mapping labels: hostname: {self.path.fqdn} spec: @@ -2218,7 +2218,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Mapping metadata: - name: {self.name.k8s}-target-mapping + name: {self.path.k8s}-target-mapping spec: ambassador_id: [ {self.ambassador_id} ] hostname: "*" diff --git a/python/tests/kat/t_ingress.py b/python/tests/kat/t_ingress.py index c132c7b695..75bd67c893 100644 --- a/python/tests/kat/t_ingress.py +++ b/python/tests/kat/t_ingress.py @@ -29,7 +29,7 @@ def manifests(self) -> str: annotations: kubernetes.io/ingress.class: ambassador getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} spec: rules: - http: @@ -55,7 +55,7 @@ def queries(self): "-n", "default", "-f", - f"metadata.name={self.name.k8s}", + f"metadata.name={self.path.k8s}", "-u", "/dev/fd/0", ] @@ -119,7 +119,7 @@ def manifests(self) -> str: annotations: kubernetes.io/ingress.class: ambassador getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} spec: rules: - http: @@ -145,7 +145,7 @@ def queries(self): "-n", "default", "-f", - f"metadata.name={self.name.k8s}", + f"metadata.name={self.path.k8s}", "-u", "/dev/fd/0", ] @@ -210,7 +210,7 @@ def manifests(self) -> str: annotations: kubernetes.io/ingress.class: ambassador getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} namespace: alt-namespace spec: rules: @@ -237,7 +237,7 @@ def queries(self): "-n", "default", "-f", - f"metadata.name={self.name.k8s}", + f"metadata.name={self.path.k8s}", "-u", "/dev/fd/0", ] @@ -310,7 +310,7 @@ def manifests(self) -> str: ambassador_id: [{self.ambassador_id}] kubernetes.io/ingress.class: ambassador getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} spec: rules: - http: @@ -335,7 +335,7 @@ def queries(self): "-n", "default", "-f", - f"metadata.name={self.name.k8s}", + f"metadata.name={self.path.k8s}", "-u", "/dev/fd/0", ] @@ -391,7 +391,7 @@ def manifests(self) -> str: annotations: kubernetes.io/ingress.class: ambassador getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} namespace: same-ingress-1 spec: rules: @@ -414,7 +414,7 @@ def manifests(self) -> str: annotations: kubernetes.io/ingress.class: ambassador getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} namespace: same-ingress-2 spec: rules: @@ -441,7 +441,7 @@ def queries(self): "-n", "default", "-f", - f"metadata.name={self.name.k8s}", + f"metadata.name={self.path.k8s}", "-u", "/dev/fd/0", ] @@ -499,7 +499,7 @@ def manifests(self) -> str: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: {self.name.k8s}-ext + name: {self.path.k8s}-ext rules: - apiGroups: ["networking.k8s.io"] resources: ["ingressclasses"] @@ -508,11 +508,11 @@ def manifests(self) -> str: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: {self.name.k8s}-ext + name: {self.path.k8s}-ext roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: {self.name.k8s}-ext + name: {self.path.k8s}-ext subjects: - kind: ServiceAccount name: {self.path.k8s} @@ -523,7 +523,7 @@ def manifests(self) -> str: metadata: annotations: getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} spec: controller: getambassador.io/ingress-controller --- @@ -532,9 +532,9 @@ def manifests(self) -> str: metadata: annotations: getambassador.io/ambassador-id: {self.ambassador_id} - name: {self.name.k8s} + name: {self.path.k8s} spec: - ingressClassName: {self.name.k8s} + ingressClassName: {self.path.k8s} rules: - http: paths: @@ -559,7 +559,7 @@ def queries(self): "-n", "default", "-f", - f"metadata.name={self.name.k8s}", + f"metadata.name={self.path.k8s}", "-u", "/dev/fd/0", ] diff --git a/python/tests/kat/t_ip_allow_deny.py b/python/tests/kat/t_ip_allow_deny.py index 3645ff694a..3454baf80a 100644 --- a/python/tests/kat/t_ip_allow_deny.py +++ b/python/tests/kat/t_ip_allow_deny.py @@ -48,7 +48,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Listener metadata: - name: {self.name.k8s}-listener + name: {self.path.k8s}-listener labels: kat-ambassador-id: {self.ambassador_id} spec: @@ -148,7 +148,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Listener metadata: - name: {self.name.k8s}-listener + name: {self.path.k8s}-listener labels: kat-ambassador-id: {self.ambassador_id} spec: diff --git a/python/tests/kat/t_tls.py b/python/tests/kat/t_tls.py index b9547cc99a..a0e128117b 100644 --- a/python/tests/kat/t_tls.py +++ b/python/tests/kat/t_tls.py @@ -1907,18 +1907,18 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: TLSContext metadata: - name: {self.name.k8s} + name: {self.path.k8s} spec: ambassador_id: [ {self.ambassador_id} ] alpn_protocols: "h2,http/1.1" hosts: - a.domain.com - secret: {self.name.k8s} + secret: {self.path.k8s} --- apiVersion: v1 kind: Secret metadata: - name: {self.name.k8s} + name: {self.path.k8s} labels: kat-ambassador-id: {self.ambassador_id} type: kubernetes.io/tls @@ -1933,7 +1933,7 @@ def manifests(self) -> str: apiVersion: getambassador.io/v3alpha1 kind: Mapping metadata: - name: {self.name.k8s}-target-mapping + name: {self.path.k8s}-target-mapping spec: ambassador_id: [ {self.ambassador_id} ] prefix: /foo From 6bb9127c29597ee482f58792eb3ed562a15105ee Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 27 Jun 2022 13:42:47 -0600 Subject: [PATCH 11/18] KAT: Fix Name.fqdn to actually be fully qualified Signed-off-by: Luke Shumaker --- python/kat/harness.py | 15 ++------------- python/tests/kat/t_cluster_tag.py | 22 +++++++++++++++------- python/tests/kat/t_extauth.py | 2 +- python/tests/kat/t_mappingtests_default.py | 4 ++-- python/tests/kat/t_optiontests.py | 9 ++++----- python/tests/kat/t_tcpmapping.py | 19 ++++++++----------- python/tests/kat/t_tracing.py | 12 +++++++++--- 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/python/kat/harness.py b/python/kat/harness.py index c90c910cad..ac04aba8db 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -305,7 +305,7 @@ def variants(cls, *args, **kwargs) -> Tuple[Any]: class Name(NamedTuple): name: str - namespace: Optional[str] + namespace: str @property def k8s(self) -> str: @@ -313,12 +313,7 @@ def k8s(self) -> str: @property def fqdn(self) -> str: - r = self.k8s - - if self.namespace and (self.namespace != "default"): - r += "." + self.namespace - - return r + return ".".join([self.k8s, self.namespace, "svc", "cluster", "local"]) class NodeLocal(threading.local): @@ -607,12 +602,6 @@ def depth(self): def format(self, st, **kwargs): return integration_manifests.format(st, self=self, **kwargs) - def get_fqdn(self, name: str) -> str: - if self.namespace and (self.namespace != "default"): - return f"{name}.{self.namespace}" - else: - return name - @functools.lru_cache() def matches(self, pattern): if fnmatch.fnmatch(self.path.name, "*%s*" % pattern): diff --git a/python/tests/kat/t_cluster_tag.py b/python/tests/kat/t_cluster_tag.py index ade55f18b2..37b848b37d 100644 --- a/python/tests/kat/t_cluster_tag.py +++ b/python/tests/kat/t_cluster_tag.py @@ -85,7 +85,7 @@ def manifests(self) -> str: def assert_cluster(self, cluster, target_ip): assert cluster is not None - assert cluster["targets"][0]["ip"] == target_ip + assert cluster["targets"][0]["ip"] == target_ip + ".default.svc.cluster.local" def queries(self): yield Query(self.url("ambassador/v0/diag/?json=true")) @@ -94,24 +94,32 @@ def check(self): result = self.results[0] clusters = result.json["cluster_info"] - cluster_1 = clusters["cluster_clustertagtest_http_target1_default"] + cluster_1 = clusters[ + "cluster_clustertagtest_http_target1_default_svc_cluster_local_default" + ] self.assert_cluster(cluster_1, "clustertagtest-http-target1") - cluster_2 = clusters["cluster_tag_1_clustertagtest_http_target1_default"] + cluster_2 = clusters[ + "cluster_tag_1_clustertagtest_http_target1_default_svc_cluster_local_default" + ] self.assert_cluster(cluster_2, "clustertagtest-http-target1") - cluster_3 = clusters["cluster_tag_2_clustertagtest_http_target1_default"] + cluster_3 = clusters[ + "cluster_tag_2_clustertagtest_http_target1_default_svc_cluster_local_default" + ] self.assert_cluster(cluster_3, "clustertagtest-http-target1") - cluster_4 = clusters["cluster_tag_2_clustertagtest_http_target2_default"] + cluster_4 = clusters[ + "cluster_tag_2_clustertagtest_http_target2_default_svc_cluster_local_default" + ] self.assert_cluster(cluster_4, "clustertagtest-http-target2") cluster_5 = clusters[ - "cluster_some_really_long_tag_that_is_really_long_clustertagtest_http_target1_default" + "cluster_some_really_long_tag_that_is_really_long_clustertagtest_http_target1_default_svc_cluster_local_default" ] self.assert_cluster(cluster_5, "clustertagtest-http-target1") cluster_6 = clusters[ - "cluster_some_really_long_tag_that_is_really_long_clustertagtest_http_target2_default" + "cluster_some_really_long_tag_that_is_really_long_clustertagtest_http_target2_default_svc_cluster_local_default" ] self.assert_cluster(cluster_6, "clustertagtest-http-target2") diff --git a/python/tests/kat/t_extauth.py b/python/tests/kat/t_extauth.py index fcfd9b544a..b0cb3f4d71 100644 --- a/python/tests/kat/t_extauth.py +++ b/python/tests/kat/t_extauth.py @@ -545,7 +545,7 @@ def check(self): ] assert self.results[4].backend.request.headers["authorization"] == ["foo-11111"] assert self.results[4].backend.request.headers["l5d-dst-override"] == [ - "authenticationhttpbufferedtest-http:80" + f"{self.target.path.fqdn}:80" ] assert self.results[4].status == 200 assert self.results[4].headers["Server"] == ["envoy"] diff --git a/python/tests/kat/t_mappingtests_default.py b/python/tests/kat/t_mappingtests_default.py index 40baa42788..e8b82c21fa 100644 --- a/python/tests/kat/t_mappingtests_default.py +++ b/python/tests/kat/t_mappingtests_default.py @@ -339,7 +339,7 @@ def manifests(self) -> str: ambassador_id: [{self.ambassador_id}] hostname: "*" prefix: /{self.name}-1/ - service: {self.target.path.fqdn}.default + service: {self.target.path.fqdn} --- apiVersion: getambassador.io/v3alpha1 kind: Mapping @@ -350,7 +350,7 @@ def manifests(self) -> str: ambassador_id: [{self.ambassador_id}] hostname: "*" prefix: /{self.name}-2/ - service: {self.target.path.fqdn}.default + service: {self.target.path.fqdn} """ ) + super().manifests() diff --git a/python/tests/kat/t_optiontests.py b/python/tests/kat/t_optiontests.py index 55b392201f..8ab800103e 100644 --- a/python/tests/kat/t_optiontests.py +++ b/python/tests/kat/t_optiontests.py @@ -132,12 +132,11 @@ def check(self): for r in self.parent.results: assert r.backend assert r.backend.request - request_host = r.backend.request.host - response_host = self.parent.get_fqdn(r.backend.name) + requested_host_echoed = r.backend.request.host + responding_host = r.backend.name - assert ( - response_host == request_host - ), f"backend {response_host} != request host {request_host}" + assert requested_host_echoed == self.parent.target.path.fqdn + assert responding_host == self.parent.target.path.k8s class Rewrite(OptionTest): diff --git a/python/tests/kat/t_tcpmapping.py b/python/tests/kat/t_tcpmapping.py index fd4c4bf736..e3d8b2015c 100644 --- a/python/tests/kat/t_tcpmapping.py +++ b/python/tests/kat/t_tcpmapping.py @@ -300,7 +300,7 @@ def queries(self): # to.) def check(self): - for idx, target, tls_wanted in [ + for idx, target, expected_tls in [ (0, self.target1, True), (1, self.target2, True), (2, self.target1, False), @@ -308,16 +308,13 @@ def check(self): (4, self.target3, True), # ( 5, self.target1 ), ]: + expected_host = target.path.k8s r = self.results[idx] - wanted_fqdn = target.path.fqdn + assert r.backend - backend_fqdn = target.get_fqdn(r.backend.name) + actual_host = r.backend.name assert r.backend.request - tls_enabled = r.backend.request.tls.enabled - - assert ( - backend_fqdn == wanted_fqdn - ), f"{idx}: backend {backend_fqdn} != expected {wanted_fqdn}" - assert ( - tls_enabled == tls_wanted - ), f"{idx}: TLS status {tls_enabled} != wanted {tls_wanted}" + actual_tls = r.backend.request.tls.enabled + + assert actual_host == expected_host + assert actual_tls == expected_tls diff --git a/python/tests/kat/t_tracing.py b/python/tests/kat/t_tracing.py index 8dcb62e6c6..2ea80784d9 100644 --- a/python/tests/kat/t_tracing.py +++ b/python/tests/kat/t_tracing.py @@ -146,7 +146,9 @@ def check(self): tracelist = set(x for x in self.results[101].backend.response) print(f"tracelist = {tracelist}") - assert "router cluster_tracingtest_http_default egress" in tracelist + assert ( + "router cluster_tracingtest_http_default_svc_cluster_local_default egress" in tracelist + ) # Look for the host that we actually queried, since that's what appears in the spans. assert self.results[0].backend @@ -246,7 +248,9 @@ def check(self): tracelist = set(x for x in self.results[101].backend.response) print(f"tracelist = {tracelist}") - assert "router cluster_tracingtestlongclustername_http_default egress" in tracelist + assert ( + "router cluster_tracingtestlongclustername_http_-2dc66d6d73240537-0 egress" in tracelist + ) # Look for the host that we actually queried, since that's what appears in the spans. assert self.results[0].backend @@ -533,7 +537,9 @@ def check(self): tracelist = set(x for x in self.results[101].backend.response) print(f"tracelist = {tracelist}") - assert "router cluster_tracingtestzipkinv2_http_default egress" in tracelist + assert ( + "router cluster_tracingtestzipkinv2_http_default-606ec0a62fedc99c-0 egress" in tracelist + ) # Look for the host that we actually queried, since that's what appears in the spans. assert self.results[0].backend From ff2dc210fb27a3079411bc35b1b4944dffcf8118 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 27 Jun 2022 13:42:47 -0600 Subject: [PATCH 12/18] KAT: Have use of httpbin be a KAT node just like other backends Signed-off-by: Luke Shumaker --- python/kat/harness.py | 8 ++--- .../manifests/httpbin_backend.yaml | 34 +++++++++++++++++++ python/tests/kat/abstract_tests.py | 12 +++++++ python/tests/kat/t_mappingtests_default.py | 22 ++++++------ python/tests/kat/t_mappingtests_plain.py | 18 ++++------ 5 files changed, 66 insertions(+), 28 deletions(-) create mode 100644 python/tests/integration/manifests/httpbin_backend.yaml diff --git a/python/kat/harness.py b/python/kat/harness.py index ac04aba8db..175e1c7e0f 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -39,7 +39,6 @@ from tests.manifests import ( cleartext_host_manifest, default_listener_manifest, - httpbin_manifests, websocket_echo_server_manifests, ) @@ -1783,12 +1782,9 @@ def _setup_k8s(self, selected): raise RuntimeError("Could not apply manifests") self.applied_manifests = True - # Finally, install httpbin and the websocket-echo-server. - print( - f"applying http_manifests + websocket_echo_server_manifests to namespaces: {namespaces}" - ) + # Finally, install the websocket-echo-server. + print(f"applying websocket_echo_server_manifests to namespaces: {namespaces}") for namespace in namespaces: - apply_kube_artifacts(namespace, httpbin_manifests) apply_kube_artifacts(namespace, websocket_echo_server_manifests) for n in self.nodes: diff --git a/python/tests/integration/manifests/httpbin_backend.yaml b/python/tests/integration/manifests/httpbin_backend.yaml new file mode 100644 index 0000000000..5abc40de48 --- /dev/null +++ b/python/tests/integration/manifests/httpbin_backend.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {self.path.k8s} +spec: + selector: + backend: {self.path.k8s} + ports: + - name: http + protocol: TCP + port: 80 + targetPort: http +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {self.path.k8s} +spec: + replicas: 1 + selector: + matchLabels: + backend: {self.path.k8s} + template: + metadata: + labels: + backend: {self.path.k8s} + spec: + containers: + - name: httpbin + image: docker.io/kennethreitz/httpbin + ports: + - name: http + containerPort: 80 diff --git a/python/tests/kat/abstract_tests.py b/python/tests/kat/abstract_tests.py index e3c59c5c7d..292e1ed9de 100644 --- a/python/tests/kat/abstract_tests.py +++ b/python/tests/kat/abstract_tests.py @@ -515,6 +515,18 @@ def requirements(self): yield ("pod", self.path.k8s) +class HTTPBin(ServiceType): + skip_variant: ClassVar[bool] = True + + def __init__(self, *args, **kwargs) -> None: + # Do this unconditionally, because that's the point of this class. + kwargs["service_manifests"] = integration_manifests.load("httpbin_backend") + super().__init__(*args, **kwargs) + + def requirements(self): + yield ("url", Query("http://%s/status/200" % self.path.fqdn)) + + @abstract_test class MappingTest(Test): diff --git a/python/tests/kat/t_mappingtests_default.py b/python/tests/kat/t_mappingtests_default.py index e8b82c21fa..f7581178d2 100644 --- a/python/tests/kat/t_mappingtests_default.py +++ b/python/tests/kat/t_mappingtests_default.py @@ -1,6 +1,6 @@ from typing import Generator, Tuple, Union -from abstract_tests import HTTP, AmbassadorTest, Node, ServiceType +from abstract_tests import HTTP, AmbassadorTest, HTTPBin, Node, ServiceType from ambassador.constants import Constants from kat.harness import EDGE_STACK, Query, variants from tests.integration.manifests import namespace_manifest @@ -61,7 +61,7 @@ class MergeSlashesDisabled(AmbassadorTest): target: ServiceType def init(self): - self.target = HTTP() + self.target = HTTPBin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -73,7 +73,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/status/ rewrite: /status/ -service: httpbin.default +service: {self.target.path.fqdn} """ ) @@ -93,7 +93,7 @@ class MergeSlashesEnabled(AmbassadorTest): target: ServiceType def init(self): - self.target = HTTP() + self.target = HTTPBin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -111,7 +111,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/status/ rewrite: /status/ -service: httpbin.default +service: {self.target.path.fqdn} """ ) @@ -131,7 +131,7 @@ class RejectRequestsWithEscapedSlashesDisabled(AmbassadorTest): target: ServiceType def init(self): - self.target = HTTP() + self.target = HTTPBin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -143,7 +143,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/status/ rewrite: /status/ -service: httpbin.default +service: {self.target.path.fqdn} """ ) @@ -166,7 +166,7 @@ class RejectRequestsWithEscapedSlashesEnabled(AmbassadorTest): target: ServiceType def init(self): - self.target = HTTP() + self.target = HTTPBin() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -184,7 +184,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/status/ rewrite: /status/ -service: httpbin +service: {self.target.path.fqdn} """ ) @@ -365,7 +365,7 @@ class LongClusterNameMapping(AmbassadorTest): target: ServiceType def init(self): - self.target = HTTP() + self.target = HTTPBin() def manifests(self) -> str: return ( @@ -378,7 +378,7 @@ def manifests(self) -> str: name: thisisaverylongservicenameoverwithsixythreecharacters123456789 spec: type: ExternalName - externalName: httpbin.default.svc.cluster.local + externalName: {self.target.path.fqdn} --- apiVersion: getambassador.io/v3alpha1 kind: Mapping diff --git a/python/tests/kat/t_mappingtests_plain.py b/python/tests/kat/t_mappingtests_plain.py index 83a0f35587..aac35c2b36 100644 --- a/python/tests/kat/t_mappingtests_plain.py +++ b/python/tests/kat/t_mappingtests_plain.py @@ -1,6 +1,6 @@ from typing import Dict, Generator, Tuple, Union -from abstract_tests import HTTP, AmbassadorTest, MappingTest, Node, OptionTest, ServiceType +from abstract_tests import HTTP, AmbassadorTest, HTTPBin, MappingTest, Node, OptionTest, ServiceType from ambassador.constants import Constants from kat.harness import EDGE_STACK, Query, variants @@ -706,10 +706,8 @@ class AddRespHeadersMapping(MappingTest): parent: AmbassadorTest target: ServiceType - @classmethod - def variants(cls) -> Generator[Node, None, None]: - for st in variants(ServiceType): - yield cls(st, name="{self.target.name}") + def init(self): + MappingTest.init(self, HTTPBin()) def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -720,7 +718,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: name: {self.name} hostname: "*" prefix: /{self.name}/ -service: httpbin.plain-namespace +service: {self.target.path.fqdn} add_response_headers: koo: append: False @@ -786,10 +784,8 @@ class RemoveReqHeadersMapping(MappingTest): parent: AmbassadorTest target: ServiceType - @classmethod - def variants(cls) -> Generator[Node, None, None]: - for st in variants(ServiceType): - yield cls(st, name="{self.target.name}") + def init(self): + MappingTest.init(self, HTTPBin()) def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -800,7 +796,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: name: {self.name} hostname: "*" prefix: /{self.name}/ -service: httpbin.plain-namespace +service: {self.target.path.fqdn} remove_request_headers: - zoo - aoo From 7fd016e2e2bfbf1086456a1bd3e4b41b35112460 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 24 Aug 2022 17:49:23 -0600 Subject: [PATCH 13/18] KAT: Have use of websocket-echo-server be a KAT node just like other backends Signed-off-by: Luke Shumaker --- python/kat/harness.py | 11 +----- .../manifests/websocket_echo_backend.yaml | 30 ++++++++++++++++ python/tests/kat/abstract_tests.py | 12 +++++++ python/tests/kat/t_extauth.py | 6 ++-- python/tests/kat/t_mappingtests_plain.py | 20 +++++++---- python/tests/manifests.py | 36 ------------------- 6 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 python/tests/integration/manifests/websocket_echo_backend.yaml diff --git a/python/kat/harness.py b/python/kat/harness.py index 175e1c7e0f..313a5d40dd 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -36,11 +36,7 @@ import tests.integration.manifests as integration_manifests from ambassador.utils import parse_bool from tests.kubeutils import apply_kube_artifacts -from tests.manifests import ( - cleartext_host_manifest, - default_listener_manifest, - websocket_echo_server_manifests, -) +from tests.manifests import cleartext_host_manifest, default_listener_manifest from .parser import SequenceView, Tag, dump, load from .utils import ShellCommand @@ -1782,11 +1778,6 @@ def _setup_k8s(self, selected): raise RuntimeError("Could not apply manifests") self.applied_manifests = True - # Finally, install the websocket-echo-server. - print(f"applying websocket_echo_server_manifests to namespaces: {namespaces}") - for namespace in namespaces: - apply_kube_artifacts(namespace, websocket_echo_server_manifests) - for n in self.nodes: if n in selected and not n.xfail: action = getattr(n, "post_manifest", None) diff --git a/python/tests/integration/manifests/websocket_echo_backend.yaml b/python/tests/integration/manifests/websocket_echo_backend.yaml new file mode 100644 index 0000000000..3225ec2805 --- /dev/null +++ b/python/tests/integration/manifests/websocket_echo_backend.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {self.path.k8s} +spec: + selector: + backend: {self.path.k8s} + ports: + - protocol: TCP + port: 80 + targetPort: 8080 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {self.path.k8s} +spec: + replicas: 1 + selector: + matchLabels: + backend: {self.path.k8s} + template: + metadata: + labels: + backend: {self.path.k8s} + spec: + containers: + - name: websocket-echo-server + image: docker.io/johnesmet/go-websocket-echo-server:latest diff --git a/python/tests/kat/abstract_tests.py b/python/tests/kat/abstract_tests.py index 292e1ed9de..d9f2158850 100644 --- a/python/tests/kat/abstract_tests.py +++ b/python/tests/kat/abstract_tests.py @@ -527,6 +527,18 @@ def requirements(self): yield ("url", Query("http://%s/status/200" % self.path.fqdn)) +class WebsocketEcho(ServiceType): + skip_variant: ClassVar[bool] = True + + def __init__(self, *args, **kwargs) -> None: + # Do this unconditionally, because that's the point of this class. + kwargs["service_manifests"] = integration_manifests.load("websocket_echo_backend") + super().__init__(*args, **kwargs) + + def requirements(self): + yield ("url", Query("http://%s/" % self.path.fqdn, expected=404)) + + @abstract_test class MappingTest(Test): diff --git a/python/tests/kat/t_extauth.py b/python/tests/kat/t_extauth.py index b0cb3f4d71..c50fb99d08 100644 --- a/python/tests/kat/t_extauth.py +++ b/python/tests/kat/t_extauth.py @@ -4,7 +4,7 @@ import pytest -from abstract_tests import AGRPC, AHTTP, HTTP, AmbassadorTest, Node, ServiceType +from abstract_tests import AGRPC, AHTTP, HTTP, AmbassadorTest, Node, ServiceType, WebsocketEcho from ambassador import Config from kat.harness import EDGE_STACK, Query from tests.selfsigned import TLSCerts @@ -1120,11 +1120,13 @@ def check(self): class AuthenticationWebsocketTest(AmbassadorTest): auth: ServiceType + backend: ServiceType def init(self): if EDGE_STACK: self.xfail = "XFailing for now, custom AuthServices not supported in Edge Stack" self.auth = HTTP(name="auth") + self.backend = WebsocketEcho() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -1145,7 +1147,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: name: {self.name} hostname: "*" prefix: /{self.name}/ -service: websocket-echo-server.default +service: {self.backend.path.fqdn} use_websocket: true """ ) diff --git a/python/tests/kat/t_mappingtests_plain.py b/python/tests/kat/t_mappingtests_plain.py index aac35c2b36..ba249b38a2 100644 --- a/python/tests/kat/t_mappingtests_plain.py +++ b/python/tests/kat/t_mappingtests_plain.py @@ -1,6 +1,15 @@ from typing import Dict, Generator, Tuple, Union -from abstract_tests import HTTP, AmbassadorTest, HTTPBin, MappingTest, Node, OptionTest, ServiceType +from abstract_tests import ( + HTTP, + AmbassadorTest, + HTTPBin, + MappingTest, + Node, + OptionTest, + ServiceType, + WebsocketEcho, +) from ambassador.constants import Constants from kat.harness import EDGE_STACK, Query, variants @@ -333,11 +342,10 @@ def check(self): class WebSocketMapping(MappingTest): parent: AmbassadorTest + target: ServiceType - @classmethod - def variants(cls) -> Generator[Node, None, None]: - for st in variants(ServiceType): - yield cls(st, name="{self.target.name}") + def init(self): + MappingTest.init(self, WebsocketEcho()) def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( @@ -348,7 +356,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: name: {self.name} hostname: "*" prefix: /{self.name}/ -service: websocket-echo-server.plain-namespace +service: {self.target.path.fqdn} use_websocket: true """ ) diff --git a/python/tests/manifests.py b/python/tests/manifests.py index 788c1a4cdd..b8c4a1dab5 100644 --- a/python/tests/manifests.py +++ b/python/tests/manifests.py @@ -75,42 +75,6 @@ """ -websocket_echo_server_manifests = """ ---- -apiVersion: v1 -kind: Service -metadata: - name: websocket-echo-server -spec: - selector: - service: websocket-echo-server - ports: - - protocol: TCP - port: 80 - targetPort: 8080 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: websocket-echo-server -spec: - selector: - matchLabels: - service: websocket-echo-server - replicas: 1 - strategy: - type: RollingUpdate - template: - metadata: - labels: - service: websocket-echo-server - spec: - containers: - - name: websocket-echo-server - image: docker.io/johnesmet/go-websocket-echo-server:latest -""" - - # This is a little weird -- you need to fill in the '%s' with the namespace # you want before you use 'format' to fill in other things from 'self'. cleartext_host_manifest = """ From 91f4fda04c5209be47f3d3ac2f69e750176833bc Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 24 Aug 2022 18:59:15 -0600 Subject: [PATCH 14/18] KAT: Have use of statsd sinks be a KAT nodes just like other backends Signed-off-by: Luke Shumaker --- .../integration/manifests/statsd_backend.yaml | 39 ++++++ python/tests/kat/abstract_tests.py | 14 ++ python/tests/kat/t_circuitbreaker.py | 77 ++--------- python/tests/kat/t_stats.py | 121 +++--------------- 4 files changed, 83 insertions(+), 168 deletions(-) create mode 100644 python/tests/integration/manifests/statsd_backend.yaml diff --git a/python/tests/integration/manifests/statsd_backend.yaml b/python/tests/integration/manifests/statsd_backend.yaml new file mode 100644 index 0000000000..aa576bdd7a --- /dev/null +++ b/python/tests/integration/manifests/statsd_backend.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {self.path.k8s} +spec: + selector: + backend: {self.path.k8s} + ports: + - protocol: UDP + port: 8125 + targetPort: 8125 + name: statsd-metrics + - protocol: TCP + port: 80 + targetPort: 3000 + name: statsd-http +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {self.path.k8s} +spec: + replicas: 1 + selector: + matchLabels: + backend: {self.path.k8s} + template: + metadata: + labels: + backend: {self.path.k8s} + spec: + containers: + - name: statsd + image: {images[test-stats]} + env: + - name: STATSD_TEST_CLUSTER + value: {self.target_cluster} + restartPolicy: Always diff --git a/python/tests/kat/abstract_tests.py b/python/tests/kat/abstract_tests.py index d9f2158850..f6c63d26d9 100644 --- a/python/tests/kat/abstract_tests.py +++ b/python/tests/kat/abstract_tests.py @@ -539,6 +539,20 @@ def requirements(self): yield ("url", Query("http://%s/" % self.path.fqdn, expected=404)) +class StatsDSink(ServiceType): + skip_variant: ClassVar[bool] = True + target_cluster: str + + def __init__(self, target_cluster: str, *args, **kwargs) -> None: + self.target_cluster = target_cluster + # Do this unconditionally, because that's the point of this class. + kwargs["service_manifests"] = integration_manifests.load("statsd_backend") + super().__init__(*args, **kwargs) + + def requirements(self): + yield ("url", Query("http://%s/SUMMARY" % self.path.fqdn)) + + @abstract_test class MappingTest(Test): diff --git a/python/tests/kat/t_circuitbreaker.py b/python/tests/kat/t_circuitbreaker.py index 80b89c458f..f94b60c49c 100644 --- a/python/tests/kat/t_circuitbreaker.py +++ b/python/tests/kat/t_circuitbreaker.py @@ -1,74 +1,32 @@ import os -from typing import Generator, Tuple, Union +from typing import ClassVar, Generator, Tuple, Union import pytest import tests.integration.manifests as integration_manifests -from abstract_tests import HTTP, AmbassadorTest, Node, ServiceType +from abstract_tests import HTTP, AmbassadorTest, Node, ServiceType, StatsDSink from kat.harness import Query -STATSD_MANIFEST = """ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {name} -spec: - selector: - matchLabels: - service: {name} - replicas: 1 - template: - metadata: - labels: - service: {name} - spec: - containers: - - name: {name} - image: {image} - env: - - name: STATSD_TEST_CLUSTER - value: {target} - restartPolicy: Always ---- -apiVersion: v1 -kind: Service -metadata: - labels: - service: {name} - name: {name} -spec: - ports: - - protocol: UDP - port: 8125 - name: statsd-metrics - - protocol: TCP - port: 80 - targetPort: 3000 - name: statsd-http - selector: - service: {name} -""" - class CircuitBreakingTest(AmbassadorTest): target: ServiceType + statsd: ServiceType TARGET_CLUSTER = "cluster_circuitbreakingtest_http_cbdc1p1" def init(self): self.target = HTTP() + self.statsd = StatsDSink(target_cluster=self.TARGET_CLUSTER) def manifests(self) -> str: envs = """ - name: STATSD_ENABLED value: 'true' - name: STATSD_HOST - value: 'cbstatsd-sink' + value: '{self.statsd.path.fqdn}' """ - return ( - """ + return """ --- apiVersion: getambassador.io/v3alpha1 kind: Listener @@ -97,19 +55,12 @@ def manifests(self) -> str: requestPolicy: insecure: action: Route -""" - + self.format( - integration_manifests.load("rbac_cluster_scope") - + integration_manifests.load("ambassador"), - envs=envs, - extra_ports="", - capabilities_block="", - ) - + STATSD_MANIFEST.format( - name="cbstatsd-sink", - image=integration_manifests.get_images()["test-stats"], - target=self.__class__.TARGET_CLUSTER, - ) +""" + self.format( + integration_manifests.load("rbac_cluster_scope") + + integration_manifests.load("ambassador"), + envs=envs, + extra_ports="", + capabilities_block="", ) def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: @@ -134,7 +85,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /reset/ rewrite: /RESET/ -service: cbstatsd-sink +service: {self.statsd.path.fqdn} --- apiVersion: getambassador.io/v3alpha1 kind: Mapping @@ -143,7 +94,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /dump/ rewrite: /DUMP/ -service: cbstatsd-sink +service: {self.statsd.path.fqdn} """ ) diff --git a/python/tests/kat/t_stats.py b/python/tests/kat/t_stats.py index 8a21e0aa99..6c14b62c4c 100644 --- a/python/tests/kat/t_stats.py +++ b/python/tests/kat/t_stats.py @@ -2,107 +2,21 @@ from typing import Generator, Tuple, Union import tests.integration.manifests as integration_manifests -from abstract_tests import DEV, HTTP, AmbassadorTest, Node +from abstract_tests import DEV, HTTP, AmbassadorTest, Node, ServiceType, StatsDSink from kat.harness import Query STATSD_TEST_CLUSTER = "statsdtest_http" ALT_STATSD_TEST_CLUSTER = "short-stats-name" DOGSTATSD_TEST_CLUSTER = "dogstatsdtest_http" -GRAPHITE_CONFIG = """ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {0} -spec: - selector: - matchLabels: - service: {0} - replicas: 1 - template: - metadata: - labels: - service: {0} - spec: - containers: - - name: {0} - image: {1} - env: - - name: STATSD_TEST_DEBUG - value: "true" - - name: STATSD_TEST_CLUSTER - value: {2} ---- -apiVersion: v1 -kind: Service -metadata: - labels: - service: {0} - name: {0} -spec: - ports: - - protocol: UDP - port: 8125 - targetPort: 8125 - name: statsd-metrics - - protocol: TCP - port: 80 - targetPort: 3000 - name: statsd-www - selector: - service: {0} -""" - - -DOGSTATSD_CONFIG = """ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {0} -spec: - selector: - matchLabels: - service: {0} - replicas: 1 - template: - metadata: - labels: - service: {0} - spec: - containers: - - name: {0} - image: {1} - env: - - name: STATSD_TEST_CLUSTER - value: {2} ---- -apiVersion: v1 -kind: Service -metadata: - labels: - service: {0} - name: {0} -spec: - ports: - - protocol: UDP - port: 8125 - targetPort: 8125 - name: statsd-metrics - - protocol: TCP - port: 80 - targetPort: 3000 - name: statsd-www - selector: - service: {0} -""" - class StatsdTest(AmbassadorTest): + sink: ServiceType + def init(self): self.target = HTTP() self.target2 = HTTP(name="alt-statsd") + self.sink = StatsDSink(target_cluster=f"{STATSD_TEST_CLUSTER}:{ALT_STATSD_TEST_CLUSTER}") self.stats_name = ALT_STATSD_TEST_CLUSTER if DEV: self.skip_node = True @@ -111,6 +25,8 @@ def manifests(self) -> str: envs = """ - name: STATSD_ENABLED value: 'true' + - name: STATSD_HOST + value: {self.sink.path.fqdn} """ return self.format( @@ -119,10 +35,6 @@ def manifests(self) -> str: envs=envs, extra_ports="", capabilities_block="", - ) + GRAPHITE_CONFIG.format( - "statsd-sink", - integration_manifests.get_images()["test-stats"], - f"{STATSD_TEST_CLUSTER}:{ALT_STATSD_TEST_CLUSTER}", ) def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: @@ -151,7 +63,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: case_sensitive: false prefix: /reset/ rewrite: /RESET/ -service: statsd-sink +service: {self.sink.path.fqdn} --- apiVersion: getambassador.io/v3alpha1 kind: Mapping @@ -172,11 +84,11 @@ def queries(self): yield Query(self.url(self.name + "/"), phase=1) yield Query(self.url(self.name + "-alt/"), phase=1) - yield Query("http://statsd-sink/DUMP/", phase=2) + yield Query(f"http://{self.sink.path.fqdn}/DUMP/", phase=2) yield Query(self.url("metrics"), phase=2) def check(self): - # self.results[-2] is the JSON dump from our test statsd-sink service. + # self.results[-2] is the JSON dump from our test self.sink service. stats = self.results[-2].json or {} cluster_stats = stats.get(STATSD_TEST_CLUSTER, {}) @@ -228,17 +140,20 @@ def check(self): class DogstatsdTest(AmbassadorTest): + dogstatsd: ServiceType + def init(self): self.target = HTTP() + self.sink = StatsDSink(target_cluster=DOGSTATSD_TEST_CLUSTER) if DEV: self.skip_node = True def manifests(self) -> str: - envs = """ + envs = f""" - name: STATSD_ENABLED value: 'true' - name: STATSD_HOST - value: 'dogstatsd-sink' + value: {self.sink.path.fqdn} - name: DOGSTATSD value: 'true' """ @@ -249,10 +164,6 @@ def manifests(self) -> str: envs=envs, extra_ports="", capabilities_block="", - ) + DOGSTATSD_CONFIG.format( - "dogstatsd-sink", - integration_manifests.get_images()["test-stats"], - DOGSTATSD_TEST_CLUSTER, ) def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: @@ -273,7 +184,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /reset/ rewrite: /RESET/ -service: dogstatsd-sink +service: {self.sink.path.fqdn} """ ) @@ -285,7 +196,7 @@ def queries(self): for i in range(1000): yield Query(self.url(self.name + "/"), phase=1) - yield Query("http://dogstatsd-sink/DUMP/", phase=2) + yield Query(f"http://{self.sink.path.fqdn}/DUMP/", phase=2) def check(self): stats = self.results[-1].json or {} From ea912eba6b8253368150ca74e81b133cd73e69be Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 24 Aug 2022 19:28:19 -0600 Subject: [PATCH 15/18] KAT: t_consul.py: Have the Consul backend be a KAT node Signed-off-by: Luke Shumaker --- python/tests/kat/t_consul.py | 102 +++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 45 deletions(-) diff --git a/python/tests/kat/t_consul.py b/python/tests/kat/t_consul.py index 46a4d2122b..1b0ce60acf 100644 --- a/python/tests/kat/t_consul.py +++ b/python/tests/kat/t_consul.py @@ -1,4 +1,4 @@ -from typing import Generator, Tuple, Union +from typing import ClassVar, Generator, Tuple, Union from abstract_tests import HTTP, AmbassadorTest, Node, ServiceType from kat.harness import Query @@ -20,39 +20,22 @@ ) -class ConsulTest(AmbassadorTest): - k8s_target: ServiceType - k8s_ns_target: ServiceType - - def init(self): - self.k8s_target = HTTP(name="k8s") - self.k8s_ns_target = HTTP(name="k8s-ns", namespace="consul-test-namespace") - - # This is the datacenter we'll use. - self.datacenter = "dc12" - - # We use Consul's local-config environment variable to set the datacenter name - # on the actual Consul pod. That means that we need to supply the datacenter - # name in JSON format. - # - # In a perfect world this would just be - # - # self.datacenter_dict = { "datacenter": self.datacenter } - # - # but the world is not perfect, so we have to supply it as JSON with LOTS of - # escaping, since this gets passed through self.format (hence two layers of - # doubled braces) and JSON decoding (hence backslash-escaped double quotes, - # and of course the backslashes themselves have to be escaped...) - self.datacenter_json = f'{{{{\\"datacenter\\":\\"{self.datacenter}\\"}}}}' +class ConsulPod(ServiceType): + skip_variant: ClassVar[bool] = True + service_account_name: str + datacenter_json: str - def manifests(self) -> str: - consul_manifest = self.format( - """ + def __init__(self, service_account_name: str, datacenter_json: str, *args, **kwargs) -> None: + self.service_account_name = service_account_name + self.datacenter_json = datacenter_json + kwargs[ + "service_manifests" + ] = """ --- apiVersion: v1 kind: Service metadata: - name: {self.path.k8s}-consul + name: {self.path.k8s} spec: type: ClusterIP ports: @@ -61,18 +44,18 @@ def manifests(self) -> str: port: 8500 targetPort: 8500 selector: - service: {self.path.k8s}-consul + backend: {self.path.k8s} --- apiVersion: v1 kind: Pod metadata: - name: {self.path.k8s}-consul + name: {self.path.k8s} annotations: sidecar.istio.io/inject: "false" labels: - service: {self.path.k8s}-consul + backend: {self.path.k8s} spec: - serviceAccountName: {self.path.k8s} + serviceAccountName: {self.service_account_name} containers: - name: consul image: consul:1.4.3 @@ -81,8 +64,42 @@ def manifests(self) -> str: value: "{self.datacenter_json}" restartPolicy: Always """ + super().__init__(*args, **kwargs) + + def requirements(self): + yield ("url", Query("http://%s:8500/ui/" % self.path.fqdn)) + + +class ConsulTest(AmbassadorTest): + k8s_target: ServiceType + k8s_ns_target: ServiceType + consul_target: ServiceType + + def init(self): + self.k8s_target = HTTP(name="k8s") + self.k8s_ns_target = HTTP(name="k8s-ns", namespace="consul-test-namespace") + + # This is the datacenter we'll use. + self.datacenter = "dc12" + + # We use Consul's local-config environment variable to set the datacenter name + # on the actual Consul pod. That means that we need to supply the datacenter + # name in JSON format. + # + # In a perfect world this would just be + # + # self.datacenter_dict = { "datacenter": self.datacenter } + # + # but the world is not perfect, so we have to supply it as JSON with LOTS of + # escaping, since this gets passed through self.format (hence two layers of + # doubled braces) and JSON decoding (hence backslash-escaped double quotes, + # and of course the backslashes themselves have to be escaped...) + self.consul_target = ConsulPod( + service_account_name="consultest", # `=self.name.k8s`, but self.name isn't set yet + datacenter_json=f'{{{{\\"datacenter\\":\\"{self.datacenter}\\"}}}}', ) + def manifests(self) -> str: # Unlike usual, we have stuff both before and after super().manifests(): # we want the namespace early, but we want the superclass before our other # manifests, because of some magic with ServiceAccounts? @@ -97,7 +114,6 @@ def manifests(self) -> str: """ ) + super().manifests() - + consul_manifest + self.format( """ --- @@ -107,7 +123,7 @@ def manifests(self) -> str: name: {self.path.k8s}-resolver spec: ambassador_id: [consultest] - address: {self.path.k8s}-consul:$CONSUL_WATCHER_PORT + address: {self.consul_target.path.k8s}:$CONSUL_WATCHER_PORT datacenter: {self.datacenter} --- apiVersion: getambassador.io/v3alpha1 @@ -174,14 +190,10 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: """ ) - def requirements(self): - yield from super().requirements() - yield ("url", Query(self.format("http://{self.path.k8s}-consul:8500/ui/"))) - def queries(self): # Deregister the Consul services in phase 0. yield Query( - self.format("http://{self.path.k8s}-consul:8500/v1/catalog/deregister"), + self.format("http://{self.consul_target.path.k8s}:8500/v1/catalog/deregister"), method="PUT", body={ "Datacenter": self.datacenter, @@ -190,7 +202,7 @@ def queries(self): phase=0, ) yield Query( - self.format("http://{self.path.k8s}-consul:8500/v1/catalog/deregister"), + self.format("http://{self.consul_target.path.k8s}:8500/v1/catalog/deregister"), method="PUT", body={ "Datacenter": self.datacenter, @@ -199,7 +211,7 @@ def queries(self): phase=0, ) yield Query( - self.format("http://{self.path.k8s}-consul:8500/v1/catalog/deregister"), + self.format("http://{self.consul_target.path.k8s}:8500/v1/catalog/deregister"), method="PUT", body={ "Datacenter": self.datacenter, @@ -217,7 +229,7 @@ def queries(self): # Register the Consul services in phase 2. yield Query( - self.format("http://{self.path.k8s}-consul:8500/v1/catalog/register"), + self.format("http://{self.consul_target.path.k8s}:8500/v1/catalog/register"), method="PUT", body={ "Datacenter": self.datacenter, @@ -232,7 +244,7 @@ def queries(self): phase=2, ) yield Query( - self.format("http://{self.path.k8s}-consul:8500/v1/catalog/register"), + self.format("http://{self.consul_target.path.k8s}:8500/v1/catalog/register"), method="PUT", body={ "Datacenter": self.datacenter, @@ -247,7 +259,7 @@ def queries(self): phase=2, ) yield Query( - self.format("http://{self.path.k8s}-consul:8500/v1/catalog/register"), + self.format("http://{self.consul_target.path.k8s}:8500/v1/catalog/register"), method="PUT", body={ "Datacenter": self.datacenter, From e91d4edf2c9d73669680a42c06e38cda4db65651 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 8 Sep 2022 20:17:00 -0600 Subject: [PATCH 16/18] KAT: t_shadow.py: Have the shadow backend be a KAT node Signed-off-by: Luke Shumaker --- python/tests/kat/t_shadow.py | 61 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/python/tests/kat/t_shadow.py b/python/tests/kat/t_shadow.py index 5fc7217f83..ec07fc67e4 100644 --- a/python/tests/kat/t_shadow.py +++ b/python/tests/kat/t_shadow.py @@ -1,33 +1,24 @@ -from typing import Generator, Tuple, Union +from typing import ClassVar, Generator, Tuple, Union from abstract_tests import HTTP, AmbassadorTest, MappingTest, Node, ServiceType from kat.harness import Query -class ShadowTestCANFLAKE(MappingTest): - parent: AmbassadorTest - target: ServiceType - shadow: ServiceType - - # XXX This type: ignore is here because we're deliberately overriding the - # parent's init to have a different signature... but it's also intimately - # (nay, incestuously) related to the variant()'s yield() above, and I really - # don't want to deal with that right now. So. We'll deal with it later. - def init(self) -> None: # type: ignore - self.target = HTTP(name="target") - self.options = [] +class ShadowBackend(ServiceType): + skip_variant: ClassVar[bool] = True - def manifests(self) -> str: - return ( - """ + def __init__(self, *args, **kwargs) -> None: + kwargs[ + "service_manifests" + ] = """ --- apiVersion: v1 kind: Service metadata: - name: shadow + name: {self.path.k8s} spec: selector: - app: shadow + backend: {self.path.k8s} ports: - port: 80 name: http @@ -37,18 +28,18 @@ def manifests(self) -> str: apiVersion: apps/v1 kind: Deployment metadata: - name: shadow + name: {self.path.k8s} spec: selector: matchLabels: - app: shadow + backend: {self.path.k8s} replicas: 1 strategy: type: RollingUpdate template: metadata: labels: - app: shadow + backend: {self.path.k8s} spec: containers: - name: shadow @@ -57,8 +48,22 @@ def manifests(self) -> str: - name: http containerPort: 3000 """ - + super().manifests() - ) + super().__init__(*args, **kwargs) + + def requirements(self): + yield ("url", Query(f"http://{self.path.fqdn}/clear/")) + + +class ShadowTestCANFLAKE(MappingTest): + shadow: ServiceType + + # XXX This type: ignore is here because we're deliberately overriding the + # parent's init to have a different signature... but it's also intimately + # (nay, incestuously) related to the variant()'s yield() above, and I really + # don't want to deal with that right now. So. We'll deal with it later. + def init(self) -> None: # type: ignore + MappingTest.init(self, HTTP(name="target")) + self.shadow = ShadowBackend() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self.target, self.format( @@ -86,7 +91,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/mark/ rewrite: /mark/ -service: shadow.plain-namespace +service: {self.shadow.path.fqdn} shadow: true --- apiVersion: getambassador.io/v3alpha1 @@ -95,7 +100,7 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/weighted-mark/ rewrite: /mark/ -service: shadow.plain-namespace +service: {self.shadow.path.fqdn} weight: 10 shadow: true --- @@ -105,14 +110,10 @@ def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: hostname: "*" prefix: /{self.name}/check/ rewrite: /check/ -service: shadow.plain-namespace +service: {self.shadow.path.fqdn} """ ) - def requirements(self): - yield from super().requirements() - yield ("url", Query("http://shadow.plain-namespace/clear/")) - def queries(self): # There should be no Ambassador errors. At all. yield Query(self.parent.url("ambassador/v0/diag/?json=true&filter=errors"), phase=1) From bb170ddea67a1949b2a5e13593869cd5b4faee1e Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 8 Sep 2022 21:49:55 -0600 Subject: [PATCH 17/18] KAT: t_stats.py, t_circuitbreaker.py: Use self.manifest_envs ... instead of (poorly) duplicating super().manifests(). Signed-off-by: Luke Shumaker --- python/tests/kat/t_circuitbreaker.py | 41 ++-------------------------- python/tests/kat/t_stats.py | 23 +++------------- 2 files changed, 6 insertions(+), 58 deletions(-) diff --git a/python/tests/kat/t_circuitbreaker.py b/python/tests/kat/t_circuitbreaker.py index f94b60c49c..ad4c9c02ee 100644 --- a/python/tests/kat/t_circuitbreaker.py +++ b/python/tests/kat/t_circuitbreaker.py @@ -3,7 +3,6 @@ import pytest -import tests.integration.manifests as integration_manifests from abstract_tests import HTTP, AmbassadorTest, Node, ServiceType, StatsDSink from kat.harness import Query @@ -19,49 +18,13 @@ def init(self): self.statsd = StatsDSink(target_cluster=self.TARGET_CLUSTER) def manifests(self) -> str: - envs = """ + self.manifest_envs += f""" - name: STATSD_ENABLED value: 'true' - name: STATSD_HOST value: '{self.statsd.path.fqdn}' """ - - return """ ---- -apiVersion: getambassador.io/v3alpha1 -kind: Listener -metadata: - name: cleartext-listener - labels: - kat-ambassador-id: {self.ambassador_id} -spec: - ambassador_id: [ {self.ambassador_id} ] - port: 8080 - protocol: HTTP - securityModel: INSECURE - hostBinding: - selector: - matchLabels: - kat-ambassador-id: {self.ambassador_id} ---- -apiVersion: getambassador.io/v3alpha1 -kind: Host -metadata: - name: cleartext-host - labels: - kat-ambassador-id: {self.ambassador_id} -spec: - ambassador_id: [ {self.ambassador_id} ] - requestPolicy: - insecure: - action: Route -""" + self.format( - integration_manifests.load("rbac_cluster_scope") - + integration_manifests.load("ambassador"), - envs=envs, - extra_ports="", - capabilities_block="", - ) + return super().manifests() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self, self.format( diff --git a/python/tests/kat/t_stats.py b/python/tests/kat/t_stats.py index 6c14b62c4c..85b94b064f 100644 --- a/python/tests/kat/t_stats.py +++ b/python/tests/kat/t_stats.py @@ -1,7 +1,6 @@ import os from typing import Generator, Tuple, Union -import tests.integration.manifests as integration_manifests from abstract_tests import DEV, HTTP, AmbassadorTest, Node, ServiceType, StatsDSink from kat.harness import Query @@ -22,20 +21,13 @@ def init(self): self.skip_node = True def manifests(self) -> str: - envs = """ + self.manifest_envs += f""" - name: STATSD_ENABLED value: 'true' - name: STATSD_HOST value: {self.sink.path.fqdn} """ - - return self.format( - integration_manifests.load("rbac_cluster_scope") - + integration_manifests.load("ambassador"), - envs=envs, - extra_ports="", - capabilities_block="", - ) + return super().manifests() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self.target, self.format( @@ -149,7 +141,7 @@ def init(self): self.skip_node = True def manifests(self) -> str: - envs = f""" + self.manifest_envs += f""" - name: STATSD_ENABLED value: 'true' - name: STATSD_HOST @@ -157,14 +149,7 @@ def manifests(self) -> str: - name: DOGSTATSD value: 'true' """ - - return self.format( - integration_manifests.load("rbac_cluster_scope") - + integration_manifests.load("ambassador"), - envs=envs, - extra_ports="", - capabilities_block="", - ) + return super().manifests() def config(self) -> Generator[Union[str, Tuple[Node, str]], None, None]: yield self.target, self.format( From 526fc54abf21a99cf2962ea02936dd21e44c26b0 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 21 Sep 2022 12:27:08 -0600 Subject: [PATCH 18/18] Upgrade golangci-lint to a version with the depguard bugfix https://github.com/golangci/golangci-lint/issues/3116 https://github.com/OpenPeeDeeP/depguard/issues/25 Signed-off-by: Luke Shumaker --- .golangci.yml | 2 +- tools/src/golangci-lint/go.mod | 22 ++++++++-------- tools/src/golangci-lint/go.sum | 48 ++++++++++++++++------------------ 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a39b418282..021579fe96 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,7 +5,7 @@ linters: enable: - gofmt - govet - #- depguard # there's a bug in depguard with (or just exacerbated by?) Go 1.19 that causes it to have false positives + - depguard - unused - errcheck linters-settings: diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod index 493d450328..3ee54f16e4 100644 --- a/tools/src/golangci-lint/go.mod +++ b/tools/src/golangci-lint/go.mod @@ -2,7 +2,7 @@ module local go 1.19 -require github.com/golangci/golangci-lint v1.49.0 +require github.com/golangci/golangci-lint v1.49.1-0.20220903190357-db4955a3bb7e require ( 4d63.com/gochecknoglobals v0.1.0 // indirect @@ -12,7 +12,7 @@ require ( github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/OpenPeeDeeP/depguard v1.1.0 // indirect + github.com/OpenPeeDeeP/depguard v1.1.1 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/ashanbrown/forbidigo v1.3.0 // indirect @@ -38,10 +38,10 @@ require ( github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.6.4 // indirect + github.com/go-critic/go-critic v0.6.5 // indirect github.com/go-toolsmith/astcast v1.0.0 // indirect - github.com/go-toolsmith/astcopy v1.0.1 // indirect - github.com/go-toolsmith/astequal v1.0.2 // indirect + github.com/go-toolsmith/astcopy v1.0.2 // indirect + github.com/go-toolsmith/astequal v1.0.3 // indirect github.com/go-toolsmith/astfmt v1.0.0 // indirect github.com/go-toolsmith/astp v1.0.0 // indirect github.com/go-toolsmith/strparse v1.0.0 // indirect @@ -53,7 +53,7 @@ require ( github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a // indirect + github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect github.com/golangci/misspell v0.3.5 // indirect @@ -111,15 +111,15 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.3.17 // indirect - github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 // indirect + github.com/quasilyte/go-ruleguard v0.3.18 // indirect + github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/ryancurrah/gomodguard v1.2.4 // indirect github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.13.0 // indirect + github.com/sashamelentyev/usestdlibvars v1.14.0 // indirect github.com/securego/gosec/v2 v2.13.1 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.0 // indirect @@ -139,7 +139,7 @@ require ( github.com/stretchr/objx v0.4.0 // indirect github.com/stretchr/testify v1.8.0 // indirect github.com/subosito/gotenv v1.4.0 // indirect - github.com/sylvia7788/contextcheck v1.0.6 // indirect + github.com/sylvia7788/contextcheck v1.0.8 // indirect github.com/tdakkota/asciicheck v0.1.1 // indirect github.com/tetafro/godot v1.4.11 // indirect github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect @@ -156,7 +156,7 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d // indirect + golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect diff --git a/tools/src/golangci-lint/go.sum b/tools/src/golangci-lint/go.sum index 9ec670339b..4640971571 100644 --- a/tools/src/golangci-lint/go.sum +++ b/tools/src/golangci-lint/go.sum @@ -52,8 +52,8 @@ github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7I github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard v1.1.0 h1:pjK9nLPS1FwQYGGpPxoMYpe7qACHOhAWQMQzV71i49o= -github.com/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= +github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= +github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -100,7 +100,7 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/acmd v0.7.0/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= +github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/curioswitch/go-reassign v0.1.2 h1:ekM07+z+VFT560Exz4mTv0/s1yU9gem6CJc/tlYpkmI= github.com/curioswitch/go-reassign v0.1.2/go.mod h1:bFJIHgtTM3hRm2sKXSPkbwNjSFyGURQXyn4IXD2qwfQ= github.com/daixiang0/gci v0.6.3 h1:wUAqXChk8HbwXn8AfxD9DYSCp9Bpz1L3e6Q4Roe+q9E= @@ -131,8 +131,8 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/go-critic/go-critic v0.6.4 h1:tucuG1pvOyYgpBIrVxw0R6gwO42lNa92Aq3VaDoIs+E= -github.com/go-critic/go-critic v0.6.4/go.mod h1:qL5SOlk7NtY6sJPoVCTKDIgzNOxHkkkOCVDyi9wJe1U= +github.com/go-critic/go-critic v0.6.5 h1:fDaR/5GWURljXwF8Eh31T2GZNz9X4jeboS912mWF8Uo= +github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -146,13 +146,12 @@ github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astcopy v1.0.1 h1:l09oBhAPyV74kLJ3ZO31iBU8htZGTwr9LTjuMCyL8go= -github.com/go-toolsmith/astcopy v1.0.1/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= +github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= +github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= -github.com/go-toolsmith/astequal v1.0.2 h1:+XvaV8zNxua+9+Oa4AHmgmpo4RYAbwr/qjNppLfX2yM= github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.0.3 h1:+LVdyRatFS+XO78SGV4I3TCEA0AC7fKEGma+fH+674o= +github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= @@ -204,10 +203,10 @@ github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9 github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.49.0 h1:I8WHOavragDttlLHtSraHn/h39C+R60bEQ5NoGcHQr8= -github.com/golangci/golangci-lint v1.49.0/go.mod h1:+V/7lLv449R6w9mQ3WdV0EKh7Je/jTylMeSwBZcLeWE= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= +github.com/golangci/golangci-lint v1.49.1-0.20220903190357-db4955a3bb7e h1:YFHkdtNp1SbxFx38nro/Xfo7bmQmUlppiZuMomNs4Go= +github.com/golangci/golangci-lint v1.49.1-0.20220903190357-db4955a3bb7e/go.mod h1:oi1vHOkgkQ7qIZ/cDImcbbKTQ/zHRDj35Ux3JWdreoU= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -230,7 +229,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -428,14 +426,14 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.17 h1:cDdoaSbQg11LXPDQqiCK54QmQXsEQQCTIgdcpeULGSI= -github.com/quasilyte/go-ruleguard v0.3.17/go.mod h1:sST5PvaR7yb/Az5ksX8oc88usJ4EGjmJv7cK7y3jyig= +github.com/quasilyte/go-ruleguard v0.3.18 h1:sd+abO1PEI9fkYennwzHn9kl3nqP6M5vE7FiOzZ+5CE= +github.com/quasilyte/go-ruleguard v0.3.18/go.mod h1:lOIzcYlgxrQ2sGJ735EHXmf/e9MJ516j16K/Ifcttvs= github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 h1:PDWGei+Rf2bBiuZIbZmM20J2ftEy9IeUCHA8HbQqed8= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= +github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f h1:6Gtn2i04RD0gVyYf2/IUMTIs+qYleBt4zxDqkLTcu4U= +github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= @@ -451,8 +449,8 @@ github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3 github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.13.0 h1:uObNudVEEHf6JbOJy5bgKJloA1bWjxR9fwgNFpPzKnI= -github.com/sashamelentyev/usestdlibvars v1.13.0/go.mod h1:D2Wb7niIYmTB+gB8z7kh8tyP5ccof1dQ+SFk+WW5NtY= +github.com/sashamelentyev/usestdlibvars v1.14.0 h1:7wPN67PB88SQX3JTUISetLC3j6d2KCI7DtpiQx5XK3A= +github.com/sashamelentyev/usestdlibvars v1.14.0/go.mod h1:D2Wb7niIYmTB+gB8z7kh8tyP5ccof1dQ+SFk+WW5NtY= github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= github.com/securego/gosec/v2 v2.13.1/go.mod h1:EO1sImBMBWFjOTFzMWfTRrZW6M15gm60ljzrmy/wtHo= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= @@ -506,8 +504,8 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= -github.com/sylvia7788/contextcheck v1.0.6 h1:o2EZgVPyMKE/Mtoqym61DInKEjwEbsmyoxg3VrmjNO4= -github.com/sylvia7788/contextcheck v1.0.6/go.mod h1:9XDxwvxyuKD+8N+a7Gs7bfWLityh5t70g/GjdEt2N2M= +github.com/sylvia7788/contextcheck v1.0.8 h1:Uk1S0K326MH6obdpYj1kYriU/g/5oXZM8Dc27ttpezM= +github.com/sylvia7788/contextcheck v1.0.8/go.mod h1:9XDxwvxyuKD+8N+a7Gs7bfWLityh5t70g/GjdEt2N2M= github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= @@ -577,8 +575,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d h1:+W8Qf4iJtMGKkyAygcKohjxTk4JPsL9DpzApJ22m5Ic= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 h1:Ic/qN6TEifvObMGQy72k0n1LlJr7DjWWEi+MOsDOiSk= +golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=