Skip to content

Commit

Permalink
Image Customizer: Add tests for Azure Linux 3.0. (#10249)
Browse files Browse the repository at this point in the history
Allow the functional tests to accept both Azure Linux 2.0 and 3.0 image versions as input. Then, for the features that have different behavior based on the image version, ensure the tests for those features cover both image versions.
  • Loading branch information
cwize1 authored Aug 30, 2024
1 parent 5f41f3f commit d7765f9
Show file tree
Hide file tree
Showing 17 changed files with 235 additions and 95 deletions.
21 changes: 13 additions & 8 deletions toolkit/tools/imagecustomizer/DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ sudo go test -C ./toolkit/tools ./...

## Run Image Customizer specific tests

1. Build (or download) the
[core-efi](https://github.com/microsoft/CBL-Mariner/blob/2.0/toolkit/imageconfigs/core-efi.json)
vhdx image file for Azure Linux 2.0.
1. Build (or download) the vhdx/vhd image files for:

- [Azure Linux 2.0 core-efi](https://github.com/microsoft/CBL-Mariner/blob/2.0/toolkit/imageconfigs/core-efi.json)
- [Azure Linux 3.0 core-efi](https://github.com/microsoft/CBL-Mariner/blob/3.0/toolkit/imageconfigs/core-efi.json)
- [Azure Linux 2.0 core-legacy](https://github.com/microsoft/CBL-Mariner/blob/2.0/toolkit/imageconfigs/core-legacy.json)
- [Azure Linux 3.0 core-legacy](https://github.com/microsoft/CBL-Mariner/blob/3.0/toolkit/imageconfigs/core-legacy.json)

2. Download the test RPM files:

Expand All @@ -32,11 +35,13 @@ sudo go test -C ./toolkit/tools ./...

```bash
AZURE_LINUX_2_CORE_EFI_VHDX="<core-efi-2.0.vhdx>"
AZURE_LINUX_3_CORE_EFI_VHDX="<core-efi-3.0.vhdx>"
AZURE_LINUX_2_CORE_LEGACY_VHD="<core-legacy-2.0.vhd>"
AZURE_LINUX_3_CORE_LEGACY_VHD="<core-legacy-3.0.vhd>"

sudo go test -C ./toolkit/tools ./pkg/imagecustomizerlib -args \
--base-image-core-efi "$AZURE_LINUX_2_CORE_EFI_VHDX"
--base-image-core-efi-azl2 "$AZURE_LINUX_2_CORE_EFI_VHDX"
--base-image-core-efi-azl3 "$AZURE_LINUX_3_CORE_EFI_VHDX"
--base-image-core-legacy-azl2 "$AZURE_LINUX_2_CORE_LEGACY_VHD"
--base-image-core-legacy-azl3 "$AZURE_LINUX_3_CORE_LEGACY_VHD"
```

Where:

- `<core-efi-2.0.vhdx>`: The vhdx image file you acquired in step 1.
8 changes: 4 additions & 4 deletions toolkit/tools/pkg/imagecustomizerlib/customizefiles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestCopyAdditionalFiles(t *testing.T) {
}

func TestCustomizeImageAdditionalFiles(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageAdditionalFiles")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down Expand Up @@ -100,7 +100,7 @@ func TestCustomizeImageAdditionalFiles(t *testing.T) {
}

func TestCustomizeImageAdditionalFilesInfiniteFile(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageAdditionalFilesInfiniteFile")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down Expand Up @@ -176,7 +176,7 @@ func TestCopyAdditionalDirs(t *testing.T) {
}

func TestCustomizeImageAdditionalDirs(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageAdditionalDirs")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down Expand Up @@ -205,7 +205,7 @@ func TestCustomizeImageAdditionalDirs(t *testing.T) {
}

func TestCustomizeImageAdditionalDirsInfiniteFile(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageAdditionalDirsInfiniteFile")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestUpdateHostname(t *testing.T) {
}

func TestCustomizeImageHostname(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageHostname")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

func TestCustomizeImageOverlays(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTempDir := filepath.Join(tmpDir, "TestCustomizeImageOverlays")
buildDir := filepath.Join(testTempDir, "build")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
func TestCustomizeImagePackagesAddOfflineDir(t *testing.T) {
testTmpDir := filepath.Join(tmpDir, "TestCustomizeImagePackagesAddOfflineDir")

baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)
downloadedRpmsDir := getDownloadedRpmsDir(t, "2.0")

buildDir := filepath.Join(testTmpDir, "build")
Expand Down Expand Up @@ -134,7 +134,7 @@ func copyRpms(sourceDir string, targetDir string, excludePrefixes []string) erro
func TestCustomizeImagePackagesAddOfflineLocalRepo(t *testing.T) {
testTmpDir := filepath.Join(tmpDir, "TestCustomizeImagePackagesAddOfflineLocalRepo")

baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

downloadedRpmsRepoFile := getDownloadedRpmsRepoFile(t, "2.0")
rpmSources := []string{downloadedRpmsRepoFile}
Expand Down Expand Up @@ -164,7 +164,7 @@ func TestCustomizeImagePackagesAddOfflineLocalRepo(t *testing.T) {
}

func TestCustomizeImagePackagesUpdate(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImagePackagesUpdate")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down Expand Up @@ -197,7 +197,7 @@ func TestCustomizeImagePackagesUpdate(t *testing.T) {
}

func TestCustomizeImagePackagesDiskSpace(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImagePackagesDiskSpace")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down
124 changes: 91 additions & 33 deletions toolkit/tools/pkg/imagecustomizerlib/customizepartitions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,35 @@ import (
)

func TestCustomizeImagePartitions(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
testCustomizeImagePartitionsToEfi(t, "TestCustomizeImagePartitions", baseImage)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImagePartitionsToEfi(t, "TestCustomizeImagePartitions"+string(version),
baseImageTypeCoreEfi, version)
})
}
}

func TestCustomizeImagePartitionsLegacyToEfi(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreLegacy)
testCustomizeImagePartitionsToEfi(t, "TestCustomizeImagePartitionsLegacyToEfi", baseImage)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImagePartitionsToEfi(t, "TestCustomizeImagePartitionsLegacyToEfi"+string(version),
baseImageTypeCoreLegacy, version)
})
}
}

func testCustomizeImagePartitionsToEfi(t *testing.T, testName string, baseImage string) {
var err error
func testCustomizeImagePartitionsToEfi(t *testing.T, testName string, imageType baseImageType,
imageVersion baseImageVersion,
) {
baseImage := checkSkipForCustomizeImage(t, imageType, imageVersion)

testTmpDir := filepath.Join(tmpDir, testName)
buildDir := filepath.Join(testTmpDir, "build")
configFile := filepath.Join(testDir, "partitions-config.yaml")
outImageFilePath := filepath.Join(testTmpDir, "image.raw")

// Customize image.
err = CustomizeImageWithConfigFile(buildDir, configFile, baseImage, nil, outImageFilePath, "raw", "",
err := CustomizeImageWithConfigFile(buildDir, configFile, baseImage, nil, outImageFilePath, "raw", "",
false /*useBaseImageRpmRepos*/, false /*enableShrinkFilesystems*/)
if !assert.NoError(t, err) {
return
Expand Down Expand Up @@ -100,30 +110,41 @@ func testCustomizeImagePartitionsToEfi(t *testing.T, testName string, baseImage
// Check that the fstab entries are correct.
verifyFstabEntries(t, imageConnection, mountPoints, partitions)
verifyBootloaderConfig(t, imageConnection, "console=tty0 console=ttyS0",
partitions[mountPoints[1].PartitionNum].Uuid,
partitions[mountPoints[0].PartitionNum].PartUuid)
partitions[mountPoints[1].PartitionNum],
partitions[mountPoints[0].PartitionNum],
imageVersion)
}

func TestCustomizeImagePartitionsEfiToLegacy(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
testCustomizeImagePartitionsToLegacy(t, "TestCustomizeImagePartitionsEfiToLegacy", baseImage)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImagePartitionsToLegacy(t, "TestCustomizeImagePartitionsEfiToLegacy"+string(version),
baseImageTypeCoreEfi, version)
})
}
}

func TestCustomizeImagePartitionsLegacy(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreLegacy)
testCustomizeImagePartitionsToLegacy(t, "TestCustomizeImagePartitionsLegacy", baseImage)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImagePartitionsToLegacy(t, "TestCustomizeImagePartitionsLegacy"+string(version),
baseImageTypeCoreLegacy, version)
})
}
}

func testCustomizeImagePartitionsToLegacy(t *testing.T, testName string, baseImage string) {
var err error
func testCustomizeImagePartitionsToLegacy(t *testing.T, testName string, imageType baseImageType,
imageVersion baseImageVersion,
) {
baseImage := checkSkipForCustomizeImage(t, imageType, imageVersion)

testTmpDir := filepath.Join(tmpDir, testName)
buildDir := filepath.Join(testTmpDir, "build")
configFile := filepath.Join(testDir, "legacyboot-config.yaml")
outImageFilePath := filepath.Join(buildDir, "image.raw")

// Customize image.
err = CustomizeImageWithConfigFile(buildDir, configFile, baseImage, nil, outImageFilePath, "raw", "",
err := CustomizeImageWithConfigFile(buildDir, configFile, baseImage, nil, outImageFilePath, "raw", "",
false /*useBaseImageRpmRepos*/, false /*enableShrinkFilesystems*/)
if !assert.NoError(t, err) {
return
Expand All @@ -145,16 +166,24 @@ func testCustomizeImagePartitionsToLegacy(t *testing.T, testName string, baseIma
// Check that the fstab entries are correct.
verifyFstabEntries(t, imageConnection, coreLegacyMountPoints, partitions)
verifyBootGrubCfg(t, imageConnection, "",
partitions[coreLegacyMountPoints[0].PartitionNum].Uuid,
partitions[coreLegacyMountPoints[0].PartitionNum].PartUuid)
partitions[coreLegacyMountPoints[0].PartitionNum],
partitions[coreLegacyMountPoints[0].PartitionNum],
imageVersion)
}

func TestCustomizeImageKernelCommandLine(t *testing.T) {
var err error
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, version)
testCustomizeImageKernelCommandLineHelper(t, "TestCustomizeImageKernelCommandLine"+string(version), baseImage)
})
}
}

baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
func testCustomizeImageKernelCommandLineHelper(t *testing.T, testName string, baseImage string) {
var err error

buildDir := filepath.Join(tmpDir, "TestCustomizeImageKernelCommandLine")
buildDir := filepath.Join(tmpDir, testName)
configFile := filepath.Join(testDir, "extracommandline-config.yaml")
outImageFilePath := filepath.Join(buildDir, "image.qcow2")

Expand All @@ -179,9 +208,20 @@ func TestCustomizeImageKernelCommandLine(t *testing.T) {
}

func TestCustomizeImageNewUUIDs(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImageNewUUIDsHelper(t, "TestCustomizeImageNewUUIDs"+string(version), baseImageTypeCoreEfi,
version)
})
}
}

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageNewUUIDs")
func testCustomizeImageNewUUIDsHelper(t *testing.T, testName string, imageType baseImageType,
imageVersion baseImageVersion,
) {
baseImage := checkSkipForCustomizeImage(t, imageType, imageVersion)

testTmpDir := filepath.Join(tmpDir, testName)
buildDir := filepath.Join(testTmpDir, "build")
configFile := filepath.Join(testDir, "newpartitionsuuids-config.yaml")
tempRawBaseImage := filepath.Join(testTmpDir, "baseImage.raw")
Expand Down Expand Up @@ -253,8 +293,9 @@ func TestCustomizeImageNewUUIDs(t *testing.T) {
// Check that the fstab entries are correct.
verifyFstabEntries(t, imageConnection, coreEfiMountPoints, newImagePartitions)
verifyBootloaderConfig(t, imageConnection, "",
newImagePartitions[coreEfiMountPoints[0].PartitionNum].Uuid,
newImagePartitions[coreEfiMountPoints[0].PartitionNum].PartUuid)
newImagePartitions[coreEfiMountPoints[0].PartitionNum],
newImagePartitions[coreEfiMountPoints[0].PartitionNum],
imageVersion)
}

func verifyFstabEntries(t *testing.T, imageConnection *ImageConnection, mountPoints []mountPoint,
Expand Down Expand Up @@ -286,10 +327,10 @@ func verifyFstabEntries(t *testing.T, imageConnection *ImageConnection, mountPoi
}

func verifyBootloaderConfig(t *testing.T, imageConnection *ImageConnection, extraCommandLineArgs string,
bootUuid string, rootfsPartUuid string,
bootInfo diskutils.PartitionInfo, rootfsInfo diskutils.PartitionInfo, imageVersion baseImageVersion,
) {
verifyEspGrubCfg(t, imageConnection, bootUuid)
verifyBootGrubCfg(t, imageConnection, extraCommandLineArgs, bootUuid, rootfsPartUuid)
verifyEspGrubCfg(t, imageConnection, bootInfo.Uuid)
verifyBootGrubCfg(t, imageConnection, extraCommandLineArgs, bootInfo, rootfsInfo, imageVersion)
}

func verifyEspGrubCfg(t *testing.T, imageConnection *ImageConnection, bootUuid string) {
Expand All @@ -302,20 +343,37 @@ func verifyEspGrubCfg(t *testing.T, imageConnection *ImageConnection, bootUuid s
assert.Regexp(t, fmt.Sprintf("(?m)^search -n -u %s -s$", regexp.QuoteMeta(bootUuid)), grubCfgContents)
}

func verifyBootGrubCfg(t *testing.T, imageConnection *ImageConnection, extraCommandLineArgs string, bootUuid string,
rootfsPartUuid string,
func verifyBootGrubCfg(t *testing.T, imageConnection *ImageConnection, extraCommandLineArgs string,
bootInfo diskutils.PartitionInfo, rootfsInfo diskutils.PartitionInfo,
imageVersion baseImageVersion,
) {
grubCfgFilePath := filepath.Join(imageConnection.Chroot().RootDir(), "/boot/grub2/grub.cfg")
grubCfgContents, err := file.Read(grubCfgFilePath)
if !assert.NoError(t, err, "read boot grub.cfg file") {
return
}

assert.Regexp(t, fmt.Sprintf("(?m)^search -n -u %s -s$", regexp.QuoteMeta(bootUuid)), grubCfgContents)
assert.Regexp(t, fmt.Sprintf("(?m)^set rootdevice=PARTUUID=%s$", regexp.QuoteMeta(rootfsPartUuid)), grubCfgContents)
switch imageVersion {
case baseImageVersionAzl2:
assert.Regexp(t, fmt.Sprintf(`(?m)^search -n -u %s -s$`, regexp.QuoteMeta(bootInfo.Uuid)),
grubCfgContents)
assert.Regexp(t, fmt.Sprintf(`(?m)^set rootdevice=PARTUUID=%s$`, regexp.QuoteMeta(rootfsInfo.PartUuid)),
grubCfgContents)

case baseImageVersionAzl3:
assert.Regexp(t, fmt.Sprintf(`(?m)[\t ]*search.* --fs-uuid --set=root %s$`, regexp.QuoteMeta(bootInfo.Uuid)),
grubCfgContents)

// In theory, UUID should always be used (unless GRUB_DISABLE_UUID is set in the /etc/default/grub file, which
// it isn't). But on some build hosts, PARTUUID is used instead. Not sure why this is the case. But the OS will
// still boot either way. So, allow both for now.
assert.Regexp(t, fmt.Sprintf(`(?m)[\t ]*linux.* root=(UUID=%s|PARTUUID=%s) `, regexp.QuoteMeta(rootfsInfo.Uuid),
regexp.QuoteMeta(rootfsInfo.PartUuid)),
grubCfgContents)
}

if extraCommandLineArgs != "" {
assert.Regexp(t, fmt.Sprintf("linux.* %s ", regexp.QuoteMeta(extraCommandLineArgs)), grubCfgContents)
assert.Regexp(t, fmt.Sprintf(`(?m)[\t ]*linux.* %s `, regexp.QuoteMeta(extraCommandLineArgs)), grubCfgContents)
}
}

Expand Down
32 changes: 27 additions & 5 deletions toolkit/tools/pkg/imagecustomizerlib/customizeselinux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,20 @@ import (
)

func TestCustomizeImageSELinux(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImageSELinuxHelper(t, "TestCustomizeImageSELinux"+string(version), baseImageTypeCoreEfi,
version)
})
}
}

func testCustomizeImageSELinuxHelper(t *testing.T, testName string, imageType baseImageType,
imageVersion baseImageVersion,
) {
baseImage := checkSkipForCustomizeImage(t, imageType, imageVersion)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageSELinux")
testTmpDir := filepath.Join(tmpDir, testName)
buildDir := filepath.Join(testTmpDir, "build")
outImageFilePath := filepath.Join(testTmpDir, "image.raw")

Expand Down Expand Up @@ -100,9 +111,20 @@ func TestCustomizeImageSELinux(t *testing.T) {
}

func TestCustomizeImageSELinuxAndPartitions(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
for _, version := range supportedAzureLinuxVersions {
t.Run(string(version), func(t *testing.T) {
testCustomizeImageSELinuxAndPartitionsHelper(t, "TestCustomizeImageSELinuxAndPartitions"+string(version),
baseImageTypeCoreEfi, version)
})
}
}

func testCustomizeImageSELinuxAndPartitionsHelper(t *testing.T, testName string, imageType baseImageType,
imageVersion baseImageVersion,
) {
baseImage := checkSkipForCustomizeImage(t, imageType, imageVersion)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageSELinuxAndPartitions")
testTmpDir := filepath.Join(tmpDir, testName)
buildDir := filepath.Join(testTmpDir, "build")
outImageFilePath := filepath.Join(testTmpDir, "image.raw")

Expand Down Expand Up @@ -150,7 +172,7 @@ func TestCustomizeImageSELinuxAndPartitions(t *testing.T) {
}

func TestCustomizeImageSELinuxNoPolicy(t *testing.T) {
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi)
baseImage := checkSkipForCustomizeImage(t, baseImageTypeCoreEfi, baseImageVersionDefault)

testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageSELinuxNoPolicy")
buildDir := filepath.Join(testTmpDir, "build")
Expand Down
Loading

0 comments on commit d7765f9

Please sign in to comment.