Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ROCK for contour #1

Merged
merged 11 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
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)
44 changes: 44 additions & 0 deletions rockcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: contour
base: bare
build-base: [email protected]
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

2 changes: 2 additions & 0 deletions tests/.copyright.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Copyright ${years} ${owner}.
See LICENSE file for licensing details
123 changes: 123 additions & 0 deletions tests/integration/test_contour.py
Original file line number Diff line number Diff line change
@@ -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 "<title>httpbin.org</title>" in out
5 changes: 5 additions & 0 deletions tests/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
black==24.3.0
codespell==2.2.4
flake8==6.0.0
isort==5.12.0
licenseheaders==0.8.8
5 changes: 5 additions & 0 deletions tests/requirements-test.txt
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions tests/sanity/test_rock.py
Original file line number Diff line number Diff line change
@@ -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
39 changes: 39 additions & 0 deletions tests/templates/httpbin.yaml
Original file line number Diff line number Diff line change
@@ -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
70 changes: 70 additions & 0 deletions tests/tox.ini
Original file line number Diff line number Diff line change
@@ -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
Loading