Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ jobs:
hostDistro: azl3
permissions:
contents: read
# Azure login.
id-token: write

tests-vmtests-imagecreator-ubuntu2404-amd64:
name: VMTests suite image creator Ubuntu24.04 AMD64
Expand All @@ -173,6 +175,8 @@ jobs:
hostDistro: ubuntu2404
permissions:
contents: read
# Azure login.
id-token: write

tests-vmtests-imagecreator-ubuntu2404-arm64:
name: VMTests suite image creator Ubuntu24.04 ARM64
Expand All @@ -184,6 +188,8 @@ jobs:
hostDistro: ubuntu2404
permissions:
contents: read
# Azure login.
id-token: write

tests-vmtests-osmodifier-azl3-amd64:
name: VMTests suite osmodifier AZL3 AMD64
Expand Down
58 changes: 49 additions & 9 deletions .github/workflows/tests-vmtests-imagecreator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ jobs:
- 1ES.Pool=${{ inputs.hostDistro == 'azl3' && (inputs.hostArch == 'amd64' && 'maritimus-github-runner-azl3-amd64' || 'maritimus-github-runner-azl3-arm64') || (inputs.hostArch == 'amd64' && 'maritimus-github-runner-ubuntu2404-amd64' || 'maritimus-github-runner-ubuntu2404-arm64') }}
permissions:
contents: read
# Azure login.
id-token: write
environment: public
steps:
- name: setup go 1.x
uses: actions/setup-go@v6
Expand Down Expand Up @@ -114,27 +117,64 @@ jobs:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""

make create-venv


- name: Azure Login
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

- name: ACR Login
env:
AZURE_CR_CACHE: ${{ vars.AZURE_CR_CACHE }}
run: |
set -eux
# login to ACR
az acr login -n "${AZURE_CR_CACHE}"

- name: Download RPMS and tools file
run: |
set -eux

# Download the test RPM and tools file.
./repo/toolkit/tools/internal/testutils/testrpms/download-test-utils.sh -t 3.0 -s true
# Download the test RPM and tools file for azurelinux
./repo/toolkit/tools/internal/testutils/testrpms/download-test-utils.sh -d azurelinux -t 3.0 -s true

# Download the test RPM and tools file for fedora
CI=true ./repo/toolkit/tools/internal/testutils/testrpms/download-test-utils.sh -d fedora -t 42 -s true


- name: Run image creator tests
run: |
set -eux

# Define common paths and variables
TOOLKIT_DIR="../../toolkit"
TOOLS_DIR="$TOOLKIT_DIR/tools"
TESTRPMS_DIR="$TOOLS_DIR/internal/testutils/testrpms"

# Binary paths
IMAGE_CREATOR_BIN="$TOOLKIT_DIR/out/tools/imagecreator"
IMAGE_CUSTOMIZER_BIN="$TOOLKIT_DIR/out/tools/imagecustomizer"

# Function to run tests for a specific distro
run_tests() {
local distro=$1
local version=$2

sudo make test-imagecreator-$distro \
IMAGE_CREATOR_BIN="$IMAGE_CREATOR_BIN" \
TOOLS_TAR="$TESTRPMS_DIR/build/tools-$distro-$version.tar.gz" \
RPM_SOURCES="$TESTRPMS_DIR/downloadedrpms/$distro/$version" \
IMAGE_CUSTOMIZER_BINARY_PATH="$IMAGE_CUSTOMIZER_BIN" \
SSH_PRIVATE_KEY_FILE=~/.ssh/id_ed25519
}

pushd ./repo/test/vmtests

sudo make test-imagecreator \
IMAGE_CREATOR_BIN="../../toolkit/out/tools/imagecreator" \
TOOLS_TAR="../../toolkit/tools/internal/testutils/testrpms/build/tools-azurelinux-3.0.tar.gz" \
RPM_SOURCES="../../toolkit/tools/internal/testutils/testrpms/downloadedrpms/azurelinux/3.0" \
IMAGE_CUSTOMIZER_BINARY_PATH="../../toolkit/out/tools/imagecustomizer" \
SSH_PRIVATE_KEY_FILE=~/.ssh/id_ed25519
# Run tests for each distro
run_tests "azurelinux" "3.0"
run_tests "fedora" "42"

- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
Expand Down
23 changes: 19 additions & 4 deletions test/vmtests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ test-imagecustomizer:
--junitxml=./out/$(DATETIME_AS_VERSION)/report.xml \
./vmtests/imagecustomizer/test_min_change.py

.PHONY: test-imagecreator
test-imagecreator:
.PHONY: test-imagecreator-azurelinux
test-imagecreator-azurelinux:
${PYTEST} \
--image-creator-binary-path="${IMAGE_CREATOR_BIN}" \
--rpm-sources="${RPM_SOURCES}" \
Expand All @@ -112,7 +112,22 @@ test-imagecreator:
--show-capture=all \
--tb=short \
--junitxml=./out/$(DATETIME_AS_VERSION)/report.xml \
./vmtests/imagecreator/test_imagecreator.py
./vmtests/imagecreator/test_imagecreator_azurelinux.py

.PHONY: test-imagecreator-fedora
test-imagecreator-fedora:
${PYTEST} \
--image-creator-binary-path="${IMAGE_CREATOR_BIN}" \
--rpm-sources="${RPM_SOURCES}" \
--tools-tar="${TOOLS_TAR}" \
--image-customizer-binary-path="${IMAGE_CUSTOMIZER_BINARY_PATH}" \
--ssh-private-key="${SSH_PRIVATE_KEY_FILE}" \
$(if $(filter y,$(KEEP_ENVIRONMENT)),--keep-environment) \
--log-cli-level=DEBUG \
--show-capture=all \
--tb=short \
--junitxml=./out/$(DATETIME_AS_VERSION)/report.xml \
./vmtests/imagecreator/test_imagecreator_fedora.py

.PHONY: test-osmodifier
test-osmodifier:
Expand All @@ -133,7 +148,7 @@ test-osmodifier:
run-imagecustomizer: image-customizer-container test-imagecustomizer

.PHONY: run-imagecreator
run-imagecreator: ${IMAGE_CREATOR_BIN} test-imagecreator
run-imagecreator: ${IMAGE_CREATOR_BIN} test-imagecreator-azurelinux test-imagecreator-fedora

.PHONY: run-osmodifier
run-osmodifier: ${OSMODIFIER_BIN} test-osmodifier
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@

import logging
import os
import platform
from pathlib import Path
from typing import List, Tuple
from typing import Any, Dict, List, Tuple

import libvirt # type: ignore
import pytest

from ..utils import local_client
from ..utils.closeable import Closeable
from ..utils.host_utils import get_host_distro
from ..utils.imagecreator import run_image_creator, run_image_customizer_binary
from ..utils.imagecustomizer import add_ssh_to_config
from ..utils.imagecustomizer import add_preview_features_to_config, add_ssh_to_config
from ..utils.libvirt_utils import VmSpec, create_libvirt_domain_xml
from ..utils.libvirt_vm import LibvirtVm
from ..utils.ssh_client import SshClient
Expand All @@ -25,6 +23,94 @@
"toolkit/tools/pkg/imagecreatorlib/testdata"
)

# Common packages that should be present in all distributions
COMMON_PACKAGES = ["kernel", "systemd", "bash"]

# Distribution-specific configuration
DISTRO_CONFIGS: Dict[str, Dict[str, Any]] = {
"fedora": {
"os_release": {
"ID": "fedora",
"VERSION_ID": "42",
},
"packages": COMMON_PACKAGES + ["grub2-efi-x64"],
},
"azurelinux": {
"os_release": {
"ID": "azurelinux",
"VERSION_ID": "3.0",
},
"packages": COMMON_PACKAGES + ["grub2"],
},
}


def verify_packages(ssh_client: SshClient, packages_to_check: List[str]) -> None:
"""Verify that specified packages are present in the system.

Args:
ssh_client: SSH client connected to the target system
packages_to_check: List of package names to verify
"""
for package in packages_to_check:
ssh_client.run(f"rpm -q {package}").check_exit_code()


def verify_os_release(os_release_text: str, expected_values: Dict[str, str]) -> None:
"""Verify os-release content matches expected values.

Args:
os_release_text: Content of os-release file
expected_values: Dictionary of key-value pairs to verify
"""

# Parse os-release into a dictionary
os_release_dict = {}
for line in os_release_text.splitlines():
if "=" in line:
key, value = line.split("=", 1)
# Remove quotes if present
value = value.strip('"')
os_release_dict[key] = value

for key, value in expected_values.items():
if key not in os_release_dict:
raise AssertionError(f"Key '{key}' not found in os-release")
if os_release_dict[key] != value:
raise AssertionError(f"Value mismatch for '{key}': expected '{value}', got '{os_release_dict[key]}'")


def run_basic_checks(
ssh_client: SshClient,
test_temp_dir: Path,
distro: str,
) -> None:
"""Run basic checks for the specified distribution.

Args:
ssh_client: SSH client for running commands
test_temp_dir: Temporary directory for test artifacts
distro: Distribution name (must be a key in DISTRO_CONFIGS)
"""
if distro not in DISTRO_CONFIGS:
raise ValueError(f"Unsupported distribution: {distro}")

config = DISTRO_CONFIGS[distro]

# Check kernel cmdline
ssh_client.run("cat /proc/cmdline").check_exit_code()

# Get and verify os-release
os_release_path = test_temp_dir.joinpath("os-release")
ssh_client.get_file(Path("/etc/os-release"), os_release_path)

with open(os_release_path, "r") as os_release_fd:
os_release_text = os_release_fd.read()
verify_os_release(os_release_text, config["os_release"])

# Check required packages
verify_packages(ssh_client, config["packages"])


def run_image_creator_test(
image_creator_binary_path: Path,
Expand Down Expand Up @@ -89,6 +175,10 @@ def run_image_creator_test(
base_ssh_config_path = IMAGECREATOR_TEST_CONFIGS_DIR.joinpath("ssh-base-config.yaml")
customizer_config_path_obj = add_ssh_to_config(base_ssh_config_path, username, ssh_public_key, close_list)

# Add Fedora preview features if needed
if distro.lower() == "fedora":
customizer_config_path_obj = add_preview_features_to_config(customizer_config_path_obj, "fedora-42", close_list)

run_image_customizer_binary(
image_customizer_binary_path,
initial_output_image_path,
Expand Down Expand Up @@ -189,65 +279,5 @@ def run_image_creator_test(
logging.info(f"SSH connection established successfully!")
# Run the test
logging.info(f"Running basic checks on the VM")
run_basic_checks(ssh_client, test_temp_dir)
run_basic_checks(ssh_client, test_temp_dir, distro)
logging.info(f"Basic checks completed successfully!")


def run_basic_checks(
ssh_client: SshClient,
test_temp_dir: Path,
) -> None:

ssh_client.run("cat /proc/cmdline").check_exit_code()

os_release_path = test_temp_dir.joinpath("os-release")
ssh_client.get_file(Path("/etc/os-release"), os_release_path)

with open(os_release_path, "r") as os_release_fd:
os_release_text = os_release_fd.read()

# Since imagecreator creates new images, we expect Azure Linux 3.0
assert "ID=azurelinux" in os_release_text
assert 'VERSION_ID="3.0"' in os_release_text

# Check that essential packages are installed
ssh_client.run("rpm -q kernel").check_exit_code()
ssh_client.run("rpm -q systemd").check_exit_code()
ssh_client.run("rpm -q grub2").check_exit_code()
ssh_client.run("rpm -q bash").check_exit_code()


@pytest.mark.skipif(platform.machine() != "x86_64", reason="arm64 is not supported for this combination")
def test_create_image_efi_qcow_output_azurelinux(
image_creator_binary_path: Path,
rpm_sources: List[Path],
tools_tar: Path,
ssh_key: Tuple[str, Path],
test_temp_dir: Path,
test_instance_name: str,
logs_dir: Path,
libvirt_conn: libvirt.virConnect,
close_list: List[Closeable],
image_customizer_binary_path: Path,
) -> None:
config_path = IMAGECREATOR_TEST_CONFIGS_DIR.joinpath("minimal-os.yaml")
output_format = "qcow2"
# debug message
logging.debug("Running test_create_image_efi_qcow_output_azurelinux")

run_image_creator_test(
image_creator_binary_path,
rpm_sources,
tools_tar,
config_path,
output_format,
ssh_key,
test_temp_dir,
test_instance_name,
logs_dir,
libvirt_conn,
close_list,
image_customizer_binary_path,
"azurelinux",
"3.0",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import logging
import platform
from pathlib import Path
from typing import List, Tuple

import libvirt # type: ignore
import pytest

from ..utils.closeable import Closeable
from .imagecreator_test_utils import IMAGECREATOR_TEST_CONFIGS_DIR, run_image_creator_test


@pytest.mark.skipif(platform.machine() != "x86_64", reason="arm64 is not supported for this combination")
def test_create_image_efi_qcow_output_azurelinux(
image_creator_binary_path: Path,
rpm_sources: List[Path],
tools_tar: Path,
ssh_key: Tuple[str, Path],
test_temp_dir: Path,
test_instance_name: str,
logs_dir: Path,
libvirt_conn: libvirt.virConnect,
close_list: List[Closeable],
image_customizer_binary_path: Path,
) -> None:
config_path = IMAGECREATOR_TEST_CONFIGS_DIR.joinpath("minimal-os.yaml")
output_format = "qcow2"
# debug message
logging.debug("Running test_create_image_efi_qcow_output_azurelinux")

run_image_creator_test(
image_creator_binary_path,
rpm_sources,
tools_tar,
config_path,
output_format,
ssh_key,
test_temp_dir,
test_instance_name,
logs_dir,
libvirt_conn,
close_list,
image_customizer_binary_path,
"azurelinux",
"3.0",
)
Loading
Loading