From b783210b2edfdb4b549b91605cbfd502d4bf3f4f Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Fri, 9 Oct 2026 21:53:49 +0000 Subject: [PATCH 01/16] migrate test images to tailor Replace the tests/images Python builder with a tailor workspace and legacy image-name mapping. Update the image build pipeline and local docs to use tailor commands and selectors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../build_image/build-image-template.yml | 103 +++- .../trident-testimg-template.yml | 2 +- docs/Development/Testing/E2E-Tests.md | 61 +-- docs/Development/Testing/Functional-Tests.md | 9 +- docs/Development/Testing/Rollback-Tests.md | 2 +- docs/Development/Testing/Servicing-Tests.md | 13 +- tests/images/README.md | 66 +++ tests/images/azl-installer/image.yaml | 18 + .../by-arch/arm64.yaml | 3 + .../image.yaml | 19 + .../tailor/baseimg.yaml | 68 +++ tests/images/builder/README.md | 130 ----- tests/images/builder/__init__.py | 272 ---------- tests/images/builder/builder.py | 501 ------------------ tests/images/builder/cli.py | 303 ----------- tests/images/builder/context_managers.py | 63 --- tests/images/builder/convert.py | 87 --- tests/images/builder/customize.py | 169 ------ tests/images/builder/download.py | 41 -- tests/images/builder/run.py | 175 ------ tests/images/builder/sign.py | 474 ----------------- tests/images/builder/utils.py | 24 - .../by-arch+source/arm64+ubuntu-2204.yaml | 3 + .../by-arch+source/arm64+ubuntu-2404.yaml | 3 + .../by-source/gb200-2404.yaml | 3 + .../by-source/ubuntu-2404.yaml | 3 + .../image.yaml | 16 + tests/images/legacy-map.json | 263 +++++++++ tests/images/tailor.yaml | 76 +++ tests/images/testimages.py | 267 ---------- .../trident-container-installer/README.md | 2 +- .../trident-container-installer/image.yaml | 13 + .../tailor/baseimg.yaml | 71 +++ .../trident-container-testimage/README.md | 2 +- .../trident-container-testimage/image.yaml | 13 + .../tailor/baseimg.yaml | 71 +++ tests/images/trident-functest/image.yaml | 13 + .../trident-functest/tailor/baseimg.yaml | 75 +++ tests/images/trident-installer/README.md | 17 +- .../trident-installer/by-arch/arm64.yaml | 3 + .../by-variant/direct-streaming.yaml | 3 + .../trident-installer/by-variant/split.yaml | 3 + tests/images/trident-installer/image.yaml | 26 + .../tailor/baseimg-direct-streaming.yaml | 90 ++++ .../tailor/baseimg-split.yaml | 74 +++ .../trident-installer/tailor/baseimg.yaml | 81 +++ tests/images/trident-testimage/README.md | 4 +- .../trident-testimage/by-arch/arm64.yaml | 3 + tests/images/trident-testimage/image.yaml | 19 + .../trident-testimage/tailor/baseimg.yaml | 66 +++ .../images/trident-verity-testimage/README.md | 10 +- .../by-deployment+mode/container+root.yaml | 3 + .../by-deployment+mode/container+usr.yaml | 4 + .../by-deployment+mode/host+root.yaml | 5 + .../by-deployment+mode/host+usr.yaml | 6 + .../by-deployment/host.yaml | 2 + .../trident-verity-testimage/image.yaml | 17 + .../tailor/baseimg-container.yaml | 112 ++++ .../tailor/baseimg.yaml | 110 ++++ .../tailor/usr-container.yaml | 104 ++++ .../tailor/usr-host.yaml | 106 ++++ .../trident-vm-testimage/by-arch/arm64.yaml | 3 + .../by-scenario/acl-agent.yaml | 3 + .../by-scenario/grub-verity-azure.yaml | 6 + .../by-scenario/grub-verity.yaml | 3 + .../by-scenario/grub.yaml | 3 + .../by-scenario/root-verity.yaml | 3 + .../by-scenario/usr-verity.yaml | 3 + tests/images/trident-vm-testimage/image.yaml | 23 + .../tailor/baseimg-root-verity.yaml | 151 ++++++ .../tailor/baseimg-usr-verity.yaml | 141 +++++ .../tailor/updateimg-acl-agent.yaml | 170 ++++++ .../tailor/updateimg-grub-verity-azure.yaml | 127 +++++ .../tailor/updateimg-grub-verity.yaml | 122 +++++ .../tailor/updateimg-grub.yaml | 75 +++ 75 files changed, 2625 insertions(+), 2573 deletions(-) create mode 100644 tests/images/README.md create mode 100644 tests/images/azl-installer/image.yaml create mode 100644 tests/images/azurelinux-direct-streaming-testimage/by-arch/arm64.yaml create mode 100644 tests/images/azurelinux-direct-streaming-testimage/image.yaml create mode 100644 tests/images/azurelinux-direct-streaming-testimage/tailor/baseimg.yaml delete mode 100644 tests/images/builder/README.md delete mode 100644 tests/images/builder/__init__.py delete mode 100644 tests/images/builder/builder.py delete mode 100644 tests/images/builder/cli.py delete mode 100644 tests/images/builder/context_managers.py delete mode 100644 tests/images/builder/convert.py delete mode 100644 tests/images/builder/customize.py delete mode 100644 tests/images/builder/download.py delete mode 100644 tests/images/builder/run.py delete mode 100644 tests/images/builder/sign.py delete mode 100644 tests/images/builder/utils.py create mode 100644 tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2204.yaml create mode 100644 tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2404.yaml create mode 100644 tests/images/foreign-direct-streaming-testimage/by-source/gb200-2404.yaml create mode 100644 tests/images/foreign-direct-streaming-testimage/by-source/ubuntu-2404.yaml create mode 100644 tests/images/foreign-direct-streaming-testimage/image.yaml create mode 100644 tests/images/legacy-map.json create mode 100644 tests/images/tailor.yaml delete mode 100755 tests/images/testimages.py create mode 100644 tests/images/trident-container-installer/image.yaml create mode 100644 tests/images/trident-container-installer/tailor/baseimg.yaml create mode 100644 tests/images/trident-container-testimage/image.yaml create mode 100644 tests/images/trident-container-testimage/tailor/baseimg.yaml create mode 100644 tests/images/trident-functest/image.yaml create mode 100644 tests/images/trident-functest/tailor/baseimg.yaml create mode 100644 tests/images/trident-installer/by-arch/arm64.yaml create mode 100644 tests/images/trident-installer/by-variant/direct-streaming.yaml create mode 100644 tests/images/trident-installer/by-variant/split.yaml create mode 100644 tests/images/trident-installer/image.yaml create mode 100644 tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml create mode 100644 tests/images/trident-installer/tailor/baseimg-split.yaml create mode 100644 tests/images/trident-installer/tailor/baseimg.yaml create mode 100644 tests/images/trident-testimage/by-arch/arm64.yaml create mode 100644 tests/images/trident-testimage/image.yaml create mode 100644 tests/images/trident-testimage/tailor/baseimg.yaml create mode 100644 tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml create mode 100644 tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml create mode 100644 tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml create mode 100644 tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml create mode 100644 tests/images/trident-verity-testimage/by-deployment/host.yaml create mode 100644 tests/images/trident-verity-testimage/image.yaml create mode 100644 tests/images/trident-verity-testimage/tailor/baseimg-container.yaml create mode 100644 tests/images/trident-verity-testimage/tailor/baseimg.yaml create mode 100644 tests/images/trident-verity-testimage/tailor/usr-container.yaml create mode 100644 tests/images/trident-verity-testimage/tailor/usr-host.yaml create mode 100644 tests/images/trident-vm-testimage/by-arch/arm64.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/grub.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/root-verity.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml create mode 100644 tests/images/trident-vm-testimage/image.yaml create mode 100644 tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml create mode 100644 tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml create mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml create mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml create mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml create mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml diff --git a/.pipelines/templates/stages/build_image/build-image-template.yml b/.pipelines/templates/stages/build_image/build-image-template.yml index 75b3521d6b..55212e7004 100644 --- a/.pipelines/templates/stages/build_image/build-image-template.yml +++ b/.pipelines/templates/stages/build_image/build-image-template.yml @@ -82,8 +82,17 @@ steps: retryCountOnTaskFailure: 3 - bash: | - ./tests/images/testimages.py show-image ${{ parameters.imageName }} base-image --devops-var baseImageType - displayName: "Get Image Info" + set -euo pipefail + python3 - <<'PY' "${{ parameters.imageName }}" +import json +import sys +from pathlib import Path + +legacy = json.loads(Path("tests/images/legacy-map.json").read_text()) +entry = legacy[sys.argv[1]] +print(f"##vso[task.setvariable variable=baseImageType]{entry['baseImage']}") +PY + displayName: "Resolve image metadata" workingDirectory: ${{ parameters.tridentSourceDirectory }} - bash: | @@ -120,7 +129,7 @@ steps: - bash: | set -ex - # Move base VHDX to artifacts/ (builder expects artifacts/*.vhdx) + # Move base VHDX to artifacts/ (tailor baseImages catalogue points at artifacts/*.vhdx) mkdir -p artifacts if ls "$(Build.ArtifactStagingDirectory)/images" | grep -q ".*\.vhdx$"; then mv $(Build.ArtifactStagingDirectory)/images/*.vhdx artifacts/ @@ -144,7 +153,7 @@ steps: DISTRO=azl4 fi - # Move Trident RPMs to bin/RPMS/ (builder expects bin/RPMS/*.rpm) + # Move Trident RPMs to bin/RPMS/ (tailor rpmSources point at bin/RPMS/) if [ -d "$(Build.ArtifactStagingDirectory)/trident" ]; then mkdir -p bin/RPMS find "$(Build.ArtifactStagingDirectory)/trident" -name "*${DISTRO}*.rpm" -exec mv {} bin/RPMS/ \; @@ -154,18 +163,86 @@ steps: workingDirectory: ${{ parameters.tridentSourceDirectory }} - bash: | - set -ex - - EXTRA_ARGS="" + set -euo pipefail + + legacy_name='${{ parameters.imageName }}' + export PATH="$HOME/.cargo/bin:$PATH" + export CLICOLOR_FORCE=1 + + readarray -t selector_lines < <(python3 - <<'PY' "$legacy_name" +import json +import sys +from pathlib import Path + +entry = json.loads(Path("tests/images/legacy-map.json").read_text())[sys.argv[1]] +print(entry["image"]) +print(entry["ext"]) +print(entry.get("tailorExt", entry["ext"])) +for key, value in entry["selectors"].items(): + print(f"{key}={value}") +PY +) + + tailor_image="${selector_lines[0]}" + artifact_ext="${selector_lines[1]}" + source_ext="${selector_lines[2]}" + selector_args=() + if (( ${#selector_lines[@]} > 3 )); then + for selector in "${selector_lines[@]:3}"; do + selector_args+=("-s" "$selector") + done + fi + manifest_path=tests/images/tailor.yaml if [[ "${{ parameters.micBuildType }}" == "dev" ]]; then - EXTRA_ARGS+=" --container imagecustomizer:dev" + manifest_path=tests/images/.tailor.pipeline.yaml + python3 - <<'PY' +from pathlib import Path +text = Path("tests/images/tailor.yaml").read_text() +needle = """toolchains: + default: ic + entries: + - name: ic + container: mcr.microsoft.com/azurelinux/imagecustomizer + tag: latest +""" +replacement = """toolchains: + default: ic-dev + entries: + - name: ic + container: mcr.microsoft.com/azurelinux/imagecustomizer + tag: latest + - name: ic-dev + container: imagecustomizer + tag: dev + pull: never +""" +Path("tests/images/.tailor.pipeline.yaml").write_text(text.replace(needle, replacement, 1)) +PY + fi + + matrix_json=$(cargo run --manifest-path tools/tailor/Cargo.toml --quiet -- --manifest "$manifest_path" matrix "$tailor_image" --format json "${selector_args[@]}") + + slug=$(python3 - <<'PY' "$matrix_json" +import json +import sys +cells = json.loads(sys.argv[1]) +if len(cells) != 1: + raise SystemExit(f"expected exactly one cell, got {len(cells)}") +print(cells[0]["slug"]) +PY +) + + cargo run --manifest-path tools/tailor/Cargo.toml --quiet -- --manifest "$manifest_path" build "$tailor_image" "${selector_args[@]}" --output-dir $(ob_outputDirectory) --clones ${{ parameters.clones }} + + if [[ ${{ parameters.clones }} -eq 1 ]]; then + mv "$(ob_outputDirectory)/${slug}.${source_ext}" "$(ob_outputDirectory)/${legacy_name}.${artifact_ext}" + else + for ((i=0; i<${{ parameters.clones }}; i++)); do + mv "$(ob_outputDirectory)/${slug}_clone${i}.${source_ext}" "$(ob_outputDirectory)/${legacy_name}_${i}.${artifact_ext}" + done fi - python3 ./tests/images/testimages.py build \ - "${{ parameters.imageName }}" $EXTRA_ARGS \ - --output-dir $(ob_outputDirectory) \ - --no-download \ - --clones ${{ parameters.clones }} + rm -f tests/images/.tailor.pipeline.yaml displayName: "Build ${{ parameters.imageName }}" workingDirectory: ${{ parameters.tridentSourceDirectory }} diff --git a/.pipelines/templates/stages/trident_images/trident-testimg-template.yml b/.pipelines/templates/stages/trident_images/trident-testimg-template.yml index c2d53a4694..993f65f602 100644 --- a/.pipelines/templates/stages/trident_images/trident-testimg-template.yml +++ b/.pipelines/templates/stages/trident_images/trident-testimg-template.yml @@ -135,7 +135,7 @@ steps: displayName: Copy SSH Keys - script: | - echo "##[warning]THE PIPELINE TEMPLATE trident-testimg-template.yaml IS DEPRECATED. PLEASE SWITCH TO USING testimages.py TO BUILD TEST IMAGES." + echo "##[warning]THE PIPELINE TEMPLATE trident-testimg-template.yaml IS DEPRECATED. PLEASE SWITCH TO USING the tailor workspace under tests/images." cat /etc/os-release displayName: "Report Host Info" diff --git a/docs/Development/Testing/E2E-Tests.md b/docs/Development/Testing/E2E-Tests.md index 13169b5e42..0ec172c2a8 100644 --- a/docs/Development/Testing/E2E-Tests.md +++ b/docs/Development/Testing/E2E-Tests.md @@ -132,8 +132,8 @@ make bin/rcp-agent # Remote control plane agent ### 4. Build Trident RPMs The **host** test images include Trident packages built from your local tree. -This step builds the RPMs into `bin/RPMS/`, which `testimages.py` passes to -Image Customizer via `--rpm-source`: +This step builds the RPMs into `bin/RPMS/`, which the `tests/images` tailor +workspace passes to Image Customizer via `rpmSources:`: ```bash make bin/trident-rpms.tar.gz @@ -168,8 +168,7 @@ make artifacts/id_rsa ### 7. Download Base Image ```bash -# Downloads baremetal.vhdx from MCR -./tests/images/testimages.py download-image baremetal +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml bases download baremetal ``` ### 8. Build COSI Images @@ -184,29 +183,27 @@ then rename them into `artifacts/test-image/`. ```bash mkdir -p artifacts/test-image -# Build two clones (produces trident-testimage_0.cosi and trident-testimage_1.cosi) -sudo ./tests/images/testimages.py build trident-testimage \ - --output-dir ./artifacts/test-image --clones 2 +# Build two clones (produces trident-testimage_amd64_cosi_clone0.cosi and +# trident-testimage_amd64_cosi_clone1.cosi) +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-testimage -s arch=amd64 --output-dir ./artifacts/test-image --clones 2 # Rename clones to the filenames referenced by Host Configurations -mv artifacts/test-image/trident-testimage_0.cosi artifacts/test-image/regular.cosi -mv artifacts/test-image/trident-testimage_1.cosi artifacts/test-image/regular_v2.cosi +mv artifacts/test-image/trident-testimage_amd64_cosi_clone0.cosi artifacts/test-image/regular.cosi +mv artifacts/test-image/trident-testimage_amd64_cosi_clone1.cosi artifacts/test-image/regular_v2.cosi ``` Repeat for other image types as needed: ```bash # Verity image (for root-verity configuration) -sudo ./tests/images/testimages.py build trident-verity-testimage \ - --output-dir ./artifacts/test-image --clones 2 -mv artifacts/test-image/trident-verity-testimage_0.cosi artifacts/test-image/verity.cosi -mv artifacts/test-image/trident-verity-testimage_1.cosi artifacts/test-image/verity_v2.cosi +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-verity-testimage -s deployment=host -s mode=root --output-dir ./artifacts/test-image --clones 2 +mv artifacts/test-image/trident-verity-testimage_host_root_amd64_cosi_clone0.cosi artifacts/test-image/verity.cosi +mv artifacts/test-image/trident-verity-testimage_host_root_amd64_cosi_clone1.cosi artifacts/test-image/verity_v2.cosi # UKI/usr-verity image (for usr-verity, combined configurations) -sudo ./tests/images/testimages.py build trident-usrverity-testimage \ - --output-dir ./artifacts/test-image --clones 2 -mv artifacts/test-image/trident-usrverity-testimage_0.cosi artifacts/test-image/usrverity.cosi -mv artifacts/test-image/trident-usrverity-testimage_1.cosi artifacts/test-image/usrverity_v2.cosi +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-verity-testimage -s deployment=host -s mode=usr --output-dir ./artifacts/test-image --clones 2 +mv artifacts/test-image/trident-verity-testimage_host_usr_amd64_cosi_clone0.cosi artifacts/test-image/usrverity.cosi +mv artifacts/test-image/trident-verity-testimage_host_usr_amd64_cosi_clone1.cosi artifacts/test-image/usrverity_v2.cosi ``` #### Container Runtime Images @@ -220,26 +217,23 @@ URLs work unchanged: mkdir -p artifacts/test-image # Regular container image -sudo ./tests/images/testimages.py build trident-container-testimage \ - --output-dir ./artifacts/test-image --clones 2 -mv artifacts/test-image/trident-container-testimage_0.cosi artifacts/test-image/regular.cosi -mv artifacts/test-image/trident-container-testimage_1.cosi artifacts/test-image/regular_v2.cosi +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-container-testimage --output-dir ./artifacts/test-image --clones 2 +mv artifacts/test-image/trident-container-testimage_amd64_cosi_clone0.cosi artifacts/test-image/regular.cosi +mv artifacts/test-image/trident-container-testimage_amd64_cosi_clone1.cosi artifacts/test-image/regular_v2.cosi # Verity container image (for root-verity configuration) -sudo ./tests/images/testimages.py build trident-container-verity-testimage \ - --output-dir ./artifacts/test-image --clones 2 -mv artifacts/test-image/trident-container-verity-testimage_0.cosi artifacts/test-image/verity.cosi -mv artifacts/test-image/trident-container-verity-testimage_1.cosi artifacts/test-image/verity_v2.cosi +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-verity-testimage -s deployment=container -s mode=root --output-dir ./artifacts/test-image --clones 2 +mv artifacts/test-image/trident-verity-testimage_container_root_amd64_cosi_clone0.cosi artifacts/test-image/verity.cosi +mv artifacts/test-image/trident-verity-testimage_container_root_amd64_cosi_clone1.cosi artifacts/test-image/verity_v2.cosi # UKI/usr-verity container image (for usr-verity, combined configurations) -sudo ./tests/images/testimages.py build trident-container-usrverity-testimage \ - --output-dir ./artifacts/test-image --clones 2 -mv artifacts/test-image/trident-container-usrverity-testimage_0.cosi artifacts/test-image/usrverity.cosi -mv artifacts/test-image/trident-container-usrverity-testimage_1.cosi artifacts/test-image/usrverity_v2.cosi +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-verity-testimage -s deployment=container -s mode=usr --output-dir ./artifacts/test-image --clones 2 +mv artifacts/test-image/trident-verity-testimage_container_usr_amd64_cosi_clone0.cosi artifacts/test-image/usrverity.cosi +mv artifacts/test-image/trident-verity-testimage_container_usr_amd64_cosi_clone1.cosi artifacts/test-image/usrverity_v2.cosi ``` -The images use the Image Customizer container from -`mcr.microsoft.com/azurelinux/imagecustomizer:latest`. +The workspace defaults to the Image Customizer container declared in +`tests/images/tailor.yaml` (`mcr.microsoft.com/azurelinux/imagecustomizer:latest`). ### 9. Build the Installer ISO @@ -255,8 +249,9 @@ make bin/trident-mos.iso **Container runtime:** ```bash -sudo ./tests/images/testimages.py build trident-container-installer \ - --output-dir ./artifacts +cargo run --manifest-path tools/tailor/Cargo.toml -- \ + --manifest tests/images/tailor.yaml \ + build trident-container-installer --output-dir ./artifacts ``` This builds `artifacts/trident-container-installer.iso` using Image Customizer. diff --git a/docs/Development/Testing/Functional-Tests.md b/docs/Development/Testing/Functional-Tests.md index 2a4d79b99f..f4bdd1115b 100644 --- a/docs/Development/Testing/Functional-Tests.md +++ b/docs/Development/Testing/Functional-Tests.md @@ -47,18 +47,17 @@ and a base image also from MCR. 1. **Download the base image:** ```bash - # Downloads baremetal.vhdx from mcr.microsoft.com/azurelinux/3.0/image/baremetal:latest - ./tests/images/testimages.py download-image baremetal + cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml bases download baremetal ``` 2. **Build the functional test image:** ```bash - sudo ./tests/images/testimages.py build trident-functest --output-dir ./artifacts + cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-functest --output-dir ./artifacts ``` - This produces `artifacts/trident-functest.qcow2`. The image configuration is - defined in `tests/images/trident-functest/base/baseimg.yaml`. + This produces `artifacts/trident-functest.qcow2`. The image is selected from + the `trident-functest` family in `tests/images/tailor.yaml`. ## Building Test Dependencies diff --git a/docs/Development/Testing/Rollback-Tests.md b/docs/Development/Testing/Rollback-Tests.md index 385fd77ee2..cf7e694f56 100644 --- a/docs/Development/Testing/Rollback-Tests.md +++ b/docs/Development/Testing/Rollback-Tests.md @@ -128,7 +128,7 @@ TEST_IMAGE_NAME="trident-vm-usr-verity-testimage" sudo rm -f artifacts/trident-vm-*-testimage.qcow2 artifacts/trident-vm-*-testimage.cosi # Build the COSI and QCOW2 -sudo ./tests/images/testimages.py build $TEST_IMAGE_NAME --output-dir ./artifacts +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-vm-testimage -s arch=amd64 -s scenario=usr-verity --output-dir ./artifacts make artifacts/$TEST_IMAGE_NAME.qcow2 ``` diff --git a/docs/Development/Testing/Servicing-Tests.md b/docs/Development/Testing/Servicing-Tests.md index af1eb33b92..dd3cc5de14 100644 --- a/docs/Development/Testing/Servicing-Tests.md +++ b/docs/Development/Testing/Servicing-Tests.md @@ -105,7 +105,7 @@ step, so the base image's pre-installed package set does not matter. :::tip Internal shortcut If you have access to the internal Azure DevOps artifacts feed, the Makefile downloads `qemu_guest` automatically (requires `az login`). You can also -download it directly: `./tests/images/testimages.py download-image qemu_guest` +download it directly: `cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml bases download qemu_guest` ::: ### 5. Build the VM Image @@ -131,15 +131,12 @@ the same filename in each directory (the update loop picks the filename from ```bash mkdir -p artifacts/update-a artifacts/update-b -# Build two clones of the COSI image (produces _0 and _1 suffixed files) -sudo ./tests/images/testimages.py build trident-vm-grub-verity-testimage \ - --output-dir ./artifacts --clones 2 +# Build two clones of the COSI image +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-vm-testimage -s arch=amd64 -s scenario=grub-verity --output-dir ./artifacts --clones 2 # Move the clones into the update directories with the same filename -mv artifacts/trident-vm-grub-verity-testimage_0.cosi \ - artifacts/update-a/trident-vm-grub-verity-testimage.cosi -mv artifacts/trident-vm-grub-verity-testimage_1.cosi \ - artifacts/update-b/trident-vm-grub-verity-testimage.cosi +mv artifacts/trident-vm-testimage_amd64_grub-verity_cosi_clone0.cosi artifacts/update-a/trident-vm-grub-verity-testimage.cosi +mv artifacts/trident-vm-testimage_amd64_grub-verity_cosi_clone1.cosi artifacts/update-b/trident-vm-grub-verity-testimage.cosi ``` :::note diff --git a/tests/images/README.md b/tests/images/README.md new file mode 100644 index 0000000000..fbd8ac44df --- /dev/null +++ b/tests/images/README.md @@ -0,0 +1,66 @@ +# Test images with tailor + +`tests/images/` is now a [tailor](../../tools/tailor/README.md) workspace. +The legacy `testimages.py` / `builder/` flow is removed. + +## Build from the repo root + +Use the in-tree tailor binary via Cargo: + +```bash +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml matrix trident-installer --format json +``` + +Build examples: + +```bash +# trident-testimage +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-testimage -s arch=amd64 --output-dir ./artifacts + +# trident-testimage-arm64 +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-testimage -s arch=arm64 --output-dir ./artifacts + +# trident-direct-streaming-installer-arm64 +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-installer -s arch=arm64 -s variant=direct-streaming --output-dir ./artifacts + +# trident-container-usrverity-testimage (signed) +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-verity-testimage -s deployment=container -s mode=usr --output-dir ./artifacts +``` + +## Base images + +The workspace uses a `baseImages:` catalogue in `tests/images/tailor.yaml`. +For the Azure Linux base slots you can materialize the defaults locally with: + +```bash +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml bases download baremetal core_arm64 core_selinux qemu_guest +``` + +Verify that every referenced base file exists: + +```bash +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml bases verify +``` + +Ubuntu / GB200 direct-streaming inputs still come from the pipeline-managed blob +staging flow; those slots are intentionally catalogued without an in-workspace +remote source. + +## Legacy name mapping + +Pipelines still accept the historical image names. `tests/images/legacy-map.json` +maps each legacy name to the tailor image family, selectors, expected base slot, +and published artifact extension. + +The current families are: + +- `azl-installer` +- `azurelinux-direct-streaming-testimage` +- `foreign-direct-streaming-testimage` +- `trident-container-installer` +- `trident-container-testimage` +- `trident-functest` +- `trident-installer` +- `trident-testimage` +- `trident-verity-testimage` +- `trident-vm-testimage` diff --git a/tests/images/azl-installer/image.yaml b/tests/images/azl-installer/image.yaml new file mode 100644 index 0000000000..0622ba3131 --- /dev/null +++ b/tests/images/azl-installer/image.yaml @@ -0,0 +1,18 @@ +name: azl-installer + +base: + ref: baremetal + +outputs: + - format: iso + +rpmSources: + - ../../../bin/RPMS + +extraDependencies: + - ./installer-iso.yaml + - ./mos + - ./iso + +config: + $include: ./installer-iso.yaml diff --git a/tests/images/azurelinux-direct-streaming-testimage/by-arch/arm64.yaml b/tests/images/azurelinux-direct-streaming-testimage/by-arch/arm64.yaml new file mode 100644 index 0000000000..6fe6f6f38d --- /dev/null +++ b/tests/images/azurelinux-direct-streaming-testimage/by-arch/arm64.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: core_arm64 diff --git a/tests/images/azurelinux-direct-streaming-testimage/image.yaml b/tests/images/azurelinux-direct-streaming-testimage/image.yaml new file mode 100644 index 0000000000..c6cca2f107 --- /dev/null +++ b/tests/images/azurelinux-direct-streaming-testimage/image.yaml @@ -0,0 +1,19 @@ +name: azurelinux-direct-streaming-testimage + +matrix: + arch: [amd64, arm64] + +base: + ref: baremetal + +outputs: + - format: baremetal-image + +rpmSources: + - ../../../bin/RPMS + +extraDependencies: + - ./base + +config: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/azurelinux-direct-streaming-testimage/tailor/baseimg.yaml b/tests/images/azurelinux-direct-streaming-testimage/tailor/baseimg.yaml new file mode 100644 index 0000000000..a6af1726ae --- /dev/null +++ b/tests/images/azurelinux-direct-streaming-testimage/tailor/baseimg.yaml @@ -0,0 +1,68 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 15G + partitions: + - id: esp + type: esp + size: 50M + label: esp + - id: root-a + size: 4G + type: root + label: root-a + - id: root-b + size: 4G + type: root + label: root-b + - id: swap + size: 2G + type: swap + label: swap + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: root-a + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-rawcosi-testimage + selinux: + mode: permissive + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + packages: + install: + - curl + - dnf + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - openssh-server + - tpm2-tools + - vim + - audit + - device-mapper + - dosfstools + - lvm2 + - veritysetup + - ntfs-3g + - ntfsprogs + - selinux-policy + services: + enable: + - sshd diff --git a/tests/images/builder/README.md b/tests/images/builder/README.md deleted file mode 100644 index 0fafbd66a9..0000000000 --- a/tests/images/builder/README.md +++ /dev/null @@ -1,130 +0,0 @@ -# Builder - -Builder is a Python tool to declare, customize, and build images with AZL Image Customizer locally and in the pipelines. - -## Overview - -Builder is a builder system designed around declarative image definitions that wraps around the AZL Image Customizer concepts and API. - -`testimages.py` script in the top-level directory contains declarative definitions of all images and artifacts, such as the Image Customizer container. It is a convenient entry point for building an image locally or in the pipelines. To learn more about the supported commands, run: - -```bash -python3 ./testimages.py --help -``` - -## Directory Structure - -```md -builder/ -├── __init__.py # Definitions of wrappers around Image Customizer concepts -├── builder.py # High-level logic for building image clones -├── cli.py # Command-line interface and command execution -├── context_managers.py # Utilities for resource cleanup -├── customize.py # Image Customizer API wrapper -├── download.py # Utilities for image download -├── README.md # README -├── run.py # Core build functions and orchestration -└── sign.py # Utilities for image signing -``` - -## Key Components - -### `__init__.py` - -Defines foundational data structures and enums used throughout Builder. Specifically, defines `ImageConfig`, which represents an Image Customizer config, and `ArtifactManifest`, which describes the Image Cuztomizer container to be used for building images. - -Also, contains a series of other definitions that represent the base image type, output format, system architecture, etc. - -### `cli.py` - -Implements Builder's command-line interface and executes commands such as `build()`. Most of the high-level logic happens in `cli.init()`, which orchestrates the entire build process. - -### `run.py` - -Contains the implementations of the core functions supported by Builder, such as `build()` or `generate_matrix()`. - -### `builder.py` - -This is where the high-level logic around building images, signed and unsigned, lives. This file calls into Image Customizer APIs inside `customize.py` to build images, using cloning and parallel processing. - -### `customize.py` - -Wrapper around the AZL Image Customizer API. Only container-based execution is now supported since running IC as a raw binary is no longer supported. - -Specifically, provides APIs for (1) building an image and (2) injecting signed boot artifacts into an image via the preview feature `inject-files`. - -### Utility Files - -#### `sign.py` - -Utility functions needed for signing an image built via Image Customizer. This is needed for enabling `SecureBoot` in a host. - -#### `download.py` - -Utility functions for downloading images as AZ artifacts. - -#### `context_managers.py` - -Utility functions for resource cleanup. - -## Key Concepts - -### Image Cloning - -The builder supports creating multiple clones of the same image with different UUIDs. This is essential for testing updates where you need identical images with unique identifiers: - -### Parallel Processing - -The system uses Python's `multiprocessing` package to build image clones in parallel, significantly reducing build times. Each clone is built in its own process with a deep copy of the `ImageConfig` object to avoid race conditions. - -### Resource Management - -The builder uses `ExitStack()` context managers to ensure proper cleanup of temporary resources. - -## Running Builder - -Builder can be run locally as a stand-alone tool: - -```bash - python3 ./testimages.py -``` - -The following commands are supported: - -```bash - # List images available for building - python3 ./testimages.py list - # Download a base image: baremetal, core_selinux, qemu_guest, or minimal - python3 ./testimages.py download-image - # List required dependencies for an image - python3 ./testimages.py dependencies - # Build an image locally - python3 ./testimages.py build - # Show key info about the image, such as name, source, config path, etc. - python3 ./testimages.py show-image - # Show info on key artifacts, such as the Image Customizer version or container image - python3 ./testimages.py show-artifact - # List images that have been built and are available to be used - python3 ./testimages.py list-files -``` - -To build an image with Builder or test your changes to Builder, follow these steps: - -1. If necessary, make changes to the Builder source code. -1. Download the base image: - -```bash - ./testimages.py download-image -``` - -1. If necessary, update the Image Customizer config for the image you want to build, by modifying the corresponding YAML in `test-images/platform-integration-images`. You can also find the relevant YAML by running: - -```bash - python3 ./testimages.py show-image config-file -``` - -1. Build the image: - -```bash - python3 ./testimages.py build --output-dir --no-download --clones -``` diff --git a/tests/images/builder/__init__.py b/tests/images/builder/__init__.py deleted file mode 100644 index ca82f58db9..0000000000 --- a/tests/images/builder/__init__.py +++ /dev/null @@ -1,272 +0,0 @@ -import yaml - -from dataclasses import dataclass, field, fields -from enum import Enum -from pathlib import Path -from typing import List, Optional - - -@dataclass -class BaseImageData: - name: str - path: Path - - -class BaseImage(Enum): - BAREMETAL = BaseImageData("baremetal", Path("artifacts/baremetal.vhdx")) - CORE_SELINUX = BaseImageData("core_selinux", Path("artifacts/core_selinux.vhdx")) - QEMU_GUEST = BaseImageData("qemu_guest", Path("artifacts/qemu_guest.vhdx")) - CORE_ARM64 = BaseImageData("core_arm64", Path("artifacts/core_arm64.vhdx")) - MINIMAL = BaseImageData("minimal", Path("artifacts/minimal.vhdx")) - MINIMAL_AARCH64 = BaseImageData( - "minimal_aarch64", Path("artifacts/minimal_aarch64.vhdx") - ) - UBUNTU_2204_AMD64 = BaseImageData( - "ubuntu_2204_amd64", Path("artifacts/ubuntu_2204_amd64.vhdx") - ) - UBUNTU_2204_ARM64 = BaseImageData( - "ubuntu_2204_arm64", Path("artifacts/ubuntu_2204_arm64.vhdx") - ) - UBUNTU_2404_AMD64 = BaseImageData( - "ubuntu_2404_amd64", Path("artifacts/ubuntu_2404_amd64.vhdx") - ) - UBUNTU_2404_ARM64 = BaseImageData( - "ubuntu_2404_arm64", Path("artifacts/ubuntu_2404_arm64.vhdx") - ) - GB200_2404_ARM64 = BaseImageData( - "gb200_2404_arm64", Path("artifacts/gb200_2404_arm64.vhdx") - ) - - @property - def path(self) -> Path: - return self.value.path - - @property - def name(self) -> str: - return self.value.name - - def __str__(self) -> str: - return self.value.name - - -@dataclass -class BaseImageManifest: - image: BaseImage - package_name: str - version: str - org: str = "https://dev.azure.com/mariner-org/" - project: str = "36d030d6-1d99-4ebd-878b-09af1f4f722f" - feed: str = "AzureLinuxArtifacts" - glob: str = "*.vhdx" - - -class OutputFormat(Enum): - BAREMETAL_IMAGE = "baremetal-image" - COSI = "cosi" - VHDX = "vhdx" - RAW = "raw" - QCOW2 = "qcow2" - ISO = "iso" - VHD = "vhd" - VHD_FIXED = "vhd-fixed" - - def ic_name(self): - """Return the Image Customizer name for this format.""" - return self.value - - def ext(self) -> str: - """Return the file extension for this format.""" - if self == OutputFormat.VHD_FIXED: - return "vhd" - elif self == OutputFormat.BAREMETAL_IMAGE: - return "cosi" - return self.value - - -class RpmSources(Enum): - TRIDENT = Path("bin/RPMS") - DHCP = Path("artifacts/dhcp") - RPM_OVERRIDES = Path("artifacts/rpm-overrides") - - def path(self) -> Path: - return self.value - - -class SystemArchitecture(Enum): - AMD64 = "amd64" - ARM64 = "arm64" - - def __str__(self) -> str: - return self.value - - -@dataclass -class ImageConfig: - # Friendly name of the image - name: str - - # Top level config dir - source: str = "tests/images" - - # Second-level dir, generally same as name - config: str = None - - # YAML config file inside the config dir - config_file: Path = Path("base/baseimg.yaml") - - # The base image to use - base_image: BaseImage = BaseImage.BAREMETAL - - # Whether the image requires Trident RPMs - requires_trident: bool = True - - # Whether the image requires DHCP RPMs - requires_dhcp: bool = False - - # Desired output format for this image - output_format: OutputFormat = OutputFormat.COSI - - # Extra dependencies for this image - extra_dependencies: List[Path] = field(default_factory=list) - - # Requires ukify to be present on the host - requires_ukify: bool = False - - # When present, path to write a public SSH key to for customizer to consume - # into the image. Both keys will be written to the output directory. - ssh_key: Optional[Path] = None - - # Architecture of the image - architecture: SystemArchitecture = SystemArchitecture.AMD64 - - # Use ImageCustomizer convert command rather than customize - image_customizer_convert: bool = False - - @classmethod - def kebab_fields(cls) -> List[str]: - """Return a list of fields in kebab-case.""" - return [f.name.replace("_", "-") for f in fields(cls)] - - def __post_init__(self): - self.suffix = None - if not self.config: - self.config = self.name - - # Update the ssh key to be a Path object if it's a string - if isinstance(self.ssh_key, str): - self.ssh_key = Path(self.ssh_key) - - # Update config_file to be a Path object if it's a string - if isinstance(self.config_file, str): - self.config_file = Path(self.config_file) - - # Automatically set the architecture to arm64 if the base image is ARM64 - if self.base_image == BaseImage.CORE_ARM64: - self.architecture = SystemArchitecture.ARM64 - - # Placeholder for the loaded base Image Customizer config - self.__base_ic_config = None - - @property - def base_ic_config(self) -> dict: - """Lazy-load and return the base Image Customizer config as a dict.""" - if self.__base_ic_config is None: - try: - with open(self.full_yaml_path(), "r") as f: - self.__base_ic_config = yaml.safe_load(f) - except Exception as e: - raise RuntimeError( - f"Error loading image config '{self.full_yaml_path()}': {e}" - ) from e - return self.__base_ic_config - - def base_dir(self) -> Path: - return Path(self.source) / self.config - - def full_yaml_path(self) -> Path: - return self.base_dir() / self.config_file - - def dependencies(self) -> List[Path]: - deps = [self.base_image.path] - if not self.image_customizer_convert: - deps.append(self.full_yaml_path()) - for file in self.base_dir().rglob("*"): - if file.is_file(): - deps.append(file) - self.base_dir().glob - if self.requires_trident: - deps.append(RpmSources.TRIDENT.path()) - deps.extend(RpmSources.TRIDENT.path().rglob("*.rpm")) - if self.requires_dhcp: - deps.append(RpmSources.DHCP.path()) - deps.extend(RpmSources.DHCP.path().rglob("*.rpm")) - deps.extend(self.extra_dependencies) - return deps - - def file_name(self) -> str: - """ - Returns the file name for the image. - """ - return f"{self.id}.{self.output_format.ext()}" - - def file_name_unsigned_raw(self) -> str: - """Returns the file name for the unsigned raw image.""" - return f"{self.id}-unsigned.{OutputFormat.RAW.ext()}" - - def set_suffix(self, suffix: str) -> None: - self.suffix = suffix - - @property - def id(self) -> str: - """Return the image ID.""" - if self.suffix is None: - return self.name - return f"{self.name}_{self.suffix}" - - def get_output_artifacts_dir(self) -> Optional[str]: - """ - Return the output.artifacts.path from the image configuration YAML. - - Throws: - ValueError if the path is present but empty. - """ - path = self.base_ic_config.get("output", {}).get("artifacts", {}).get("path") - if path is not None and not path: - raise ValueError("output.artifacts.path cannot be empty") - return path - - def get_items_to_sign(self) -> List[str]: - """Return the list of items to sign from the image configuration YAML.""" - return ( - self.base_ic_config.get("output", {}).get("artifacts", {}).get("items", []) - ) - - -# IMPORTANT: THESE NAMES ARE EXPOSED IN THE CLI, MAKE SURE TO UPDATE ALL -# REFERENCES IF YOU CHANGE THEM! -@dataclass -class ArtifactManifest: - customizer_version: str - customizer_container: str - customizer_container_full: str = None - base_images: List[BaseImageManifest] = field(default_factory=list) - - def __post_init__(self): - if self.customizer_container_full is None: - self.customizer_container_full = self.customizer_container - if ":" not in self.customizer_container_full: - self.customizer_container_full = ( - f"{self.customizer_container}:{self.customizer_version}" - ) - - @classmethod - def kebab_fields(cls) -> List[str]: - """Return a list of fields in kebab-case.""" - return [f.name.replace("_", "-") for f in fields(cls)] - - def find_base_image(self, img: BaseImage) -> Optional[BaseImageManifest]: - """Find a base image by its name.""" - for base_image in self.base_images: - if base_image.image == img: - return base_image - return None diff --git a/tests/images/builder/builder.py b/tests/images/builder/builder.py deleted file mode 100644 index 3c066d0216..0000000000 --- a/tests/images/builder/builder.py +++ /dev/null @@ -1,501 +0,0 @@ -import copy -import logging -import multiprocessing -import multiprocessing.dummy -import re -import shutil -import yaml -import threading -import tempfile - -from contextlib import ExitStack -from cryptography.hazmat.backends import default_backend as crypto_default_backend -from cryptography.hazmat.primitives import serialization as crypto_serialization -from cryptography.hazmat.primitives.asymmetric import rsa, ed25519 -from pathlib import Path -from typing import List, Optional, Tuple - -from builder import ( - ArtifactManifest, - ImageConfig, - OutputFormat, - convert, - customize, - sign, -) -from builder.context_managers import temp_dir, temp_file - -logging.basicConfig(level=logging.INFO) -log = logging.getLogger(__name__) - -# Name of helper configuration file generated by Image Customizer under the same directory as -# output artifacts, when output.artifacts feature is used. This file is used to inject signed -# artifacts back into an image. Docs: -# https://microsoft.github.io/azure-linux-image-tools/imagecustomizer/api/configuration/injectFilesConfig.html. -INJECT_FILES_YAML = "inject-files.yaml" - - -def build_image( - *, - container_image: str, - image: ImageConfig, - output_dir: Path, - artifacts: ArtifactManifest, - clones: int = 1, - rpm_sources: List[Path] = [], - image_architecture: Optional[str] = None, - dry_run: bool = False, - force: bool = False, -): - """Build the image using the specified Image Customizer container.""" - - if not dry_run: - # Create the output directory if it doesn't exist - output_dir.mkdir(parents=True, exist_ok=True) - log.info(f"Output directory: {output_dir}") - - ssh_file = generate_ssh_keys( - output_dir, - image, - dry_run=dry_run, - ) - - # If image needs signing, generate a CA certificate - ca_tmp_dir, ca_nss_key_db = None, None - if image.get_output_artifacts_dir(): - ca_tmp_dir = Path(tempfile.mkdtemp(prefix="ca_")) - ca_nss_key_db = sign.generate_ca_certificate(ca_tmp_dir) - - try: - if clones == 1: - build_one( - container_image, - image, - output_dir, - rpm_sources, - image_architecture, - dry_run, - force, - ca_nss_key_db=ca_nss_key_db, - ) - else: - # Parallel execution - build_with_clones( - container_image, - image, - output_dir, - clones, - rpm_sources, - image_architecture, - dry_run, - force, - ca_nss_key_db=ca_nss_key_db, - ) - - # Publish the CA certificate to the output dir - if ca_nss_key_db and not dry_run: - sign.publish_ca_certificate(ca_nss_key_db, output_dir) - - finally: - if ssh_file: - # Clean up the SSH key file - ssh_file.unlink(missing_ok=True) - log.info(f"SSH key file {ssh_file} removed.") - - # Clean up the CA temporary directory - if ca_tmp_dir: - shutil.rmtree(ca_tmp_dir, ignore_errors=True) - log.info(f"CA temporary directory {ca_tmp_dir} removed.") - - -def build_one( - container_image: str, - image: ImageConfig, - output_dir: Path, - rpm_sources: List[Path] = [], - image_architecture: Optional[str] = None, - dry_run: bool = False, - force: bool = False, - ca_nss_key_db: Optional[Path] = None, -): - for dep in image.dependencies(): - if not dep.exists(): - raise FileNotFoundError(f"Dependency '{dep}' does not exist.") - - # Check if final image output exists, to see if building is necessary - output_file = output_dir / image.file_name() - if output_file.exists(): - log.info(f"Output file {output_file} already exists.") - if force: - log.info(f"Force build requested for '{image.id}', rebuilding.") - else: - dest_mod_time = output_file.stat().st_mtime - for dep in image.dependencies(): - if dep.is_dir(): - # Ignore directories - continue - if dep.stat().st_mtime > dest_mod_time: - log.info(f"Dependency '{dep}' is newer than output file.") - break - else: - log.info(f"Output file {output_file} is up to date.") - return output_file - - if image.image_customizer_convert: - # If 'convert' is requested, run Image Customizer convert subcommand - convert.convert_image( - container_image, - image.id, - image.base_image.path, - image.output_format.ic_name(), - output_file, - image_architecture, - dry_run, - ) - else: - # Copy RPM sources to standalone temporary directories - with ExitStack() as stack: - tmp_rpm_sources = [] - for rpm_src in rpm_sources: - # Create a temporary directory for each RPM source, delete with sudo because - # createrepo is run as root. - tmp = stack.enter_context( - temp_dir(prefix=f"rpm-{rpm_src.stem}-", sudo=True) - ) - tmp_rpm_sources.append(tmp) - log.debug(f"Copying RPM source {rpm_src} to {tmp}") - shutil.copytree(rpm_src, tmp, dirs_exist_ok=True) - - if image.get_output_artifacts_dir(): - # If config YAML contains output.artifacts, then need to output signed image. First, build - # an unsigned image; then, sign boot artifacts, and inject the signed copies back, to build - # a signed image as final output. - build_signed_image( - stack, - container_image, - image, - tmp_rpm_sources, - output_dir, - output_file, - ca_nss_key_db, - image_architecture, - dry_run, - ) - else: - # Otherwise, only build an unsigned image - customize.build_config( - container_image, - image.id, - image.full_yaml_path(), - image.base_image.path, - image.output_format.ic_name(), - output_file, - tmp_rpm_sources, - image_architecture, - dry_run, - ) - - output_file = output_dir / image.file_name() - log.info(f"Image '{image.id}' built successfully in {output_file}") - - -def build_with_clones( - container_image: str, - image: ImageConfig, - output_dir: Path, - clones: int, - rpm_sources: List[Path] = [], - image_architecture: Optional[str] = None, - dry_run: bool = False, - force: bool = False, - ca_nss_key_db: Optional[Path] = None, -): - # Build all the clones in parallel - build_clones( - container_image, - image, - output_dir, - clones, - rpm_sources, - image_architecture, - dry_run, - force, - ca_nss_key_db=ca_nss_key_db, - ) - - # In the future, when enabled by Prism, we want to build an intermediate - # image and then build the clones from that image. Leaving that code here - # for future reference. - - # # Extract kernel command line config - # with open(yaml_path, "r") as f: - # config = yaml.load(f, Loader=yaml.Loader) - # kernel_cmdline = ( - # config.get("os", {}).get("kernelCommandLine", {}).get("extraCommandLine", []) - # ) - - # # Run the build process once for the intermediate image. - # intermediate_img = build_one( - # build_runtime, - # f"{config_name}-intermediate", - # yaml_path, - # base_image, - # OutputFormat.RAW, - # output_dir, - # rpm_sources, - # dry_run, - # ) - - # log.info(f"Intermediate image created: {intermediate_img}") - - # cfg = tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", suffix=".yaml") - # try: - # final_yaml = yaml.dump( - # { - # "storage": { - # "resetPartitionsUuidsType": "reset-all", - # }, - # "os": { - # "bootloader": { - # "resetType": "hard-reset", - # }, - # # Preserve the kernel command line from the original config - # "kernelCommandLine": { - # "extraCommandLine": kernel_cmdline, - # }, - # }, - # }, - # Dumper=yaml.Dumper, - # ) - # log.debug(f"Final YAML:\n{final_yaml}") - # cfg.write(final_yaml) - # cfg.flush() - # cfg.seek(0) - - # build_clones( - # build_runtime, - # config_name, - # Path(cfg.name), - # intermediate_img, - # img_format, - # output_dir, - # clones, - # rpm_sources, - # dry_run, - # ) - # finally: - # # Clean up the temporary files - # cfg.close() - # intermediate_img.unlink(missing_ok=True) - - -def build_clones( - container_image: str, - image: ImageConfig, - output_dir: Path, - clones: int, - rpm_sources: List[Path] = [], - image_architecture: Optional[str] = None, - dry_run: bool = False, - force: bool = False, - ca_nss_key_db: Optional[Path] = None, -): - def clone_image(image: ImageConfig, clone_index: int) -> ImageConfig: - img = copy.deepcopy(image) - img.set_suffix(str(clone_index)) - return img - - pool = multiprocessing.dummy.Pool(clones) - try: - log.info(f"Building {clones} clones of {image.name}") - results = pool.starmap( - build_one, - [ - ( - container_image, - clone_image(image, i), - output_dir, - rpm_sources, - image_architecture, - dry_run, - force, - ca_nss_key_db, - ) - for i in range(clones) - ], - ) - return results - finally: - pool.close() - pool.join() - - -def generate_ssh_keys( - output_dir: Path, - image: ImageConfig, - dry_run: bool = False, -) -> Optional[Path]: - """Generate SSH keys for the image.""" - if not image.ssh_key: - return - - # the artifact path is relative to the image's YAML file - artifact_path = image.full_yaml_path().parent / image.ssh_key - - if artifact_path.exists(): - log.warning( - f"SSH key file {artifact_path} already exists, not generating a new key!" - ) - return artifact_path - - filename = image.ssh_key.name - m = re.match(r"^id_(rsa|ed25519).pub$", filename) - if not m: - raise ValueError(f"Invalid SSH key name: {filename}") - - key_type = m.group(1) - - if key_type == "rsa": - key = rsa.generate_private_key( - backend=crypto_default_backend(), public_exponent=65537, key_size=2048 - ) - elif key_type == "ed25519": - key = ed25519.Ed25519PrivateKey.generate() - else: - raise ValueError(f"Unsupported SSH key type: {key_type}") - - private_key = key.private_bytes( - crypto_serialization.Encoding.PEM, - crypto_serialization.PrivateFormat.TraditionalOpenSSL, - crypto_serialization.NoEncryption(), - ) - - public_key = key.public_key().public_bytes( - crypto_serialization.Encoding.OpenSSH, crypto_serialization.PublicFormat.OpenSSH - ) - - if dry_run: - print(f"Dry run: would generate SSH keys for {image.name}") - print(f"Private key: {private_key.decode()}") - print(f"Public key: {public_key.decode()}") - return - - # Write the private key to a file - private_key_path = output_dir / f"key_{image.name}_private.pem" - public_key_path = output_dir / f"key_{image.name}_public.pub" - with open(private_key_path, "wb") as f: - f.write(private_key) - with open(public_key_path, "wb") as f: - f.write(public_key) - - with open(artifact_path, "wb") as f: - f.write(public_key) - log.info(f"SSH keys generated for {image.name}") - - return artifact_path - - -def build_signed_image( - stack: ExitStack, - container_image: str, - image: ImageConfig, - tmp_rpm_sources: List[Path], - output_dir: Path, - output_file: Path, - ca_nss_key_db: Path, - image_architecture: Optional[str] = None, - dry_run: bool = False, -): - - # Set up thread-specific YAML and output artifacts directory - working_yaml_path, output_artifacts_dir = setup_temp_yaml_and_dir(stack, image) - - # Construct the path to the unsigned image - unsigned_output_file = output_artifacts_dir / image.file_name_unsigned_raw() - log.debug( - f"Process with PID {threading.get_ident()} will write unsigned image and output artifacts to {output_artifacts_dir.absolute()}" - ) - - # Build the unsigned image - customize.build_config( - container_image, - image.id, - working_yaml_path, - image.base_image.path, - # Set output format of unsigned image to raw file since that's the format used - # internally by Image Customizer for file injection - OutputFormat.RAW.ic_name(), - unsigned_output_file, - tmp_rpm_sources, - image_architecture, - dry_run, - ) - - log.info(f"Building signed image: {output_file}") - - # Generate a leaf certificate for this clone using the CA certificate. The leaf certificate - # must be generated in the same NSS key database as the CA certificate. - leaf_key_name = sign.generate_leaf_certificate(ca_nss_key_db, image.id) - - # Construct full path of inject-files.yaml - inject_files_yaml_path = output_artifacts_dir / INJECT_FILES_YAML - # Sign boot artifacts that Image Customizer output when building the unsigned image - sign.sign_boot_artifacts( - ca_nss_key_db, - leaf_key_name, - inject_files_yaml_path, - output_artifacts_dir, - ) - - # Run inject-files via Image Customizer to inject the signed UKI back into the image - log.info( - f"Running imagecustomizer inject-files using YAML: {inject_files_yaml_path}" - ) - log.debug( - f"Contents of output artifacts directory: {output_artifacts_dir}:\n" - + "\n".join([str(p) for p in output_artifacts_dir.rglob("*") if p.is_file()]) - ) - customize.inject_files( - container_image, - inject_files_yaml_path, - unsigned_output_file, - image.output_format.ic_name(), - output_file, - dry_run, - ) - - -def setup_temp_yaml_and_dir( - stack: ExitStack, - image: ImageConfig, -) -> Tuple[Path, Path]: - """ - Sets up a temporary YAML file and output artifacts directory for building a signed image. - Returns the path to the temporary YAML file and the output artifacts directory. - """ - - # Figure out the directory of the main YAML file - yaml_dir = image.full_yaml_path().parent.absolute() - - # Create a temp dir inside yaml_dir to store the unsigned image and output artifacts - output_artifacts_dir = stack.enter_context( - temp_dir(prefix=f".{image.id}-", dir=yaml_dir, sudo=True) - ) - - # Now figure out the relative path from yaml_dir to output_artifacts_dir - tmp_rel_path = output_artifacts_dir.absolute().relative_to(yaml_dir) - - # Update the in-memory config, this is safe because every thread has its own copy of the YAML. - # We use the relative path because the path should be relative to the YAML location. - image.base_ic_config["output"]["artifacts"]["path"] = f"./{tmp_rel_path}" - - # Create a thread-specific copy of YAML in the same dir as main YAML - working_yaml_path = yaml_dir / f".config_{image.id}.yaml" - - with open(working_yaml_path, "w") as f: - yaml.safe_dump(image.base_ic_config, f) - - # Ensure the temp YAML file is deleted at the end - stack.enter_context(temp_file(working_yaml_path)) - - return working_yaml_path, output_artifacts_dir diff --git a/tests/images/builder/cli.py b/tests/images/builder/cli.py deleted file mode 100644 index 741f0c2396..0000000000 --- a/tests/images/builder/cli.py +++ /dev/null @@ -1,303 +0,0 @@ -import argparse -from enum import Enum -import logging -from pathlib import Path - -from typing import List - -from builder import ( - ImageConfig, - ArtifactManifest, - SystemArchitecture, - run, -) - - -logging.basicConfig(level=logging.INFO) -log = logging.getLogger("trident-testimages") - - -def positive_int(value) -> int: - ivalue = int(value) - if ivalue < 1: - raise argparse.ArgumentTypeError(f"{value} is an invalid positive int value") - return ivalue - - -class SubCommand(Enum): - LIST = "list" - DEPENDENCIES = "dependencies" - BUILD = "build" - LIST_FILES = "list-files" - SHOW_ARTIFACT = "show-artifact" - SHOW_IMAGE = "show-image" - DOWNLOAD_IMAGE = "download-image" - MATRIX = "matrix" - - -def init(configs: List[ImageConfig], artifacts: ArtifactManifest) -> None: - parser = argparse.ArgumentParser( - description="Get dependency list for specific image" - ) - subparsers = parser.add_subparsers( - help="Thing to do", dest="command", required=True, metavar="COMMAND" - ) - - setup_parser_list(subparsers) - setup_parser_show(subparsers, artifacts) - setup_subparser_dependencies(subparsers) - setup_parser_build(subparsers, configs, artifacts) - setup_parser_list_files(subparsers) - setup_parser_download_image(subparsers, artifacts) - setup_parser_matrix(subparsers) - setup_parser_image_info(subparsers, configs) - - args = parser.parse_args() - subcommand = SubCommand(args.command) - - run_cmd(configs, artifacts, subcommand, args) - - -def positive_int(value) -> int: - ivalue = int(value) - if ivalue < 1: - raise argparse.ArgumentTypeError(f"{value} is an invalid positive int value") - return ivalue - - -def setup_parser_list(subparsers: argparse._SubParsersAction) -> None: - parser_list = subparsers.add_parser( - SubCommand.LIST.value, help="List all image definitions" - ) - parser_list.add_argument( - "--filter-type", - default=None, - type=str, - help="Filter images by type", - ) - - -def setup_parser_show( - subparsers: argparse._SubParsersAction, - artifacts: ArtifactManifest, -) -> None: - parser_show = subparsers.add_parser( - SubCommand.SHOW_ARTIFACT.value, - help="Show default artifact configuration.", - ) - parser_show.set_defaults(artifacts=artifacts) - parser_show.add_argument( - "item", - choices=ArtifactManifest.kebab_fields(), - help="The item to show", - ) - - -def setup_subparser_dependencies( - subparsers: argparse._SubParsersAction, -) -> None: - parser_dependencies = subparsers.add_parser( - SubCommand.DEPENDENCIES.value, - help="List all dependencies for a specific image", - ) - parser_dependencies.add_argument("image", help="The image to get dependencies for") - - -def setup_parser_build( - subparsers: argparse._SubParsersAction, - configs: List[ImageConfig], - artifacts: ArtifactManifest, -) -> None: - parser_build = subparsers.add_parser( - SubCommand.BUILD.value, help="Build a specific image" - ) - - parser_build.set_defaults(artifacts=artifacts) - - parser_build.add_argument( - "image", help="The image to build", choices=[c.name for c in configs] - ) - parser_build.add_argument( - "--output-dir", - help="Where to write the output image.", - default=Path.cwd() / "artifacts", - type=Path, - ) - parser_build.add_argument( - "--dry-run", action="store_true", help="Do not run the command" - ) - parser_build.add_argument( - "--container", - default=artifacts.customizer_container_full, - type=str, - help="Configure Prism container image", - ) - parser_build.add_argument( - "--image-architecture", - default=None, - type=str, - help="Provide image architecture override for cross-compile", - ) - parser_build.add_argument( - "--clones", - type=positive_int, - default=1, - help="Number of clones of this image to create. " - "The default is 1, which means no cloning will be done. When more than 1 is requested, " - "the image file names will be suffixed with `_` for each clone, starting with 0." - " Clones are built in parallel, requesting multiple clones will become very resource " - "intensive.", - ) - parser_build.add_argument( - "-f", - "--force", - action="store_true", - help="Force the build even if the image already exists and it is up to date", - ) - parser_build.add_argument( - "--no-download", - action="store_false", - dest="download", - help="By default, the builder will try to download any missing artifacts, " - "this flag will disable that behavior.", - ) - - -def setup_parser_list_files( - subparsers: argparse._SubParsersAction, -) -> None: - parser_targets = subparsers.add_parser( - SubCommand.LIST_FILES.value, help="List all images as file targets" - ) - parser_targets.add_argument( - "--output-dir", - help="Where to write the output image.", - default=Path("build"), - type=Path, - ) - - -def setup_parser_download_image( - subparsers: argparse._SubParsersAction, - artifacts: ArtifactManifest, -) -> None: - parser_download_img = subparsers.add_parser( - SubCommand.DOWNLOAD_IMAGE.value, - help="Download a base image from the Azure DevOps feed", - ) - parser_download_img.set_defaults(artifacts=artifacts) - parser_download_img.add_argument( - "image", - help="The image to download", - choices=[c.image.name for c in artifacts.base_images], - ) - - -def setup_parser_matrix( - subparsers: argparse._SubParsersAction, -) -> None: - parser_matrix = subparsers.add_parser( - SubCommand.MATRIX.value, - help="Generate ADO Pipeline matrix for all images", - ) - parser_matrix.add_argument( - "-a", - "--arch", - help=f"Architecture to build for. '{SystemArchitecture.AMD64.value}' or " - f"'{SystemArchitecture.ARM64.value}'", - default=SystemArchitecture.AMD64.value, - type=SystemArchitecture, - ) - parser_matrix.add_argument( - "--indent", - help="Indentation for the matrix", - default=None, - type=int, - ) - - -def setup_parser_image_info( - subparsers: argparse._SubParsersAction, - configs: List[ImageConfig], -) -> None: - parser_image_info = subparsers.add_parser( - SubCommand.SHOW_IMAGE.value, - help="Show image information", - ) - parser_image_info.add_argument( - "image", - help="The image to show", - choices=[c.name for c in configs], - ) - parser_image_info.add_argument( - "field", - help="The field to show", - choices=ImageConfig.kebab_fields(), - ) - parser_image_info.add_argument( - "--devops-var", - help="Output the field as a DevOps variable with the given name", - default=None, - type=str, - ) - - -def run_cmd( - configs: List[ImageConfig], - artifacts: ArtifactManifest, - subcommand: SubCommand, - args: argparse.Namespace, -): - if subcommand == SubCommand.LIST: - run.list_configs( - configs=configs, - filter_type=args.filter_type, - ) - elif subcommand == SubCommand.DEPENDENCIES: - run.list_dependencies( - configs=configs, - name=args.image, - ) - elif subcommand == SubCommand.BUILD: - run.build( - artifacts=args.artifacts, - configs=configs, - name=args.image, - container_name=args.container, - output_dir=args.output_dir, - clones=args.clones, - image_architecture=args.image_architecture, - dry_run=args.dry_run, - force=args.force, - download=args.download, - ) - elif subcommand == SubCommand.LIST_FILES: - run.list_files( - configs=configs, - output_dir=args.output_dir, - ) - elif subcommand == SubCommand.SHOW_ARTIFACT: - run.show_artifact( - artifacts=args.artifacts, - item=args.item, - ) - elif subcommand == SubCommand.DOWNLOAD_IMAGE: - run.download_base_image( - artifacts=args.artifacts, - name=args.image, - ) - elif subcommand == SubCommand.MATRIX: - run.generate_matrix( - configs=configs, - arch=args.arch, - indent=args.indent, - ) - elif subcommand == SubCommand.SHOW_IMAGE: - run.show_image( - configs=configs, - name=args.image, - field_name=args.field, - devops_var=args.devops_var, - ) - else: - raise ValueError(f"Unknown subcommand: {subcommand}") diff --git a/tests/images/builder/context_managers.py b/tests/images/builder/context_managers.py deleted file mode 100644 index 8b957653f7..0000000000 --- a/tests/images/builder/context_managers.py +++ /dev/null @@ -1,63 +0,0 @@ -import logging -import os -import shutil -import subprocess -import tempfile -from typing import Optional - -from contextlib import contextmanager -from pathlib import Path - -logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger(__name__) - - -@contextmanager -def temp_dir( - prefix: Optional[str] = None, dir: Optional[Path] = None, sudo: bool = False -): - """ - Context manager for temporary directory cleanup. - - Args: - prefix: Prefix for the temp directory name - dir: Parent directory in which to create the temp dir (default None, system temp dir) - sudo: Whether to use sudo for cleanup - - Yields: - Path: Path of temp dir - """ - parent = str(dir) if dir is not None else None - build_dir = tempfile.mkdtemp(prefix=prefix, dir=parent) - try: - yield Path(build_dir) - finally: - log.debug(f"Cleaning up build dir: {build_dir}") - if sudo: - log.debug(f"Removing build dir as root: {build_dir}") - subprocess.run(["sudo", "rm", "-rf", build_dir], check=True) - else: - shutil.rmtree(build_dir) - - -@contextmanager -def temp_file(path: Path, sudo: bool = False): - """ - Context manager that deletes the specified file upon exit. - - Args: - path: Path of the temporary file to remove - sudo: Whether to use sudo for cleanup - - Yields: - Path: Path of the temp file (optional, you can just yield) - """ - try: - yield path - finally: - if path.exists(): - log.debug(f"Cleaning up temp file: {path}") - if sudo: - subprocess.run(["sudo", "rm", "-f", str(path)], check=True) - else: - os.remove(path) diff --git a/tests/images/builder/convert.py b/tests/images/builder/convert.py deleted file mode 100644 index 20f2cc9e55..0000000000 --- a/tests/images/builder/convert.py +++ /dev/null @@ -1,87 +0,0 @@ -import logging -from pathlib import Path -import subprocess -import sys -from typing import Optional - -from builder import utils - -logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger(__name__ if __name__ != "__main__" else "convert-image") - - -def convert_image( - container_image: str, - config_name: str, - base_image: Path, - img_format: str, - output_file: Path, - image_architecture: Optional[str] = None, - dry_run: bool = False, -): - """ - Convert an image to a `baremetal-image` using AZL Image Customizer `convert` via Docker container. - - Args: - container_image: Docker container image for Image Customizer - config_name: Name of Image Customizer config - base_image: Path to the base image file to customize - img_format: Output image format - output_file: Path where the customized image will be saved - dry_run: If True, only log the command without executing it - - Raises: - Exception: If the Image Customizer container execution fails - """ - log.info(f"Building '{config_name}'") - - base_cmd = [ - "docker", - "run", - "--rm", - "--privileged", - "-v", - f"/:{utils.HOST_PATH}", - "-v", - "/dev:/dev", - ] - - if image_architecture: - base_cmd.append("--platform") - base_cmd.append(image_architecture) - - base_cmd.extend( - [ - container_image, - "convert", - "--log-level", - "debug", - "--build-dir", - utils.BUILD_DIR, - "--image-file", - utils.build_path(base_image), - "--output-image-format", - img_format, - "--output-image-file", - utils.build_path(output_file), - ] - ) - - # Stringify all the args - base_cmd = [str(x) for x in base_cmd] - - cmd = " \\\n ".join(base_cmd) - - log.debug(f"Running:\n {cmd}") - - if dry_run: - log.info("Dry run, not executing command") - return - - # Run the command - try: - result = subprocess.run(base_cmd, stdout=sys.stdout, stderr=sys.stderr) - result.check_returncode() - except Exception as e: - log.error(f"Error building config '{config_name}': {e}") - raise e diff --git a/tests/images/builder/customize.py b/tests/images/builder/customize.py deleted file mode 100644 index 7fd4d00004..0000000000 --- a/tests/images/builder/customize.py +++ /dev/null @@ -1,169 +0,0 @@ -import logging -from pathlib import Path -import subprocess -import sys -from typing import List, Optional - -from builder import utils - -logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger(__name__ if __name__ != "__main__" else "customize-image") - - -def build_config( - container_image: str, - config_name: str, - yaml_path: Path, - base_image: Path, - img_format: str, - output_file: Path, - rpm_sources: List[Path] = [], - image_architecture: Optional[str] = None, - dry_run: bool = False, -): - """ - Build a custom image using AZL Image Customizer via Docker container. - - Note: Image Customizer no longer supports running as a raw binary and must be - executed within a Docker container. This function orchestrates the containerized - build process. - - Args: - container_image: Docker container image for Image Customizer - config_name: Name of Image Customizer config - yaml_path: Path to the Image Customizer YAML configuration file - base_image: Path to the base image file to customize - img_format: Output image format - output_file: Path where the customized image will be saved - rpm_sources: List of paths to additional RPM source directories - dry_run: If True, only log the command without executing it - - Raises: - Exception: If the Image Customizer container execution fails - """ - log.info(f"Building '{config_name}'") - log.info(f"Using YAML: {yaml_path}") - - base_cmd = [ - "docker", - "run", - "--rm", - "--privileged", - "-v", - f"/:{utils.HOST_PATH}", - "-v", - "/dev:/dev", - ] - - if image_architecture: - base_cmd.append("--platform") - base_cmd.append(image_architecture) - - base_cmd.extend( - [ - container_image, - "--config-file", - utils.build_path(yaml_path), - "--log-level", - "debug", - "--build-dir", - utils.BUILD_DIR, - "--image-file", - utils.build_path(base_image), - "--output-image-format", - img_format, - "--output-image-file", - utils.build_path(output_file), - ] - ) - - for _, rpm in enumerate(rpm_sources): - base_cmd.append("--rpm-source") - base_cmd.append(utils.build_path(rpm)) - - # Stringify all the args - base_cmd = [str(x) for x in base_cmd] - - cmd = " \\\n ".join(base_cmd) - - log.debug(f"Running:\n {cmd}") - - if dry_run: - log.info("Dry run, not executing command") - return - - # Run the command - try: - result = subprocess.run(base_cmd, stdout=sys.stdout, stderr=sys.stderr) - result.check_returncode() - except Exception as e: - log.error(f"Error building config '{config_name}': {e}") - raise e - - -def inject_files( - container_image: str, - inject_files_yaml_path: Path, - unsigned_image_file: Path, - img_format: str, - output_image_file: Path, - dry_run: bool = False, -): - """ - Run the imagecustomizer inject-files command to inject files into the image. - - Args: - container_image: Image Customizer container image to run the command in - inject_files_yaml_path: Path to the inject-files YAML configuration file listing the signed - and unsigned sources - unsigned_image_file: Path to the unsigned image - img_format: Format of the output image - output_image_file: Path to the signed output image - dry_run: If True, do not run the command - - Raises: - Exception: If docker command fails. - """ - base_cmd = [ - "docker", - "run", - "--rm", - "--privileged", - "-v", - f"/:{utils.HOST_PATH}", - "-v", - "/dev:/dev", - container_image, - "inject-files", - "--config-file", - utils.build_path(inject_files_yaml_path), - "--log-level", - "debug", - "--build-dir", - utils.BUILD_DIR, - "--image-file", - utils.build_path(unsigned_image_file), - "--output-image-format", - img_format, - "--output-image-file", - utils.build_path(output_image_file), - ] - - # Stringify all the args - base_cmd = [str(x) for x in base_cmd] - - cmd = " \\\n ".join(base_cmd) - - log.debug(f"Running:\n {cmd}") - - if dry_run: - log.info("Dry run, not executing command") - return - - # Run the command - try: - result = subprocess.run(base_cmd, stdout=sys.stdout, stderr=sys.stderr) - result.check_returncode() - except Exception as e: - log.error(f"Error running inject-files using YAML: {inject_files_yaml_path}") - raise e diff --git a/tests/images/builder/download.py b/tests/images/builder/download.py deleted file mode 100644 index 6f9db4c9f0..0000000000 --- a/tests/images/builder/download.py +++ /dev/null @@ -1,41 +0,0 @@ -from pathlib import Path -import shutil -import subprocess -import tempfile - -from builder import BaseImageManifest - - -def download_base_image(image: BaseImageManifest) -> None: - """Download the base image from MCR.""" - with tempfile.TemporaryDirectory() as tempdir: - subprocess.run( - [ - "oras", - "pull", - f"mcr.microsoft.com/azurelinux/3.0/image/{image.image.name}:latest", - "--output", - tempdir, - "--platform", - "linux/amd64", - ], - check=True, - ) - - # Find and copy the .vhdx file to the target location - tempdir_path = Path(tempdir) - vhdx_files = list(tempdir_path.glob("*.vhdx")) - if not vhdx_files: - raise RuntimeError( - f"No .vhdx file found in downloaded image for {image.image.name}" - ) - if len(vhdx_files) > 1: - raise RuntimeError( - f"Multiple .vhdx files found in downloaded image for {image.image.name}" - ) - - # Ensure the parent directory exists - image.image.path.parent.mkdir(parents=True, exist_ok=True) - - # Copy the .vhdx file to the target location - shutil.copy2(vhdx_files[0], image.image.path) diff --git a/tests/images/builder/run.py b/tests/images/builder/run.py deleted file mode 100644 index d465beb2f2..0000000000 --- a/tests/images/builder/run.py +++ /dev/null @@ -1,175 +0,0 @@ -import logging -from pathlib import Path -import json -from typing import List, Optional - -from builder import ImageConfig, RpmSources, ArtifactManifest -from .builder import build_image -from .convert import convert_image -from . import download - -log = logging.getLogger(__name__) - - -def find_image(configs: List[ImageConfig], name: str) -> ImageConfig: - for config in configs: - if config.name == name: - return config - raise ValueError(f"Image '{name}' is not defined") - - -def list_configs( - *, configs: List[ImageConfig], filter_type: Optional[str] = None -) -> None: - for config in configs: - if filter_type is None or config.output_format.ext() == filter_type: - print(config.name) - - -def list_files(*, configs: List[ImageConfig], output_dir: Path) -> None: - for config in configs: - print(output_dir / config.file_name()) - - -def list_dependencies(*, configs: List[ImageConfig], name: str) -> None: - image = find_image(configs, name) - for dep in image.dependencies(): - print(dep) - - -def show_artifact(*, artifacts: ArtifactManifest, item: str) -> None: - item = getattr(artifacts, item.replace("-", "_")) - if isinstance(item, str): - print(item) - elif isinstance(item, list): - for i in item: - print(i) - else: - raise ValueError(f"Unknown item type: {type(item)}") - - -def show_image( - *, - configs: List[ImageConfig], - name: str, - field_name: str, - devops_var: Optional[str] = None, -) -> None: - image = find_image(configs, name) - field = getattr(image, field_name.replace("-", "_"), None) - - out: str = None - - if field is None: - raise ValueError(f"Field '{field_name}' not found in image '{name}'") - if isinstance(field, str): - out = field - elif isinstance(field, list): - out = "\n".join([str(i) for i in field]) - elif hasattr(field, "__str__") and callable(field.__str__): - out = str(field) - else: - raise ValueError(f"Unknown field type: {type(field)}") - - if devops_var: - print(f"##vso[task.setvariable variable={devops_var}]{out}") - else: - print(out) - - -def build( - *, - artifacts: ArtifactManifest, - configs: List[ImageConfig], - name: str, - container_name: str, - output_dir: Path, - clones: int, - dry_run: bool, - force: bool, - image_architecture: Optional[str] = None, - download: bool = True, -) -> None: - image = find_image(configs, name) - log.info(f"Building image '{image.name}'") - - container_image: Optional[str] = container_name - if container_image is None: - log.error("Image Customizer container image is required") - exit(1) - - if image.image_customizer_convert: - # If 'convert' is requested, run Image Customizer convert subcommand - convert_image( - container_image, - image.id, - image.base_image.path, - image.output_format.ic_name(), - output_dir / image.file_name(), - image_architecture, - dry_run, - ) - else: - rpm_sources: List[Path] = [] - if image.requires_trident: - rpm_sources.append(RpmSources.TRIDENT.path()) - if image.requires_dhcp: - rpm_sources.append(RpmSources.DHCP.path()) - - rpm_overrides_path = RpmSources.RPM_OVERRIDES.path() - if rpm_overrides_path.exists(): - rpm_sources.append(rpm_overrides_path) - - if not image.base_image.path.exists(): - if download: - log.info( - f"Downloading base image to '{image.base_image.path}'" - " (use --no-download to skip this step)" - ) - - else: - log.error(f"Base image '{image.base_image.path}' does not exist.") - exit(1) - - build_image( - container_image=container_image, - image=image, - output_dir=output_dir, - artifacts=artifacts, - clones=clones, - rpm_sources=rpm_sources, - image_architecture=image_architecture, - dry_run=dry_run, - force=force, - ) - - -def download_base_image( - *, - artifacts: ArtifactManifest, - name: str, -) -> None: - image_manifest = next( - (img for img in artifacts.base_images if img.image.name == name), None - ) - if image_manifest is None: - raise ValueError(f"Image '{name}' not found in artifacts") - log.info(f"Downloading base image '{name}' to '{image_manifest.image.path}'") - download.download_base_image(image_manifest) - - -def generate_matrix( - *, - configs: List[ImageConfig], - arch: str, - indent: Optional[int] = None, -) -> None: - matrix = {} - for config in configs: - if config.architecture == arch: - matrix[config.name] = { - "image_name": config.name, - "base_image": config.base_image.name, - "img_file": str(config.base_image.path), - } - print(json.dumps(matrix, indent=indent)) diff --git a/tests/images/builder/sign.py b/tests/images/builder/sign.py deleted file mode 100644 index 0045feef8e..0000000000 --- a/tests/images/builder/sign.py +++ /dev/null @@ -1,474 +0,0 @@ -import logging -import os -import re -import subprocess -import yaml -import threading - -from pathlib import Path -from typing import Optional - -from builder.context_managers import temp_dir - - -logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger(__name__) - -# Common name of CA (Certificate Authority) certificate -CA_CN = "Trident Testing CA" - -# Name of CA certificate -CA_NAME = "trident_ca" - -# Common name of signing key -KEY_CN = "Trident Testing Signing Key" - -# Name of signing key -KEY_NAME = "trident_signing_key" - -# Directory for the NSS key database -NSS_KEY_DB = "db" - -# Name of PKCS#12 archive file that contains private key and signing certificate -PKCS12_ARCH_FILE = "signer.p12" - -# IMAGE CUSTOMIZER ARTIFACT NAMES -IC_ARTIFACT_NAME_UKIS = "ukis" -IC_ARTIFACT_NAME_SHIM = "shim" -IC_ARTIFACT_NAME_SYSTEMD_BOOT = "systemd-boot" -IC_ARTIFACT_NAME_VERITY_HASH = "verity-hash" - -_KERNEL_FLAG_SUPPORTED = None -_PESIGN_CERT_ARG = None - - -def _efikeygen_supports_kernel_flag() -> bool: - global _KERNEL_FLAG_SUPPORTED - - if _KERNEL_FLAG_SUPPORTED is None: - result = subprocess.run( - ["efikeygen", "--help"], capture_output=True, text=True, check=False - ) - help_output = f"{result.stdout}\n{result.stderr}" - _KERNEL_FLAG_SUPPORTED = "--kernel" in help_output - log.debug(f"efikeygen --kernel support: {_KERNEL_FLAG_SUPPORTED}") - - return _KERNEL_FLAG_SUPPORTED - - -def _get_pesign_certificate_arg() -> str: - global _PESIGN_CERT_ARG - - if _PESIGN_CERT_ARG is None: - result = subprocess.run( - ["pesign", "--help"], capture_output=True, text=True, check=False - ) - help_output = f"{result.stdout}\n{result.stderr}" - _PESIGN_CERT_ARG = ( - "--certficate" if "--certficate" in help_output else "--certificate" - ) - log.debug(f"Using pesign certificate argument: {_PESIGN_CERT_ARG}") - - return _PESIGN_CERT_ARG - - -def generate_ca_certificate(tmp_dir: Path): - """ - Generates a single CA certificate and key that will be used to sign all leaf certificates. - This should be called once per build process. - - Args: - tmp_dir: Path to the temporary directory where the CA key is stored - - Returns: - ca_nss_key_db: Full path to the NSS key database - - Raises: - Exception: If certutil or efikeygen fails. - """ - ca_nss_key_db = tmp_dir / NSS_KEY_DB - os.makedirs(ca_nss_key_db, exist_ok=True) - log.debug(f"Initializing CA NSS key database in {ca_nss_key_db}") - - # Initialize a NSS key database for CA - subprocess.run( - ["certutil", "-N", "-d", str(ca_nss_key_db), "--empty-password"], check=True - ) - - # Generate CA certificate - subprocess.run( - [ - "efikeygen", - "-C", - "-S", - "-n", - CA_NAME, - "-c", - f"CN={CA_CN}", - "-d", - str(ca_nss_key_db), - ], - check=True, - ) - - log.info(f"Generated CA certificate {CA_NAME} at {ca_nss_key_db}") - return ca_nss_key_db - - -def generate_leaf_certificate(ca_nss_key_db: Path, id: str): - """ - Generates a leaf certificate signed by the CA for a specific image clone. - - Args: - ca_nss_key_db: Path to the CA's NSS key database - id: ID of the signing key for this image clone - - Returns: - leaf_key_name: Name of the leaf key that was generated - - Raises: - Exception: If certificate generation fails. - """ - # Generate unique leaf key name - leaf_key_name = f"{KEY_NAME}_{id}" - - cmd = [ - "efikeygen", - "-n", - leaf_key_name, - "-c", - f"CN={KEY_CN} {id}", - "--signer", - CA_NAME, - "-d", - str(ca_nss_key_db), - ] - - if _efikeygen_supports_kernel_flag(): - cmd.append("--kernel") - - # Generate signing key/cert, signed by CA in the shared DB - subprocess.run(cmd, check=True) - - log.debug( - f"Process with PID {threading.get_ident()} generated leaf key {leaf_key_name} in {ca_nss_key_db}" - ) - return leaf_key_name - - -def publish_ca_certificate(ca_nss_key_db: Path, output_dir: Path): - """ - Extract and publish the CA certificate that can validate all leaf certificates. - - Args: - ca_nss_key_db: Path to the CA's NSS key database - output_dir: Directory where the CA certificate will be published - - Raises: - Exception: If any shell command fails. - """ - # Export PKCS#12 from NSS DB - key_path = ca_nss_key_db / PKCS12_ARCH_FILE - subprocess.run( - [ - "pk12util", - "-d", - str(ca_nss_key_db), - "-n", - CA_NAME, - "-o", - str(key_path), - "-W", - "", - ], - check=True, - ) - - # Extract certificate from PKCS#12 file, no private key - ca_cert_path = output_dir / "ca_cert.pem" - subprocess.run( - [ - "openssl", - "pkcs12", - "-in", - str(key_path), - "-out", - str(ca_cert_path), - "-nokeys", - "-passin", - "pass:", - ], - check=True, - ) - - log.info(f"CA Certificate published to {ca_cert_path}") - - -def sign_boot_artifacts( - ca_nss_key_db: Path, - leaf_key_name: str, - inject_files_yaml_path: Path, - output_artifacts_dir: Path, -): - """ - Signs unsigned boot artifacts listed in inject-files.yaml and produces signed boot artifacts. - - Args: - ca_nss_key_db: Path to the NSS key database for the CA certificate - leaf_key_name: Name of the leaf certificate - inject_files_yaml_path: Full path to inject-files.yaml - output_artifacts_dir: Dir where artifacts are output by Image Customizer - """ - with open(inject_files_yaml_path, "r") as f: - data = f.read() - - log.debug(f"Contents of {inject_files_yaml_path}:\n{data}") - inject_files_config = yaml.safe_load(data) - - for entry in inject_files_config.get("injectFiles", []): - artifact_type = entry.get("type", "") - signed_path_str = entry.get("source") - unsigned_path_str = entry.get("unsignedSource", "") - - if not signed_path_str: - raise RuntimeError(f"Missing source in inject-files entry: {entry}") - - if not unsigned_path_str: - # MIC v1.1+ uses the same path for unsigned and signed files. - unsigned_path_str = signed_path_str - - signed_rel_path = ( - signed_path_str[2:] if signed_path_str.startswith("./") else signed_path_str - ) - unsigned_rel_path = ( - unsigned_path_str[2:] - if unsigned_path_str.startswith("./") - else unsigned_path_str - ) - signed_path = output_artifacts_dir.absolute() / signed_rel_path - unsigned_path = output_artifacts_dir.absolute() / unsigned_rel_path - - if not artifact_type: - artifact_type = get_artifact_type_from_name(unsigned_path.name) - - log.info( - f"Signing file of type '{artifact_type}' at {unsigned_path} to {signed_path}" - ) - if artifact_type == IC_ARTIFACT_NAME_VERITY_HASH: - sign_verity_hash( - ca_nss_key_db, - leaf_key_name, - unsigned_path, - signed_path, - ) - else: - sign_pe_artifact( - ca_nss_key_db, - leaf_key_name, - unsigned_path, - signed_path, - ) - - -def get_artifact_type_from_name(name: str) -> Optional[str]: - if re.match(r"vmlinuz.*\.efi", name): - return IC_ARTIFACT_NAME_UKIS - if re.match(r"bootx64\.efi", name): - return IC_ARTIFACT_NAME_SHIM - if re.match(r"systemd-bootx64\.efi", name): - return IC_ARTIFACT_NAME_SYSTEMD_BOOT - if re.match(r".*hash.*", name): - return IC_ARTIFACT_NAME_VERITY_HASH - - return None - - -def sign_verity_hash( - ca_nss_key_db: Path, - leaf_key_name: str, - unsigned_verity_hash_path: Path, - signed_verity_hash_path: Path, -): - """ - Sign the verity hash file using the signing key. - - Args: - ca_nss_key_db: Path to the NSS key database for the CA certificate - leaf_key_name: Name of the leaf certificate - unsigned_verity_hash_path: Path to the unsigned verity hash file - signed_verity_hash_path: Path to the signed verity hash file - - Raises: - Exception: If pesign fails. - """ - log.debug( - f"Process with PID {threading.get_ident()} is signing {unsigned_verity_hash_path}" - ) - - signed_verity_hash_path.parent.mkdir(parents=True, exist_ok=True) - signed_verity_hash_path.parent.chmod(0o700) - - with temp_dir(sudo=True) as tmpdir: - tmp_signed_artifact = ( - tmpdir - / f"{unsigned_verity_hash_path.stem}.signed{unsigned_verity_hash_path.suffix}" - ) - tmp_unsigned_artifact = ( - tmpdir - / f"{unsigned_verity_hash_path.stem}.unsigned{unsigned_verity_hash_path.suffix}" - ) - key_path = tmpdir / "key.p12" - key_crt_path = tmpdir / "key.crt" - - subprocess.run( - ["sudo", "cp", str(unsigned_verity_hash_path), str(tmp_unsigned_artifact)], - check=True, - ) - - log.debug(f"Exporting PKCS12 key to {key_path}") - subprocess.run( - [ - "pk12util", - "-d", - str(ca_nss_key_db), - "-n", - leaf_key_name, - "-o", - str(key_path), - "-W", - "", - ], - check=True, - ) - - log.debug(f"Extracting cert from PKCS12 key to {key_crt_path}") - subprocess.run( - [ - "openssl", - "pkcs12", - "-in", - str(key_path), - "-out", - str(key_crt_path), - "-clcerts", - "-nodes", - "-passin", - "pass:", - ], - check=True, - ) - - log.debug( - f"Signing verity hash file at {tmp_unsigned_artifact} using openssl smime" - ) - subprocess.run( - [ - "openssl", - "smime", - "-sign", - "-noattr", - "-binary", - "-in", - str(tmp_unsigned_artifact), - "-signer", - str(key_crt_path), - "-passin", - "pass:", - "-outform", - "der", - "-out", - str(tmp_signed_artifact), - ], - check=True, - ) - - try: - result = subprocess.run( - [ - "openssl", - "pkcs7", - "-inform", - "DER", - "-in", - str(tmp_signed_artifact), - "-print_certs", - "-text", - ], - check=True, - capture_output=True, - text=True, - ) - log.debug(f"Certs for {unsigned_verity_hash_path}:\n{result.stdout}") - except subprocess.CalledProcessError as e: - log.error(f"Failed to print certs for {unsigned_verity_hash_path}: {e}") - - subprocess.run( - ["sudo", "cp", str(tmp_signed_artifact), str(signed_verity_hash_path)], - check=True, - ) - - log.debug(f"Signed verity-hash artifact generated at {signed_verity_hash_path}") - - -def sign_pe_artifact( - ca_nss_key_db: Path, - leaf_key_name: str, - unsigned_artifact_path: Path, - signed_artifact_path: Path, -): - """ - Sign the artifact using the signing key. - - Args: - ca_nss_key_db: Path to the NSS key database for the CA certificate - leaf_key_name: Name of the leaf certificate - unsigned_artifact_path: Path to the unsigned artifact - signed_artifact_path: Path to the signed artifact - - Raises: - Exception: If pesign fails. - """ - log.debug( - f"Process with PID {threading.get_ident()} is signing {unsigned_artifact_path} to {signed_artifact_path}" - ) - - with temp_dir(sudo=True) as tmpdir: - tmp_signed_artifact = ( - tmpdir - / f"{unsigned_artifact_path.stem}.signed{unsigned_artifact_path.suffix}" - ) - tmp_unsigned_artifact = ( - tmpdir - / f"{unsigned_artifact_path.stem}.unsigned{unsigned_artifact_path.suffix}" - ) - - subprocess.run( - ["sudo", "cp", str(unsigned_artifact_path), str(tmp_unsigned_artifact)], - check=True, - ) - - cert_arg = _get_pesign_certificate_arg() - - subprocess.run( - [ - "pesign", - "--certdir", - str(ca_nss_key_db), - cert_arg, - leaf_key_name, - "--sign", - "--in", - str(tmp_unsigned_artifact), - "--out", - str(tmp_signed_artifact), - "--force", - ], - check=True, - ) - - subprocess.run( - ["sudo", "cp", str(tmp_signed_artifact), str(signed_artifact_path)], - check=True, - ) - - log.debug(f"Artifact signed to {signed_artifact_path}") diff --git a/tests/images/builder/utils.py b/tests/images/builder/utils.py deleted file mode 100644 index 33692361ee..0000000000 --- a/tests/images/builder/utils.py +++ /dev/null @@ -1,24 +0,0 @@ -from pathlib import Path - -BUILD_DIR = "/tmp" -HOST_PATH = Path("/host") - - -def build_path(path: Path) -> Path: - """ - Convert a host filesystem path to its corresponding path inside the Docker container. - - The Docker container mounts the host's root filesystem at /host, so this function - transforms absolute host paths like '/home/user/file.txt' to container paths - like '/host/home/user/file.txt'. - - Args: - path: Absolute or relative path on the host filesystem - - Returns: - Path that can be used inside the Docker container to access the same file - - Example: - build_path(Path("/home/user/config.yaml")) -> Path("/host/home/user/config.yaml") - """ - return HOST_PATH / path.absolute().relative_to(Path("/")) diff --git a/tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2204.yaml b/tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2204.yaml new file mode 100644 index 0000000000..3f1dcbc0e4 --- /dev/null +++ b/tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2204.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: ubuntu_2204_arm64 diff --git a/tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2404.yaml b/tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2404.yaml new file mode 100644 index 0000000000..94f6b20459 --- /dev/null +++ b/tests/images/foreign-direct-streaming-testimage/by-arch+source/arm64+ubuntu-2404.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: ubuntu_2404_arm64 diff --git a/tests/images/foreign-direct-streaming-testimage/by-source/gb200-2404.yaml b/tests/images/foreign-direct-streaming-testimage/by-source/gb200-2404.yaml new file mode 100644 index 0000000000..6799181856 --- /dev/null +++ b/tests/images/foreign-direct-streaming-testimage/by-source/gb200-2404.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: gb200_2404_arm64 diff --git a/tests/images/foreign-direct-streaming-testimage/by-source/ubuntu-2404.yaml b/tests/images/foreign-direct-streaming-testimage/by-source/ubuntu-2404.yaml new file mode 100644 index 0000000000..1fc2ef81f2 --- /dev/null +++ b/tests/images/foreign-direct-streaming-testimage/by-source/ubuntu-2404.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: ubuntu_2404_amd64 diff --git a/tests/images/foreign-direct-streaming-testimage/image.yaml b/tests/images/foreign-direct-streaming-testimage/image.yaml new file mode 100644 index 0000000000..3d006bffb6 --- /dev/null +++ b/tests/images/foreign-direct-streaming-testimage/image.yaml @@ -0,0 +1,16 @@ +name: foreign-direct-streaming-testimage +operation: convert + +matrix: + arch: [amd64, arm64] + source: [ubuntu-2204, ubuntu-2404, gb200-2404] + +selectors: + exclude: + - { arch: amd64, source: gb200-2404 } + +base: + ref: ubuntu_2204_amd64 + +outputs: + - format: baremetal-image diff --git a/tests/images/legacy-map.json b/tests/images/legacy-map.json new file mode 100644 index 0000000000..b87725ff5c --- /dev/null +++ b/tests/images/legacy-map.json @@ -0,0 +1,263 @@ +{ + "trident-installer": { + "image": "trident-installer", + "selectors": { + "arch": "amd64", + "variant": "default" + }, + "baseImage": "baremetal", + "ext": "iso" + }, + "trident-split-installer": { + "image": "trident-installer", + "selectors": { + "arch": "amd64", + "variant": "split" + }, + "baseImage": "baremetal", + "ext": "iso" + }, + "trident-installer-arm64": { + "image": "trident-installer", + "selectors": { + "arch": "arm64", + "variant": "default" + }, + "baseImage": "core_arm64", + "ext": "iso" + }, + "trident-container-installer": { + "image": "trident-container-installer", + "selectors": {}, + "baseImage": "baremetal", + "ext": "iso" + }, + "trident-direct-streaming-installer-amd64": { + "image": "trident-installer", + "selectors": { + "arch": "amd64", + "variant": "direct-streaming" + }, + "baseImage": "baremetal", + "ext": "iso" + }, + "trident-direct-streaming-installer-arm64": { + "image": "trident-installer", + "selectors": { + "arch": "arm64", + "variant": "direct-streaming" + }, + "baseImage": "core_arm64", + "ext": "iso" + }, + "trident-functest": { + "image": "trident-functest", + "selectors": {}, + "baseImage": "baremetal", + "ext": "qcow2" + }, + "trident-testimage": { + "image": "trident-testimage", + "selectors": { + "arch": "amd64" + }, + "baseImage": "baremetal", + "ext": "cosi" + }, + "trident-testimage-arm64": { + "image": "trident-testimage", + "selectors": { + "arch": "arm64" + }, + "baseImage": "core_arm64", + "ext": "cosi" + }, + "trident-verity-testimage": { + "image": "trident-verity-testimage", + "selectors": { + "deployment": "host", + "mode": "root" + }, + "baseImage": "baremetal", + "ext": "cosi" + }, + "trident-usrverity-testimage": { + "image": "trident-verity-testimage", + "selectors": { + "deployment": "host", + "mode": "usr" + }, + "baseImage": "baremetal", + "ext": "cosi" + }, + "trident-container-verity-testimage": { + "image": "trident-verity-testimage", + "selectors": { + "deployment": "container", + "mode": "root" + }, + "baseImage": "baremetal", + "ext": "cosi" + }, + "trident-container-usrverity-testimage": { + "image": "trident-verity-testimage", + "selectors": { + "deployment": "container", + "mode": "usr" + }, + "baseImage": "baremetal", + "ext": "cosi" + }, + "trident-container-testimage": { + "image": "trident-container-testimage", + "selectors": {}, + "baseImage": "baremetal", + "ext": "cosi" + }, + "azurelinux-direct-streaming-testimage-amd64": { + "image": "azurelinux-direct-streaming-testimage", + "selectors": { + "arch": "amd64" + }, + "baseImage": "baremetal", + "ext": "cosi", + "tailorExt": "raw" + }, + "azurelinux-direct-streaming-testimage-arm64": { + "image": "azurelinux-direct-streaming-testimage", + "selectors": { + "arch": "arm64" + }, + "baseImage": "core_arm64", + "ext": "cosi", + "tailorExt": "raw" + }, + "azl-installer": { + "image": "azl-installer", + "selectors": {}, + "baseImage": "baremetal", + "ext": "iso" + }, + "trident-vm-grub-testimage": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "amd64", + "scenario": "grub" + }, + "baseImage": "qemu_guest", + "ext": "cosi" + }, + "trident-vm-grub-verity-testimage": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "amd64", + "scenario": "grub-verity" + }, + "baseImage": "qemu_guest", + "ext": "cosi" + }, + "trident-vm-root-verity-testimage": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "amd64", + "scenario": "root-verity" + }, + "baseImage": "qemu_guest", + "ext": "cosi" + }, + "trident-vm-usr-verity-testimage": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "amd64", + "scenario": "usr-verity" + }, + "baseImage": "qemu_guest", + "ext": "cosi" + }, + "trident-vm-acl-agent-update-testimage": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "amd64", + "scenario": "acl-agent" + }, + "baseImage": "qemu_guest", + "ext": "cosi" + }, + "trident-vm-grub-verity-azure-testimage": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "amd64", + "scenario": "grub-verity-azure" + }, + "baseImage": "core_selinux", + "ext": "cosi" + }, + "trident-vm-grub-testimage-arm64": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "arm64", + "scenario": "grub" + }, + "baseImage": "core_arm64", + "ext": "cosi" + }, + "trident-vm-grub-verity-testimage-arm64": { + "image": "trident-vm-testimage", + "selectors": { + "arch": "arm64", + "scenario": "grub-verity" + }, + "baseImage": "core_arm64", + "ext": "cosi" + }, + "ubuntu-direct-streaming-testimage-2204-amd64": { + "image": "foreign-direct-streaming-testimage", + "selectors": { + "arch": "amd64", + "source": "ubuntu-2204" + }, + "baseImage": "ubuntu_2204_amd64", + "ext": "cosi", + "tailorExt": "raw" + }, + "ubuntu-direct-streaming-testimage-2204-arm64": { + "image": "foreign-direct-streaming-testimage", + "selectors": { + "arch": "arm64", + "source": "ubuntu-2204" + }, + "baseImage": "ubuntu_2204_arm64", + "ext": "cosi", + "tailorExt": "raw" + }, + "ubuntu-direct-streaming-testimage-2404-amd64": { + "image": "foreign-direct-streaming-testimage", + "selectors": { + "arch": "amd64", + "source": "ubuntu-2404" + }, + "baseImage": "ubuntu_2404_amd64", + "ext": "cosi", + "tailorExt": "raw" + }, + "ubuntu-direct-streaming-testimage-2404-arm64": { + "image": "foreign-direct-streaming-testimage", + "selectors": { + "arch": "arm64", + "source": "ubuntu-2404" + }, + "baseImage": "ubuntu_2404_arm64", + "ext": "cosi", + "tailorExt": "raw" + }, + "gb200-direct-streaming-testimage-2404-arm64": { + "image": "foreign-direct-streaming-testimage", + "selectors": { + "arch": "arm64", + "source": "gb200-2404" + }, + "baseImage": "gb200_2404_arm64", + "ext": "cosi", + "tailorExt": "raw" + } +} diff --git a/tests/images/tailor.yaml b/tests/images/tailor.yaml new file mode 100644 index 0000000000..2d7b1d5a75 --- /dev/null +++ b/tests/images/tailor.yaml @@ -0,0 +1,76 @@ +schemaVersion: 1 + +previewFeatures: + - signing + +toolchains: + default: ic + entries: + - name: ic + container: mcr.microsoft.com/azurelinux/imagecustomizer + tag: latest + +signing: + default: test-ca + profiles: + test-ca: + backend: local-test-ca + publishCaCert: ./artifacts/ca_cert.pem + +baseImages: + - name: baremetal + path: ../../artifacts/baremetal.vhdx + arch: amd64 + source: + oci: + uri: mcr.microsoft.com/azurelinux/3.0/image/baremetal:latest + platform: linux/amd64 + - name: core_arm64 + path: ../../artifacts/core_arm64.vhdx + arch: arm64 + source: + oci: + uri: mcr.microsoft.com/azurelinux/3.0/image/core_arm64:latest + platform: linux/arm64 + - name: core_selinux + path: ../../artifacts/core_selinux.vhdx + arch: amd64 + source: + oci: + uri: mcr.microsoft.com/azurelinux/3.0/image/core_selinux:latest + platform: linux/amd64 + - name: qemu_guest + path: ../../artifacts/qemu_guest.vhdx + arch: amd64 + source: + oci: + uri: mcr.microsoft.com/azurelinux/3.0/image/qemu_guest:latest + platform: linux/amd64 + - name: ubuntu_2204_amd64 + path: ../../artifacts/ubuntu_2204_amd64.vhdx + arch: amd64 + - name: ubuntu_2204_arm64 + path: ../../artifacts/ubuntu_2204_arm64.vhdx + arch: arm64 + - name: ubuntu_2404_amd64 + path: ../../artifacts/ubuntu_2404_amd64.vhdx + arch: amd64 + - name: ubuntu_2404_arm64 + path: ../../artifacts/ubuntu_2404_arm64.vhdx + arch: arm64 + - name: gb200_2404_arm64 + path: ../../artifacts/gb200_2404_arm64.vhdx + arch: arm64 + +images: + members: + - azl-installer + - azurelinux-direct-streaming-testimage + - foreign-direct-streaming-testimage + - trident-container-installer + - trident-container-testimage + - trident-functest + - trident-installer + - trident-testimage + - trident-verity-testimage + - trident-vm-testimage diff --git a/tests/images/testimages.py b/tests/images/testimages.py deleted file mode 100755 index a5137a2114..0000000000 --- a/tests/images/testimages.py +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/env python3 - -from pathlib import Path -from typing import List - -from builder import ( - ArtifactManifest, - BaseImage, - BaseImageManifest, - ImageConfig, - OutputFormat, - SystemArchitecture, - cli, -) - -# # # # # # # # # # # # # # # # # # # -# DEFAULT CUSTOMIZER VERSION # -# # -# The version of Image Customizer # -# to use by default when building # -# images. # -# # # # # # # # # # # # # # # # # # # -DEFAULT_IMAGE_CUSTOMIZER_VERSION = "latest" - - -DEFINED_IMAGES: List[ImageConfig] = [ - # Installer images - ImageConfig( - "trident-installer", - config="trident-installer", - output_format=OutputFormat.ISO, - ), - ImageConfig( - "trident-split-installer", - config="trident-installer", - config_file="base/baseimg-split.yaml", - output_format=OutputFormat.ISO, - ), - ImageConfig( - "trident-installer-arm64", - config="trident-installer", - output_format=OutputFormat.ISO, - base_image=BaseImage.CORE_ARM64, - architecture=SystemArchitecture.ARM64, - ), - ImageConfig( - "trident-container-installer", - config="trident-container-installer", - output_format=OutputFormat.ISO, - requires_trident=False, - ), - ImageConfig( - "trident-direct-streaming-installer-amd64", - config="trident-installer", - config_file="base/baseimg-direct-streaming.yaml", - output_format=OutputFormat.ISO, - ), - ImageConfig( - "trident-direct-streaming-installer-arm64", - config="trident-installer", - config_file="base/baseimg-direct-streaming.yaml", - output_format=OutputFormat.ISO, - base_image=BaseImage.CORE_ARM64, - architecture=SystemArchitecture.ARM64, - ), - # Test images - ImageConfig( - "trident-functest", - output_format=OutputFormat.QCOW2, - requires_trident=False, - ), - ImageConfig("trident-testimage"), - ImageConfig( - "trident-testimage-arm64", - config="trident-testimage", - base_image=BaseImage.CORE_ARM64, - architecture=SystemArchitecture.ARM64, - ), - ImageConfig("trident-verity-testimage"), - ImageConfig( - "trident-usrverity-testimage", - config="trident-verity-testimage", - config_file="usr/host.yaml", - requires_ukify=True, - ), - ImageConfig( - "trident-container-verity-testimage", - config="trident-verity-testimage", - config_file="base/baseimg-container.yaml", - requires_trident=False, - ), - ImageConfig( - "trident-container-usrverity-testimage", - config="trident-verity-testimage", - config_file="usr/container.yaml", - requires_ukify=True, - requires_trident=False, - ), - ImageConfig( - "trident-container-testimage", - requires_trident=False, - ), - # Direct streaming images - ImageConfig( - "azurelinux-direct-streaming-testimage-amd64", - config="azurelinux-direct-streaming-testimage", - output_format=OutputFormat.BAREMETAL_IMAGE, - ), - ImageConfig( - "azurelinux-direct-streaming-testimage-arm64", - config="azurelinux-direct-streaming-testimage", - output_format=OutputFormat.BAREMETAL_IMAGE, - base_image=BaseImage.CORE_ARM64, - architecture=SystemArchitecture.ARM64, - ), - # AZL installer - ImageConfig( - "azl-installer", - config_file=Path("installer-iso.yaml"), - output_format=OutputFormat.ISO, - requires_trident=True, - extra_dependencies=[ - Path("tests/images/azl-installer/iso/bin/liveinstaller"), - Path("tests/images/azl-installer/iso/images/trident-testimage.cosi"), - ], - ), - # VM test images - ImageConfig( - "trident-vm-grub-testimage", - base_image=BaseImage.QEMU_GUEST, - config="trident-vm-testimage", - config_file="base/updateimg-grub.yaml", - ssh_key="files/id_rsa.pub", - ), - ImageConfig( - "trident-vm-grub-verity-testimage", - base_image=BaseImage.QEMU_GUEST, - config="trident-vm-testimage", - config_file="base/updateimg-grub-verity.yaml", - ssh_key="files/id_rsa.pub", - ), - ImageConfig( - "trident-vm-root-verity-testimage", - base_image=BaseImage.QEMU_GUEST, - config="trident-vm-testimage", - config_file="base/baseimg-root-verity.yaml", - requires_ukify=True, - ssh_key="files/id_rsa.pub", - ), - ImageConfig( - "trident-vm-usr-verity-testimage", - base_image=BaseImage.QEMU_GUEST, - config="trident-vm-testimage", - config_file="base/baseimg-usr-verity.yaml", - requires_ukify=True, - ssh_key="files/id_rsa.pub", - ), - ImageConfig( - "trident-vm-acl-agent-update-testimage", - base_image=BaseImage.QEMU_GUEST, - config="trident-vm-testimage", - config_file="base/updateimg-acl-agent.yaml", - requires_ukify=True, - ssh_key="files/id_rsa.pub", - ), - ImageConfig( - "trident-vm-grub-verity-azure-testimage", - base_image=BaseImage.CORE_SELINUX, - config="trident-vm-testimage", - config_file="base/updateimg-grub-verity-azure.yaml", - ), - ImageConfig( - "trident-vm-grub-testimage-arm64", - base_image=BaseImage.CORE_ARM64, - config="trident-vm-testimage", - config_file="base/updateimg-grub.yaml", - ssh_key="files/id_rsa.pub", - architecture=SystemArchitecture.ARM64, - ), - ImageConfig( - "trident-vm-grub-verity-testimage-arm64", - base_image=BaseImage.CORE_ARM64, - config="trident-vm-testimage", - config_file="base/updateimg-grub-verity.yaml", - ssh_key="files/id_rsa.pub", - architecture=SystemArchitecture.ARM64, - ), - ImageConfig( - "ubuntu-direct-streaming-testimage-2204-amd64", - base_image=BaseImage.UBUNTU_2204_AMD64, - output_format=OutputFormat.BAREMETAL_IMAGE, - image_customizer_convert=True, - requires_trident=False, - ), - ImageConfig( - "ubuntu-direct-streaming-testimage-2204-arm64", - base_image=BaseImage.UBUNTU_2204_ARM64, - output_format=OutputFormat.BAREMETAL_IMAGE, - architecture=SystemArchitecture.ARM64, - image_customizer_convert=True, - requires_trident=False, - ), - ImageConfig( - "ubuntu-direct-streaming-testimage-2404-amd64", - base_image=BaseImage.UBUNTU_2404_AMD64, - output_format=OutputFormat.BAREMETAL_IMAGE, - image_customizer_convert=True, - requires_trident=False, - ), - ImageConfig( - "ubuntu-direct-streaming-testimage-2404-arm64", - base_image=BaseImage.UBUNTU_2404_ARM64, - output_format=OutputFormat.BAREMETAL_IMAGE, - architecture=SystemArchitecture.ARM64, - image_customizer_convert=True, - requires_trident=False, - ), - ImageConfig( - "gb200-direct-streaming-testimage-2404-arm64", - base_image=BaseImage.GB200_2404_ARM64, - output_format=OutputFormat.BAREMETAL_IMAGE, - architecture=SystemArchitecture.ARM64, - image_customizer_convert=True, - requires_trident=False, - ), -] - -ARTIFACTS = ArtifactManifest( - customizer_version=DEFAULT_IMAGE_CUSTOMIZER_VERSION, - customizer_container="mcr.microsoft.com/azurelinux/imagecustomizer", - base_images=[ - BaseImageManifest( - image=BaseImage.BAREMETAL, - package_name="baremetal_vhdx-3.0-stable", - version="*", - ), - BaseImageManifest( - image=BaseImage.CORE_ARM64, - package_name="core_vhdx-arm64-3.0-stable", - version="*", - ), - BaseImageManifest( - image=BaseImage.CORE_SELINUX, - package_name="core_selinux_vhdx-3.0-stable", - version="*", - ), - BaseImageManifest( - image=BaseImage.QEMU_GUEST, - package_name="qemu_guest_vhdx-3.0-stable", - version="*", - ), - BaseImageManifest( - image=BaseImage.MINIMAL, - package_name="minimal_vhdx-3.0-stable", - version="*", - ), - ], -) - -if __name__ == "__main__": - import os - - # Change to the base directory in the trident repo - os.chdir(Path(__file__).parent.parent.parent) - - # Run the CLI - cli.init(DEFINED_IMAGES, ARTIFACTS) diff --git a/tests/images/trident-container-installer/README.md b/tests/images/trident-container-installer/README.md index 19ebcd492c..5fadc6fee4 100644 --- a/tests/images/trident-container-installer/README.md +++ b/tests/images/trident-container-installer/README.md @@ -13,7 +13,7 @@ container at boot. From the repo root, run: ```bash -python3 tests/images/testimages.py build trident-container-installer +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-container-installer --output-dir ./artifacts ``` Output is written to `artifacts/trident-container-installer.iso` by default. diff --git a/tests/images/trident-container-installer/image.yaml b/tests/images/trident-container-installer/image.yaml new file mode 100644 index 0000000000..9fca7d3935 --- /dev/null +++ b/tests/images/trident-container-installer/image.yaml @@ -0,0 +1,13 @@ +name: trident-container-installer + +base: + ref: baremetal + +outputs: + - format: iso + +extraDependencies: + - ./base + +config: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/trident-container-installer/tailor/baseimg.yaml b/tests/images/trident-container-installer/tailor/baseimg.yaml new file mode 100644 index 0000000000..055f6b5e7b --- /dev/null +++ b/tests/images/trident-container-installer/tailor/baseimg.yaml @@ -0,0 +1,71 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-container-mos-testimg + packages: + install: + - curl + - device-mapper + - dnf + - docker-cli + - iproute + - iptables + - mdadm + - moby-engine + - openssh-server + - selinux-policy + - squashfs-tools + - tar + - vim + additionalFiles: + - source: base/files/getty@.service + destination: /usr/lib/systemd/system/getty@.service + - source: base/files/serial-getty@.service + destination: /usr/lib/systemd/system/serial-getty@.service + - source: base/files/root.profile + destination: /root/.profile + - source: base/files/trident-container.service + destination: /usr/lib/systemd/system/trident-container.service + - source: base/files/containerd-mmap-fix.cil + destination: /usr/share/selinux/packages/containerd-mmap-fix.cil + services: + enable: + - trident-container + - sshd +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/load-containerd-selinux-fix.sh +iso: + additionalFiles: + - source: base/files/config-placeholder.yaml + destination: /trident-config.yaml + - source: base/files/override-placeholder.conf + destination: /trident-override.conf + kernelCommandLine: + extraCommandLine: + - enforcing=0 + - console=tty0 + - console=ttyS0 + - rd.luks=0 diff --git a/tests/images/trident-container-testimage/README.md b/tests/images/trident-container-testimage/README.md index e8feada25c..004e8cb243 100644 --- a/tests/images/trident-container-testimage/README.md +++ b/tests/images/trident-container-testimage/README.md @@ -12,7 +12,7 @@ loaded at runtime. From the repo root, run: ```bash -python3 tests/images/testimages.py build trident-container-testimage +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-container-testimage --output-dir ./artifacts ``` Output is written to `artifacts/trident-container-testimage.cosi` by default. diff --git a/tests/images/trident-container-testimage/image.yaml b/tests/images/trident-container-testimage/image.yaml new file mode 100644 index 0000000000..69785cda6e --- /dev/null +++ b/tests/images/trident-container-testimage/image.yaml @@ -0,0 +1,13 @@ +name: trident-container-testimage + +base: + ref: baremetal + +outputs: + - format: cosi + +extraDependencies: + - ./base + +config: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/trident-container-testimage/tailor/baseimg.yaml b/tests/images/trident-container-testimage/tailor/baseimg.yaml new file mode 100644 index 0000000000..98cef436fb --- /dev/null +++ b/tests/images/trident-container-testimage/tailor/baseimg.yaml @@ -0,0 +1,71 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-container-testimg + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + packages: + remove: + - grub2-efi-binary + install: + - grub2-efi-binary-noprefix + - curl + - dnf + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - openssh-server + - tpm2-tools + - vim + - device-mapper + - dosfstools + - lvm2 + - veritysetup + - ntfs-3g + - ntfsprogs + - docker-cli + - moby-engine + - selinux-policy + - squashfs-tools + - tar + additionalFiles: + - source: base/files/trident-container.service + destination: /usr/lib/systemd/system/trident-container.service + - source: base/files/containerd-mmap-fix.cil + destination: /usr/share/selinux/packages/containerd-mmap-fix.cil + services: + enable: + - trident-container + - sshd +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/load-containerd-selinux-fix.sh diff --git a/tests/images/trident-functest/image.yaml b/tests/images/trident-functest/image.yaml new file mode 100644 index 0000000000..4f9d4ff305 --- /dev/null +++ b/tests/images/trident-functest/image.yaml @@ -0,0 +1,13 @@ +name: trident-functest + +base: + ref: baremetal + +outputs: + - format: qcow2 + +extraDependencies: + - ./base + +config: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/trident-functest/tailor/baseimg.yaml b/tests/images/trident-functest/tailor/baseimg.yaml new file mode 100644 index 0000000000..c087bee4c6 --- /dev/null +++ b/tests/images/trident-functest/tailor/baseimg.yaml @@ -0,0 +1,75 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 15G + partitions: + - id: esp + type: esp + size: 50M + label: esp + - id: root-a + size: 4G + type: root + label: root-a + - id: root-b + size: 4G + type: root + label: root-b + - id: swap + size: 2G + type: swap + label: swap + - id: trident + size: 100M + type: linux-generic + label: trident + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: root-a + type: ext4 + mountPoint: + path: / + - deviceId: trident + type: ext4 + mountPoint: + path: /var/lib/trident +os: + bootloader: + resetType: hard-reset + hostname: trident-functest + selinux: + mode: permissive + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + packages: + install: + - curl + - dnf + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - openssh-server + - tpm2-tools + - vim + - audit + - device-mapper + - dosfstools + - lvm2 + - veritysetup + - ntfs-3g + - ntfsprogs + services: + enable: + - sshd diff --git a/tests/images/trident-installer/README.md b/tests/images/trident-installer/README.md index b3f1e2d7c8..7226026ce5 100644 --- a/tests/images/trident-installer/README.md +++ b/tests/images/trident-installer/README.md @@ -1,4 +1,19 @@ # Trident Installer ISO Test Image This image is used by the Trident test pipelines. It contains a copy of Trident that launches at -startup and reads a configuration that can be patched into the ISO. \ No newline at end of file +startup and reads a configuration that can be patched into the ISO. + +## Building + +From the repo root, run: + +```bash +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-installer -s arch=amd64 -s variant=default --output-dir ./artifacts +``` + +Other legacy variants map to selectors on the same family: + +- `trident-split-installer` → `-s arch=amd64 -s variant=split` +- `trident-direct-streaming-installer-amd64` → `-s arch=amd64 -s variant=direct-streaming` +- `trident-installer-arm64` → `-s arch=arm64 -s variant=default` +- `trident-direct-streaming-installer-arm64` → `-s arch=arm64 -s variant=direct-streaming` diff --git a/tests/images/trident-installer/by-arch/arm64.yaml b/tests/images/trident-installer/by-arch/arm64.yaml new file mode 100644 index 0000000000..6fe6f6f38d --- /dev/null +++ b/tests/images/trident-installer/by-arch/arm64.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: core_arm64 diff --git a/tests/images/trident-installer/by-variant/direct-streaming.yaml b/tests/images/trident-installer/by-variant/direct-streaming.yaml new file mode 100644 index 0000000000..020757f552 --- /dev/null +++ b/tests/images/trident-installer/by-variant/direct-streaming.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/baseimg-direct-streaming.yaml diff --git a/tests/images/trident-installer/by-variant/split.yaml b/tests/images/trident-installer/by-variant/split.yaml new file mode 100644 index 0000000000..4a201dd734 --- /dev/null +++ b/tests/images/trident-installer/by-variant/split.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/baseimg-split.yaml diff --git a/tests/images/trident-installer/image.yaml b/tests/images/trident-installer/image.yaml new file mode 100644 index 0000000000..abd8160359 --- /dev/null +++ b/tests/images/trident-installer/image.yaml @@ -0,0 +1,26 @@ +name: trident-installer + +matrix: + arch: [amd64, arm64] + variant: [default, split, direct-streaming] + +selectors: + exclude: + - { arch: arm64, variant: split } + +base: + ref: baremetal + +outputs: + - format: iso + +rpmSources: + - ../../../bin/RPMS + +extraDependencies: + - ./base + - ../../../bin/rcp-agent + - ../../../tools/cmd/rcp-agent/rcp-agent.service + +config: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml b/tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml new file mode 100644 index 0000000000..8a12653f29 --- /dev/null +++ b/tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml @@ -0,0 +1,90 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-direct-streaming-mos-testimage + packages: + update: + - systemd + install: + - binutils + - curl + - device-mapper + - dnf + - dosfstools + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - ntfs-3g + - ntfsprogs + - openssh-server + - squashfs-tools + - tar + - tpm2-tools + - veritysetup + - vim + - selinux-policy-devel + - setools-console + - trident + - trident-selinux + - trident-install-service + services: + enable: + - sshd + - rcp-agent + - tridentd.socket + disable: + - trident-install + additionalFiles: + - source: base/files/getty@.service + destination: /usr/lib/systemd/system/getty@.service + - source: base/files/serial-getty@.service + destination: /usr/lib/systemd/system/serial-getty@.service + - source: base/files/root.profile + destination: /root/.profile + - source: base/../../../../bin/rcp-agent + destination: /usr/bin/rcp-agent + - source: base/../../../../tools/cmd/rcp-agent/rcp-agent.service + destination: /usr/lib/systemd/system/rcp-agent.service + selinux: + mode: enforcing +scripts: + postCustomization: + - path: base/post-install.sh + arguments: + - stream-image-test +iso: + additionalFiles: + - source: base/files/pre-trident-script.sh + destination: /pre-trident-script.sh + - source: base/files/rcp-agent.yaml + destination: /rcp-agent.yaml + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.luks=0 + - selinux=1 diff --git a/tests/images/trident-installer/tailor/baseimg-split.yaml b/tests/images/trident-installer/tailor/baseimg-split.yaml new file mode 100644 index 0000000000..3b63840ce9 --- /dev/null +++ b/tests/images/trident-installer/tailor/baseimg-split.yaml @@ -0,0 +1,74 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-mos-testimage + packages: + install: + - curl + - device-mapper + - dnf + - dosfstools + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - ntfs-3g + - ntfsprogs + - openssh-server + - squashfs-tools + - tar + - tpm2-tools + - trident + - vim + - veritysetup + services: + enable: + - sshd + - trident-install + - tridentd.socket + selinux: + mode: enforcing + additionalFiles: + - source: base/files/getty@.service + destination: /usr/lib/systemd/system/getty@.service + - source: base/files/serial-getty@.service + destination: /usr/lib/systemd/system/serial-getty@.service + - source: base/files/root.profile + destination: /root/.profile + - source: base/files/trident-split-install.service + destination: /usr/lib/systemd/system/trident-install.service +scripts: + postCustomization: + - path: base/post-install.sh +iso: + additionalFiles: + - source: base/files/config-placeholder.yaml + destination: /trident-config.yaml + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.luks=0 diff --git a/tests/images/trident-installer/tailor/baseimg.yaml b/tests/images/trident-installer/tailor/baseimg.yaml new file mode 100644 index 0000000000..1a09fdbc7d --- /dev/null +++ b/tests/images/trident-installer/tailor/baseimg.yaml @@ -0,0 +1,81 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-mos-testimage + packages: + install: + - binutils + - curl + - device-mapper + - dnf + - dosfstools + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - ntfs-3g + - ntfsprogs + - openssh-server + - trident-static-pcrlock-files + - squashfs-tools + - tar + - tpm2-tools + - trident + - vim + - veritysetup + - selinux-policy + - selinux-policy-devel + - audit + services: + enable: + - sshd + - trident-install + - tridentd.socket + additionalFiles: + - source: base/files/getty@.service + destination: /usr/lib/systemd/system/getty@.service + - source: base/files/serial-getty@.service + destination: /usr/lib/systemd/system/serial-getty@.service + - source: base/files/root.profile + destination: /root/.profile + - source: base/files/trident-install.service + destination: /usr/lib/systemd/system/trident-install.service + selinux: + mode: enforcing +scripts: + postCustomization: + - path: base/post-install.sh +iso: + additionalFiles: + - source: base/files/config-placeholder.yaml + destination: /trident-config.yaml + - source: base/files/override-placeholder.conf + destination: /trident-override.conf + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.luks=0 diff --git a/tests/images/trident-testimage/README.md b/tests/images/trident-testimage/README.md index 108ab80e11..fb1f2174a2 100644 --- a/tests/images/trident-testimage/README.md +++ b/tests/images/trident-testimage/README.md @@ -17,8 +17,10 @@ It also includes openssh-server to allow for remote access. From the repo root, run: ```bash -python3 tests/images/testimages.py build trident-testimage +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-testimage -s arch=amd64 --output-dir ./artifacts ``` +Use `-s arch=arm64` for the ARM64 variant. + Output is written to `artifacts/trident-testimage.cosi` by default. Use `--output-dir ` to change the output location. diff --git a/tests/images/trident-testimage/by-arch/arm64.yaml b/tests/images/trident-testimage/by-arch/arm64.yaml new file mode 100644 index 0000000000..6fe6f6f38d --- /dev/null +++ b/tests/images/trident-testimage/by-arch/arm64.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: core_arm64 diff --git a/tests/images/trident-testimage/image.yaml b/tests/images/trident-testimage/image.yaml new file mode 100644 index 0000000000..06bd41af16 --- /dev/null +++ b/tests/images/trident-testimage/image.yaml @@ -0,0 +1,19 @@ +name: trident-testimage + +matrix: + arch: [amd64, arm64] + +base: + ref: baremetal + +outputs: + - format: cosi + +rpmSources: + - ../../../bin/RPMS + +extraDependencies: + - ./base + +config: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/trident-testimage/tailor/baseimg.yaml b/tests/images/trident-testimage/tailor/baseimg.yaml new file mode 100644 index 0000000000..89cbfd7bd9 --- /dev/null +++ b/tests/images/trident-testimage/tailor/baseimg.yaml @@ -0,0 +1,66 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / +os: + bootloader: + resetType: hard-reset + hostname: trident-testimg + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + packages: + remove: + - grub2-efi-binary + install: + - grub2-efi-binary-noprefix + - curl + - dnf + - efibootmgr + - iproute + - iptables + - lsof + - mdadm + - netplan + - openssh-server + - tpm2-tools + - trident-service + - vim + - audit + - device-mapper + - dosfstools + - lvm2 + - veritysetup + - ntfs-3g + - ntfsprogs + services: + enable: + - sshd + - trident + - tridentd.socket + additionalFiles: + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf +scripts: + postCustomization: + - path: base/post-install.sh diff --git a/tests/images/trident-verity-testimage/README.md b/tests/images/trident-verity-testimage/README.md index 0c8dd782a7..af74e5886b 100644 --- a/tests/images/trident-verity-testimage/README.md +++ b/tests/images/trident-verity-testimage/README.md @@ -18,8 +18,14 @@ dm-verity. From the repo root, run: ```bash -python3 tests/images/testimages.py build trident-verity-testimage +cargo run --manifest-path tools/tailor/Cargo.toml -- --manifest tests/images/tailor.yaml build trident-verity-testimage -s deployment=host -s mode=root --output-dir ./artifacts ``` -Output is written to `artifacts/trident-verity-testimage.cosi` by default. Use +Other legacy variants map to selectors on the same family: + +- `trident-usrverity-testimage` → `-s deployment=host -s mode=usr` +- `trident-container-verity-testimage` → `-s deployment=container -s mode=root` +- `trident-container-usrverity-testimage` → `-s deployment=container -s mode=usr` + +Output is written to `artifacts/` using the tailor cell slug by default. Use `--output-dir ` to change the output location. diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml new file mode 100644 index 0000000000..2ecf021158 --- /dev/null +++ b/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/baseimg-container.yaml diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml new file mode 100644 index 0000000000..3c18d9bf93 --- /dev/null +++ b/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml @@ -0,0 +1,4 @@ +config: + $set: + $include: ./tailor/usr-container.yaml +signing: true diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml new file mode 100644 index 0000000000..6baa2109a3 --- /dev/null +++ b/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml @@ -0,0 +1,5 @@ +rpmSources: + - ../../../bin/RPMS +config: + $set: + $include: ./tailor/baseimg.yaml diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml new file mode 100644 index 0000000000..3c4e34fd73 --- /dev/null +++ b/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml @@ -0,0 +1,6 @@ +rpmSources: + - ../../../bin/RPMS +config: + $set: + $include: ./tailor/usr-host.yaml +signing: true diff --git a/tests/images/trident-verity-testimage/by-deployment/host.yaml b/tests/images/trident-verity-testimage/by-deployment/host.yaml new file mode 100644 index 0000000000..359df4941f --- /dev/null +++ b/tests/images/trident-verity-testimage/by-deployment/host.yaml @@ -0,0 +1,2 @@ +rpmSources: + - ../../bin/RPMS diff --git a/tests/images/trident-verity-testimage/image.yaml b/tests/images/trident-verity-testimage/image.yaml new file mode 100644 index 0000000000..47417c6b27 --- /dev/null +++ b/tests/images/trident-verity-testimage/image.yaml @@ -0,0 +1,17 @@ +name: trident-verity-testimage + +matrix: + deployment: [host, container] + mode: [root, usr] + +base: + ref: baremetal + +outputs: + - format: cosi + +extraDependencies: + - ./base + - ./usr + +config: {} diff --git a/tests/images/trident-verity-testimage/tailor/baseimg-container.yaml b/tests/images/trident-verity-testimage/tailor/baseimg-container.yaml new file mode 100644 index 0000000000..580ab768a6 --- /dev/null +++ b/tests/images/trident-verity-testimage/tailor/baseimg-container.yaml @@ -0,0 +1,112 @@ +storage: + disks: + - partitionTableType: gpt + maxSize: 5G + partitions: + - id: esp + type: esp + size: 8M + - id: boot + size: 1G + - label: root + id: root + size: 2G + - label: root-hash + id: verityhash + size: 128M + - id: sysexts + size: 1G + - id: confexts + size: 200M + - id: var + size: grow + bootType: efi + verity: + - id: rootverity + name: root + dataDeviceId: root + hashDeviceId: verityhash + dataDeviceMountIdType: part-label + hashDeviceMountIdType: part-label + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: sysexts + type: ext4 + mountPoint: + path: /var/lib/extensions + - deviceId: confexts + type: ext4 + mountPoint: + path: /var/lib/confexts + - deviceId: var + type: ext4 + mountPoint: + path: /var +os: + bootloader: + resetType: hard-reset + hostname: trident-container-verity-testimg + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + packages: + remove: + - grub2-efi-binary + install: + - grub2-efi-binary-noprefix + - curl + - device-mapper + - dnf + - docker-cli + - dosfstools + - dracut-overlayfs + - efibootmgr + - iproute + - iptables + - lsof + - lvm2 + - mdadm + - moby-engine + - netplan + - openssh-server + - systemd-udev + - tpm2-tools + - veritysetup + - squashfs-tools + - tar + - vim + additionalFiles: + - source: base/etc-mount.service + destination: /etc/systemd/system/etc-mount.service + - source: base/etc-mount.sh + destination: /usr/local/bin/etc-mount.sh + - source: base/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/trident-container.service + destination: /usr/lib/systemd/system/trident-container.service + services: + enable: + - etc-mount + - sshd + - trident-container +scripts: + postCustomization: + - path: base/create-web-dir.sh diff --git a/tests/images/trident-verity-testimage/tailor/baseimg.yaml b/tests/images/trident-verity-testimage/tailor/baseimg.yaml new file mode 100644 index 0000000000..d6f0980fe7 --- /dev/null +++ b/tests/images/trident-verity-testimage/tailor/baseimg.yaml @@ -0,0 +1,110 @@ +storage: + disks: + - partitionTableType: gpt + maxSize: 5G + partitions: + - id: esp + type: esp + size: 8M + - id: boot + size: 1G + - label: root + id: root + size: 2G + - label: root-hash + id: verityhash + size: 128M + - id: sysexts + size: 1G + - id: confexts + size: 200M + - id: var + size: grow + bootType: efi + verity: + - id: rootverity + name: root + dataDeviceId: root + hashDeviceId: verityhash + dataDeviceMountIdType: part-label + hashDeviceMountIdType: part-label + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: sysexts + type: ext4 + mountPoint: + path: /var/lib/extensions + - deviceId: confexts + type: ext4 + mountPoint: + path: /var/lib/confexts + - deviceId: var + type: ext4 + mountPoint: + path: /var +os: + bootloader: + resetType: hard-reset + hostname: trident-verity-testimg + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + packages: + remove: + - grub2-efi-binary + install: + - grub2-efi-binary-noprefix + - curl + - device-mapper + - dosfstools + - dracut-overlayfs + - efibootmgr + - iproute + - iptables + - lsof + - lvm2 + - mdadm + - netplan + - openssh-server + - systemd-udev + - tpm2-tools + - trident-service + - veritysetup + - vim + additionalFiles: + - source: base/etc-mount.service + destination: /etc/systemd/system/etc-mount.service + - source: base/etc-mount.sh + destination: /usr/local/bin/etc-mount.sh + - source: base/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf + services: + enable: + - etc-mount + - sshd + - trident + - tridentd.socket +scripts: + postCustomization: + - path: base/trident-debug-log.sh + - path: base/create-web-dir.sh diff --git a/tests/images/trident-verity-testimage/tailor/usr-container.yaml b/tests/images/trident-verity-testimage/tailor/usr-container.yaml new file mode 100644 index 0000000000..c4e9defa9d --- /dev/null +++ b/tests/images/trident-verity-testimage/tailor/usr-container.yaml @@ -0,0 +1,104 @@ +storage: + disks: + - partitionTableType: gpt + maxSize: 5G + partitions: + - id: esp + type: esp + size: 500M + label: esp + - id: boot + size: 150M + - id: root + size: 2G + - id: usr-data + label: usr + size: 1G + - id: usr-hash + label: usr-hash + size: 128M + bootType: efi + verity: + - id: usr + name: usr + dataDeviceId: usr-data + hashDeviceId: usr-hash + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: root + type: ext4 + mountPoint: + path: / + - deviceId: usr + type: ext4 + mountPoint: + path: /usr + options: defaults,ro +os: + bootloader: + resetType: hard-reset + hostname: trident-container-usrverity-testimg + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + - rd.hostonly=0 + packages: + remove: + - grub2-efi-binary + install: + - curl + - device-mapper + - docker-cli + - efibootmgr + - iproute + - iptables + - lvm2 + - mdadm + - moby-engine + - netplan + - openssh-server + - systemd-udev + - tpm2-tools + - veritysetup + - vim + - systemd-ukify + - systemd-boot + - efibootmgr + - squashfs-tools + - tar + services: + enable: + - trident-container + - sshd + uki: + mode: create + additionalFiles: + - source: usr/files/dracut-nohostonly.conf + destination: /usr/lib/dracut/dracut.conf.d/nohostonly.conf + - source: usr/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: usr/files/trident-container.service + destination: /usr/lib/systemd/system/trident-container.service +output: + artifacts: + items: + - ukis + path: ./usr/output +previewFeatures: +- uki +- output-artifacts diff --git a/tests/images/trident-verity-testimage/tailor/usr-host.yaml b/tests/images/trident-verity-testimage/tailor/usr-host.yaml new file mode 100644 index 0000000000..b85c3b9eab --- /dev/null +++ b/tests/images/trident-verity-testimage/tailor/usr-host.yaml @@ -0,0 +1,106 @@ +storage: + disks: + - partitionTableType: gpt + maxSize: 5G + partitions: + - id: esp + type: esp + size: 500M + label: esp + - id: boot + size: 150M + - id: root + size: 2G + - id: usr-data + label: usr + size: 1G + - id: usr-hash + label: usr-hash + size: 128M + bootType: efi + verity: + - id: usr + name: usr + dataDeviceId: usr-data + hashDeviceId: usr-hash + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: root + type: ext4 + mountPoint: + path: / + - deviceId: usr + type: ext4 + mountPoint: + path: /usr + options: defaults,ro +os: + bootloader: + resetType: hard-reset + hostname: trident-usrverity-testimg + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + - rd.hostonly=0 + packages: + remove: + - grub2-efi-binary + install: + - binutils + - curl + - device-mapper + - efibootmgr + - iproute + - iptables + - lvm2 + - mdadm + - netplan + - openssh-server + - systemd-udev + - tpm2-tools + - trident-service + - trident-static-pcrlock-files + - veritysetup + - vim + - systemd-ukify + - systemd-boot + - efibootmgr + - audit + - selinux-policy-devel + services: + enable: + - sshd + - trident + - tridentd.socket + uki: + mode: create + additionalFiles: + - source: usr/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: usr/files/dracut-nohostonly.conf + destination: /usr/lib/dracut/dracut.conf.d/nohostonly.conf + - source: usr/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf +output: + artifacts: + items: + - ukis + path: ./usr/output +previewFeatures: +- uki +- output-artifacts diff --git a/tests/images/trident-vm-testimage/by-arch/arm64.yaml b/tests/images/trident-vm-testimage/by-arch/arm64.yaml new file mode 100644 index 0000000000..6fe6f6f38d --- /dev/null +++ b/tests/images/trident-vm-testimage/by-arch/arm64.yaml @@ -0,0 +1,3 @@ +base: + $set: + ref: core_arm64 diff --git a/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml b/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml new file mode 100644 index 0000000000..6e4fa214da --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/updateimg-acl-agent.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml b/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml new file mode 100644 index 0000000000..275ab1d6db --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml @@ -0,0 +1,6 @@ +base: + $set: + ref: core_selinux +config: + $set: + $include: ./tailor/updateimg-grub-verity-azure.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml b/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml new file mode 100644 index 0000000000..cd34fd3dd6 --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/updateimg-grub-verity.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/grub.yaml b/tests/images/trident-vm-testimage/by-scenario/grub.yaml new file mode 100644 index 0000000000..5cf4ffb966 --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/grub.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/updateimg-grub.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml b/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml new file mode 100644 index 0000000000..629c76513b --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/baseimg-root-verity.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml b/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml new file mode 100644 index 0000000000..6b0671c39b --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml @@ -0,0 +1,3 @@ +config: + $set: + $include: ./tailor/baseimg-usr-verity.yaml diff --git a/tests/images/trident-vm-testimage/image.yaml b/tests/images/trident-vm-testimage/image.yaml new file mode 100644 index 0000000000..ce0f3c26a3 --- /dev/null +++ b/tests/images/trident-vm-testimage/image.yaml @@ -0,0 +1,23 @@ +name: trident-vm-testimage + +matrix: + arch: [amd64, arm64] + scenario: [grub, grub-verity, root-verity, usr-verity, acl-agent, grub-verity-azure] + +selectors: + exclude: + - { arch: arm64, scenario: [root-verity, usr-verity, acl-agent, grub-verity-azure] } + +base: + ref: qemu_guest + +outputs: + - format: cosi + +rpmSources: + - ../../../bin/RPMS + +extraDependencies: + - ./base + +config: {} diff --git a/tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml b/tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml new file mode 100644 index 0000000000..08d401d3a1 --- /dev/null +++ b/tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml @@ -0,0 +1,151 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + label: esp + size: 512M + - id: boot-a + size: 256M + - id: boot-b + size: 256M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: root-hash-a + size: 128M + - id: root-hash-b + size: 128M + - id: var-a + size: 1G + - id: var-b + size: 1G + - id: trident + label: trident + size: 512M + - id: home + label: home + size: 1G + - id: srv + label: srv + size: 128M + verity: + - id: rootverity + name: root + dataDeviceId: root-a + hashDeviceId: root-hash-a + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + idType: part-label + path: /boot/efi + options: umask=0077 + - deviceId: boot-a + type: ext4 + mountPoint: + idType: uuid + path: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: var-a + type: ext4 + mountPoint: + idType: uuid + path: /var + options: defaults,x-initrd.mount + - deviceId: trident + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident + - deviceId: home + type: ext4 + mountPoint: + idType: part-label + path: /home + - deviceId: srv + type: ext4 + mountPoint: + idType: part-label + path: /srv +os: + bootloader: + resetType: hard-reset + hostname: trident-vm-root-verity-testimg + selinux: + mode: disabled + uki: + mode: create + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + - rd.hostonly=0 + packages: + install: + - device-mapper + - dnf + - efibootmgr + - iproute + - iptables + - jq + - kexec-tools + - lvm2 + - openssh-server + - systemd-boot + - systemd-udev + - trident-service + - veritysetup + - vim + - netplan + remove: + - grub2-efi-binary + additionalFiles: + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + overlays: + - mountPoint: /etc + lowerDirs: + - /etc + upperDir: /var/lib/overlays/etc/upper + workDir: /var/lib/overlays/etc/work + mountDependencies: + - /var + isInitrdOverlay: true + services: + enable: + - kdump + - trident + - tridentd.socket + users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/update-host-status.sh + - path: base/scripts/prepare-update-config-verity.sh + arguments: + - uki + - path: base/scripts/duid-type-to-link-layer.sh +previewFeatures: +- uki diff --git a/tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml b/tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml new file mode 100644 index 0000000000..e0facb4f94 --- /dev/null +++ b/tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml @@ -0,0 +1,141 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + label: esp + size: 512M + - id: boot-a + size: 256M + - id: boot-b + size: 256M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: usr-a + size: 1G + - id: usr-b + size: 1G + - id: usr-hash-a + size: 128M + - id: usr-hash-b + size: 128M + - id: trident + label: trident + size: 512M + - id: home + label: home + size: 1G + - id: srv + label: srv + size: 128M + verity: + - id: usrverity + name: usr + dataDeviceId: usr-a + hashDeviceId: usr-hash-a + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + idType: part-label + path: /boot/efi + options: umask=0077 + - deviceId: boot-a + type: ext4 + mountPoint: + idType: uuid + path: /boot + - deviceId: usrverity + type: ext4 + mountPoint: + path: /usr + options: defaults,ro + - deviceId: root-a + type: ext4 + mountPoint: + idType: uuid + path: / + - deviceId: trident + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident + - deviceId: home + type: ext4 + mountPoint: + idType: part-label + path: /home + - deviceId: srv + type: ext4 + mountPoint: + idType: part-label + path: /srv +os: + bootloader: + resetType: hard-reset + hostname: trident-vm-usr-verity-testimg + selinux: + mode: disabled + uki: + mode: create + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + - rd.hostonly=0 + packages: + install: + - device-mapper + - dnf + - efibootmgr + - iproute + - iptables + - jq + - kexec-tools + - lvm2 + - openssh-server + - systemd-boot + - systemd-udev + - trident-service + - veritysetup + - vim + - netplan + remove: + - grub2-efi-binary + additionalFiles: + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + services: + enable: + - kdump + - trident + - tridentd.socket + users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/update-host-status.sh + - path: base/scripts/prepare-update-config-verity.sh + arguments: + - uki + - path: base/scripts/duid-type-to-link-layer.sh +previewFeatures: +- uki diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml new file mode 100644 index 0000000000..d0990a2d65 --- /dev/null +++ b/tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml @@ -0,0 +1,170 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + label: esp + size: 512M + - id: boot-a + size: 256M + - id: boot-b + size: 256M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: usr-a + size: 1G + - id: usr-b + size: 1G + - id: usr-hash-a + size: 128M + - id: usr-hash-b + size: 128M + - id: trident + label: trident + size: 512M + - id: trident-acl-agent + label: trident-acl-agent + size: 128M + - id: kubelet + label: kubelet + size: 128M + - id: etc-trident + label: etc-trident + size: 128M + - id: home + label: home + size: 1G + - id: srv + label: srv + size: 128M + verity: + - id: usrverity + name: usr + dataDeviceId: usr-a + hashDeviceId: usr-hash-a + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + idType: part-label + path: /boot/efi + options: umask=0077 + - deviceId: boot-a + type: ext4 + mountPoint: + idType: uuid + path: /boot + - deviceId: usrverity + type: ext4 + mountPoint: + path: /usr + options: defaults,ro + - deviceId: root-a + type: ext4 + mountPoint: + idType: uuid + path: / + - deviceId: trident + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident + - deviceId: trident-acl-agent + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident-acl-agent + - deviceId: kubelet + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/kubelet + - deviceId: etc-trident + type: ext4 + mountPoint: + idType: part-label + path: /etc/trident + - deviceId: home + type: ext4 + mountPoint: + idType: part-label + path: /home + - deviceId: srv + type: ext4 + mountPoint: + idType: part-label + path: /srv +os: + bootloader: + resetType: hard-reset + hostname: trident-acl-agent-testimg + selinux: + mode: disabled + uki: + mode: create + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + - rd.hostonly=0 + packages: + install: + - device-mapper + - dnf + - efibootmgr + - iproute + - iptables + - jq + - kexec-tools + - lvm2 + - openssh-server + - systemd-boot + - systemd-udev + - trident-acl + - veritysetup + - vim + - netplan + remove: + - grub2-efi-binary + additionalFiles: + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/trident-acl-agent-override.conf + destination: /etc/systemd/system/trident-acl-agent.service.d/override.conf + - source: base/files/trident-acl-agent-cert-install.service + destination: /etc/systemd/system/trident-acl-agent-cert-install.service + services: + enable: + - kdump + - tridentd.socket + - trident-acl-agent-cert-install.service + - trident-acl-agent.service + users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/update-host-status.sh + - path: base/scripts/prepare-update-config-verity.sh + arguments: + - uki + - path: base/scripts/duid-type-to-link-layer.sh +previewFeatures: +- uki diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml new file mode 100644 index 0000000000..765d6950b0 --- /dev/null +++ b/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml @@ -0,0 +1,127 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + maxSize: 7G + partitions: + - id: esp + type: esp + size: 8M + - id: boot + size: 256M + - id: root + size: 4G + - id: root-hash + size: 128M + - id: var + size: 1G + - id: trident-overlay + size: 32M + - id: srv + size: 1G + - id: home + size: 32M + verity: + - id: rootverity + name: root + dataDeviceId: root + hashDeviceId: root-hash + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + options: umask=0077 + path: /boot/efi + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: var + type: ext4 + mountPoint: + path: /var + - deviceId: trident-overlay + type: ext4 + mountPoint: + path: /var/lib/trident-overlay + - deviceId: srv + type: ext4 + mountPoint: + path: /srv + - deviceId: home + type: ext4 + mountPoint: + path: /home +os: + bootloader: + resetType: hard-reset + hostname: trident-vm-testimg + selinux: + mode: permissive + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + packages: + install: + - curl + - device-mapper + - dnf + - dracut-overlayfs + - efibootmgr + - grub2-efi-binary-noprefix + - iproute + - iptables + - jq + - kexec-tools + - lsof + - lvm2 + - netplan + - openssh-server + - selinux-policy + - systemd-udev + - trident-service + - veritysetup + - vim + - WALinuxAgent + remove: + - grub2-efi-binary + additionalFiles: + - source: base/files/etc-mount.service + destination: /etc/systemd/system/etc-mount.service + - source: base/files/etc-mount.sh + destination: /usr/local/bin/etc-mount.sh + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf + services: + enable: + - etc-mount + - kdump + - trident + - tridentd.socket + users: + - name: testuser + secondaryGroups: + - wheel +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/ssh-move-host-keys.sh + - path: base/scripts/update-os-release.sh + - path: base/scripts/duid-type-to-link-layer.sh diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml new file mode 100644 index 0000000000..bd87eaaa7d --- /dev/null +++ b/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml @@ -0,0 +1,122 @@ +storage: + bootType: efi + disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + size: 8M + - id: boot + size: 256M + - id: root + size: 4G + - id: root-hash + size: 128M + - id: var + size: 1G + - id: trident-overlay + size: 32M + - id: srv + size: 1G + - id: home + size: 32M + verity: + - id: rootverity + name: root + dataDeviceId: root + hashDeviceId: root-hash + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid + filesystems: + - deviceId: esp + type: fat32 + mountPoint: + options: umask=0077 + path: /boot/efi + - deviceId: boot + type: ext4 + mountPoint: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: var + type: ext4 + mountPoint: /var + - deviceId: trident-overlay + type: ext4 + mountPoint: /var/lib/trident-overlay + - deviceId: srv + type: ext4 + mountPoint: /srv + - deviceId: home + type: ext4 + mountPoint: /home +os: + bootloader: + resetType: hard-reset + hostname: trident-vm-verity-testimg + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + packages: + install: + - curl + - device-mapper + - dnf + - dracut-overlayfs + - efibootmgr + - grub2-efi-binary-noprefix + - iproute + - iptables + - jq + - kexec-tools + - lsof + - lvm2 + - netplan + - openssh-server + - systemd-udev + - trident-service + - veritysetup + - vim + - netplan + remove: + - grub2-efi-binary + additionalFiles: + - source: base/files/etc-mount.service + destination: /etc/systemd/system/etc-mount.service + - source: base/files/etc-mount.sh + destination: /usr/local/bin/etc-mount.sh + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf + services: + enable: + - etc-mount + - kdump + - trident + - tridentd.socket + users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/ssh-move-host-keys.sh + - path: base/scripts/update-os-release.sh + - path: base/scripts/duid-type-to-link-layer.sh diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml new file mode 100644 index 0000000000..34b1dd8cfa --- /dev/null +++ b/tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml @@ -0,0 +1,75 @@ +storage: + bootType: efi + disks: + - maxSize: 5G + partitionTableType: gpt + partitions: + - id: esp + size: 8M + type: esp + - id: root + size: 4G + filesystems: + - deviceId: esp + mountPoint: + options: umask=0077 + path: /boot/efi + type: fat32 + - deviceId: root + mountPoint: / + type: ext4 +os: + hostname: trident-vm-testimg + packages: + install: + - curl + - dnf + - efibootmgr + - grub2-efi-binary-noprefix + - iproute + - iptables + - jq + - lsof + - netplan + - openssh-server + - trident-service + - vim + - netplan + remove: + - grub2-efi-binary + bootloader: + resetType: hard-reset + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + services: + enable: + - trident + - tridentd.socket + users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel + additionalFiles: + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf +scripts: + postCustomization: + - path: base/scripts/post-install.sh + - path: base/scripts/ssh-move-host-keys.sh + - path: base/scripts/duid-type-to-link-layer.sh + - path: base/scripts/update-os-release.sh From b63869902c01edde0691b2765784e10da2598957 Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Fri, 9 Oct 2026 22:32:06 +0000 Subject: [PATCH 02/16] Factor shared tailor image config Replace per-scenario full YAML copies with shared include snippets and smaller delta fragments in the installer, verity, and VM image families. Preserve the existing matrix cells and rendered configs while reducing duplicated Image Customizer config. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../by-variant/direct-streaming.yaml | 49 ++++- .../trident-installer/by-variant/split.yaml | 23 ++- tests/images/trident-installer/image.yaml | 38 +++- .../include/common-files.yaml | 6 + .../include/common-packages.yaml | 19 ++ .../include/kernel-args.yaml | 3 + .../trident-installer/include/storage.yaml | 20 +++ .../tailor/baseimg-direct-streaming.yaml | 90 ---------- .../tailor/baseimg-split.yaml | 74 -------- .../trident-installer/tailor/baseimg.yaml | 81 --------- .../by-deployment+mode/container+root.yaml | 20 ++- .../by-deployment+mode/container+usr.yaml | 17 +- .../by-deployment+mode/host+root.yaml | 20 ++- .../by-deployment+mode/host+usr.yaml | 21 ++- .../by-deployment/container.yaml | 1 + .../by-deployment/host.yaml | 2 +- .../by-mode/root.yaml | 5 + .../trident-verity-testimage/by-mode/usr.yaml | 14 ++ .../include/root-os-common.yaml | 42 +++++ .../include/root-storage.yaml | 56 ++++++ .../include/usr-os-common.yaml | 41 +++++ .../include/usr-storage.yaml | 45 +++++ .../tailor/baseimg-container.yaml | 112 ------------ .../tailor/baseimg.yaml | 110 ------------ .../tailor/usr-container.yaml | 104 ----------- .../tailor/usr-host.yaml | 106 ----------- .../by-scenario/acl-agent.yaml | 25 ++- .../grub-verity+grub-verity-azure.yaml | 6 + .../by-scenario/grub-verity-azure.yaml | 21 ++- .../by-scenario/grub-verity.yaml | 6 +- .../by-scenario/grub.yaml | 56 +++++- .../root-verity+usr-verity+acl-agent.yaml | 8 + .../by-scenario/root-verity.yaml | 25 ++- .../by-scenario/usr-verity.yaml | 16 +- .../include/grub-os-common.yaml | 22 +++ .../include/grub-scripts.yaml | 4 + .../include/grub-verity-os-common.yaml | 59 ++++++ .../include/grub-verity-scripts.yaml | 4 + .../include/storage-acl-agent.yaml | 101 +++++++++++ .../include/storage-grub-verity.yaml | 54 ++++++ .../include/storage-grub.yaml | 31 ++++ .../include/storage-root-verity.yaml | 78 ++++++++ .../include/storage-usr-verity.yaml | 77 ++++++++ .../include/uki-verity-os-common.yaml | 41 +++++ .../include/uki-verity-scripts.yaml | 6 + .../tailor/baseimg-root-verity.yaml | 151 ---------------- .../tailor/baseimg-usr-verity.yaml | 141 --------------- .../tailor/updateimg-acl-agent.yaml | 170 ------------------ .../tailor/updateimg-grub-verity-azure.yaml | 127 ------------- .../tailor/updateimg-grub-verity.yaml | 122 ------------- .../tailor/updateimg-grub.yaml | 75 -------- 51 files changed, 1050 insertions(+), 1495 deletions(-) create mode 100644 tests/images/trident-installer/include/common-files.yaml create mode 100644 tests/images/trident-installer/include/common-packages.yaml create mode 100644 tests/images/trident-installer/include/kernel-args.yaml create mode 100644 tests/images/trident-installer/include/storage.yaml delete mode 100644 tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml delete mode 100644 tests/images/trident-installer/tailor/baseimg-split.yaml delete mode 100644 tests/images/trident-installer/tailor/baseimg.yaml create mode 100644 tests/images/trident-verity-testimage/by-deployment/container.yaml create mode 100644 tests/images/trident-verity-testimage/by-mode/root.yaml create mode 100644 tests/images/trident-verity-testimage/by-mode/usr.yaml create mode 100644 tests/images/trident-verity-testimage/include/root-os-common.yaml create mode 100644 tests/images/trident-verity-testimage/include/root-storage.yaml create mode 100644 tests/images/trident-verity-testimage/include/usr-os-common.yaml create mode 100644 tests/images/trident-verity-testimage/include/usr-storage.yaml delete mode 100644 tests/images/trident-verity-testimage/tailor/baseimg-container.yaml delete mode 100644 tests/images/trident-verity-testimage/tailor/baseimg.yaml delete mode 100644 tests/images/trident-verity-testimage/tailor/usr-container.yaml delete mode 100644 tests/images/trident-verity-testimage/tailor/usr-host.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/grub-verity+grub-verity-azure.yaml create mode 100644 tests/images/trident-vm-testimage/by-scenario/root-verity+usr-verity+acl-agent.yaml create mode 100644 tests/images/trident-vm-testimage/include/grub-os-common.yaml create mode 100644 tests/images/trident-vm-testimage/include/grub-scripts.yaml create mode 100644 tests/images/trident-vm-testimage/include/grub-verity-os-common.yaml create mode 100644 tests/images/trident-vm-testimage/include/grub-verity-scripts.yaml create mode 100644 tests/images/trident-vm-testimage/include/storage-acl-agent.yaml create mode 100644 tests/images/trident-vm-testimage/include/storage-grub-verity.yaml create mode 100644 tests/images/trident-vm-testimage/include/storage-grub.yaml create mode 100644 tests/images/trident-vm-testimage/include/storage-root-verity.yaml create mode 100644 tests/images/trident-vm-testimage/include/storage-usr-verity.yaml create mode 100644 tests/images/trident-vm-testimage/include/uki-verity-os-common.yaml create mode 100644 tests/images/trident-vm-testimage/include/uki-verity-scripts.yaml delete mode 100644 tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml delete mode 100644 tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml delete mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml delete mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml delete mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml delete mode 100644 tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml diff --git a/tests/images/trident-installer/by-variant/direct-streaming.yaml b/tests/images/trident-installer/by-variant/direct-streaming.yaml index 020757f552..8c65ae00a5 100644 --- a/tests/images/trident-installer/by-variant/direct-streaming.yaml +++ b/tests/images/trident-installer/by-variant/direct-streaming.yaml @@ -1,3 +1,48 @@ config: - $set: - $include: ./tailor/baseimg-direct-streaming.yaml + os: + hostname: + $set: trident-direct-streaming-mos-testimage + packages: + update: + - systemd + install: + $remove: + - trident-static-pcrlock-files + - selinux-policy + - audit + $append: + - setools-console + - trident-selinux + - trident-install-service + services: + enable: + $remove: + - trident-install + $append: + - rcp-agent + additionalFiles: + $remove: + - source: base/files/trident-install.service + destination: /usr/lib/systemd/system/trident-install.service + $append: + - source: ../../../bin/rcp-agent + destination: /usr/bin/rcp-agent + - source: ../../../tools/cmd/rcp-agent/rcp-agent.service + destination: /usr/lib/systemd/system/rcp-agent.service + scripts: + postCustomization: + $replace: + - path: base/post-install.sh + arguments: + - stream-image-test + iso: + additionalFiles: + $replace: + - source: base/files/pre-trident-script.sh + destination: /pre-trident-script.sh + - source: base/files/rcp-agent.yaml + destination: /rcp-agent.yaml + kernelCommandLine: + extraCommandLine: + $append: + - selinux=1 diff --git a/tests/images/trident-installer/by-variant/split.yaml b/tests/images/trident-installer/by-variant/split.yaml index 4a201dd734..328eeb6654 100644 --- a/tests/images/trident-installer/by-variant/split.yaml +++ b/tests/images/trident-installer/by-variant/split.yaml @@ -1,3 +1,22 @@ config: - $set: - $include: ./tailor/baseimg-split.yaml + os: + packages: + install: + $remove: + - binutils + - trident-static-pcrlock-files + - selinux-policy + - selinux-policy-devel + - audit + additionalFiles: + $remove: + - source: base/files/trident-install.service + destination: /usr/lib/systemd/system/trident-install.service + $append: + - source: base/files/trident-split-install.service + destination: /usr/lib/systemd/system/trident-install.service + iso: + additionalFiles: + $remove: + - source: base/files/override-placeholder.conf + destination: /trident-override.conf diff --git a/tests/images/trident-installer/image.yaml b/tests/images/trident-installer/image.yaml index abd8160359..eb762357ba 100644 --- a/tests/images/trident-installer/image.yaml +++ b/tests/images/trident-installer/image.yaml @@ -23,4 +23,40 @@ extraDependencies: - ../../../tools/cmd/rcp-agent/rcp-agent.service config: - $include: ./tailor/baseimg.yaml + storage: + $include: ./include/storage.yaml + os: + bootloader: + resetType: hard-reset + hostname: trident-mos-testimage + packages: + install: + - $include: ./include/common-packages.yaml + - binutils + - trident-static-pcrlock-files + - selinux-policy + - selinux-policy-devel + - audit + services: + enable: + - sshd + - trident-install + - tridentd.socket + additionalFiles: + - $include: ./include/common-files.yaml + - source: base/files/trident-install.service + destination: /usr/lib/systemd/system/trident-install.service + selinux: + mode: enforcing + scripts: + postCustomization: + - path: base/post-install.sh + iso: + additionalFiles: + - source: base/files/config-placeholder.yaml + destination: /trident-config.yaml + - source: base/files/override-placeholder.conf + destination: /trident-override.conf + kernelCommandLine: + extraCommandLine: + - $include: ./include/kernel-args.yaml diff --git a/tests/images/trident-installer/include/common-files.yaml b/tests/images/trident-installer/include/common-files.yaml new file mode 100644 index 0000000000..ff0048588d --- /dev/null +++ b/tests/images/trident-installer/include/common-files.yaml @@ -0,0 +1,6 @@ +- source: base/files/getty@.service + destination: /usr/lib/systemd/system/getty@.service +- source: base/files/serial-getty@.service + destination: /usr/lib/systemd/system/serial-getty@.service +- source: base/files/root.profile + destination: /root/.profile diff --git a/tests/images/trident-installer/include/common-packages.yaml b/tests/images/trident-installer/include/common-packages.yaml new file mode 100644 index 0000000000..82b2d430e0 --- /dev/null +++ b/tests/images/trident-installer/include/common-packages.yaml @@ -0,0 +1,19 @@ +- curl +- device-mapper +- dnf +- dosfstools +- efibootmgr +- iproute +- iptables +- lsof +- mdadm +- netplan +- ntfs-3g +- ntfsprogs +- openssh-server +- squashfs-tools +- tar +- tpm2-tools +- trident +- vim +- veritysetup diff --git a/tests/images/trident-installer/include/kernel-args.yaml b/tests/images/trident-installer/include/kernel-args.yaml new file mode 100644 index 0000000000..9b4f24cc61 --- /dev/null +++ b/tests/images/trident-installer/include/kernel-args.yaml @@ -0,0 +1,3 @@ +- console=tty0 +- console=ttyS0 +- rd.luks=0 diff --git a/tests/images/trident-installer/include/storage.yaml b/tests/images/trident-installer/include/storage.yaml new file mode 100644 index 0000000000..28c45f83e1 --- /dev/null +++ b/tests/images/trident-installer/include/storage.yaml @@ -0,0 +1,20 @@ +bootType: efi +disks: + - partitionTableType: gpt + maxSize: 4G + partitions: + - id: esp + type: esp + size: 8M + - id: rootfs + size: grow +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: rootfs + type: ext4 + mountPoint: + path: / diff --git a/tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml b/tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml deleted file mode 100644 index 8a12653f29..0000000000 --- a/tests/images/trident-installer/tailor/baseimg-direct-streaming.yaml +++ /dev/null @@ -1,90 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - maxSize: 4G - partitions: - - id: esp - type: esp - size: 8M - - id: rootfs - size: grow - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: rootfs - type: ext4 - mountPoint: - path: / -os: - bootloader: - resetType: hard-reset - hostname: trident-direct-streaming-mos-testimage - packages: - update: - - systemd - install: - - binutils - - curl - - device-mapper - - dnf - - dosfstools - - efibootmgr - - iproute - - iptables - - lsof - - mdadm - - netplan - - ntfs-3g - - ntfsprogs - - openssh-server - - squashfs-tools - - tar - - tpm2-tools - - veritysetup - - vim - - selinux-policy-devel - - setools-console - - trident - - trident-selinux - - trident-install-service - services: - enable: - - sshd - - rcp-agent - - tridentd.socket - disable: - - trident-install - additionalFiles: - - source: base/files/getty@.service - destination: /usr/lib/systemd/system/getty@.service - - source: base/files/serial-getty@.service - destination: /usr/lib/systemd/system/serial-getty@.service - - source: base/files/root.profile - destination: /root/.profile - - source: base/../../../../bin/rcp-agent - destination: /usr/bin/rcp-agent - - source: base/../../../../tools/cmd/rcp-agent/rcp-agent.service - destination: /usr/lib/systemd/system/rcp-agent.service - selinux: - mode: enforcing -scripts: - postCustomization: - - path: base/post-install.sh - arguments: - - stream-image-test -iso: - additionalFiles: - - source: base/files/pre-trident-script.sh - destination: /pre-trident-script.sh - - source: base/files/rcp-agent.yaml - destination: /rcp-agent.yaml - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.luks=0 - - selinux=1 diff --git a/tests/images/trident-installer/tailor/baseimg-split.yaml b/tests/images/trident-installer/tailor/baseimg-split.yaml deleted file mode 100644 index 3b63840ce9..0000000000 --- a/tests/images/trident-installer/tailor/baseimg-split.yaml +++ /dev/null @@ -1,74 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - maxSize: 4G - partitions: - - id: esp - type: esp - size: 8M - - id: rootfs - size: grow - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: rootfs - type: ext4 - mountPoint: - path: / -os: - bootloader: - resetType: hard-reset - hostname: trident-mos-testimage - packages: - install: - - curl - - device-mapper - - dnf - - dosfstools - - efibootmgr - - iproute - - iptables - - lsof - - mdadm - - netplan - - ntfs-3g - - ntfsprogs - - openssh-server - - squashfs-tools - - tar - - tpm2-tools - - trident - - vim - - veritysetup - services: - enable: - - sshd - - trident-install - - tridentd.socket - selinux: - mode: enforcing - additionalFiles: - - source: base/files/getty@.service - destination: /usr/lib/systemd/system/getty@.service - - source: base/files/serial-getty@.service - destination: /usr/lib/systemd/system/serial-getty@.service - - source: base/files/root.profile - destination: /root/.profile - - source: base/files/trident-split-install.service - destination: /usr/lib/systemd/system/trident-install.service -scripts: - postCustomization: - - path: base/post-install.sh -iso: - additionalFiles: - - source: base/files/config-placeholder.yaml - destination: /trident-config.yaml - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.luks=0 diff --git a/tests/images/trident-installer/tailor/baseimg.yaml b/tests/images/trident-installer/tailor/baseimg.yaml deleted file mode 100644 index 1a09fdbc7d..0000000000 --- a/tests/images/trident-installer/tailor/baseimg.yaml +++ /dev/null @@ -1,81 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - maxSize: 4G - partitions: - - id: esp - type: esp - size: 8M - - id: rootfs - size: grow - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: rootfs - type: ext4 - mountPoint: - path: / -os: - bootloader: - resetType: hard-reset - hostname: trident-mos-testimage - packages: - install: - - binutils - - curl - - device-mapper - - dnf - - dosfstools - - efibootmgr - - iproute - - iptables - - lsof - - mdadm - - netplan - - ntfs-3g - - ntfsprogs - - openssh-server - - trident-static-pcrlock-files - - squashfs-tools - - tar - - tpm2-tools - - trident - - vim - - veritysetup - - selinux-policy - - selinux-policy-devel - - audit - services: - enable: - - sshd - - trident-install - - tridentd.socket - additionalFiles: - - source: base/files/getty@.service - destination: /usr/lib/systemd/system/getty@.service - - source: base/files/serial-getty@.service - destination: /usr/lib/systemd/system/serial-getty@.service - - source: base/files/root.profile - destination: /root/.profile - - source: base/files/trident-install.service - destination: /usr/lib/systemd/system/trident-install.service - selinux: - mode: enforcing -scripts: - postCustomization: - - path: base/post-install.sh -iso: - additionalFiles: - - source: base/files/config-placeholder.yaml - destination: /trident-config.yaml - - source: base/files/override-placeholder.conf - destination: /trident-override.conf - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.luks=0 diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml index 2ecf021158..8d3e5de076 100644 --- a/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml +++ b/tests/images/trident-verity-testimage/by-deployment+mode/container+root.yaml @@ -1,3 +1,19 @@ config: - $set: - $include: ./tailor/baseimg-container.yaml + os: + hostname: trident-container-verity-testimg + packages: + install: + - dnf + - docker-cli + - moby-engine + - squashfs-tools + - tar + additionalFiles: + - source: base/files/trident-container.service + destination: /usr/lib/systemd/system/trident-container.service + services: + enable: + - trident-container + scripts: + postCustomization: + - path: base/create-web-dir.sh diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml index 3c18d9bf93..c7eed50273 100644 --- a/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml +++ b/tests/images/trident-verity-testimage/by-deployment+mode/container+usr.yaml @@ -1,4 +1,15 @@ config: - $set: - $include: ./tailor/usr-container.yaml -signing: true + os: + hostname: trident-container-usrverity-testimg + packages: + install: + - docker-cli + - moby-engine + - squashfs-tools + - tar + additionalFiles: + - source: usr/files/trident-container.service + destination: /usr/lib/systemd/system/trident-container.service + services: + enable: + - trident-container diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml index 6baa2109a3..e75de1bfb6 100644 --- a/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml +++ b/tests/images/trident-verity-testimage/by-deployment+mode/host+root.yaml @@ -1,5 +1,17 @@ -rpmSources: - - ../../../bin/RPMS config: - $set: - $include: ./tailor/baseimg.yaml + os: + hostname: trident-verity-testimg + packages: + install: + - trident-service + additionalFiles: + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf + services: + enable: + - trident + - tridentd.socket + scripts: + postCustomization: + - path: base/trident-debug-log.sh + - path: base/create-web-dir.sh diff --git a/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml b/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml index 3c4e34fd73..567cc110db 100644 --- a/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml +++ b/tests/images/trident-verity-testimage/by-deployment+mode/host+usr.yaml @@ -1,6 +1,17 @@ -rpmSources: - - ../../../bin/RPMS config: - $set: - $include: ./tailor/usr-host.yaml -signing: true + os: + hostname: trident-usrverity-testimg + packages: + install: + - binutils + - trident-service + - trident-static-pcrlock-files + - audit + - selinux-policy-devel + additionalFiles: + - source: usr/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf + services: + enable: + - trident + - tridentd.socket diff --git a/tests/images/trident-verity-testimage/by-deployment/container.yaml b/tests/images/trident-verity-testimage/by-deployment/container.yaml new file mode 100644 index 0000000000..de2ca21c3f --- /dev/null +++ b/tests/images/trident-verity-testimage/by-deployment/container.yaml @@ -0,0 +1 @@ +features: [] diff --git a/tests/images/trident-verity-testimage/by-deployment/host.yaml b/tests/images/trident-verity-testimage/by-deployment/host.yaml index 359df4941f..7ef528ff76 100644 --- a/tests/images/trident-verity-testimage/by-deployment/host.yaml +++ b/tests/images/trident-verity-testimage/by-deployment/host.yaml @@ -1,2 +1,2 @@ rpmSources: - - ../../bin/RPMS + - ../../../bin/RPMS diff --git a/tests/images/trident-verity-testimage/by-mode/root.yaml b/tests/images/trident-verity-testimage/by-mode/root.yaml new file mode 100644 index 0000000000..04d59a7568 --- /dev/null +++ b/tests/images/trident-verity-testimage/by-mode/root.yaml @@ -0,0 +1,5 @@ +config: + os: + $include: ./include/root-os-common.yaml + storage: + $include: ./include/root-storage.yaml diff --git a/tests/images/trident-verity-testimage/by-mode/usr.yaml b/tests/images/trident-verity-testimage/by-mode/usr.yaml new file mode 100644 index 0000000000..8a5445367a --- /dev/null +++ b/tests/images/trident-verity-testimage/by-mode/usr.yaml @@ -0,0 +1,14 @@ +signing: true +config: + os: + $include: ./include/usr-os-common.yaml + storage: + $include: ./include/usr-storage.yaml + output: + artifacts: + items: + - ukis + path: ./output + previewFeatures: + - uki + - output-artifacts diff --git a/tests/images/trident-verity-testimage/include/root-os-common.yaml b/tests/images/trident-verity-testimage/include/root-os-common.yaml new file mode 100644 index 0000000000..16faa0d324 --- /dev/null +++ b/tests/images/trident-verity-testimage/include/root-os-common.yaml @@ -0,0 +1,42 @@ +bootloader: + resetType: hard-reset +selinux: + mode: disabled +kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M +packages: + install: + - grub2-efi-binary-noprefix + - curl + - device-mapper + - dosfstools + - dracut-overlayfs + - efibootmgr + - iproute + - iptables + - lsof + - lvm2 + - mdadm + - netplan + - openssh-server + - systemd-udev + - tpm2-tools + - veritysetup + - vim + remove: + - grub2-efi-binary +additionalFiles: + - source: base/etc-mount.service + destination: /etc/systemd/system/etc-mount.service + - source: base/etc-mount.sh + destination: /usr/local/bin/etc-mount.sh + - source: base/sudoers-wheel + destination: /etc/sudoers.d/wheel +services: + enable: + - etc-mount + - sshd diff --git a/tests/images/trident-verity-testimage/include/root-storage.yaml b/tests/images/trident-verity-testimage/include/root-storage.yaml new file mode 100644 index 0000000000..cb38c27f81 --- /dev/null +++ b/tests/images/trident-verity-testimage/include/root-storage.yaml @@ -0,0 +1,56 @@ +disks: + - partitionTableType: gpt + maxSize: 5G + partitions: + - id: esp + type: esp + size: 8M + - id: boot + size: 1G + - label: root + id: root + size: 2G + - label: root-hash + id: verityhash + size: 128M + - id: sysexts + size: 1G + - id: confexts + size: 200M + - id: var + size: grow +bootType: efi +verity: + - id: rootverity + name: root + dataDeviceId: root + hashDeviceId: verityhash + dataDeviceMountIdType: part-label + hashDeviceMountIdType: part-label +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: sysexts + type: ext4 + mountPoint: + path: /var/lib/extensions + - deviceId: confexts + type: ext4 + mountPoint: + path: /var/lib/confexts + - deviceId: var + type: ext4 + mountPoint: + path: /var diff --git a/tests/images/trident-verity-testimage/include/usr-os-common.yaml b/tests/images/trident-verity-testimage/include/usr-os-common.yaml new file mode 100644 index 0000000000..3817dbcc59 --- /dev/null +++ b/tests/images/trident-verity-testimage/include/usr-os-common.yaml @@ -0,0 +1,41 @@ +bootloader: + resetType: hard-reset +selinux: + mode: disabled +uki: + mode: create +kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=ttyS0 + - rd.info + - log_buf_len=1M + - rd.hostonly=0 +packages: + install: + - curl + - device-mapper + - efibootmgr + - iproute + - iptables + - lvm2 + - mdadm + - netplan + - openssh-server + - systemd-udev + - tpm2-tools + - veritysetup + - vim + - systemd-ukify + - systemd-boot + - efibootmgr + remove: + - grub2-efi-binary +additionalFiles: + - source: usr/files/dracut-nohostonly.conf + destination: /usr/lib/dracut/dracut.conf.d/nohostonly.conf + - source: usr/files/sudoers-wheel + destination: /etc/sudoers.d/wheel +services: + enable: + - sshd diff --git a/tests/images/trident-verity-testimage/include/usr-storage.yaml b/tests/images/trident-verity-testimage/include/usr-storage.yaml new file mode 100644 index 0000000000..ce7337eaa0 --- /dev/null +++ b/tests/images/trident-verity-testimage/include/usr-storage.yaml @@ -0,0 +1,45 @@ +disks: + - partitionTableType: gpt + maxSize: 5G + partitions: + - id: esp + type: esp + size: 500M + label: esp + - id: boot + size: 150M + - id: root + size: 2G + - id: usr-data + label: usr + size: 1G + - id: usr-hash + label: usr-hash + size: 128M +bootType: efi +verity: + - id: usr + name: usr + dataDeviceId: usr-data + hashDeviceId: usr-hash + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: + path: /boot + - deviceId: root + type: ext4 + mountPoint: + path: / + - deviceId: usr + type: ext4 + mountPoint: + path: /usr + options: defaults,ro diff --git a/tests/images/trident-verity-testimage/tailor/baseimg-container.yaml b/tests/images/trident-verity-testimage/tailor/baseimg-container.yaml deleted file mode 100644 index 580ab768a6..0000000000 --- a/tests/images/trident-verity-testimage/tailor/baseimg-container.yaml +++ /dev/null @@ -1,112 +0,0 @@ -storage: - disks: - - partitionTableType: gpt - maxSize: 5G - partitions: - - id: esp - type: esp - size: 8M - - id: boot - size: 1G - - label: root - id: root - size: 2G - - label: root-hash - id: verityhash - size: 128M - - id: sysexts - size: 1G - - id: confexts - size: 200M - - id: var - size: grow - bootType: efi - verity: - - id: rootverity - name: root - dataDeviceId: root - hashDeviceId: verityhash - dataDeviceMountIdType: part-label - hashDeviceMountIdType: part-label - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: boot - type: ext4 - mountPoint: - path: /boot - - deviceId: rootverity - type: ext4 - mountPoint: - path: / - options: defaults,ro - - deviceId: sysexts - type: ext4 - mountPoint: - path: /var/lib/extensions - - deviceId: confexts - type: ext4 - mountPoint: - path: /var/lib/confexts - - deviceId: var - type: ext4 - mountPoint: - path: /var -os: - bootloader: - resetType: hard-reset - hostname: trident-container-verity-testimg - selinux: - mode: disabled - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.info - - log_buf_len=1M - packages: - remove: - - grub2-efi-binary - install: - - grub2-efi-binary-noprefix - - curl - - device-mapper - - dnf - - docker-cli - - dosfstools - - dracut-overlayfs - - efibootmgr - - iproute - - iptables - - lsof - - lvm2 - - mdadm - - moby-engine - - netplan - - openssh-server - - systemd-udev - - tpm2-tools - - veritysetup - - squashfs-tools - - tar - - vim - additionalFiles: - - source: base/etc-mount.service - destination: /etc/systemd/system/etc-mount.service - - source: base/etc-mount.sh - destination: /usr/local/bin/etc-mount.sh - - source: base/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: base/files/trident-container.service - destination: /usr/lib/systemd/system/trident-container.service - services: - enable: - - etc-mount - - sshd - - trident-container -scripts: - postCustomization: - - path: base/create-web-dir.sh diff --git a/tests/images/trident-verity-testimage/tailor/baseimg.yaml b/tests/images/trident-verity-testimage/tailor/baseimg.yaml deleted file mode 100644 index d6f0980fe7..0000000000 --- a/tests/images/trident-verity-testimage/tailor/baseimg.yaml +++ /dev/null @@ -1,110 +0,0 @@ -storage: - disks: - - partitionTableType: gpt - maxSize: 5G - partitions: - - id: esp - type: esp - size: 8M - - id: boot - size: 1G - - label: root - id: root - size: 2G - - label: root-hash - id: verityhash - size: 128M - - id: sysexts - size: 1G - - id: confexts - size: 200M - - id: var - size: grow - bootType: efi - verity: - - id: rootverity - name: root - dataDeviceId: root - hashDeviceId: verityhash - dataDeviceMountIdType: part-label - hashDeviceMountIdType: part-label - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: boot - type: ext4 - mountPoint: - path: /boot - - deviceId: rootverity - type: ext4 - mountPoint: - path: / - options: defaults,ro - - deviceId: sysexts - type: ext4 - mountPoint: - path: /var/lib/extensions - - deviceId: confexts - type: ext4 - mountPoint: - path: /var/lib/confexts - - deviceId: var - type: ext4 - mountPoint: - path: /var -os: - bootloader: - resetType: hard-reset - hostname: trident-verity-testimg - selinux: - mode: disabled - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.info - - log_buf_len=1M - packages: - remove: - - grub2-efi-binary - install: - - grub2-efi-binary-noprefix - - curl - - device-mapper - - dosfstools - - dracut-overlayfs - - efibootmgr - - iproute - - iptables - - lsof - - lvm2 - - mdadm - - netplan - - openssh-server - - systemd-udev - - tpm2-tools - - trident-service - - veritysetup - - vim - additionalFiles: - - source: base/etc-mount.service - destination: /etc/systemd/system/etc-mount.service - - source: base/etc-mount.sh - destination: /usr/local/bin/etc-mount.sh - - source: base/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: base/files/use-grpc-client-commit.conf - destination: /etc/systemd/system/trident.service.d/override.conf - services: - enable: - - etc-mount - - sshd - - trident - - tridentd.socket -scripts: - postCustomization: - - path: base/trident-debug-log.sh - - path: base/create-web-dir.sh diff --git a/tests/images/trident-verity-testimage/tailor/usr-container.yaml b/tests/images/trident-verity-testimage/tailor/usr-container.yaml deleted file mode 100644 index c4e9defa9d..0000000000 --- a/tests/images/trident-verity-testimage/tailor/usr-container.yaml +++ /dev/null @@ -1,104 +0,0 @@ -storage: - disks: - - partitionTableType: gpt - maxSize: 5G - partitions: - - id: esp - type: esp - size: 500M - label: esp - - id: boot - size: 150M - - id: root - size: 2G - - id: usr-data - label: usr - size: 1G - - id: usr-hash - label: usr-hash - size: 128M - bootType: efi - verity: - - id: usr - name: usr - dataDeviceId: usr-data - hashDeviceId: usr-hash - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: boot - type: ext4 - mountPoint: - path: /boot - - deviceId: root - type: ext4 - mountPoint: - path: / - - deviceId: usr - type: ext4 - mountPoint: - path: /usr - options: defaults,ro -os: - bootloader: - resetType: hard-reset - hostname: trident-container-usrverity-testimg - selinux: - mode: disabled - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.info - - log_buf_len=1M - - rd.hostonly=0 - packages: - remove: - - grub2-efi-binary - install: - - curl - - device-mapper - - docker-cli - - efibootmgr - - iproute - - iptables - - lvm2 - - mdadm - - moby-engine - - netplan - - openssh-server - - systemd-udev - - tpm2-tools - - veritysetup - - vim - - systemd-ukify - - systemd-boot - - efibootmgr - - squashfs-tools - - tar - services: - enable: - - trident-container - - sshd - uki: - mode: create - additionalFiles: - - source: usr/files/dracut-nohostonly.conf - destination: /usr/lib/dracut/dracut.conf.d/nohostonly.conf - - source: usr/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: usr/files/trident-container.service - destination: /usr/lib/systemd/system/trident-container.service -output: - artifacts: - items: - - ukis - path: ./usr/output -previewFeatures: -- uki -- output-artifacts diff --git a/tests/images/trident-verity-testimage/tailor/usr-host.yaml b/tests/images/trident-verity-testimage/tailor/usr-host.yaml deleted file mode 100644 index b85c3b9eab..0000000000 --- a/tests/images/trident-verity-testimage/tailor/usr-host.yaml +++ /dev/null @@ -1,106 +0,0 @@ -storage: - disks: - - partitionTableType: gpt - maxSize: 5G - partitions: - - id: esp - type: esp - size: 500M - label: esp - - id: boot - size: 150M - - id: root - size: 2G - - id: usr-data - label: usr - size: 1G - - id: usr-hash - label: usr-hash - size: 128M - bootType: efi - verity: - - id: usr - name: usr - dataDeviceId: usr-data - hashDeviceId: usr-hash - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - path: /boot/efi - options: umask=0077 - - deviceId: boot - type: ext4 - mountPoint: - path: /boot - - deviceId: root - type: ext4 - mountPoint: - path: / - - deviceId: usr - type: ext4 - mountPoint: - path: /usr - options: defaults,ro -os: - bootloader: - resetType: hard-reset - hostname: trident-usrverity-testimg - selinux: - mode: disabled - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=ttyS0 - - rd.info - - log_buf_len=1M - - rd.hostonly=0 - packages: - remove: - - grub2-efi-binary - install: - - binutils - - curl - - device-mapper - - efibootmgr - - iproute - - iptables - - lvm2 - - mdadm - - netplan - - openssh-server - - systemd-udev - - tpm2-tools - - trident-service - - trident-static-pcrlock-files - - veritysetup - - vim - - systemd-ukify - - systemd-boot - - efibootmgr - - audit - - selinux-policy-devel - services: - enable: - - sshd - - trident - - tridentd.socket - uki: - mode: create - additionalFiles: - - source: usr/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: usr/files/dracut-nohostonly.conf - destination: /usr/lib/dracut/dracut.conf.d/nohostonly.conf - - source: usr/files/use-grpc-client-commit.conf - destination: /etc/systemd/system/trident.service.d/override.conf -output: - artifacts: - items: - - ukis - path: ./usr/output -previewFeatures: -- uki -- output-artifacts diff --git a/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml b/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml index 6e4fa214da..a2210cc7f8 100644 --- a/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml +++ b/tests/images/trident-vm-testimage/by-scenario/acl-agent.yaml @@ -1,3 +1,24 @@ config: - $set: - $include: ./tailor/updateimg-acl-agent.yaml + storage: + $include: ./include/storage-acl-agent.yaml + os: + hostname: trident-acl-agent-testimg + packages: + install: + $append: + - trident-acl + additionalFiles: + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/trident-acl-agent-override.conf + destination: /etc/systemd/system/trident-acl-agent.service.d/override.conf + - source: base/files/trident-acl-agent-cert-install.service + destination: /etc/systemd/system/trident-acl-agent-cert-install.service + services: + enable: + - kdump + - tridentd.socket + - trident-acl-agent-cert-install.service + - trident-acl-agent.service diff --git a/tests/images/trident-vm-testimage/by-scenario/grub-verity+grub-verity-azure.yaml b/tests/images/trident-vm-testimage/by-scenario/grub-verity+grub-verity-azure.yaml new file mode 100644 index 0000000000..ad0608c844 --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/grub-verity+grub-verity-azure.yaml @@ -0,0 +1,6 @@ +config: + os: + $include: ./include/grub-verity-os-common.yaml + scripts: + postCustomization: + - $include: ./include/grub-verity-scripts.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml b/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml index 275ab1d6db..d2b2c5464e 100644 --- a/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml +++ b/tests/images/trident-vm-testimage/by-scenario/grub-verity-azure.yaml @@ -2,5 +2,22 @@ base: $set: ref: core_selinux config: - $set: - $include: ./tailor/updateimg-grub-verity-azure.yaml + storage: + $include: ./include/storage-grub-verity.yaml + os: + hostname: trident-vm-testimg + selinux: + mode: + $set: permissive + packages: + install: + $remove: + - netplan + $append: + - selinux-policy + - WALinuxAgent + users: + $replace: + - name: testuser + secondaryGroups: + - wheel diff --git a/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml b/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml index cd34fd3dd6..413e42b822 100644 --- a/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml +++ b/tests/images/trident-vm-testimage/by-scenario/grub-verity.yaml @@ -1,3 +1,5 @@ config: - $set: - $include: ./tailor/updateimg-grub-verity.yaml + storage: + $include: ./include/storage-grub-verity.yaml + os: + hostname: trident-vm-verity-testimg diff --git a/tests/images/trident-vm-testimage/by-scenario/grub.yaml b/tests/images/trident-vm-testimage/by-scenario/grub.yaml index 5cf4ffb966..d9bfa313ae 100644 --- a/tests/images/trident-vm-testimage/by-scenario/grub.yaml +++ b/tests/images/trident-vm-testimage/by-scenario/grub.yaml @@ -1,3 +1,55 @@ config: - $set: - $include: ./tailor/updateimg-grub.yaml + storage: + $include: ./include/storage-grub.yaml + os: + bootloader: + resetType: hard-reset + hostname: trident-vm-testimg + selinux: + mode: disabled + kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + packages: + install: + - curl + - dnf + - efibootmgr + - grub2-efi-binary-noprefix + - iproute + - iptables + - jq + - lsof + - netplan + - openssh-server + - trident-service + - vim + - netplan + remove: + - grub2-efi-binary + services: + enable: + - trident + - tridentd.socket + users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel + additionalFiles: + - source: base/files/sshd-keygen.service + destination: /usr/lib/systemd/system/sshd-keygen.service + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + scripts: + postCustomization: + - $include: ./include/grub-scripts.yaml diff --git a/tests/images/trident-vm-testimage/by-scenario/root-verity+usr-verity+acl-agent.yaml b/tests/images/trident-vm-testimage/by-scenario/root-verity+usr-verity+acl-agent.yaml new file mode 100644 index 0000000000..ac986e4ae7 --- /dev/null +++ b/tests/images/trident-vm-testimage/by-scenario/root-verity+usr-verity+acl-agent.yaml @@ -0,0 +1,8 @@ +config: + os: + $include: ./include/uki-verity-os-common.yaml + scripts: + postCustomization: + - $include: ./include/uki-verity-scripts.yaml + previewFeatures: + - uki diff --git a/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml b/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml index 629c76513b..a19ba87c3e 100644 --- a/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml +++ b/tests/images/trident-vm-testimage/by-scenario/root-verity.yaml @@ -1,3 +1,24 @@ config: - $set: - $include: ./tailor/baseimg-root-verity.yaml + storage: + $include: ./include/storage-root-verity.yaml + os: + hostname: trident-vm-root-verity-testimg + additionalFiles: + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + overlays: + - mountPoint: /etc + lowerDirs: + - /etc + upperDir: /var/lib/overlays/etc/upper + workDir: /var/lib/overlays/etc/work + mountDependencies: + - /var + isInitrdOverlay: true + services: + enable: + - kdump + - trident + - tridentd.socket diff --git a/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml b/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml index 6b0671c39b..766620fea4 100644 --- a/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml +++ b/tests/images/trident-vm-testimage/by-scenario/usr-verity.yaml @@ -1,3 +1,15 @@ config: - $set: - $include: ./tailor/baseimg-usr-verity.yaml + storage: + $include: ./include/storage-usr-verity.yaml + os: + hostname: trident-vm-usr-verity-testimg + additionalFiles: + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + services: + enable: + - kdump + - trident + - tridentd.socket diff --git a/tests/images/trident-vm-testimage/include/grub-os-common.yaml b/tests/images/trident-vm-testimage/include/grub-os-common.yaml new file mode 100644 index 0000000000..08805a784d --- /dev/null +++ b/tests/images/trident-vm-testimage/include/grub-os-common.yaml @@ -0,0 +1,22 @@ +bootloader: + resetType: hard-reset +selinux: + mode: disabled +kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 +packages: + remove: + - grub2-efi-binary +users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel diff --git a/tests/images/trident-vm-testimage/include/grub-scripts.yaml b/tests/images/trident-vm-testimage/include/grub-scripts.yaml new file mode 100644 index 0000000000..cefd80ff51 --- /dev/null +++ b/tests/images/trident-vm-testimage/include/grub-scripts.yaml @@ -0,0 +1,4 @@ +- path: base/scripts/post-install.sh +- path: base/scripts/ssh-move-host-keys.sh +- path: base/scripts/duid-type-to-link-layer.sh +- path: base/scripts/update-os-release.sh diff --git a/tests/images/trident-vm-testimage/include/grub-verity-os-common.yaml b/tests/images/trident-vm-testimage/include/grub-verity-os-common.yaml new file mode 100644 index 0000000000..6432937bc3 --- /dev/null +++ b/tests/images/trident-vm-testimage/include/grub-verity-os-common.yaml @@ -0,0 +1,59 @@ +bootloader: + resetType: hard-reset +selinux: + mode: disabled +kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 +packages: + install: + - curl + - device-mapper + - dnf + - dracut-overlayfs + - efibootmgr + - grub2-efi-binary-noprefix + - iproute + - iptables + - jq + - kexec-tools + - lsof + - lvm2 + - netplan + - openssh-server + - systemd-udev + - trident-service + - veritysetup + - vim + - netplan + remove: + - grub2-efi-binary +additionalFiles: + - source: base/files/etc-mount.service + destination: /etc/systemd/system/etc-mount.service + - source: base/files/etc-mount.sh + destination: /usr/local/bin/etc-mount.sh + - source: base/files/sudoers-wheel + destination: /etc/sudoers.d/wheel + - source: base/files/99-dhcp-eth0.network + destination: /etc/systemd/network/99-dhcp-eth0.network + - source: base/files/use-grpc-client-commit.conf + destination: /etc/systemd/system/trident.service.d/override.conf +services: + enable: + - etc-mount + - kdump + - trident + - tridentd.socket +users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel diff --git a/tests/images/trident-vm-testimage/include/grub-verity-scripts.yaml b/tests/images/trident-vm-testimage/include/grub-verity-scripts.yaml new file mode 100644 index 0000000000..db0dca3e4c --- /dev/null +++ b/tests/images/trident-vm-testimage/include/grub-verity-scripts.yaml @@ -0,0 +1,4 @@ +- path: base/scripts/post-install.sh +- path: base/scripts/ssh-move-host-keys.sh +- path: base/scripts/update-os-release.sh +- path: base/scripts/duid-type-to-link-layer.sh diff --git a/tests/images/trident-vm-testimage/include/storage-acl-agent.yaml b/tests/images/trident-vm-testimage/include/storage-acl-agent.yaml new file mode 100644 index 0000000000..82632328f0 --- /dev/null +++ b/tests/images/trident-vm-testimage/include/storage-acl-agent.yaml @@ -0,0 +1,101 @@ +bootType: efi +disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + label: esp + size: 512M + - id: boot-a + size: 256M + - id: boot-b + size: 256M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: usr-a + size: 1G + - id: usr-b + size: 1G + - id: usr-hash-a + size: 128M + - id: usr-hash-b + size: 128M + - id: trident + label: trident + size: 512M + - id: trident-acl-agent + label: trident-acl-agent + size: 128M + - id: kubelet + label: kubelet + size: 128M + - id: etc-trident + label: etc-trident + size: 128M + - id: home + label: home + size: 1G + - id: srv + label: srv + size: 128M +verity: + - id: usrverity + name: usr + dataDeviceId: usr-a + hashDeviceId: usr-hash-a + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + idType: part-label + path: /boot/efi + options: umask=0077 + - deviceId: boot-a + type: ext4 + mountPoint: + idType: uuid + path: /boot + - deviceId: usrverity + type: ext4 + mountPoint: + path: /usr + options: defaults,ro + - deviceId: root-a + type: ext4 + mountPoint: + idType: uuid + path: / + - deviceId: trident + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident + - deviceId: trident-acl-agent + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident-acl-agent + - deviceId: kubelet + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/kubelet + - deviceId: etc-trident + type: ext4 + mountPoint: + idType: part-label + path: /etc/trident + - deviceId: home + type: ext4 + mountPoint: + idType: part-label + path: /home + - deviceId: srv + type: ext4 + mountPoint: + idType: part-label + path: /srv diff --git a/tests/images/trident-vm-testimage/include/storage-grub-verity.yaml b/tests/images/trident-vm-testimage/include/storage-grub-verity.yaml new file mode 100644 index 0000000000..fbe1d145ea --- /dev/null +++ b/tests/images/trident-vm-testimage/include/storage-grub-verity.yaml @@ -0,0 +1,54 @@ +bootType: efi +disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + size: 8M + - id: boot + size: 256M + - id: root + size: 4G + - id: root-hash + size: 128M + - id: var + size: 1G + - id: trident-overlay + size: 32M + - id: srv + size: 1G + - id: home + size: 32M +verity: + - id: rootverity + name: root + dataDeviceId: root + hashDeviceId: root-hash + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: boot + type: ext4 + mountPoint: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: var + type: ext4 + mountPoint: /var + - deviceId: trident-overlay + type: ext4 + mountPoint: /var/lib/trident-overlay + - deviceId: srv + type: ext4 + mountPoint: /srv + - deviceId: home + type: ext4 + mountPoint: /home diff --git a/tests/images/trident-vm-testimage/include/storage-grub.yaml b/tests/images/trident-vm-testimage/include/storage-grub.yaml new file mode 100644 index 0000000000..f36e7979e8 --- /dev/null +++ b/tests/images/trident-vm-testimage/include/storage-grub.yaml @@ -0,0 +1,31 @@ +bootType: efi +disks: + - partitionTableType: gpt + maxSize: 10G + partitions: + - id: esp + type: esp + size: 16M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: trident + size: 1G + - id: srv + size: grow +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + path: /boot/efi + options: umask=0077 + - deviceId: root-a + type: ext4 + mountPoint: / + - deviceId: trident + type: ext4 + mountPoint: /var/lib/trident + - deviceId: srv + type: ext4 + mountPoint: /srv diff --git a/tests/images/trident-vm-testimage/include/storage-root-verity.yaml b/tests/images/trident-vm-testimage/include/storage-root-verity.yaml new file mode 100644 index 0000000000..e5e3cbd74d --- /dev/null +++ b/tests/images/trident-vm-testimage/include/storage-root-verity.yaml @@ -0,0 +1,78 @@ +bootType: efi +disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + label: esp + size: 512M + - id: boot-a + size: 256M + - id: boot-b + size: 256M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: root-hash-a + size: 128M + - id: root-hash-b + size: 128M + - id: var-a + size: 1G + - id: var-b + size: 1G + - id: trident + label: trident + size: 512M + - id: home + label: home + size: 1G + - id: srv + label: srv + size: 128M +verity: + - id: rootverity + name: root + dataDeviceId: root-a + hashDeviceId: root-hash-a + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + idType: part-label + path: /boot/efi + options: umask=0077 + - deviceId: boot-a + type: ext4 + mountPoint: + idType: uuid + path: /boot + - deviceId: rootverity + type: ext4 + mountPoint: + path: / + options: defaults,ro + - deviceId: var-a + type: ext4 + mountPoint: + idType: uuid + path: /var + options: defaults,x-initrd.mount + - deviceId: trident + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident + - deviceId: home + type: ext4 + mountPoint: + idType: part-label + path: /home + - deviceId: srv + type: ext4 + mountPoint: + idType: part-label + path: /srv diff --git a/tests/images/trident-vm-testimage/include/storage-usr-verity.yaml b/tests/images/trident-vm-testimage/include/storage-usr-verity.yaml new file mode 100644 index 0000000000..a380c8eb59 --- /dev/null +++ b/tests/images/trident-vm-testimage/include/storage-usr-verity.yaml @@ -0,0 +1,77 @@ +bootType: efi +disks: + - partitionTableType: gpt + partitions: + - id: esp + type: esp + label: esp + size: 512M + - id: boot-a + size: 256M + - id: boot-b + size: 256M + - id: root-a + size: 4G + - id: root-b + size: 4G + - id: usr-a + size: 1G + - id: usr-b + size: 1G + - id: usr-hash-a + size: 128M + - id: usr-hash-b + size: 128M + - id: trident + label: trident + size: 512M + - id: home + label: home + size: 1G + - id: srv + label: srv + size: 128M +verity: + - id: usrverity + name: usr + dataDeviceId: usr-a + hashDeviceId: usr-hash-a + dataDeviceMountIdType: uuid + hashDeviceMountIdType: uuid +filesystems: + - deviceId: esp + type: fat32 + mountPoint: + idType: part-label + path: /boot/efi + options: umask=0077 + - deviceId: boot-a + type: ext4 + mountPoint: + idType: uuid + path: /boot + - deviceId: usrverity + type: ext4 + mountPoint: + path: /usr + options: defaults,ro + - deviceId: root-a + type: ext4 + mountPoint: + idType: uuid + path: / + - deviceId: trident + type: ext4 + mountPoint: + idType: part-label + path: /var/lib/trident + - deviceId: home + type: ext4 + mountPoint: + idType: part-label + path: /home + - deviceId: srv + type: ext4 + mountPoint: + idType: part-label + path: /srv diff --git a/tests/images/trident-vm-testimage/include/uki-verity-os-common.yaml b/tests/images/trident-vm-testimage/include/uki-verity-os-common.yaml new file mode 100644 index 0000000000..6f277178bd --- /dev/null +++ b/tests/images/trident-vm-testimage/include/uki-verity-os-common.yaml @@ -0,0 +1,41 @@ +bootloader: + resetType: hard-reset +selinux: + mode: disabled +uki: + mode: create +kernelCommandLine: + extraCommandLine: + - console=tty0 + - console=tty1 + - console=ttyS0 + - rd.debug + - loglevel=6 + - log_buf_len=1M + - systemd.journald.forward_to_console=1 + - rd.hostonly=0 +packages: + install: + - device-mapper + - dnf + - efibootmgr + - iproute + - iptables + - jq + - kexec-tools + - lvm2 + - openssh-server + - systemd-boot + - systemd-udev + - trident-service + - veritysetup + - vim + - netplan + remove: + - grub2-efi-binary +users: + - name: testuser + sshPublicKeyPaths: + - base/files/id_rsa.pub + secondaryGroups: + - wheel diff --git a/tests/images/trident-vm-testimage/include/uki-verity-scripts.yaml b/tests/images/trident-vm-testimage/include/uki-verity-scripts.yaml new file mode 100644 index 0000000000..89bf812cc3 --- /dev/null +++ b/tests/images/trident-vm-testimage/include/uki-verity-scripts.yaml @@ -0,0 +1,6 @@ +- path: base/scripts/post-install.sh +- path: base/scripts/update-host-status.sh +- path: base/scripts/prepare-update-config-verity.sh + arguments: + - uki +- path: base/scripts/duid-type-to-link-layer.sh diff --git a/tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml b/tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml deleted file mode 100644 index 08d401d3a1..0000000000 --- a/tests/images/trident-vm-testimage/tailor/baseimg-root-verity.yaml +++ /dev/null @@ -1,151 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - partitions: - - id: esp - type: esp - label: esp - size: 512M - - id: boot-a - size: 256M - - id: boot-b - size: 256M - - id: root-a - size: 4G - - id: root-b - size: 4G - - id: root-hash-a - size: 128M - - id: root-hash-b - size: 128M - - id: var-a - size: 1G - - id: var-b - size: 1G - - id: trident - label: trident - size: 512M - - id: home - label: home - size: 1G - - id: srv - label: srv - size: 128M - verity: - - id: rootverity - name: root - dataDeviceId: root-a - hashDeviceId: root-hash-a - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - idType: part-label - path: /boot/efi - options: umask=0077 - - deviceId: boot-a - type: ext4 - mountPoint: - idType: uuid - path: /boot - - deviceId: rootverity - type: ext4 - mountPoint: - path: / - options: defaults,ro - - deviceId: var-a - type: ext4 - mountPoint: - idType: uuid - path: /var - options: defaults,x-initrd.mount - - deviceId: trident - type: ext4 - mountPoint: - idType: part-label - path: /var/lib/trident - - deviceId: home - type: ext4 - mountPoint: - idType: part-label - path: /home - - deviceId: srv - type: ext4 - mountPoint: - idType: part-label - path: /srv -os: - bootloader: - resetType: hard-reset - hostname: trident-vm-root-verity-testimg - selinux: - mode: disabled - uki: - mode: create - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=tty1 - - console=ttyS0 - - rd.debug - - loglevel=6 - - log_buf_len=1M - - systemd.journald.forward_to_console=1 - - rd.hostonly=0 - packages: - install: - - device-mapper - - dnf - - efibootmgr - - iproute - - iptables - - jq - - kexec-tools - - lvm2 - - openssh-server - - systemd-boot - - systemd-udev - - trident-service - - veritysetup - - vim - - netplan - remove: - - grub2-efi-binary - additionalFiles: - - source: base/files/99-dhcp-eth0.network - destination: /etc/systemd/network/99-dhcp-eth0.network - - source: base/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - overlays: - - mountPoint: /etc - lowerDirs: - - /etc - upperDir: /var/lib/overlays/etc/upper - workDir: /var/lib/overlays/etc/work - mountDependencies: - - /var - isInitrdOverlay: true - services: - enable: - - kdump - - trident - - tridentd.socket - users: - - name: testuser - sshPublicKeyPaths: - - base/files/id_rsa.pub - secondaryGroups: - - wheel -scripts: - postCustomization: - - path: base/scripts/post-install.sh - - path: base/scripts/update-host-status.sh - - path: base/scripts/prepare-update-config-verity.sh - arguments: - - uki - - path: base/scripts/duid-type-to-link-layer.sh -previewFeatures: -- uki diff --git a/tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml b/tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml deleted file mode 100644 index e0facb4f94..0000000000 --- a/tests/images/trident-vm-testimage/tailor/baseimg-usr-verity.yaml +++ /dev/null @@ -1,141 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - partitions: - - id: esp - type: esp - label: esp - size: 512M - - id: boot-a - size: 256M - - id: boot-b - size: 256M - - id: root-a - size: 4G - - id: root-b - size: 4G - - id: usr-a - size: 1G - - id: usr-b - size: 1G - - id: usr-hash-a - size: 128M - - id: usr-hash-b - size: 128M - - id: trident - label: trident - size: 512M - - id: home - label: home - size: 1G - - id: srv - label: srv - size: 128M - verity: - - id: usrverity - name: usr - dataDeviceId: usr-a - hashDeviceId: usr-hash-a - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - idType: part-label - path: /boot/efi - options: umask=0077 - - deviceId: boot-a - type: ext4 - mountPoint: - idType: uuid - path: /boot - - deviceId: usrverity - type: ext4 - mountPoint: - path: /usr - options: defaults,ro - - deviceId: root-a - type: ext4 - mountPoint: - idType: uuid - path: / - - deviceId: trident - type: ext4 - mountPoint: - idType: part-label - path: /var/lib/trident - - deviceId: home - type: ext4 - mountPoint: - idType: part-label - path: /home - - deviceId: srv - type: ext4 - mountPoint: - idType: part-label - path: /srv -os: - bootloader: - resetType: hard-reset - hostname: trident-vm-usr-verity-testimg - selinux: - mode: disabled - uki: - mode: create - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=tty1 - - console=ttyS0 - - rd.debug - - loglevel=6 - - log_buf_len=1M - - systemd.journald.forward_to_console=1 - - rd.hostonly=0 - packages: - install: - - device-mapper - - dnf - - efibootmgr - - iproute - - iptables - - jq - - kexec-tools - - lvm2 - - openssh-server - - systemd-boot - - systemd-udev - - trident-service - - veritysetup - - vim - - netplan - remove: - - grub2-efi-binary - additionalFiles: - - source: base/files/99-dhcp-eth0.network - destination: /etc/systemd/network/99-dhcp-eth0.network - - source: base/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - services: - enable: - - kdump - - trident - - tridentd.socket - users: - - name: testuser - sshPublicKeyPaths: - - base/files/id_rsa.pub - secondaryGroups: - - wheel -scripts: - postCustomization: - - path: base/scripts/post-install.sh - - path: base/scripts/update-host-status.sh - - path: base/scripts/prepare-update-config-verity.sh - arguments: - - uki - - path: base/scripts/duid-type-to-link-layer.sh -previewFeatures: -- uki diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml deleted file mode 100644 index d0990a2d65..0000000000 --- a/tests/images/trident-vm-testimage/tailor/updateimg-acl-agent.yaml +++ /dev/null @@ -1,170 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - partitions: - - id: esp - type: esp - label: esp - size: 512M - - id: boot-a - size: 256M - - id: boot-b - size: 256M - - id: root-a - size: 4G - - id: root-b - size: 4G - - id: usr-a - size: 1G - - id: usr-b - size: 1G - - id: usr-hash-a - size: 128M - - id: usr-hash-b - size: 128M - - id: trident - label: trident - size: 512M - - id: trident-acl-agent - label: trident-acl-agent - size: 128M - - id: kubelet - label: kubelet - size: 128M - - id: etc-trident - label: etc-trident - size: 128M - - id: home - label: home - size: 1G - - id: srv - label: srv - size: 128M - verity: - - id: usrverity - name: usr - dataDeviceId: usr-a - hashDeviceId: usr-hash-a - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - idType: part-label - path: /boot/efi - options: umask=0077 - - deviceId: boot-a - type: ext4 - mountPoint: - idType: uuid - path: /boot - - deviceId: usrverity - type: ext4 - mountPoint: - path: /usr - options: defaults,ro - - deviceId: root-a - type: ext4 - mountPoint: - idType: uuid - path: / - - deviceId: trident - type: ext4 - mountPoint: - idType: part-label - path: /var/lib/trident - - deviceId: trident-acl-agent - type: ext4 - mountPoint: - idType: part-label - path: /var/lib/trident-acl-agent - - deviceId: kubelet - type: ext4 - mountPoint: - idType: part-label - path: /var/lib/kubelet - - deviceId: etc-trident - type: ext4 - mountPoint: - idType: part-label - path: /etc/trident - - deviceId: home - type: ext4 - mountPoint: - idType: part-label - path: /home - - deviceId: srv - type: ext4 - mountPoint: - idType: part-label - path: /srv -os: - bootloader: - resetType: hard-reset - hostname: trident-acl-agent-testimg - selinux: - mode: disabled - uki: - mode: create - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=tty1 - - console=ttyS0 - - rd.debug - - loglevel=6 - - log_buf_len=1M - - systemd.journald.forward_to_console=1 - - rd.hostonly=0 - packages: - install: - - device-mapper - - dnf - - efibootmgr - - iproute - - iptables - - jq - - kexec-tools - - lvm2 - - openssh-server - - systemd-boot - - systemd-udev - - trident-acl - - veritysetup - - vim - - netplan - remove: - - grub2-efi-binary - additionalFiles: - - source: base/files/99-dhcp-eth0.network - destination: /etc/systemd/network/99-dhcp-eth0.network - - source: base/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: base/files/trident-acl-agent-override.conf - destination: /etc/systemd/system/trident-acl-agent.service.d/override.conf - - source: base/files/trident-acl-agent-cert-install.service - destination: /etc/systemd/system/trident-acl-agent-cert-install.service - services: - enable: - - kdump - - tridentd.socket - - trident-acl-agent-cert-install.service - - trident-acl-agent.service - users: - - name: testuser - sshPublicKeyPaths: - - base/files/id_rsa.pub - secondaryGroups: - - wheel -scripts: - postCustomization: - - path: base/scripts/post-install.sh - - path: base/scripts/update-host-status.sh - - path: base/scripts/prepare-update-config-verity.sh - arguments: - - uki - - path: base/scripts/duid-type-to-link-layer.sh -previewFeatures: -- uki diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml deleted file mode 100644 index 765d6950b0..0000000000 --- a/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity-azure.yaml +++ /dev/null @@ -1,127 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - maxSize: 7G - partitions: - - id: esp - type: esp - size: 8M - - id: boot - size: 256M - - id: root - size: 4G - - id: root-hash - size: 128M - - id: var - size: 1G - - id: trident-overlay - size: 32M - - id: srv - size: 1G - - id: home - size: 32M - verity: - - id: rootverity - name: root - dataDeviceId: root - hashDeviceId: root-hash - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - options: umask=0077 - path: /boot/efi - - deviceId: boot - type: ext4 - mountPoint: - path: /boot - - deviceId: rootverity - type: ext4 - mountPoint: - path: / - options: defaults,ro - - deviceId: var - type: ext4 - mountPoint: - path: /var - - deviceId: trident-overlay - type: ext4 - mountPoint: - path: /var/lib/trident-overlay - - deviceId: srv - type: ext4 - mountPoint: - path: /srv - - deviceId: home - type: ext4 - mountPoint: - path: /home -os: - bootloader: - resetType: hard-reset - hostname: trident-vm-testimg - selinux: - mode: permissive - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=tty1 - - console=ttyS0 - - rd.debug - - loglevel=6 - - log_buf_len=1M - - systemd.journald.forward_to_console=1 - packages: - install: - - curl - - device-mapper - - dnf - - dracut-overlayfs - - efibootmgr - - grub2-efi-binary-noprefix - - iproute - - iptables - - jq - - kexec-tools - - lsof - - lvm2 - - netplan - - openssh-server - - selinux-policy - - systemd-udev - - trident-service - - veritysetup - - vim - - WALinuxAgent - remove: - - grub2-efi-binary - additionalFiles: - - source: base/files/etc-mount.service - destination: /etc/systemd/system/etc-mount.service - - source: base/files/etc-mount.sh - destination: /usr/local/bin/etc-mount.sh - - source: base/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: base/files/99-dhcp-eth0.network - destination: /etc/systemd/network/99-dhcp-eth0.network - - source: base/files/use-grpc-client-commit.conf - destination: /etc/systemd/system/trident.service.d/override.conf - services: - enable: - - etc-mount - - kdump - - trident - - tridentd.socket - users: - - name: testuser - secondaryGroups: - - wheel -scripts: - postCustomization: - - path: base/scripts/post-install.sh - - path: base/scripts/ssh-move-host-keys.sh - - path: base/scripts/update-os-release.sh - - path: base/scripts/duid-type-to-link-layer.sh diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml deleted file mode 100644 index bd87eaaa7d..0000000000 --- a/tests/images/trident-vm-testimage/tailor/updateimg-grub-verity.yaml +++ /dev/null @@ -1,122 +0,0 @@ -storage: - bootType: efi - disks: - - partitionTableType: gpt - partitions: - - id: esp - type: esp - size: 8M - - id: boot - size: 256M - - id: root - size: 4G - - id: root-hash - size: 128M - - id: var - size: 1G - - id: trident-overlay - size: 32M - - id: srv - size: 1G - - id: home - size: 32M - verity: - - id: rootverity - name: root - dataDeviceId: root - hashDeviceId: root-hash - dataDeviceMountIdType: uuid - hashDeviceMountIdType: uuid - filesystems: - - deviceId: esp - type: fat32 - mountPoint: - options: umask=0077 - path: /boot/efi - - deviceId: boot - type: ext4 - mountPoint: /boot - - deviceId: rootverity - type: ext4 - mountPoint: - path: / - options: defaults,ro - - deviceId: var - type: ext4 - mountPoint: /var - - deviceId: trident-overlay - type: ext4 - mountPoint: /var/lib/trident-overlay - - deviceId: srv - type: ext4 - mountPoint: /srv - - deviceId: home - type: ext4 - mountPoint: /home -os: - bootloader: - resetType: hard-reset - hostname: trident-vm-verity-testimg - selinux: - mode: disabled - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=tty1 - - console=ttyS0 - - rd.debug - - loglevel=6 - - log_buf_len=1M - - systemd.journald.forward_to_console=1 - packages: - install: - - curl - - device-mapper - - dnf - - dracut-overlayfs - - efibootmgr - - grub2-efi-binary-noprefix - - iproute - - iptables - - jq - - kexec-tools - - lsof - - lvm2 - - netplan - - openssh-server - - systemd-udev - - trident-service - - veritysetup - - vim - - netplan - remove: - - grub2-efi-binary - additionalFiles: - - source: base/files/etc-mount.service - destination: /etc/systemd/system/etc-mount.service - - source: base/files/etc-mount.sh - destination: /usr/local/bin/etc-mount.sh - - source: base/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: base/files/99-dhcp-eth0.network - destination: /etc/systemd/network/99-dhcp-eth0.network - - source: base/files/use-grpc-client-commit.conf - destination: /etc/systemd/system/trident.service.d/override.conf - services: - enable: - - etc-mount - - kdump - - trident - - tridentd.socket - users: - - name: testuser - sshPublicKeyPaths: - - base/files/id_rsa.pub - secondaryGroups: - - wheel -scripts: - postCustomization: - - path: base/scripts/post-install.sh - - path: base/scripts/ssh-move-host-keys.sh - - path: base/scripts/update-os-release.sh - - path: base/scripts/duid-type-to-link-layer.sh diff --git a/tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml b/tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml deleted file mode 100644 index 34b1dd8cfa..0000000000 --- a/tests/images/trident-vm-testimage/tailor/updateimg-grub.yaml +++ /dev/null @@ -1,75 +0,0 @@ -storage: - bootType: efi - disks: - - maxSize: 5G - partitionTableType: gpt - partitions: - - id: esp - size: 8M - type: esp - - id: root - size: 4G - filesystems: - - deviceId: esp - mountPoint: - options: umask=0077 - path: /boot/efi - type: fat32 - - deviceId: root - mountPoint: / - type: ext4 -os: - hostname: trident-vm-testimg - packages: - install: - - curl - - dnf - - efibootmgr - - grub2-efi-binary-noprefix - - iproute - - iptables - - jq - - lsof - - netplan - - openssh-server - - trident-service - - vim - - netplan - remove: - - grub2-efi-binary - bootloader: - resetType: hard-reset - selinux: - mode: disabled - kernelCommandLine: - extraCommandLine: - - console=tty0 - - console=tty1 - - console=ttyS0 - - rd.debug - - loglevel=6 - - log_buf_len=1M - - systemd.journald.forward_to_console=1 - services: - enable: - - trident - - tridentd.socket - users: - - name: testuser - sshPublicKeyPaths: - - base/files/id_rsa.pub - secondaryGroups: - - wheel - additionalFiles: - - source: base/files/sudoers-wheel - destination: /etc/sudoers.d/wheel - - source: base/files/99-dhcp-eth0.network - destination: /etc/systemd/network/99-dhcp-eth0.network - - source: base/files/use-grpc-client-commit.conf - destination: /etc/systemd/system/trident.service.d/override.conf -scripts: - postCustomization: - - path: base/scripts/post-install.sh - - path: base/scripts/ssh-move-host-keys.sh - - path: base/scripts/duid-type-to-link-layer.sh - - path: base/scripts/update-os-release.sh From 6c8a6ec02a8c8def0832e94a64f00e3ab3ae060a Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Fri, 9 Oct 2026 22:45:14 +0000 Subject: [PATCH 03/16] fix(pipelines): indent inline python heredocs in build-image-template.yml The python3 < --- .../build_image/build-image-template.yml | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/.pipelines/templates/stages/build_image/build-image-template.yml b/.pipelines/templates/stages/build_image/build-image-template.yml index 55212e7004..c3ffe95e2d 100644 --- a/.pipelines/templates/stages/build_image/build-image-template.yml +++ b/.pipelines/templates/stages/build_image/build-image-template.yml @@ -84,14 +84,14 @@ steps: - bash: | set -euo pipefail python3 - <<'PY' "${{ parameters.imageName }}" -import json -import sys -from pathlib import Path - -legacy = json.loads(Path("tests/images/legacy-map.json").read_text()) -entry = legacy[sys.argv[1]] -print(f"##vso[task.setvariable variable=baseImageType]{entry['baseImage']}") -PY + import json + import sys + from pathlib import Path + + legacy = json.loads(Path("tests/images/legacy-map.json").read_text()) + entry = legacy[sys.argv[1]] + print(f"##vso[task.setvariable variable=baseImageType]{entry['baseImage']}") + PY displayName: "Resolve image metadata" workingDirectory: ${{ parameters.tridentSourceDirectory }} @@ -170,18 +170,18 @@ PY export CLICOLOR_FORCE=1 readarray -t selector_lines < <(python3 - <<'PY' "$legacy_name" -import json -import sys -from pathlib import Path - -entry = json.loads(Path("tests/images/legacy-map.json").read_text())[sys.argv[1]] -print(entry["image"]) -print(entry["ext"]) -print(entry.get("tailorExt", entry["ext"])) -for key, value in entry["selectors"].items(): - print(f"{key}={value}") -PY -) + import json + import sys + from pathlib import Path + + entry = json.loads(Path("tests/images/legacy-map.json").read_text())[sys.argv[1]] + print(entry["image"]) + print(entry["ext"]) + print(entry.get("tailorExt", entry["ext"])) + for key, value in entry["selectors"].items(): + print(f"{key}={value}") + PY + ) tailor_image="${selector_lines[0]}" artifact_ext="${selector_lines[1]}" @@ -197,41 +197,41 @@ PY if [[ "${{ parameters.micBuildType }}" == "dev" ]]; then manifest_path=tests/images/.tailor.pipeline.yaml python3 - <<'PY' -from pathlib import Path -text = Path("tests/images/tailor.yaml").read_text() -needle = """toolchains: - default: ic - entries: - - name: ic - container: mcr.microsoft.com/azurelinux/imagecustomizer - tag: latest -""" -replacement = """toolchains: - default: ic-dev - entries: - - name: ic - container: mcr.microsoft.com/azurelinux/imagecustomizer - tag: latest - - name: ic-dev - container: imagecustomizer - tag: dev - pull: never -""" -Path("tests/images/.tailor.pipeline.yaml").write_text(text.replace(needle, replacement, 1)) -PY + from pathlib import Path + text = Path("tests/images/tailor.yaml").read_text() + needle = """toolchains: + default: ic + entries: + - name: ic + container: mcr.microsoft.com/azurelinux/imagecustomizer + tag: latest + """ + replacement = """toolchains: + default: ic-dev + entries: + - name: ic + container: mcr.microsoft.com/azurelinux/imagecustomizer + tag: latest + - name: ic-dev + container: imagecustomizer + tag: dev + pull: never + """ + Path("tests/images/.tailor.pipeline.yaml").write_text(text.replace(needle, replacement, 1)) + PY fi matrix_json=$(cargo run --manifest-path tools/tailor/Cargo.toml --quiet -- --manifest "$manifest_path" matrix "$tailor_image" --format json "${selector_args[@]}") slug=$(python3 - <<'PY' "$matrix_json" -import json -import sys -cells = json.loads(sys.argv[1]) -if len(cells) != 1: - raise SystemExit(f"expected exactly one cell, got {len(cells)}") -print(cells[0]["slug"]) -PY -) + import json + import sys + cells = json.loads(sys.argv[1]) + if len(cells) != 1: + raise SystemExit(f"expected exactly one cell, got {len(cells)}") + print(cells[0]["slug"]) + PY + ) cargo run --manifest-path tools/tailor/Cargo.toml --quiet -- --manifest "$manifest_path" build "$tailor_image" "${selector_args[@]}" --output-dir $(ob_outputDirectory) --clones ${{ parameters.clones }} From 5b6ad22a023493074156c25047285d22a08b0823 Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Fri, 9 Oct 2026 22:58:18 +0000 Subject: [PATCH 04/16] fix(pipelines): authenticate cargo before invoking tailor via cargo run build-image-template.yml runs `cargo run --manifest-path tools/tailor/Cargo.toml` to build images, but never ran the CargoAuthenticate@0 task first. Every other job in this pipeline that invokes cargo (check.yml, functional-testing.yml, dev-build.yml, etc.) includes `../common_tasks/cargo-auth.yml` before doing so; this template was missing it, so cargo failed to resolve the crates-io mirror: error: failed to get `clap` as a dependency of package `tailor v1.3.0 ...` Caused by: authenticated registries require a credential-provider to be configured That caused the bash step to exit 101 before tailor ever ran, which in turn left $(ob_outputDirectory) (/tmp/output) never created by tailor (tailor itself does `fs::create_dir_all(output_dir)`, so it would have created it on a successful run) - hence the secondary "Path does not exist: /tmp/output" error surfaced by the output-publishing step. Add the same `cargo-auth.yml` template step used elsewhere in this pipeline, pointed at $(TRIDENT_SOURCE_DIR)/.cargo/config.toml per the existing convention (set by common_tasks/checkout_trident.yml). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../templates/stages/build_image/build-image-template.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.pipelines/templates/stages/build_image/build-image-template.yml b/.pipelines/templates/stages/build_image/build-image-template.yml index c3ffe95e2d..71bb3da896 100644 --- a/.pipelines/templates/stages/build_image/build-image-template.yml +++ b/.pipelines/templates/stages/build_image/build-image-template.yml @@ -62,6 +62,10 @@ parameters: steps: - template: ../common_tasks/avoid-pypi-usage.yml + - template: ../common_tasks/cargo-auth.yml + parameters: + cargoConfigPath: $(TRIDENT_SOURCE_DIR)/.cargo/config.toml + - template: common/sfi-enforce-isolation-with-etc-hosts.yaml@platform-pipelines - script: | From be730fe7bf703734804010964a04bae1a337fa31 Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Fri, 9 Oct 2026 23:58:52 +0000 Subject: [PATCH 05/16] Migrate Makefile image entrypoints Replace the root Makefile test image integration with a legacy-name helper that resolves into tailor selectors, updates base-image download rules, and removes the remaining deleted testimages.py call sites used by the older direct-streaming pipeline path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../trident-testimg-template.yml | 8 +- Makefile | 52 ++-- tests/images/legacy_targets.py | 246 ++++++++++++++++++ 3 files changed, 280 insertions(+), 26 deletions(-) create mode 100755 tests/images/legacy_targets.py diff --git a/.pipelines/templates/stages/trident_images/trident-testimg-template.yml b/.pipelines/templates/stages/trident_images/trident-testimg-template.yml index 993f65f602..fe48c16295 100644 --- a/.pipelines/templates/stages/trident_images/trident-testimg-template.yml +++ b/.pipelines/templates/stages/trident_images/trident-testimg-template.yml @@ -280,11 +280,9 @@ steps: export MIC_CONTAINER_IMAGE="imagecustomizer:dev" fi - # Allow cross-platform (i.e. amd64 pipeline creating arm64 images) - if [[ "${{ parameters.micArchitecture }}" != "${{ parameters.pipelineArchitecture }}" ]]; then - # Export variable to tell Makefile and testimages to use `docker --platform` - export MIC_ARCHITECTURE="linux/${{ parameters.micArchitecture }}" - fi + # The Makefile's tailor-backed legacy target helper resolves the cell arch + # from the historical image name, so no extra MIC_ARCHITECTURE export is + # needed here for cross-arch direct-streaming builds. # Compress the full image & delete the uncompressed image make ${{ parameters.target }} diff --git a/Makefile b/Makefile index 28ec9dc5d7..a393a16d34 100644 --- a/Makefile +++ b/Makefile @@ -651,7 +651,7 @@ $(ARTIFACTS_TEST_IMAGE_DIR)/azl-installer.iso: \ mkdir -p $(AZL_INSTALLER_ISO_DIR)/bin cp bin/liveinstaller $(AZL_INSTALLER_ISO_DIR)/bin/ # Build ISO - ./tests/images/testimages.py build azl-installer --output-dir $(ARTIFACTS_TEST_IMAGE_DIR) + python3 ./tests/images/legacy_targets.py build azl-installer --output-path $(ARTIFACTS_TEST_IMAGE_DIR)/azl-installer.iso $(if $(strip $(MIC_CONTAINER_IMAGE)),--container $(MIC_CONTAINER_IMAGE)) .PHONY: validate validate: $(TRIDENT_CONFIG) target/release/trident @@ -885,9 +885,15 @@ download-trident-container-installer-iso: --path artifacts/ \ --artifact-name 'trident-container-installer' -artifacts/trident-container-installer.iso: - $(MAKE) download-trident-container-installer-iso; \ - ls -l artifacts/trident-container-installer.iso +artifacts/trident-container-installer.iso: $(shell python3 ./tests/images/legacy_targets.py dependencies trident-container-installer) + @echo "Building 'trident-container-installer' [$@] from $<" + @echo "Prerequisites:" + @echo "$^" | tr ' ' '\n' | sed 's/^/ /' + @echo "Building image..." + python3 ./tests/images/legacy_targets.py build \ + trident-container-installer \ + --output-path $@ \ + $(if $(strip $(MIC_CONTAINER_IMAGE)),--container $(MIC_CONTAINER_IMAGE)) # Copies locally built runtime images from ../test-images/build to ./artifacts/test-image. # Expects that both the regular and verity Trident test images have been built. @@ -1015,7 +1021,7 @@ validate-pipeline-website-artifact: # # Generic COSI image build target pattern # -COSI_TARGETS = $(shell ./tests/images/testimages.py list --filter-type cosi) +COSI_TARGETS = $(shell python3 ./tests/images/legacy_targets.py list --filter-type cosi) .PHONY: $(COSI_TARGETS) $(COSI_TARGETS): %: artifacts/%.cosi @@ -1026,7 +1032,7 @@ all-cosi: $(COSI_TARGETS) # # Generic ISO image build target pattern # -ISO_TARGETS = $(shell ./tests/images/testimages.py list --filter-type iso) +ISO_TARGETS = $(shell python3 ./tests/images/legacy_targets.py list --filter-type iso) .PHONY: $(ISO_TARGETS) $(ISO_TARGETS): %: artifacts/%.iso @@ -1038,26 +1044,25 @@ all-iso: $(ISO_TARGETS) # prerequisites so that we can use find to get all the files in the directory. # https://www.gnu.org/software/make/manual/make.html#Secondary-Expansion .SECONDEXPANSION: -artifacts/%.cosi artifacts/%.iso artifacts/%.vhdx: $$(shell ./tests/images/testimages.py dependencies $$*) +artifacts/%.cosi artifacts/%.iso artifacts/%.vhdx: $$(shell python3 ./tests/images/legacy_targets.py dependencies $$*) @echo "Building '$*' [$@] from $<" @echo "Prerequisites:" @echo "$^" | tr ' ' '\n' | sed 's/^/ /' @echo "Building image..." - sudo ./tests/images/testimages.py build \ + python3 ./tests/images/legacy_targets.py build \ $* \ - --output-dir ./artifacts \ - $(if $(strip $(MIC_CONTAINER_IMAGE)),--container $(MIC_CONTAINER_IMAGE)) \ - $(if $(strip $(MIC_ARCHITECTURE)),--image-architecture $(MIC_ARCHITECTURE)) + --output-path $@ \ + $(if $(strip $(MIC_CONTAINER_IMAGE)),--container $(MIC_CONTAINER_IMAGE)) -MIC_CONTAINER_IMAGE ?= $(shell ./tests/images/testimages.py show-artifact customizer-container-full) -artifacts/trident-functest.qcow2: $$(shell ./tests/images/testimages.py dependencies $$(basename $$(notdir $$@))) +MIC_CONTAINER_IMAGE ?= $(shell python3 ./tests/images/legacy_targets.py show-artifact customizer-container-full) +artifacts/trident-functest.qcow2: $$(shell python3 ./tests/images/legacy_targets.py dependencies $$(basename $$(notdir $$@))) @echo "Building '$*' [$@] from $<" @echo "Prerequisites:" @echo "$^" | tr ' ' '\n' | sed 's/^/ /' @echo "Building image..." - sudo ./tests/images/testimages.py build \ + python3 ./tests/images/legacy_targets.py build \ $(basename $(notdir $@)) \ - --output-dir ./artifacts \ + --output-path $@ \ $(if $(strip $(MIC_CONTAINER_IMAGE)),--container $(MIC_CONTAINER_IMAGE)) # TRIDENT VM UPDATE IMAGES @@ -1097,23 +1102,28 @@ $(QEMU_GUEST_IMAGE): BAREMETAL_IMAGE = artifacts/baremetal.vhdx $(BAREMETAL_IMAGE): @mkdir -p artifacts - @tests/images/testimages.py download-image baremetal + @python3 ./tests/images/legacy_targets.py download-image baremetal CORE_SELINUX_IMAGE = artifacts/core_selinux.vhdx $(CORE_SELINUX_IMAGE): @mkdir -p artifacts - @tests/images/testimages.py download-image core_selinux + @python3 ./tests/images/legacy_targets.py download-image core_selinux +CORE_ARM64_IMAGE = artifacts/core_arm64.vhdx +$(CORE_ARM64_IMAGE): + @mkdir -p artifacts + @oras pull mcr.microsoft.com/azurelinux/3.0/image/core_arm64:latest --output artifacts --platform linux/amd64 + @mv artifacts/image.vhdx $(CORE_ARM64_IMAGE) MINIMAL_IMAGE = artifacts/minimal.vhdx $(MINIMAL_IMAGE): @mkdir -p artifacts - @tests/images/testimages.py download-image minimal + @python3 ./tests/images/legacy_targets.py download-image minimal MINIMAL_IMAGE_AARCH64 = artifacts/minimal_aarch64.vhdx $(MINIMAL_IMAGE_AARCH64): @mkdir -p artifacts - @tests/images/testimages.py download-image minimal_aarch64 + @python3 ./tests/images/legacy_targets.py download-image minimal_aarch64 artifacts/trident-vm-grub-testimage.qcow2: \ $(QEMU_GUEST_IMAGE) \ @@ -1137,7 +1147,7 @@ artifacts/trident-vm-grub-testimage.qcow2: \ --config-file /repo/$(VM_IMAGE_PATH_PREFIX)/baseimg-grub.yaml artifacts/trident-vm-grub-testimage-arm64.qcow2: \ - base/core_arm64.vhdx \ + $(CORE_ARM64_IMAGE) \ $(TRIDENT_VM_DEPENDENCIES) \ $(VM_IMAGE_PATH_PREFIX)/baseimg-grub.yaml \ $(VM_IMAGE_PATH_PREFIX)/files/id_rsa.pub @@ -1200,7 +1210,7 @@ artifacts/trident-vm-root-verity-testimage.qcow2: \ --config-file /repo/$(VM_IMAGE_PATH_PREFIX)/baseimg-root-verity.yaml artifacts/trident-vm-verity-testimage-arm64.qcow2: \ - base/core_arm64.vhdx \ + $(CORE_ARM64_IMAGE) \ $(TRIDENT_VM_DEPENDENCIES) \ $(VM_IMAGE_PATH_PREFIX)/baseimg-verity.yaml \ $(VM_IMAGE_PATH_PREFIX)/files/etc-mount.service \ diff --git a/tests/images/legacy_targets.py b/tests/images/legacy_targets.py new file mode 100755 index 0000000000..4b0ea753e4 --- /dev/null +++ b/tests/images/legacy_targets.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +import argparse +import json +import shutil +import subprocess +import sys +import tempfile +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[2] +WORKSPACE = REPO_ROOT / "tests" / "images" / "tailor.yaml" +LEGACY_MAP = REPO_ROOT / "tests" / "images" / "legacy-map.json" +SELF = Path(__file__).resolve() + + +def load_map(): + return json.loads(LEGACY_MAP.read_text()) + + +def cargo_cmd() -> str: + cargo = shutil.which("cargo") + if cargo: + return cargo + fallback = Path.home() / ".cargo" / "bin" / "cargo" + if fallback.exists(): + return str(fallback) + alt = Path('/home/bfjelds/.cargo/bin/cargo') + if alt.exists(): + return str(alt) + raise SystemExit("cargo not found") + + +def default_container_full() -> str: + text = WORKSPACE.read_text() + needle = """ entries:\n - name: ic\n container: """ + idx = text.find(needle) + if idx == -1: + raise SystemExit("default toolchain not found in tests/images/tailor.yaml") + rest = text[idx + len(needle):].splitlines() + container = rest[0].strip() + tag = None + for line in rest[1:6]: + s = line.strip() + if s.startswith("tag:"): + tag = s.split(":", 1)[1].strip() + break + if tag: + return f"{container}:{tag}" + return container + + +def tailor_manifest_for_container(container_ref: str | None) -> Path: + if not container_ref or container_ref == default_container_full(): + return WORKSPACE + text = WORKSPACE.read_text() + name = "ic-override" + if ":" in container_ref.rsplit("/", 1)[-1]: + container, tag = container_ref.rsplit(":", 1) + tag_block = f" tag: {tag}\n" + else: + container = container_ref + tag_block = "" + needle = """toolchains:\n default: ic\n entries:\n - name: ic\n container: mcr.microsoft.com/azurelinux/imagecustomizer\n tag: latest\n""" + replacement = ( + "toolchains:\n" + f" default: {name}\n" + " entries:\n" + " - name: ic\n" + " container: mcr.microsoft.com/azurelinux/imagecustomizer\n" + " tag: latest\n" + f" - name: {name}\n" + f" container: {container}\n" + f"{tag_block}" + " pull: never\n" + ) + rendered = text.replace(needle, replacement, 1) + tmp = REPO_ROOT / "tests" / "images" / ".tailor.make.yaml" + tmp.write_text(rendered) + return tmp + + +def selector_args(entry: dict) -> list[str]: + args: list[str] = [] + for key, value in entry["selectors"].items(): + args.extend(["-s", f"{key}={value}"]) + return args + + +def call_tailor(*args: str, capture: bool = False) -> subprocess.CompletedProcess: + cmd = [cargo_cmd(), "run", "--manifest-path", "tools/tailor/Cargo.toml", "--quiet", "--", *args] + env = dict(os.environ) + env["PATH"] = f"{Path.home() / '.cargo' / 'bin'}:{env.get('PATH','')}" + return subprocess.run(cmd, cwd=str(REPO_ROOT), check=True, text=True, capture_output=capture, env=env) + + +def legacy_list(filter_type: str): + for name, entry in load_map().items(): + if entry["ext"] == filter_type: + print(name) + + +def dependencies(name: str): + mapping = load_map() + entry = mapping[name] + image_dir = REPO_ROOT / "tests" / "images" / entry["image"] + deps: list[Path] = [WORKSPACE, LEGACY_MAP, SELF] + base_dep_map = { + "baremetal": REPO_ROOT / "artifacts" / "baremetal.vhdx", + "core_selinux": REPO_ROOT / "artifacts" / "core_selinux.vhdx", + "core_arm64": REPO_ROOT / "artifacts" / "core_arm64.vhdx", + "qemu_guest": REPO_ROOT / "artifacts" / "qemu_guest.vhdx", + } + base_dep = base_dep_map.get(entry.get("baseImage")) + if base_dep is not None: + deps.append(base_dep) + for path in sorted(image_dir.rglob("*")): + if path.is_file() and ".rendered" not in path.parts and path.name != ".tailor.make.yaml": + deps.append(path) + needs_rpms = name not in { + "trident-functest", + "trident-container-installer", + "trident-container-testimage", + "trident-container-verity-testimage", + "trident-container-usrverity-testimage", + "ubuntu-direct-streaming-testimage-2204-amd64", + "ubuntu-direct-streaming-testimage-2204-arm64", + "ubuntu-direct-streaming-testimage-2404-amd64", + "ubuntu-direct-streaming-testimage-2404-arm64", + "gb200-direct-streaming-testimage-2404-arm64", + } + if needs_rpms: + rpm_dir = REPO_ROOT / "bin" / "RPMS" + if rpm_dir.exists(): + deps.append(rpm_dir) + deps.extend(sorted(rpm_dir.rglob("*.rpm"))) + if entry["image"] == "trident-installer": + for extra in [REPO_ROOT / "bin" / "rcp-agent", REPO_ROOT / "tools" / "cmd" / "rcp-agent" / "rcp-agent.service"]: + if extra.exists(): + deps.append(extra) + if name == "azl-installer": + for extra in [ + REPO_ROOT / "tests" / "images" / "azl-installer" / "iso" / "bin" / "liveinstaller", + REPO_ROOT / "tests" / "images" / "azl-installer" / "iso" / "images" / "trident-testimage.cosi", + ]: + if extra.exists(): + deps.append(extra) + seen = set() + for dep in deps: + try: + s = str(dep.relative_to(REPO_ROOT)) + except ValueError: + s = str(dep) + if s not in seen: + seen.add(s) + print(s) + + +def resolve_slug(entry: dict, manifest: Path) -> str: + proc = call_tailor("--manifest", str(manifest), "matrix", entry["image"], "--format", "json", *selector_args(entry), capture=True) + cells = json.loads(proc.stdout) + if len(cells) != 1: + raise SystemExit(f"expected exactly one cell for {entry['image']}, got {len(cells)}") + return cells[0]["slug"] + + +def build(name: str, output_path: str, container: str | None): + mapping = load_map() + entry = mapping[name] + target = Path(output_path) + target.parent.mkdir(parents=True, exist_ok=True) + manifest = tailor_manifest_for_container(container) + try: + slug = resolve_slug(entry, manifest) + call_tailor("--manifest", str(manifest), "build", entry["image"], *selector_args(entry), "--output-dir", str(target.parent)) + source_ext = entry.get("tailorExt", entry["ext"]) + built = target.parent / f"{slug}.{source_ext}" + if not built.exists(): + raise SystemExit(f"expected built artifact not found: {built}") + built.replace(target) + finally: + if manifest.name == ".tailor.make.yaml": + manifest.unlink(missing_ok=True) + + +def oras_download(name: str, out_path: Path): + ref = f"mcr.microsoft.com/azurelinux/3.0/image/{name}:latest" + with tempfile.TemporaryDirectory() as td: + subprocess.run(["oras", "pull", ref, "--output", td, "--platform", "linux/amd64"], check=True) + files = list(Path(td).glob("*.vhdx")) + if len(files) != 1: + raise SystemExit(f"expected one .vhdx from {ref}, got {len(files)}") + out_path.parent.mkdir(parents=True, exist_ok=True) + shutil.move(str(files[0]), str(out_path)) + + +def download_image(name: str): + target_map = { + "baremetal": REPO_ROOT / "artifacts" / "baremetal.vhdx", + "core_selinux": REPO_ROOT / "artifacts" / "core_selinux.vhdx", + "minimal": REPO_ROOT / "artifacts" / "minimal.vhdx", + "minimal_aarch64": REPO_ROOT / "artifacts" / "minimal_aarch64.vhdx", + } + if name not in target_map: + raise SystemExit(f"unsupported base image: {name}") + oras_download(name, target_map[name]) + + +def main(): + ap = argparse.ArgumentParser() + sub = ap.add_subparsers(dest="cmd", required=True) + + p = sub.add_parser("list") + p.add_argument("--filter-type", required=True) + + p = sub.add_parser("dependencies") + p.add_argument("name") + + p = sub.add_parser("build") + p.add_argument("name") + p.add_argument("--output-path", required=True) + p.add_argument("--container") + + p = sub.add_parser("show-artifact") + p.add_argument("item") + + p = sub.add_parser("download-image") + p.add_argument("name") + + args = ap.parse_args() + if args.cmd == "list": + legacy_list(args.filter_type) + elif args.cmd == "dependencies": + dependencies(args.name) + elif args.cmd == "build": + build(args.name, args.output_path, args.container) + elif args.cmd == "show-artifact": + if args.item != "customizer-container-full": + raise SystemExit(f"unsupported artifact item: {args.item}") + print(default_container_full()) + elif args.cmd == "download-image": + download_image(args.name) + + +if __name__ == "__main__": + import os + main() From d4b238e231fb2ad3874da753a6577867bd05903e Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Sat, 10 Oct 2026 00:16:11 +0000 Subject: [PATCH 06/16] fix(tests/images): apply black formatting to legacy_targets.py The Check amd64 pipeline job's "Check Python Formatting" step runs `black --check .` over the whole repo and failed because the new tests/images/legacy_targets.py shim was not Black-formatted. Reformat with black==24.1.0 (matching the version pinned in CI) to fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/images/legacy_targets.py | 76 ++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/tests/images/legacy_targets.py b/tests/images/legacy_targets.py index 4b0ea753e4..939d0e17b6 100755 --- a/tests/images/legacy_targets.py +++ b/tests/images/legacy_targets.py @@ -24,7 +24,7 @@ def cargo_cmd() -> str: fallback = Path.home() / ".cargo" / "bin" / "cargo" if fallback.exists(): return str(fallback) - alt = Path('/home/bfjelds/.cargo/bin/cargo') + alt = Path("/home/bfjelds/.cargo/bin/cargo") if alt.exists(): return str(alt) raise SystemExit("cargo not found") @@ -36,7 +36,7 @@ def default_container_full() -> str: idx = text.find(needle) if idx == -1: raise SystemExit("default toolchain not found in tests/images/tailor.yaml") - rest = text[idx + len(needle):].splitlines() + rest = text[idx + len(needle) :].splitlines() container = rest[0].strip() tag = None for line in rest[1:6]: @@ -87,10 +87,20 @@ def selector_args(entry: dict) -> list[str]: def call_tailor(*args: str, capture: bool = False) -> subprocess.CompletedProcess: - cmd = [cargo_cmd(), "run", "--manifest-path", "tools/tailor/Cargo.toml", "--quiet", "--", *args] + cmd = [ + cargo_cmd(), + "run", + "--manifest-path", + "tools/tailor/Cargo.toml", + "--quiet", + "--", + *args, + ] env = dict(os.environ) env["PATH"] = f"{Path.home() / '.cargo' / 'bin'}:{env.get('PATH','')}" - return subprocess.run(cmd, cwd=str(REPO_ROOT), check=True, text=True, capture_output=capture, env=env) + return subprocess.run( + cmd, cwd=str(REPO_ROOT), check=True, text=True, capture_output=capture, env=env + ) def legacy_list(filter_type: str): @@ -114,7 +124,11 @@ def dependencies(name: str): if base_dep is not None: deps.append(base_dep) for path in sorted(image_dir.rglob("*")): - if path.is_file() and ".rendered" not in path.parts and path.name != ".tailor.make.yaml": + if ( + path.is_file() + and ".rendered" not in path.parts + and path.name != ".tailor.make.yaml" + ): deps.append(path) needs_rpms = name not in { "trident-functest", @@ -134,13 +148,28 @@ def dependencies(name: str): deps.append(rpm_dir) deps.extend(sorted(rpm_dir.rglob("*.rpm"))) if entry["image"] == "trident-installer": - for extra in [REPO_ROOT / "bin" / "rcp-agent", REPO_ROOT / "tools" / "cmd" / "rcp-agent" / "rcp-agent.service"]: + for extra in [ + REPO_ROOT / "bin" / "rcp-agent", + REPO_ROOT / "tools" / "cmd" / "rcp-agent" / "rcp-agent.service", + ]: if extra.exists(): deps.append(extra) if name == "azl-installer": for extra in [ - REPO_ROOT / "tests" / "images" / "azl-installer" / "iso" / "bin" / "liveinstaller", - REPO_ROOT / "tests" / "images" / "azl-installer" / "iso" / "images" / "trident-testimage.cosi", + REPO_ROOT + / "tests" + / "images" + / "azl-installer" + / "iso" + / "bin" + / "liveinstaller", + REPO_ROOT + / "tests" + / "images" + / "azl-installer" + / "iso" + / "images" + / "trident-testimage.cosi", ]: if extra.exists(): deps.append(extra) @@ -156,10 +185,21 @@ def dependencies(name: str): def resolve_slug(entry: dict, manifest: Path) -> str: - proc = call_tailor("--manifest", str(manifest), "matrix", entry["image"], "--format", "json", *selector_args(entry), capture=True) + proc = call_tailor( + "--manifest", + str(manifest), + "matrix", + entry["image"], + "--format", + "json", + *selector_args(entry), + capture=True, + ) cells = json.loads(proc.stdout) if len(cells) != 1: - raise SystemExit(f"expected exactly one cell for {entry['image']}, got {len(cells)}") + raise SystemExit( + f"expected exactly one cell for {entry['image']}, got {len(cells)}" + ) return cells[0]["slug"] @@ -171,7 +211,15 @@ def build(name: str, output_path: str, container: str | None): manifest = tailor_manifest_for_container(container) try: slug = resolve_slug(entry, manifest) - call_tailor("--manifest", str(manifest), "build", entry["image"], *selector_args(entry), "--output-dir", str(target.parent)) + call_tailor( + "--manifest", + str(manifest), + "build", + entry["image"], + *selector_args(entry), + "--output-dir", + str(target.parent), + ) source_ext = entry.get("tailorExt", entry["ext"]) built = target.parent / f"{slug}.{source_ext}" if not built.exists(): @@ -185,7 +233,10 @@ def build(name: str, output_path: str, container: str | None): def oras_download(name: str, out_path: Path): ref = f"mcr.microsoft.com/azurelinux/3.0/image/{name}:latest" with tempfile.TemporaryDirectory() as td: - subprocess.run(["oras", "pull", ref, "--output", td, "--platform", "linux/amd64"], check=True) + subprocess.run( + ["oras", "pull", ref, "--output", td, "--platform", "linux/amd64"], + check=True, + ) files = list(Path(td).glob("*.vhdx")) if len(files) != 1: raise SystemExit(f"expected one .vhdx from {ref}, got {len(files)}") @@ -243,4 +294,5 @@ def main(): if __name__ == "__main__": import os + main() From e883819c460269b7a729492a441ce3add227a13b Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Sat, 10 Oct 2026 00:36:56 +0000 Subject: [PATCH 07/16] fix(tests/images): add missing Ubuntu base-image prerequisites in legacy_targets.py dependencies() base_dep_map only listed baremetal/core_selinux/core_arm64/ qemu_guest, so `make artifacts/ubuntu-direct-streaming-testimage-*.cosi` never pulled in the Ubuntu cloud image as a prerequisite before invoking tailor build. The Makefile's own curl+qemu-img-convert rules for artifacts/ubuntu_22{0,4}4_{amd64,arm64}.vhdx were preserved by the earlier Makefile migration, but nothing wired them in as dependencies anymore, so tailor failed with "failed to read local base ... No such file or directory" (reproduced locally). Add the four ubuntu_*_vhdx entries to base_dep_map, keyed by the same baseImage values already present in tests/images/legacy-map.json. Note: gb200_2404_arm64 has no equivalent Makefile download rule on main either (pre-existing gap, not introduced by this migration) and is gated off by default in the pipeline (testGB200StreamingImage: false), so it is not fixed here - flagging as a known follow-up. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tests/images/legacy_targets.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/images/legacy_targets.py b/tests/images/legacy_targets.py index 939d0e17b6..1751a5b426 100755 --- a/tests/images/legacy_targets.py +++ b/tests/images/legacy_targets.py @@ -119,6 +119,10 @@ def dependencies(name: str): "core_selinux": REPO_ROOT / "artifacts" / "core_selinux.vhdx", "core_arm64": REPO_ROOT / "artifacts" / "core_arm64.vhdx", "qemu_guest": REPO_ROOT / "artifacts" / "qemu_guest.vhdx", + "ubuntu_2204_amd64": REPO_ROOT / "artifacts" / "ubuntu_2204_amd64.vhdx", + "ubuntu_2204_arm64": REPO_ROOT / "artifacts" / "ubuntu_2204_arm64.vhdx", + "ubuntu_2404_amd64": REPO_ROOT / "artifacts" / "ubuntu_2404_amd64.vhdx", + "ubuntu_2404_arm64": REPO_ROOT / "artifacts" / "ubuntu_2404_arm64.vhdx", } base_dep = base_dep_map.get(entry.get("baseImage")) if base_dep is not None: From 34d1a7a5481ae5ab2000b5a0bce019fb2578da05 Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Sat, 10 Oct 2026 00:42:06 +0000 Subject: [PATCH 08/16] fix(tests/images,Makefile): add GB200 base-image download rule and dependency GB200 had no existing Makefile rule or legacy_targets.py dependency entry on main either - the pipeline staged artifacts/gb200_2404_arm64.vhdx purely via a dedicated az storage blob download step (.pipelines/templates/stages/trident_images/trident-testimg-template.yml), bypassing the Makefile entirely. Add a Makefile rule mirroring that same az CLI download (for local/dev builds with access to the azlinuxbmpstaging storage account), and register it in legacy_targets.py's base_dep_map so make correctly tracks it as a prerequisite, consistent with the other base images. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- Makefile | 15 +++++++++++++++ tests/images/legacy_targets.py | 1 + 2 files changed, 16 insertions(+) diff --git a/Makefile b/Makefile index a393a16d34..7078514cb1 100644 --- a/Makefile +++ b/Makefile @@ -1325,3 +1325,18 @@ artifacts/ubuntu_2404_arm64.vhdx: curl -LO https://cloud-images.ubuntu.com/releases/server/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img qemu-img convert -O vhdx ubuntu-24.04-server-cloudimg-arm64.img artifacts/ubuntu_2404_arm64.vhdx rm -f ubuntu-24.04-server-cloudimg-arm64.img + +# GB200 base image is staged from a private Azure Linux storage account (see +# .pipelines/templates/stages/trident_images/trident-testimg-template.yml, +# "Download Base Image - gb200_2404_arm64"), not a public URL, so this rule +# mirrors the pipeline's az CLI download for local/dev builds that have +# access to the azlinuxbmpstaging storage account. +GB200_BLOB_NAME = gb200/arm64/20260318/image.vhdx +artifacts/gb200_2404_arm64.vhdx: + mkdir -p artifacts + az storage blob download \ + --auth-mode login \ + --account-name azlinuxbmpstaging \ + --container-name os-image-cache \ + --name "$(GB200_BLOB_NAME)" \ + --file artifacts/gb200_2404_arm64.vhdx diff --git a/tests/images/legacy_targets.py b/tests/images/legacy_targets.py index 1751a5b426..0108ab7c2e 100755 --- a/tests/images/legacy_targets.py +++ b/tests/images/legacy_targets.py @@ -123,6 +123,7 @@ def dependencies(name: str): "ubuntu_2204_arm64": REPO_ROOT / "artifacts" / "ubuntu_2204_arm64.vhdx", "ubuntu_2404_amd64": REPO_ROOT / "artifacts" / "ubuntu_2404_amd64.vhdx", "ubuntu_2404_arm64": REPO_ROOT / "artifacts" / "ubuntu_2404_arm64.vhdx", + "gb200_2404_arm64": REPO_ROOT / "artifacts" / "gb200_2404_arm64.vhdx", } base_dep = base_dep_map.get(entry.get("baseImage")) if base_dep is not None: From e01664aa39d824530ab9cca67faf9e318cece436 Mon Sep 17 00:00:00 2001 From: Brian Fjeldstad Date: Sat, 10 Oct 2026 00:54:23 +0000 Subject: [PATCH 09/16] fix(pipelines): install Rust toolchain in legacy Prepare-Image jobs .pipelines/templates/stages/trident_images/build-image.yml and build-image-arm64.yml drive the "Prepare Image