From 134499fa851a00672a8b2120c27e125f5e31ac78 Mon Sep 17 00:00:00 2001 From: Cristovao Cordeiro Date: Mon, 8 Jul 2024 18:33:50 +0200 Subject: [PATCH 1/4] chore(24.04): add README file --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..53405f243 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# ubuntu-24.04 + +This is the `ubuntu-24.04` Chisel release. + +To learn more about Chisel, Chisel releases and how to contribute to this +branch, please read +[this](https://github.com/canonical/chisel-releases/blob/main/README.md). \ No newline at end of file From 468955d1a0936b70dda73010c5a590498d6dff0e Mon Sep 17 00:00:00 2001 From: Cristovao Cordeiro Date: Wed, 17 Jul 2024 07:47:12 +0200 Subject: [PATCH 2/4] ci(spread): support slice testing through Spread --- .github/workflows/ci.yaml | 4 + spread.yaml | 74 +++++++++++++++++++ .../spread/integration/base-passwd/task.yaml | 13 ++++ tests/spread/integration/python3.12/task.yaml | 14 ++++ .../integration/python3.12/test_core.py | 45 +++++++++++ .../integration/python3.12/test_standard.py | 35 +++++++++ tests/spread/lib/install-slices | 10 +++ 7 files changed, 195 insertions(+) create mode 100644 spread.yaml create mode 100644 tests/spread/integration/base-passwd/task.yaml create mode 100644 tests/spread/integration/python3.12/task.yaml create mode 100644 tests/spread/integration/python3.12/test_core.py create mode 100644 tests/spread/integration/python3.12/test_standard.py create mode 100755 tests/spread/lib/install-slices diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 9187a7ee1..06f09607a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,3 +19,7 @@ jobs: lint: name: Lint uses: canonical/chisel-releases/.github/workflows/lint.yaml@main + + integration-tests: + name: Integration tests + uses: canonical/chisel-releases/.github/workflows/spread.yaml@main diff --git a/spread.yaml b/spread.yaml new file mode 100644 index 000000000..1ddafa8e4 --- /dev/null +++ b/spread.yaml @@ -0,0 +1,74 @@ +project: chisel-releases + +path: /chisel-releases + +environment: + PROJECT_PATH: /chisel-releases + SHARED_LIBRARIES: $PROJECT_PATH/tests/spread/lib + PATH: /snap/bin:$PATH:$SHARED_LIBRARIES + +exclude: + - .github + +backends: + docker: + type: adhoc + allocate: | + echo "Allocating $SPREAD_SYSTEM..." + docker_image=$(echo $SPREAD_SYSTEM | awk -F '-' '{print $1":"$2}') + docker_arch=$(echo $SPREAD_SYSTEM | awk -F '-' '{print $NF}') + docker run --rm -e DEBIAN_FRONTEND=noninteractice \ + -e usr=$SPREAD_SYSTEM_USERNAME -e pass=$SPREAD_SYSTEM_PASSWORD \ + --name $SPREAD_SYSTEM -d $docker_arch/$docker_image sh -c ' + set -x + apt update + apt install -y openssh-server sudo + mkdir /run/sshd + echo "root:$pass" | chpasswd + echo "PermitRootLogin yes" >> /etc/ssh/sshd_config + /usr/sbin/sshd -D + ' + # The container will be up really fast, but the CMD might take time to + # run, and Spread will timeout the SSH op after 5 min. So we wait for the + # container during the allocation script. + until docker exec $SPREAD_SYSTEM pgrep sshd + do + sleep 5 + done + ADDRESS `docker inspect $SPREAD_SYSTEM --format '{{.NetworkSettings.Networks.bridge.IPAddress}}'` + discard: docker rm -f $SPREAD_SYSTEM + systems: + - ubuntu-24.04-amd64: + password: ubuntu + - ubuntu-24.04-arm64v8: + password: ubuntu + - ubuntu-24.04-arm32v7: + password: ubuntu + - ubuntu-24.04-ppc64le: + password: ubuntu + - ubuntu-24.04-s390x: + password: ubuntu + # Re-enable risvc64 once we have re-enabled this arch for the Ubuntu container + # - ubuntu-24.04-riscv64: + # password: ubuntu + +prepare: | + # Deb arch to GOARCH + arch="$(dpkg --print-architecture | sed -e 's/armhf/arm/g' -e 's/ppc64el/ppc64le/g')" + chisel_tar="chisel.tar.gz" + + apt install -y curl wget + curl -s https://api.github.com/repos/canonical/chisel/releases/latest \ + | awk "/browser_download_url/ && /chisel_v/ && /$arch/" \ + | cut -d : -f 2,3 \ + | tr -d \" \ + | xargs wget -O $chisel_tar + + tar -xf $chisel_tar -C /usr/local/bin + +prepare-each: + chisel version + +suites: + tests/spread/integration/: + summary: Tests common scenarios diff --git a/tests/spread/integration/base-passwd/task.yaml b/tests/spread/integration/base-passwd/task.yaml new file mode 100644 index 000000000..7b0b74638 --- /dev/null +++ b/tests/spread/integration/base-passwd/task.yaml @@ -0,0 +1,13 @@ +summary: Integration tests for base-passwd + +execute: | + rootfs="$(install-slices base-passwd_data)" + + test -f ${rootfs}/etc/group + ! grep FIXME ${rootfs}/etc/group + + test -f ${rootfs}/etc/passwd + ! grep FIXME ${rootfs}/etc/passwd + + test ! -f ${rootfs}/usr/share/base-passwd/group.master + test ! -f ${rootfs}/usr/share/base-passwd/passwd.master diff --git a/tests/spread/integration/python3.12/task.yaml b/tests/spread/integration/python3.12/task.yaml new file mode 100644 index 000000000..30a2849ee --- /dev/null +++ b/tests/spread/integration/python3.12/task.yaml @@ -0,0 +1,14 @@ +summary: Integration tests for Python3.12 + +environment: + SLICE/core: "core" + SLICE/standard: "standard" + +execute: | + # Test different slice installations + echo "SLICE=${SLICE}" + + rootfs="$(install-slices python3.12_${SLICE})" + + cp test_${SLICE}.py "${rootfs}/" + chroot "$rootfs" python3.12 /test_${SLICE}.py diff --git a/tests/spread/integration/python3.12/test_core.py b/tests/spread/integration/python3.12/test_core.py new file mode 100644 index 000000000..f2c3728a7 --- /dev/null +++ b/tests/spread/integration/python3.12/test_core.py @@ -0,0 +1,45 @@ +""" +Tests some of the core Python functionality +""" + +import sys +import os +import socket +import time +import urllib +import urllib.request + + +def hello_world(): + print("Hello, world!") + + +def check_python_version(): + print("Checking Python version...") + assert sys.version.startswith( + "3.12" + ), f"Wrong Python version installed: {sys.version}. Expected 3.12." + + +def check_file_operations(): + print("Checking file operations...") + filename = f"/test-file-{int(time.time())}" + + with open(filename, "w") as f: + f.write("This is a test file.") + with open(filename, "r") as f: + content = f.read() + os.remove(filename) + print(f"File operations are working. Content: {content}") + + +def check_network_operations(): + print("Checking network operations...") + print(socket.gethostname()) + + +if __name__ == "__main__": + hello_world() + check_python_version() + check_file_operations() + check_network_operations() diff --git a/tests/spread/integration/python3.12/test_standard.py b/tests/spread/integration/python3.12/test_standard.py new file mode 100644 index 000000000..40ef2e2ee --- /dev/null +++ b/tests/spread/integration/python3.12/test_standard.py @@ -0,0 +1,35 @@ +""" +Tests some of the standard Python functionality +""" + +import html +import json +import urllib +import uuid + + +def check_json_loading(): + print("Checking JSON loading...") + + sample = '{"foo": ["bar"]}' + assert json.loads(sample) == {"foo": ["bar"]} + + +def check_html_escaping(): + print("Checking HTML escaping...") + + sample = "Some & 'text' with \"HTML\" characters" + exp = "Some <sample> & 'text' with "HTML" characters" + assert html.escape(sample) == exp + + +def check_uuid_gen(): + print("Checking UUID generation...") + + assert type(uuid.uuid1().int) == int + + +if __name__ == "__main__": + check_json_loading() + check_html_escaping() + check_uuid_gen() diff --git a/tests/spread/lib/install-slices b/tests/spread/lib/install-slices new file mode 100755 index 000000000..c67f99784 --- /dev/null +++ b/tests/spread/lib/install-slices @@ -0,0 +1,10 @@ +#!/bin/bash -ex + +# Installs one or more slices into a dynamically created temporary path. +# Usage: install-slices [...] +# Returns the path of the chiselled rootfs + +tmpdir="$(mktemp -d)" + +echo "${tmpdir}" +chisel cut --release "$PROJECT_PATH" --root "$tmpdir" $@ From 026583b5850dbbaa7399c77cea763ec1cf0b1ef5 Mon Sep 17 00:00:00 2001 From: Cristovao Cordeiro Date: Wed, 17 Jul 2024 07:47:27 +0200 Subject: [PATCH 3/4] fix(python3.12): arm installation needs libgcc-s1 --- slices/libpython3.12-stdlib.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/slices/libpython3.12-stdlib.yaml b/slices/libpython3.12-stdlib.yaml index c74270774..cfd8eb05e 100644 --- a/slices/libpython3.12-stdlib.yaml +++ b/slices/libpython3.12-stdlib.yaml @@ -15,6 +15,13 @@ slices: essential: - libbz2-1.0_libs - libc6_libs + # Adding libgcc-s1 here because it is required for the arm arch. + # In practice, libc6 should bring it anyway, BUT, there is a circular + # dependency in the archives, where libc6 depends on libgcc-s1 and + # vice versa. We don't allow that circular dependency to exist in Chisel + # and libgcc-s1 already depends on libc6, so we'll have to include this + # line here, explicitly. + - libgcc-s1_libs - liblzma5_libs - libpython3.12-minimal_libs - media-types_data From bf19889d55c1f3930993893a037b59c9dc2467ae Mon Sep 17 00:00:00 2001 From: Cristovao Cordeiro Date: Fri, 19 Jul 2024 10:42:28 +0200 Subject: [PATCH 4/4] test(python3.12): add more assertions --- tests/spread/integration/python3.12/test_core.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/spread/integration/python3.12/test_core.py b/tests/spread/integration/python3.12/test_core.py index f2c3728a7..f36798ce0 100644 --- a/tests/spread/integration/python3.12/test_core.py +++ b/tests/spread/integration/python3.12/test_core.py @@ -6,11 +6,12 @@ import os import socket import time -import urllib -import urllib.request def hello_world(): + # Asserting the stdout would require additional modules (like StringIO) + # that are not available in the "core" slice. So this test case only tests + # the functionality, but not the outcome. print("Hello, world!") @@ -25,11 +26,14 @@ def check_file_operations(): print("Checking file operations...") filename = f"/test-file-{int(time.time())}" + original_content = "This is a test file." with open(filename, "w") as f: - f.write("This is a test file.") + f.write(original_content) with open(filename, "r") as f: content = f.read() + assert content == original_content os.remove(filename) + assert not os.path.exists(filename) print(f"File operations are working. Content: {content}")