...

Text file src/github.com/datawire/ambassador/v2/python/tests/integration/test_knative.py

Documentation: github.com/datawire/ambassador/v2/python/tests/integration

     1import logging
     2import os
     3import sys
     4
     5import pytest
     6
     7import tests.integration.manifests as integration_manifests
     8from ambassador import IR, Config
     9from ambassador.fetch import ResourceFetcher
    10from ambassador.utils import NullSecretHandler, parse_bool
    11from kat.harness import is_knative_compatible
    12from tests.integration.utils import create_qotm_mapping, get_code_with_retry, install_ambassador
    13from tests.kubeutils import apply_kube_artifacts
    14from tests.manifests import qotm_manifests
    15from tests.runutils import run_and_assert
    16
    17logger = logging.getLogger("ambassador")
    18
    19# knative_service_example gets applied to the cluster with `kubectl --namespace=knative-testing
    20# apply`; we therefore DO NOT explicitly set the 'namespace:' because --namespace will imply it, and
    21# explicitly setting anything only adds room for something else to go wrong.
    22knative_service_example = """
    23---
    24apiVersion: serving.knative.dev/v1alpha1
    25kind: Service
    26metadata:
    27 name: helloworld-go
    28spec:
    29 template:
    30   spec:
    31     containers:
    32     - image: gcr.io/knative-samples/helloworld-go
    33       env:
    34       - name: TARGET
    35         value: "Ambassador is Awesome"
    36"""
    37
    38# knative_ingress_example is not applied to the cluster, but is instead fed directly to the
    39# ResourceFetcher; so we MUST explicitly set the namespace, because we can't rely on kubectl and/or
    40# the apiserver to auto-populate it for us.
    41knative_ingress_example = """
    42apiVersion: networking.internal.knative.dev/v1alpha1
    43kind: Ingress
    44metadata:
    45  name: helloworld-go
    46  namespace: default
    47spec:
    48  rules:
    49  - hosts:
    50    - helloworld-go.default.svc.cluster.local
    51    http:
    52      paths:
    53      - retries:
    54          attempts: 3
    55          perTryTimeout: 10m0s
    56        splits:
    57        - percent: 100
    58          serviceName: helloworld-go-qf94m
    59          servicePort: 80
    60        timeout: 10m0s
    61    visibility: ClusterLocal
    62  visibility: ExternalIP
    63"""
    64
    65
    66class KnativeTesting:
    67    def test_knative(self):
    68        namespace = "knative-testing"
    69
    70        # Install Knative
    71        apply_kube_artifacts(
    72            namespace=None, artifacts=integration_manifests.load("knative_serving_crds")
    73        )
    74        apply_kube_artifacts(
    75            namespace="knative-serving",
    76            artifacts=integration_manifests.load("knative_serving_0.18.0"),
    77        )
    78        run_and_assert(
    79            [
    80                "tools/bin/kubectl",
    81                "patch",
    82                "configmap/config-network",
    83                "--type",
    84                "merge",
    85                "--patch",
    86                r'{"data": {"ingress.class": "ambassador.ingress.networking.knative.dev"}}',
    87                "-n",
    88                "knative-serving",
    89            ]
    90        )
    91
    92        # Wait for Knative to become ready
    93        run_and_assert(
    94            [
    95                "tools/bin/kubectl",
    96                "wait",
    97                "--timeout=90s",
    98                "--for=condition=Ready",
    99                "pod",
   100                "-l",
   101                "app=activator",
   102                "-n",
   103                "knative-serving",
   104            ]
   105        )
   106        run_and_assert(
   107            [
   108                "tools/bin/kubectl",
   109                "wait",
   110                "--timeout=90s",
   111                "--for=condition=Ready",
   112                "pod",
   113                "-l",
   114                "app=controller",
   115                "-n",
   116                "knative-serving",
   117            ]
   118        )
   119        run_and_assert(
   120            [
   121                "tools/bin/kubectl",
   122                "wait",
   123                "--timeout=90s",
   124                "--for=condition=Ready",
   125                "pod",
   126                "-l",
   127                "app=webhook",
   128                "-n",
   129                "knative-serving",
   130            ]
   131        )
   132        run_and_assert(
   133            [
   134                "tools/bin/kubectl",
   135                "wait",
   136                "--timeout=90s",
   137                "--for=condition=Ready",
   138                "pod",
   139                "-l",
   140                "app=autoscaler",
   141                "-n",
   142                "knative-serving",
   143            ]
   144        )
   145
   146        # Install Ambassador
   147        install_ambassador(
   148            namespace=namespace, envs=[{"name": "AMBASSADOR_KNATIVE_SUPPORT", "value": "true"}]
   149        )
   150
   151        # Install QOTM
   152        apply_kube_artifacts(namespace=namespace, artifacts=qotm_manifests)
   153        create_qotm_mapping(namespace=namespace)
   154
   155        # Now let's wait for ambassador and QOTM pods to become ready
   156        run_and_assert(
   157            [
   158                "tools/bin/kubectl",
   159                "wait",
   160                "--timeout=90s",
   161                "--for=condition=Ready",
   162                "pod",
   163                "-l",
   164                "service=ambassador",
   165                "-n",
   166                namespace,
   167            ]
   168        )
   169        run_and_assert(
   170            [
   171                "tools/bin/kubectl",
   172                "wait",
   173                "--timeout=90s",
   174                "--for=condition=Ready",
   175                "pod",
   176                "-l",
   177                "service=qotm",
   178                "-n",
   179                namespace,
   180            ]
   181        )
   182
   183        # Create kservice
   184        apply_kube_artifacts(namespace=namespace, artifacts=knative_service_example)
   185
   186        # Assume we can reach Ambassador through telepresence
   187        qotm_host = "ambassador." + namespace
   188
   189        # Assert 200 OK at /qotm/ endpoint
   190        qotm_url = f"http://{qotm_host}/qotm/"
   191        code = get_code_with_retry(qotm_url)
   192        assert code == 200, f"Expected 200 OK, got {code}"
   193        print(f"{qotm_url} is ready")
   194
   195        # Assert 200 OK at / with Knative Host header and 404 with other/no header
   196        kservice_url = f"http://{qotm_host}/"
   197
   198        code = get_code_with_retry(kservice_url)
   199        assert code == 404, f"Expected 404, got {code}"
   200        print(f"{kservice_url} returns 404 with no host")
   201
   202        code = get_code_with_retry(kservice_url, headers={"Host": "random.host.whatever"})
   203        assert code == 404, f"Expected 404, got {code}"
   204        print(f"{kservice_url} returns 404 with a random host")
   205
   206        # Wait for kservice
   207        run_and_assert(
   208            [
   209                "tools/bin/kubectl",
   210                "wait",
   211                "--timeout=90s",
   212                "--for=condition=Ready",
   213                "ksvc",
   214                "helloworld-go",
   215                "-n",
   216                namespace,
   217            ]
   218        )
   219
   220        # kservice pod takes some time to spin up, so let's try a few times
   221        code = 000
   222        host = f"helloworld-go.{namespace}.example.com"
   223        for _ in range(5):
   224            code = get_code_with_retry(kservice_url, headers={"Host": host})
   225            if code == 200:
   226                break
   227
   228        assert code == 200, f"Expected 200, got {code}"
   229        print(f"{kservice_url} returns 200 OK with host helloworld-go.{namespace}.example.com")
   230
   231
   232def test_knative_counters():
   233    aconf = Config()
   234    fetcher = ResourceFetcher(logger, aconf)
   235    fetcher.parse_yaml(knative_ingress_example, k8s=True)
   236    aconf.load_all(fetcher.sorted())
   237
   238    secret_handler = NullSecretHandler(logger, None, None, "0")
   239    ir = IR(aconf, secret_handler=secret_handler)
   240    feats = ir.features()
   241
   242    assert feats["knative_ingress_count"] == 1, f"Expected a Knative ingress, did not find one"
   243    assert (
   244        feats["cluster_ingress_count"] == 0
   245    ), f"Expected no Knative cluster ingresses, found at least one"
   246
   247
   248@pytest.mark.flaky(reruns=1, reruns_delay=10)
   249def test_knative():
   250    if not parse_bool(os.environ.get("AMBASSADOR_PYTEST_KNATIVE_TEST", "false")):
   251        pytest.xfail("AMBASSADOR_PYTEST_KNATIVE_TEST is not set, xfailing...")
   252
   253    if is_knative_compatible():
   254        knative_test = KnativeTesting()
   255        knative_test.test_knative()
   256    else:
   257        pytest.xfail("Knative is not supported")
   258
   259
   260if __name__ == "__main__":
   261    pytest.main(sys.argv)

View as plain text