From 47c5a19cbd68a414f591cc2cd64df5cfa40a6092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciek=20Go=C5=82aszewski?= Date: Fri, 19 Jul 2024 10:55:30 +0200 Subject: [PATCH] ROCK for contour (#1) --- .github/workflows/pull_request.yaml | 8 +- README.md | 4 +- rockcraft.yaml | 44 ++++++++++ tests/.copyright.tmpl | 2 + tests/integration/test_contour.py | 123 ++++++++++++++++++++++++++++ tests/requirements-dev.txt | 5 ++ tests/requirements-test.txt | 5 ++ tests/sanity/test_rock.py | 20 +++++ tests/templates/httpbin.yaml | 39 +++++++++ tests/tox.ini | 70 ++++++++++++++++ 10 files changed, 317 insertions(+), 3 deletions(-) create mode 100644 rockcraft.yaml create mode 100644 tests/.copyright.tmpl create mode 100644 tests/integration/test_contour.py create mode 100644 tests/requirements-dev.txt create mode 100644 tests/requirements-test.txt create mode 100644 tests/sanity/test_rock.py create mode 100644 tests/templates/httpbin.yaml create mode 100644 tests/tox.ini diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 7cc7788..c068059 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -17,7 +17,13 @@ jobs: # pinning to use rockcraft 1.3.0 feature `entrypoint-service` rockcraft-revisions: '{"amd64": "1783", "arm64": "1784"}' arch-skipping-maximize-build-space: '["arm64"]' - platform-labels: '{"arm64": ["Ubuntu_ARM64_4C_16G_01"]}' + platform-labels: '{"arm64": ["self-hosted", "Linux", "ARM64", "jammy", "large"]}' + run-tests: + uses: canonical/k8s-workflows/.github/workflows/run_tests.yaml@main + needs: [build-and-push-arch-specifics] + secrets: inherit + with: + rock-metas: ${{ needs.build-and-push-arch-specifics.outputs.rock-metas }} scan-images: uses: canonical/k8s-workflows/.github/workflows/scan_images.yaml@main needs: [build-and-push-arch-specifics] diff --git a/README.md b/README.md index 8df0d7b..659d42c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # contour-rock -OCI image for [contour](https://bitnami.com/stack/contour) based on Ubuntu 22.04 built using [rockcraft](https://github.com/canonical/rockcraft). +OCI image for [contour](https://projectcontour.io/) based on Ubuntu 22.04 built using [rockcraft](https://github.com/canonical/rockcraft). -Image is loosely based on original Dockerfile [](https://github.com/bitnami/containers/blob/main/bitnami/contour/1.28/debian-12/Dockerfile) \ No newline at end of file +Image is loosely based on original [Dockerfile](https://github.com/projectcontour/contour/blob/main/Dockerfile) and [Makefile](https://github.com/projectcontour/contour/blob/main/Makefile) diff --git a/rockcraft.yaml b/rockcraft.yaml new file mode 100644 index 0000000..12a1603 --- /dev/null +++ b/rockcraft.yaml @@ -0,0 +1,44 @@ +name: contour +base: bare +build-base: ubuntu@22.04 +license: Apache-2.0 + +version: '1.28.5' +summary: Contour is an open source Kubernetes ingress controller. +description: | + Contour is an open source Kubernetes ingress controller that works by deploying + the Envoy proxy as a reverse proxy and load balancer. + Overview of Contour Trademarks: This software listing is packaged by Bitnami. + The respective trademarks mentioned in the offering are owned by the respective companies, + and use of them does not imply any affiliation or endorsement. +platforms: + amd64: +# arm64: + + +services: + contour: + override: replace + summary: "contour service" + startup: enabled + command: "contour [ -h ]" + on-failure: shutdown + +entrypoint-service: contour + + +parts: + contour: + plugin: nil + source: https://github.com/projectcontour/contour.git + source-type: git + source-tag: v1.28.2 + source-depth: 1 + stage-packages: + - procps + build-snaps: + - go/1.21/stable + override-build: | + make build + cp contour ${CRAFT_PART_INSTALL}/bin/contour + diff --git a/tests/.copyright.tmpl b/tests/.copyright.tmpl new file mode 100644 index 0000000..1eb2340 --- /dev/null +++ b/tests/.copyright.tmpl @@ -0,0 +1,2 @@ +Copyright ${years} ${owner}. +See LICENSE file for licensing details diff --git a/tests/integration/test_contour.py b/tests/integration/test_contour.py new file mode 100644 index 0000000..0f5e71d --- /dev/null +++ b/tests/integration/test_contour.py @@ -0,0 +1,123 @@ +# +# Copyright 2024 Canonical, Ltd. +# See LICENSE file for licensing details +# +import json +import logging +import os + +# import uuid +from pathlib import Path + +from k8s_test_harness import harness +from k8s_test_harness.util import exec_util + +pytest_plugins = ["k8s_test_harness.plugin"] + +LOG = logging.getLogger(__name__) + +# DIR = Path(__file__).absolute().parent +MANIFESTS_DIR = os.path.join(Path(__file__).absolute().parent.parent, "templates") + + +LOG = logging.getLogger(__name__) + + +def test_integration_contour(module_instance: harness.Instance): + image_name_env_variable = "ROCK_CONTOUR" + + image_uri = os.getenv(image_name_env_variable) + assert image_uri is not None, f"{image_name_env_variable} is not set" + image_split = image_uri.split(":") + image = image_split[0].rsplit("/", 1) + + helm_command = [ + "k8s", + "helm", + "install", + "contour", + "--repo", + "https://charts.bitnami.com/bitnami", + "contour", + "--namespace", + "contour", + "--create-namespace", + "--version", + "17.0.4", # chart version with 1.28.2 app + "--set", + "installCRDs=true", + "--set", + f"contour.image.repository={image[1]}", + "--set", + f"contour.image.registry={image[0]}", + "--set", + f"contour.image.tag={image_split[1]}", + "--set", + "securityContext.runAsUser=584792", + ] + + module_instance.exec(helm_command) + + # wait for envoy + exec_util.stubbornly(retries=5, delay_s=5).on(module_instance).exec( + [ + "k8s", + "kubectl", + "rollout", + "status", + "daemonset", + "contour-envoy", + "--namespace", + "contour", + "--timeout", + "180s", + ] + ) + # wait for contour + exec_util.stubbornly(retries=5, delay_s=1).on(module_instance).exec( + [ + "k8s", + "kubectl", + "rollout", + "status", + "deployment", + "contour-contour", + "--namespace", + "contour", + "--timeout", + "180s", + ] + ) + + # deploy for httpbin + manifest = os.path.join("templates", "httpbin.yaml") + module_instance.exec( + ["k8s", "kubectl", "apply", "-f", "-"], + input=Path(manifest).read_bytes(), + ) + + result = ( + exec_util.stubbornly(retries=5, delay_s=1) + .on(module_instance) + .exec( + ["k8s", "kubectl", "get", "svc", "httpbin", "-o", "json"], + capture_output=True, + ) + ) + assert result.returncode == 0, "Failed to get httpbin service" + qwe = json.loads(result.stdout.decode()) + awd = qwe["spec"]["clusterIP"] + resp = ( + exec_util.stubbornly(retries=15, delay_s=5) + .on(module_instance) + .exec( + [ + "curl", + f"{awd}:8888", + ], + capture_output=True, + ) + ) + + out = resp.stdout.decode() + assert "httpbin.org" in out diff --git a/tests/requirements-dev.txt b/tests/requirements-dev.txt new file mode 100644 index 0000000..a66721a --- /dev/null +++ b/tests/requirements-dev.txt @@ -0,0 +1,5 @@ +black==24.3.0 +codespell==2.2.4 +flake8==6.0.0 +isort==5.12.0 +licenseheaders==0.8.8 diff --git a/tests/requirements-test.txt b/tests/requirements-test.txt new file mode 100644 index 0000000..ff57d6b --- /dev/null +++ b/tests/requirements-test.txt @@ -0,0 +1,5 @@ +coverage[toml]==7.2.5 +pytest==7.3.1 +PyYAML==6.0.1 +tenacity==8.2.3 +git+https://github.com/canonical/k8s-test-harness.git@main diff --git a/tests/sanity/test_rock.py b/tests/sanity/test_rock.py new file mode 100644 index 0000000..fd3ba17 --- /dev/null +++ b/tests/sanity/test_rock.py @@ -0,0 +1,20 @@ +# +# Copyright 2024 Canonical, Ltd. +# See LICENSE file for licensing details +# +import os +import subprocess + + +def test_sanity(): + image_variable = "ROCK_CONTOUR" + entrypoint = "contour" + image = os.getenv(image_variable) + assert image is not None, f"${image_variable} is not set" + + docker_run = subprocess.run( + ["docker", "run", "--rm", "--entrypoint", entrypoint, image, "--help"], + capture_output=True, + text=True, + ) + assert "Contour Kubernetes ingress controller." in docker_run.stderr diff --git a/tests/templates/httpbin.yaml b/tests/templates/httpbin.yaml new file mode 100644 index 0000000..2df7038 --- /dev/null +++ b/tests/templates/httpbin.yaml @@ -0,0 +1,39 @@ +## +## Copyright 2024 Canonical, Ltd. +## See LICENSE file for licensing details +## +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: httpbin + name: httpbin +spec: + replicas: 3 + selector: + matchLabels: + app: httpbin + template: + metadata: + labels: + app: httpbin + spec: + containers: + - image: docker.io/kennethreitz/httpbin + name: httpbin +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: httpbin + name: httpbin +spec: + ports: + - port: 8888 + protocol: TCP + targetPort: 80 + selector: + app: httpbin + sessionAffinity: None + type: ClusterIP diff --git a/tests/tox.ini b/tests/tox.ini new file mode 100644 index 0000000..a038b15 --- /dev/null +++ b/tests/tox.ini @@ -0,0 +1,70 @@ +[tox] +no_package = True +skip_missing_interpreters = True +env_list = format, lint, integration +min_version = 4.0.0 + +[testenv] +set_env = + PYTHONBREAKPOINT=pdb.set_trace + PY_COLORS=1 +pass_env = + PYTHONPATH + +[testenv:format] +description = Apply coding style standards to code +deps = -r {tox_root}/requirements-dev.txt +commands = + licenseheaders -t {tox_root}/.copyright.tmpl -cy -o 'Canonical, Ltd' -d {tox_root} + isort {tox_root} --profile=black + black {tox_root} + +[testenv:lint] +description = Check code against coding style standards +deps = -r {tox_root}/requirements-dev.txt +commands = + codespell {tox_root} --skip=".tox" + flake8 {tox_root} + licenseheaders -t {tox_root}/.copyright.tmpl -cy -o 'Canonical, Ltd' -d {tox_root} --dry + isort {tox_root} --profile=black --check + black {tox_root} --check --diff + +[testenv:sanity] +description = Run integration tests +deps = + -r {tox_root}/requirements-test.txt +commands = + pytest -v \ + --maxfail 1 \ + --tb native \ + --log-cli-level DEBUG \ + --disable-warnings \ + {posargs} \ + {tox_root}/sanity +pass_env = + TEST_* + ROCK_* + +[testenv:integration] +description = Run integration tests +deps = + -r {tox_root}/requirements-test.txt +commands = + pytest -v \ + --maxfail 1 \ + --tb native \ + --log-cli-level DEBUG \ + --disable-warnings \ + {posargs} \ + {tox_root}/integration +pass_env = + TEST_* + ROCK_* + + +[flake8] +max-line-length = 120 +select = E,W,F,C,N +ignore = W503 +exclude = venv,.git,.tox,.tox_env,.venv,build,dist,*.egg_info +show-source = true