diff --git a/toolkit/tools/imagecustomizer/main.go b/toolkit/tools/imagecustomizer/main.go index 773cf7545..8b418f551 100644 --- a/toolkit/tools/imagecustomizer/main.go +++ b/toolkit/tools/imagecustomizer/main.go @@ -55,6 +55,7 @@ type InjectFilesCmd struct { OutputImageFile string `name:"output-image-file" aliases:"output-path" help:"Path to write the injected image to."` OutputImageFormat string `name:"output-image-format" placeholder:"(vhd|vhd-fixed|vhdx|qcow2|raw|iso|pxe-dir|pxe-tar|cosi|baremetal-image)" help:"Format of output image." enum:"${imageformat}" default:""` CosiCompressionLevel *int `name:"cosi-compression-level" help:"Zstd compression level for COSI output (1-22, default: 9)."` + ToolsDir string `name:"tools-dir" help:"Path to a directory containing tdnf/dnf and its dependencies. Required for package operations on images that do not include a package manager (e.g. ACL)."` } type ConvertCmd struct { @@ -63,6 +64,7 @@ type ConvertCmd struct { OutputImageFile string `name:"output-image-file" aliases:"output-path" help:"Path to write the converted image to." required:""` OutputImageFormat string `name:"output-image-format" placeholder:"(vhd|vhd-fixed|vhdx|qcow2|raw|cosi|baremetal-image)" help:"Format of output image." required:"" enum:"${imageformatconvert}"` CosiCompressionLevel *int `name:"cosi-compression-level" help:"Zstd compression level for COSI output (1-22, default: 9)."` + ToolsDir string `name:"tools-dir" help:"Path to a directory containing tdnf/dnf and its dependencies. Required for package operations on images that do not include a package manager (e.g. ACL)."` } type ValidateConfigCmd struct { @@ -200,6 +202,7 @@ func injectFiles(ctx context.Context, cmd InjectFilesCmd) error { OutputImageFile: cmd.OutputImageFile, OutputImageFormat: cmd.OutputImageFormat, CosiCompressionLevel: cmd.CosiCompressionLevel, + ToolsDir: cmd.ToolsDir, }) if err != nil { return err @@ -216,6 +219,7 @@ func convertImage(ctx context.Context, cmd ConvertCmd) error { OutputImageFile: cmd.OutputImageFile, OutputImageFormat: imagecustomizerapi.ImageFormatType(cmd.OutputImageFormat), CosiCompressionLevel: cmd.CosiCompressionLevel, + ToolsDir: cmd.ToolsDir, }) if err != nil { return err diff --git a/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput.go b/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput.go index 8d49ba2e2..81d376e4d 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput.go +++ b/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput.go @@ -23,6 +23,7 @@ import ( "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/imageconnection" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/logger" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/randomization" + "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/safechroot" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/safeloopback" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/safemount" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/sliceutils" @@ -57,7 +58,7 @@ var ukiRegex = regexp.MustCompile(`^vmlinuz-.*\.efi$`) func outputArtifacts(ctx context.Context, items []imagecustomizerapi.OutputArtifactsItemType, outputDir string, buildDir string, buildImage string, verityMetadata []verityDeviceMetadata, - previewFeatures []imagecustomizerapi.PreviewFeature, distroHandler DistroHandler, + distroHandler DistroHandler, ) error { logger.Log.Infof("Outputting artifacts") @@ -280,7 +281,7 @@ func outputArtifacts(ctx context.Context, items []imagecustomizerapi.OutputArtif } } - err = writeInjectFilesYaml(outputArtifactsMetadata, outputDir, previewFeatures) + err = writeInjectFilesYaml(outputArtifactsMetadata, outputDir) if err != nil { return fmt.Errorf("%w (outputDir='%s'):\n%w", ErrArtifactInjectFilesYamlWrite, outputDir, err) } @@ -298,9 +299,7 @@ func outputArtifacts(ctx context.Context, items []imagecustomizerapi.OutputArtif return nil } -func writeInjectFilesYaml(metadata []imagecustomizerapi.InjectArtifactMetadata, outputDir string, - previewFeatures []imagecustomizerapi.PreviewFeature, -) error { +func writeInjectFilesYaml(metadata []imagecustomizerapi.InjectArtifactMetadata, outputDir string) error { injectPreviewFeatures := []imagecustomizerapi.PreviewFeature{imagecustomizerapi.PreviewFeatureInjectFiles} yamlStruct := imagecustomizerapi.InjectFilesConfig{ @@ -370,6 +369,22 @@ func injectFilesWithOptions(ctx context.Context, baseConfigPath string, return err } + var toolsChrootOuter *ToolsChroot + var toolsChroot *safechroot.Chroot + if options.ToolsDir != "" { + if err := validateToolsDir(options.ToolsDir); err != nil { + return err + } + + toolsChrootOuter, err = initToolsChroot(ctx, options.ToolsDir) + if err != nil { + return err + } + defer toolsChrootOuter.Close() + + toolsChroot = toolsChrootOuter.Chroot() + } + rawImageFile := filepath.Join(buildDirAbs, BaseImageName) detectedImageFormat, err := convertImageToRaw(options.InputImageFile, rawImageFile) @@ -392,11 +407,18 @@ func injectFilesWithOptions(ctx context.Context, baseConfigPath string, } err = convertRawImageToOutputFormat(ctx, buildDirAbs, rawImageFile, detectedImageFormat, outputImageFile, - options.CosiCompressionLevel) + options.CosiCompressionLevel, toolsChroot) if err != nil { return err } + if toolsChrootOuter != nil { + err = toolsChrootOuter.CleanClose() + if err != nil { + return err + } + } + logger.Log.Infof("Success!") return nil @@ -461,10 +483,14 @@ func injectFilesIntoImage(buildDir string, baseConfigPath string, rawImageFile s } func prepareImageConversionData(ctx context.Context, rawImageFile string, buildDir string, + toolsChroot *safechroot.Chroot, ) ([]fstabEntryPartNum, []verityDeviceMetadata, string, []OsPackage, [randomization.UuidSize]byte, string, *CosiBootloader, []string, error, ) { imageMountPoint := filepath.Join(buildDir, "imageroot") + if toolsChroot != nil { + imageMountPoint = filepath.Join(toolsChroot.RootDir(), toolsRootImageDir) + } imageConnection, partitionsLayout, baseImageVerityMetadata, readonlyPartUuids, distroHandler, err := connectToExistingImage(ctx, rawImageFile, buildDir, imageMountPoint, true, true, true, true, nil) @@ -479,7 +505,7 @@ func prepareImageConversionData(ctx context.Context, rawImageFile string, buildD return nil, nil, "", nil, [randomization.UuidSize]byte{}, "", nil, nil, err } - osPackages, cosiBootMetadata, err := collectOSInfoHelper(ctx, buildDir, imageConnection, distroHandler, nil) + osPackages, cosiBootMetadata, err := collectOSInfoHelper(ctx, buildDir, imageConnection, distroHandler, toolsChroot) if err != nil { return nil, nil, "", nil, [randomization.UuidSize]byte{}, "", nil, nil, err } diff --git a/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput_test.go b/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput_test.go index 0ca7de545..15674be82 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput_test.go +++ b/toolkit/tools/pkg/imagecustomizerlib/artifactsinputoutput_test.go @@ -118,12 +118,19 @@ func artifactsOutputConfigFile(t *testing.T, baseImageInfo testBaseImageInfo) st // artifactsOutputVerityConfigFile returns the artifacts-output-verity test config file appropriate for the // given base image version (azl3 vs azl4) and host architecture. -func artifactsOutputVerityConfigFile(t *testing.T, baseImageInfo testBaseImageInfo) string { +func artifactsOutputVerityConfigFile(t *testing.T, baseImageInfo testBaseImageInfo, useToolsDir bool) string { + toolsDirSuffix := "" + if useToolsDir { + toolsDirSuffix = "-toolsdir" + } + switch baseImageInfo.Version { case baseImageVersionAzl2, baseImageVersionAzl3: - return "artifacts-output-verity-azl3.yaml" + return fmt.Sprintf("artifacts-output-verity-azl3%s.yaml", toolsDirSuffix) + case baseImageVersionAzl4: - return fmt.Sprintf("artifacts-output-verity-%s-azl4.yaml", runtime.GOARCH) + return fmt.Sprintf("artifacts-output-verity-%s-azl4%s.yaml", runtime.GOARCH, toolsDirSuffix) + default: t.Fatalf("unsupported base image version for artifacts-output-verity test: %s", baseImageInfo.Version) return "" @@ -131,7 +138,19 @@ func artifactsOutputVerityConfigFile(t *testing.T, baseImageInfo testBaseImageIn } func TestOutputAndInjectArtifactsCosi(t *testing.T) { - baseImage, baseImageInfo := checkSkipForCustomizeDefaultAzureLinuxImage(t) + for _, baseImageInfo := range baseImageAzureLinuxAll { + t.Run(baseImageInfo.Name, func(t *testing.T) { + testOutputAndInjectArtifactsCosiHelper(t, baseImageInfo, false) + }) + + t.Run(baseImageInfo.Name+"ToolsDir", func(t *testing.T) { + testOutputAndInjectArtifactsCosiHelper(t, baseImageInfo, true) + }) + } +} + +func testOutputAndInjectArtifactsCosiHelper(t *testing.T, baseImageInfo testBaseImageInfo, useToolsDir bool) { + baseImage := checkSkipForCustomizeImage(t, baseImageInfo) if baseImageInfo.Version == baseImageVersionAzl2 { t.Skip("'systemd-boot' is not available on Azure Linux 2.0") } @@ -142,13 +161,21 @@ func TestOutputAndInjectArtifactsCosi(t *testing.T) { t.Skip("The 'ukify' command is not available") } - testTempDir := filepath.Join(tmpDir, "TestOutputAndInjectArtifacts") + toolsDir := "" + if useToolsDir { + toolsDir = testutils.GetDownloadedToolsDir(t, testutilsDir, baseImageInfo.Distro, baseImageInfo.Version) + } + + testTempDir := filepath.Join(tmpDir, "TestOutputAndInjectArtifacts"+baseImageInfo.Name) + if useToolsDir { + testTempDir += "ToolsDir" + } defer os.RemoveAll(testTempDir) buildDir := filepath.Join(testTempDir, "build") outImageFilePath := filepath.Join(testTempDir, "image.raw") cosiFilePath := filepath.Join(testTempDir, "image.cosi") - configFile := filepath.Join(testDir, artifactsOutputVerityConfigFile(t, baseImageInfo)) + configFile := filepath.Join(testDir, artifactsOutputVerityConfigFile(t, baseImageInfo, useToolsDir)) outputArtifactsDir := filepath.Join(testDir, "./out/artifacts-output-verity/artifacts") injectConfigPath := filepath.Join(outputArtifactsDir, "inject-files.yaml") @@ -159,8 +186,16 @@ func TestOutputAndInjectArtifactsCosi(t *testing.T) { } // Customize image. - err = basicCustomizeImageWithConfigFile(t.Context(), buildDir, configFile, baseImage, outImageFilePath, "raw", - baseImageInfo.PreviewFeatures) + err = CustomizeImageWithConfigFile(t.Context(), configFile, ImageCustomizerOptions{ + BuildDir: buildDir, + InputImageFile: baseImage, + OutputImageFile: outImageFilePath, + OutputImageFormat: "raw", + UseBaseImageRpmRepos: true, + PreviewFeatures: baseImageInfo.PreviewFeatures, + SetFilesContext: *setfilesContext, + ToolsDir: toolsDir, + }) if !assert.NoError(t, err) { return } @@ -173,6 +208,7 @@ func TestOutputAndInjectArtifactsCosi(t *testing.T) { InputImageFile: outImageFilePath, OutputImageFile: cosiFilePath, OutputImageFormat: "cosi", + ToolsDir: toolsDir, } err = InjectFilesWithConfigFile(t.Context(), injectConfigPath, options) if !assert.NoError(t, err) { diff --git a/toolkit/tools/pkg/imagecustomizerlib/convertimage.go b/toolkit/tools/pkg/imagecustomizerlib/convertimage.go index 9824592a7..ecb95849e 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/convertimage.go +++ b/toolkit/tools/pkg/imagecustomizerlib/convertimage.go @@ -12,6 +12,7 @@ import ( "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/file" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/logger" + "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/safechroot" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" ) @@ -77,7 +78,7 @@ func ConvertImage(ctx context.Context, options ConvertImageOptions) (err error) outputFormat == imagecustomizerapi.ImageFormatTypeBareMetalImage if isCosiOutput { err = convertImageToCosi(ctx, options.BuildDir, options.InputImageFile, options.OutputImageFile, - outputFormat, options.CosiCompressionLevel) + outputFormat, options.CosiCompressionLevel, options.ToolsDir) if err != nil { return err } @@ -95,7 +96,7 @@ func ConvertImage(ctx context.Context, options ConvertImageOptions) (err error) } func convertImageToCosi(ctx context.Context, buildDir string, inputImageFile string, outputImageFile string, - outputFormat imagecustomizerapi.ImageFormatType, cosiCompressionLevel *int, + outputFormat imagecustomizerapi.ImageFormatType, cosiCompressionLevel *int, toolsDir string, ) error { buildDirAbs, err := filepath.Abs(buildDir) if err != nil { @@ -107,6 +108,22 @@ func convertImageToCosi(ctx context.Context, buildDir string, inputImageFile str return err } + var toolsChrootOuter *ToolsChroot + var toolsChroot *safechroot.Chroot + if toolsDir != "" { + if err := validateToolsDir(toolsDir); err != nil { + return err + } + + toolsChrootOuter, err = initToolsChroot(ctx, toolsDir) + if err != nil { + return err + } + defer toolsChrootOuter.Close() + + toolsChroot = toolsChrootOuter.Chroot() + } + rawImageFile := filepath.Join(buildDirAbs, BaseImageName) _, err = convertImageToRaw(inputImageFile, rawImageFile) if err != nil { @@ -114,21 +131,29 @@ func convertImageToCosi(ctx context.Context, buildDir string, inputImageFile str } err = convertRawImageToOutputFormat(ctx, buildDirAbs, rawImageFile, outputFormat, - outputImageFile, cosiCompressionLevel) + outputImageFile, cosiCompressionLevel, toolsChroot) if err != nil { return err } + if toolsChrootOuter != nil { + err = toolsChrootOuter.CleanClose() + if err != nil { + return err + } + } + return nil } func convertRawImageToOutputFormat(ctx context.Context, buildDirAbs string, rawImageFile string, outputFormat imagecustomizerapi.ImageFormatType, outputImageFile string, cosiCompressionLevel *int, + toolsChroot *safechroot.Chroot, ) error { if outputFormat == imagecustomizerapi.ImageFormatTypeCosi || outputFormat == imagecustomizerapi.ImageFormatTypeBareMetalImage { // Convert subcommand doesn't support preview features - pass empty slice partitionsLayout, baseImageVerityMetadata, osRelease, osPackages, imageUuid, imageUuidStr, cosiBootMetadata, - readonlyPartUuids, err := prepareImageConversionData(ctx, rawImageFile, buildDirAbs) + readonlyPartUuids, err := prepareImageConversionData(ctx, rawImageFile, buildDirAbs, toolsChroot) if err != nil { return fmt.Errorf("%w:\n%w", ErrArtifactCosiImageInfoCollect, err) } diff --git a/toolkit/tools/pkg/imagecustomizerlib/convertimage_test.go b/toolkit/tools/pkg/imagecustomizerlib/convertimage_test.go index 4e935b629..31b73c9dd 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/convertimage_test.go +++ b/toolkit/tools/pkg/imagecustomizerlib/convertimage_test.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "testing" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" @@ -83,25 +84,31 @@ func testConvertImageRawToQcow2(t *testing.T, baseImageInfo testBaseImageInfo) { } func TestConvertImageRawToCosi(t *testing.T) { - for _, baseImageInfo := range checkSkipForCustomizeDefaultImages(t) { + for _, baseImageInfo := range slices.Concat(baseImageAzureLinuxAll, baseImageUbuntuAll) { t.Run(baseImageInfo.Name, func(t *testing.T) { - testConvertImageRawToCosi(t, baseImageInfo) + testConvertImageRawToCosi(t, baseImageInfo, false) + }) + + t.Run(baseImageInfo.Name+"ToolsDir", func(t *testing.T) { + testConvertImageRawToCosi(t, baseImageInfo, true) }) } } -func testConvertImageRawToCosi(t *testing.T, baseImageInfo testBaseImageInfo) { +func testConvertImageRawToCosi(t *testing.T, baseImageInfo testBaseImageInfo, useToolsDir bool) { baseImage := checkSkipForCustomizeImage(t, baseImageInfo) - if baseImageInfo.Distro == baseImageDistroAzureLinux && baseImageInfo.Version == baseImageVersionAzl2 { - t.Skip("'systemd-boot' is not available on Azure Linux 2.0") - } ukifyExists, err := file.CommandExists("ukify") assert.NoError(t, err) if !ukifyExists { t.Skip("The 'ukify' command is not available") } + toolsDir := "" + if useToolsDir { + toolsDir = testutils.GetDownloadedToolsDir(t, testutilsDir, baseImageInfo.Distro, baseImageInfo.Version) + } + testTempDir := filepath.Join(tmpDir, fmt.Sprintf("TestConvertImageRawToCosi_%s", baseImageInfo.Name)) defer os.RemoveAll(testTempDir) @@ -110,7 +117,7 @@ func testConvertImageRawToCosi(t *testing.T, baseImageInfo testBaseImageInfo) { // First, we need a customized image with verity enabled customizedImage := filepath.Join(testTempDir, "customized.raw") - configFile := filepath.Join(testDir, "verity-config.yaml") + configFile := getRootVerityConfigFile(t, baseImageInfo, useToolsDir) err = CustomizeImageWithConfigFile(t.Context(), configFile, ImageCustomizerOptions{ BuildDir: buildDir, @@ -119,6 +126,7 @@ func testConvertImageRawToCosi(t *testing.T, baseImageInfo testBaseImageInfo) { OutputImageFormat: "raw", UseBaseImageRpmRepos: true, PreviewFeatures: baseImageInfo.PreviewFeatures, + ToolsDir: toolsDir, }) if baseImageInfo.Distro == baseImageDistroUbuntu { // This check should be removed once bootloader hard-reset support is added for Ubuntu. @@ -137,6 +145,7 @@ func testConvertImageRawToCosi(t *testing.T, baseImageInfo testBaseImageInfo) { InputImageFile: customizedImage, OutputImageFile: outputImageFile, OutputImageFormat: imagecustomizerapi.ImageFormatTypeCosi, + ToolsDir: toolsDir, } err = ConvertImage(t.Context(), options) @@ -184,7 +193,7 @@ func testConvertImageRawToCosiWithCompression(t *testing.T, baseImageInfo testBa // First, we need a customized image with verity enabled customizedImage := filepath.Join(testTempDir, "customized.raw") - configFile := filepath.Join(testDir, "verity-config.yaml") + configFile := getRootVerityConfigFile(t, baseImageInfo, false /*useToolsDir*/) err = CustomizeImageWithConfigFile(t.Context(), configFile, ImageCustomizerOptions{ BuildDir: buildDir, diff --git a/toolkit/tools/pkg/imagecustomizerlib/convertimageoptions.go b/toolkit/tools/pkg/imagecustomizerlib/convertimageoptions.go index 50043b191..b5c5f2ea9 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/convertimageoptions.go +++ b/toolkit/tools/pkg/imagecustomizerlib/convertimageoptions.go @@ -15,6 +15,7 @@ type ConvertImageOptions struct { OutputImageFile string OutputImageFormat imagecustomizerapi.ImageFormatType CosiCompressionLevel *int + ToolsDir string } func (o *ConvertImageOptions) IsValid() error { diff --git a/toolkit/tools/pkg/imagecustomizerlib/cosicommon.go b/toolkit/tools/pkg/imagecustomizerlib/cosicommon.go index 497df9c11..de351c205 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/cosicommon.go +++ b/toolkit/tools/pkg/imagecustomizerlib/cosicommon.go @@ -382,10 +382,6 @@ func getArchitectureForCosi() string { return runtime.GOARCH } -func getAllPackagesFromChroot(imageConnection *imageconnection.ImageConnection, distroHandler DistroHandler) ([]OsPackage, error) { - return distroHandler.GetAllPackagesFromChroot(imageConnection.Chroot()) -} - func extractCosiBootMetadata(buildDirAbs string, imageConnection *imageconnection.ImageConnection, distroHandler DistroHandler, toolsChroot *safechroot.Chroot, ) (*CosiBootloader, error) { diff --git a/toolkit/tools/pkg/imagecustomizerlib/createimage_test.go b/toolkit/tools/pkg/imagecustomizerlib/createimage_test.go index b9e6ea91a..e7438ca94 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/createimage_test.go +++ b/toolkit/tools/pkg/imagecustomizerlib/createimage_test.go @@ -286,7 +286,7 @@ func verifyCreateMinimalOs(t *testing.T, buildDir string, outputImageFilePath st } defer imageConnection.Close() - packageList, err := distroHandler.GetAllPackagesFromChroot(imageConnection.Chroot()) + packageList, err := distroHandler.GetAllPackagesFromChroot(imageConnection.Chroot(), nil) if !assert.NoError(t, err, "failed to get package list") { return } diff --git a/toolkit/tools/pkg/imagecustomizerlib/createimagehelper.go b/toolkit/tools/pkg/imagecustomizerlib/createimagehelper.go index 87c04dc1c..87f99eab8 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/createimagehelper.go +++ b/toolkit/tools/pkg/imagecustomizerlib/createimagehelper.go @@ -20,11 +20,11 @@ func CustomizeImageHelperCreate(ctx context.Context, rc *ResolvedConfig, toolsDi ) ([]fstabEntryPartNum, string, error) { logger.Log.Debugf("Customizing OS image") - toolsChroot, err := initToolsChroot(ctx, toolsDir) + toolsChrootOuter, err := initToolsChroot(ctx, toolsDir) if err != nil { return nil, "", err } - defer toolsChroot.Close() + defer toolsChrootOuter.Close() imageMountPoint := filepath.Join(toolsDir, toolsRootImageDir) @@ -36,7 +36,7 @@ func CustomizeImageHelperCreate(ctx context.Context, rc *ResolvedConfig, toolsDi defer imageConnection.Close() // Do the actual customizations. - err = doOsCustomizationsCreate(ctx, rc, imageConnection, toolsChroot.Chroot(), partitionsLayout, distroHandler) + err = doOsCustomizationsCreate(ctx, rc, imageConnection, toolsChrootOuter.Chroot(), partitionsLayout, distroHandler) // Out of disk space errors can be difficult to diagnose. // So, warn about any partitions with low free space. @@ -56,7 +56,7 @@ func CustomizeImageHelperCreate(ctx context.Context, rc *ResolvedConfig, toolsDi return nil, "", err } - err = toolsChroot.CleanClose() + err = toolsChrootOuter.CleanClose() if err != nil { return nil, "", err } diff --git a/toolkit/tools/pkg/imagecustomizerlib/createimagevalidation_test.go b/toolkit/tools/pkg/imagecustomizerlib/createimagevalidation_test.go index 03477d3cf..4469d4db4 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/createimagevalidation_test.go +++ b/toolkit/tools/pkg/imagecustomizerlib/createimagevalidation_test.go @@ -231,7 +231,7 @@ func testValidateCreateImageConfig_EmptyPackagestoInstall(t *testing.T, name str } func TestValidateCreateImageConfig_InvalidFieldsVerityConfig(t *testing.T) { - configFile := filepath.Join(testDir, "verity-config.yaml") + configFile := filepath.Join(testDir, "verity-root-base.yaml") var config imagecustomizerapi.Config err := imagecustomizerapi.UnmarshalYamlFile(configFile, &config) diff --git a/toolkit/tools/pkg/imagecustomizerlib/customizepackages_rpm.go b/toolkit/tools/pkg/imagecustomizerlib/customizepackages_rpm.go index 3d7e7ff0c..504546d5f 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/customizepackages_rpm.go +++ b/toolkit/tools/pkg/imagecustomizerlib/customizepackages_rpm.go @@ -339,10 +339,21 @@ func cleanRpmCache(ctx context.Context, imageChroot *safechroot.Chroot, toolsChr } // getAllPackagesFromChrootRpm retrieves all installed packages from an RPM-based system -func getAllPackagesFromChrootRpm(imageChroot safechroot.ChrootInterface) ([]OsPackage, error) { - out, _, err := shell.NewExecBuilder("rpm", "-qa", "--queryformat", "%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n"). +func getAllPackagesFromChrootRpm(imageChroot safechroot.ChrootInterface, toolsChroot *safechroot.Chroot, +) ([]OsPackage, error) { + args := []string{"-qa", "--queryformat", "%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n"} + + chroot := imageChroot + if toolsChroot != nil { + // Run rpm from inside the tools chroot against the image bind-mounted at /_imageroot — needed when + // imageChroot has no in-image rpm. + args = append([]string{"--root", "/" + toolsRootImageDir}, args...) + chroot = toolsChroot + } + + out, _, err := shell.NewExecBuilder("rpm", args...). LogLevel(logrus.TraceLevel, logrus.DebugLevel). - Chroot(imageChroot.ChrootDir()). + Chroot(chroot.ChrootDir()). ExecuteCaptureOutput() if err != nil { return nil, fmt.Errorf("failed to get RPM output from chroot:\n%w", err) diff --git a/toolkit/tools/pkg/imagecustomizerlib/customizeverity_test.go b/toolkit/tools/pkg/imagecustomizerlib/customizeverity_test.go index 3ad141eb3..04ad35a40 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/customizeverity_test.go +++ b/toolkit/tools/pkg/imagecustomizerlib/customizeverity_test.go @@ -39,7 +39,7 @@ func testCustomizeImageVerityHelper(t *testing.T, testName string, baseImageInfo buildDir := filepath.Join(testTempDir, "build") outImageFilePath := filepath.Join(testTempDir, "image.raw") - configFile := filepath.Join(testDir, "verity-config.yaml") + configFile := getRootVerityConfigFile(t, baseImageInfo, false /*useToolsDir*/) // Customize image. err := basicCustomizeImageWithConfigFile(t.Context(), buildDir, configFile, baseImage, outImageFilePath, "raw", @@ -60,6 +60,36 @@ func testCustomizeImageVerityHelper(t *testing.T, testName string, baseImageInfo verifyRootVerity(t, baseImageInfo, buildDir, outImageFilePath) } +func getRootVerityConfigFile(t *testing.T, baseImageInfo testBaseImageInfo, useToolsDir bool) string { + toolsDirSuffix := "" + if useToolsDir { + toolsDirSuffix = "-toolsdir" + } + + switch baseImageInfo.Distro { + case "azurelinux": + switch baseImageInfo.Version { + case "3.0", "2.0": + return filepath.Join(testDir, fmt.Sprintf("verity-root-azl3%s.yaml", toolsDirSuffix)) + + case "4.0": + return filepath.Join(testDir, fmt.Sprintf("verity-root-azl4%s.yaml", toolsDirSuffix)) + + default: + t.Fatalf("Unsupported AZL version (%s)", baseImageInfo.Version) + return "" + } + + case "ubuntu": + // Future: Once Ubuntu has bootloader hard-reset support, switch this to an Ubuntu specific config file. + return filepath.Join(testDir, "verity-root-base.yaml") + + default: + t.Fatalf("Unsupported distro (%s)", baseImageInfo.Distro) + return "" + } +} + func verifyRootVerity(t *testing.T, baseImageInfo testBaseImageInfo, buildDir string, outImageFilePath string, ) { @@ -115,20 +145,32 @@ func verifyRootVerity(t *testing.T, baseImageInfo testBaseImageInfo, buildDir st func TestCustomizeImageVerityCosiShrinkExtract(t *testing.T) { for _, baseImageInfo := range baseImageAzureLinuxAll { t.Run(baseImageInfo.Name, func(t *testing.T) { - testCustomizeImageVerityCosiExtractHelper(t, "TestCustomizeImageVerityShrinkExtract"+baseImageInfo.Name, baseImageInfo) + testCustomizeImageVerityCosiExtractHelper(t, baseImageInfo, false /*useToolsDir*/) + }) + + t.Run(baseImageInfo.Name+"ToolsDir", func(t *testing.T) { + testCustomizeImageVerityCosiExtractHelper(t, baseImageInfo, true /*useToolsDir*/) }) } } -func testCustomizeImageVerityCosiExtractHelper(t *testing.T, testName string, baseImageInfo testBaseImageInfo) { +func testCustomizeImageVerityCosiExtractHelper(t *testing.T, baseImageInfo testBaseImageInfo, useToolsDir bool) { baseImage := checkSkipForCustomizeImage(t, baseImageInfo) - testTempDir := filepath.Join(tmpDir, testName) + toolsDir := "" + if useToolsDir { + toolsDir = testutils.GetDownloadedToolsDir(t, testutilsDir, baseImageInfo.Distro, baseImageInfo.Version) + } + + testTempDir := filepath.Join(tmpDir, "TestCustomizeImageVerityCosiShrinkExtract"+baseImageInfo.Name) + if useToolsDir { + testTempDir += "ToolsDir" + } defer os.RemoveAll(testTempDir) buildDir := filepath.Join(testTempDir, "build") outImageFilePath := filepath.Join(testTempDir, "image.cosi") - configFile := filepath.Join(testDir, "verity-partition-labels.yaml") + configFile := filepath.Join(testDir, rootVerityPartLabelsConfigFile(t, baseImageInfo, useToolsDir)) espPartitionNum := 1 bootPartitionNum := 2 @@ -137,9 +179,16 @@ func testCustomizeImageVerityCosiExtractHelper(t *testing.T, testName string, ba varPartitionNum := 5 // Customize image, shrink partitions, and split the partitions into individual files. - err := basicCustomizeImageWithConfigFile(t.Context(), buildDir, configFile, baseImage, outImageFilePath, "cosi", - baseImageInfo.PreviewFeatures) - + err := CustomizeImageWithConfigFile(t.Context(), configFile, ImageCustomizerOptions{ + BuildDir: buildDir, + InputImageFile: baseImage, + OutputImageFile: outImageFilePath, + OutputImageFormat: "cosi", + UseBaseImageRpmRepos: true, + PreviewFeatures: baseImageInfo.PreviewFeatures, + SetFilesContext: *setfilesContext, + ToolsDir: toolsDir, + }) if !assert.NoError(t, err) { return } @@ -269,6 +318,25 @@ func testCustomizeImageVerityCosiExtractHelper(t *testing.T, testName string, ba "PARTLABEL=roothash", "root", "rd.info", baseImageInfo, "panic-on-corruption", false /*inlineVerity*/) } +func rootVerityPartLabelsConfigFile(t *testing.T, baseImageInfo testBaseImageInfo, useToolsDir bool) string { + toolsDirSuffix := "" + if useToolsDir { + toolsDirSuffix = "-toolsdir" + } + + switch baseImageInfo.Version { + case baseImageVersionAzl2, baseImageVersionAzl3: + return fmt.Sprintf("verity-root-part-labels-azl3%s.yaml", toolsDirSuffix) + + case baseImageVersionAzl4: + return fmt.Sprintf("verity-root-part-labels-azl4%s.yaml", toolsDirSuffix) + + default: + t.Fatalf("unsupported base image version for test: %s", baseImageInfo.Version) + return "" + } +} + func verifyVerityGrub(t *testing.T, bootPath string, dataDevice string, hashDevice string, dataId string, hashId string, verityType string, extraCommandLine string, baseImageInfo testBaseImageInfo, corruptionOption string, inlineVerity bool, @@ -548,7 +616,7 @@ func testCustomizeImageVerityReinitRootHelper(t *testing.T, testName string, bas defer os.RemoveAll(testTempDir) buildDir := filepath.Join(testTempDir, "build") - stage1ConfigFile := filepath.Join(testDir, "verity-config.yaml") + stage1ConfigFile := getRootVerityConfigFile(t, baseImageInfo, false /*useToolsDir*/) stage2aConfigFile := filepath.Join(testDir, "verity-reinit.yaml") stage2bConfigFile := filepath.Join(testDir, "verity-reinit-bootloader-reset.yaml") stage1FilePath := filepath.Join(testTempDir, "image1.raw") diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go index 4a16584a9..aebe6ce1e 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go @@ -56,8 +56,9 @@ type DistroHandler interface { // GetPackageInformation queries the installed-package database for packageName and returns its parsed information. GetPackageInformation(imageChroot *safechroot.Chroot, packageName string) (*PackageVersionInformation, error) - // Get all installed packages from the chroot - GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface) ([]OsPackage, error) + // Get all installed packages from the chroot. + // toolsChroot has the same semantics as in IsPackageInstalled. + GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface, toolsChroot *safechroot.Chroot) ([]OsPackage, error) // Detect the bootloader type installed in the image. toolsChroot has the same semantics as in IsPackageInstalled. DetectBootloaderType(imageChroot safechroot.ChrootInterface, toolsChroot *safechroot.Chroot) (BootloaderType, error) diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_acl.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_acl.go index fa48a942b..b5d324109 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_acl.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_acl.go @@ -136,15 +136,20 @@ func (d *aclDistroHandler) GetPackageInformation(imageChroot *safechroot.Chroot, return d.packageManager.getPackageInformation(imageChroot, packageName) } -func (d *aclDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface) ([]OsPackage, error) { +func (d *aclDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface, + toolsChroot *safechroot.Chroot, +) ([]OsPackage, error) { // This function is only used for metadata within a COSI file. // So, it doesn't matter too much if the package list can't be provided. // Check if the rpm command is available. - _, err := shell.LookPathChroot("rpm", imageChroot.ChrootDir()) - if err != nil { - // RPM command is not found. - return nil, nil + // (If toolsChroot is being used, then assume that the rpm command is available.) + if toolsChroot == nil { + _, err := shell.LookPathChroot("rpm", imageChroot.ChrootDir()) + if err != nil { + // RPM command is not found. + return nil, nil + } } // Check if the rpm database is available. @@ -160,7 +165,7 @@ func (d *aclDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.Chroo } // Get the list of packages. - packages, err := getAllPackagesFromChrootRpm(imageChroot) + packages, err := getAllPackagesFromChrootRpm(imageChroot, toolsChroot) if err != nil { return nil, err } diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux.go index 189093c19..986c71951 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux.go @@ -90,8 +90,10 @@ func (d *azureLinuxDistroHandler) GetPackageInformation(imageChroot *safechroot. return d.packageManager.getPackageInformation(imageChroot, packageName) } -func (d *azureLinuxDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface) ([]OsPackage, error) { - return getAllPackagesFromChrootRpm(imageChroot) +func (d *azureLinuxDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface, + toolsChroot *safechroot.Chroot, +) ([]OsPackage, error) { + return getAllPackagesFromChrootRpm(imageChroot, toolsChroot) } func (d *azureLinuxDistroHandler) DetectBootloaderType(imageChroot safechroot.ChrootInterface, diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux4.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux4.go index 9b1c170a0..9be640650 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux4.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux4.go @@ -108,8 +108,9 @@ func (d *azureLinux4DistroHandler) GetPackageInformation(imageChroot *safechroot } func (d *azureLinux4DistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface, + toolsChroot *safechroot.Chroot, ) ([]OsPackage, error) { - return getAllPackagesFromChrootRpm(imageChroot) + return getAllPackagesFromChrootRpm(imageChroot, toolsChroot) } func (d *azureLinux4DistroHandler) DetectBootloaderType(imageChroot safechroot.ChrootInterface, diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_fedora.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_fedora.go index 46cb528c8..761713e4a 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_fedora.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_fedora.go @@ -148,8 +148,10 @@ func (d *fedoraDistroHandler) GetPackageInformation(imageChroot *safechroot.Chro return d.packageManager.getPackageInformation(imageChroot, packageName) } -func (d *fedoraDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface) ([]OsPackage, error) { - return getAllPackagesFromChrootRpm(imageChroot) +func (d *fedoraDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface, + toolsChroot *safechroot.Chroot, +) ([]OsPackage, error) { + return getAllPackagesFromChrootRpm(imageChroot, toolsChroot) } func (d *fedoraDistroHandler) DetectBootloaderType(imageChroot safechroot.ChrootInterface, diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_ubuntu.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_ubuntu.go index 2612fb033..50ef6c009 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler_ubuntu.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler_ubuntu.go @@ -119,7 +119,9 @@ func (d *ubuntuDistroHandler) GetPackageInformation(imageChroot *safechroot.Chro return nil, fmt.Errorf("getting package information is not supported yet for Ubuntu images") } -func (d *ubuntuDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface) ([]OsPackage, error) { +func (d *ubuntuDistroHandler) GetAllPackagesFromChroot(imageChroot safechroot.ChrootInterface, + toolsChroot *safechroot.Chroot, +) ([]OsPackage, error) { return getAllPackagesFromChrootDeb(imageChroot) } diff --git a/toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go b/toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go index 184c83008..1fa6a568e 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go +++ b/toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go @@ -231,23 +231,23 @@ func customizeImageOptionsHelper(ctx context.Context, baseConfigPath string, con // Open the tools chroot once for the full customization run so it is available to OS-customization, // COSI metadata collection, and ISO/PXE conversion phases. - var toolsChroot *ToolsChroot + var toolsChrootOuter *ToolsChroot + var toolsChroot *safechroot.Chroot if rc.Options.ToolsDir != "" { if err := validateToolsDir(rc.Options.ToolsDir); err != nil { return err } - toolsChroot, err = initToolsChroot(ctx, rc.Options.ToolsDir) + + toolsChrootOuter, err = initToolsChroot(ctx, rc.Options.ToolsDir) if err != nil { return err } - defer toolsChroot.Close() - } - var toolsChrootInner *safechroot.Chroot - if toolsChroot != nil { - toolsChrootInner = toolsChroot.Chroot() + defer toolsChrootOuter.Close() + + toolsChroot = toolsChrootOuter.Chroot() } - im, err := customizeOSContents(ctx, rc, toolsChrootInner) + im, err := customizeOSContents(ctx, rc, toolsChroot) if err != nil { return err } @@ -256,7 +256,7 @@ func customizeImageOptionsHelper(ctx context.Context, baseConfigPath string, con outputDir := file.GetAbsPathWithBase(baseConfigPath, rc.OutputArtifacts.Path) err = outputArtifacts(ctx, rc.OutputArtifacts.Items, outputDir, rc.BuildDirAbs, - rc.RawImageFile, im.verityMetadata, rc.PreviewFeatures, im.distroHandler) + rc.RawImageFile, im.verityMetadata, im.distroHandler) if err != nil { return fmt.Errorf("%w:\n%w", ErrCustomizeOutputArtifacts, err) } @@ -270,13 +270,13 @@ func customizeImageOptionsHelper(ctx context.Context, baseConfigPath string, con } } - err = convertWriteableFormatToOutputImage(ctx, rc, im, inputIsoArtifacts, toolsChrootInner) + err = convertWriteableFormatToOutputImage(ctx, rc, im, inputIsoArtifacts, toolsChroot) if err != nil { return fmt.Errorf("%w:\n%w", ErrConvertToOutputFormat, err) } - if toolsChroot != nil { - err = toolsChroot.CleanClose() + if toolsChrootOuter != nil { + err = toolsChrootOuter.CleanClose() if err != nil { return err } @@ -533,7 +533,7 @@ func customizeOSContents(ctx context.Context, rc *ResolvedConfig, toolsChroot *s var cosiBootMetadata *CosiBootloader if rc.OutputImageFormat == imagecustomizerapi.ImageFormatTypeCosi || rc.OutputImageFormat == imagecustomizerapi.ImageFormatTypeBareMetalImage { osPackages, cosiBootMetadata, err = collectOSInfo(ctx, rc.BuildDirAbs, rc.RawImageFile, partitionsLayout, - im.distroHandler, nil) + im.distroHandler, toolsChroot) if err != nil { return im, fmt.Errorf("%w:\n%w", ErrCollectOSInfo, err) } @@ -765,6 +765,9 @@ func collectOSInfo(ctx context.Context, buildDir string, rawImageFile string, pa distroHandler DistroHandler, toolsChroot *safechroot.Chroot, ) ([]OsPackage, *CosiBootloader, error) { imageMountPoint := filepath.Join(buildDir, "imageroot") + if toolsChroot != nil { + imageMountPoint = filepath.Join(toolsChroot.ChrootDir(), toolsRootImageDir) + } imageConnection, _, err := reconnectToExistingImage(ctx, rawImageFile, buildDir, imageMountPoint, true, true, false, partitionsLayout, distroHandler) @@ -791,7 +794,7 @@ func collectOSInfoHelper(ctx context.Context, buildDir string, imageConnection * ) ([]OsPackage, *CosiBootloader, error) { _, span := otel.GetTracerProvider().Tracer(OtelTracerName).Start(ctx, "collect_os_info") defer span.End() - osPackages, err := getAllPackagesFromChroot(imageConnection, distroHandler) + osPackages, err := distroHandler.GetAllPackagesFromChroot(imageConnection.Chroot(), toolsChroot) if err != nil { return nil, nil, fmt.Errorf("%w:\n%w", ErrExtractPackages, err) } diff --git a/toolkit/tools/pkg/imagecustomizerlib/injectfilesoptions.go b/toolkit/tools/pkg/imagecustomizerlib/injectfilesoptions.go index cf2dc6f29..5ece3f26a 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/injectfilesoptions.go +++ b/toolkit/tools/pkg/imagecustomizerlib/injectfilesoptions.go @@ -11,6 +11,7 @@ type InjectFilesOptions struct { OutputImageFile string OutputImageFormat string CosiCompressionLevel *int + ToolsDir string } func (o *InjectFilesOptions) IsValid() error { diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-amd64-azl4-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-amd64-azl4-toolsdir.yaml new file mode 100644 index 000000000..14d08d755 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-amd64-azl4-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: artifacts-output-verity-amd64-azl4.yaml +- path: toolsdir-azl4.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-arm64-azl4-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-arm64-azl4-toolsdir.yaml new file mode 100644 index 000000000..a4081b12a --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-arm64-azl4-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: artifacts-output-verity-arm64-azl4.yaml +- path: toolsdir-azl4.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-azl3-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-azl3-toolsdir.yaml new file mode 100644 index 000000000..3f4f0f2f4 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/artifacts-output-verity-azl3-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: artifacts-output-verity-azl3.yaml +- path: toolsdir-azl3.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/toolsdir-azl3.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/toolsdir-azl3.yaml new file mode 100644 index 000000000..9e4761ac7 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/toolsdir-azl3.yaml @@ -0,0 +1,9 @@ +previewFeatures: +- tools-dir + +os: + packages: + remove: + # Remove tdnf and rpm command to ensure the tools directory is used instead. + - tdnf + - rpm diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/toolsdir-azl4.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/toolsdir-azl4.yaml new file mode 100644 index 000000000..037a626a3 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/toolsdir-azl4.yaml @@ -0,0 +1,19 @@ +previewFeatures: +- tools-dir + +os: + packages: + remove: + #- dnf5 + #- rpm + +scripts: + postCustomization: + - content: | + set -eux + + # Remove dnf and rpm command to ensure the tools directory is used instead. + # Ideally, 'os.packages.remove' would be used. But protected packages need to be disabled to remove dnf5. And rpm + # can't be removed until the 'postCustomization' stage, due to the workaround to remove grub2-efi-* in other + # config files. + dnf remove --assumeyes --setopt=protected_packages= dnf5 rpm diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl3-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl3-toolsdir.yaml new file mode 100644 index 000000000..4498c6fb9 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl3-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-azl3.yaml +- path: toolsdir-azl3.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl3.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl3.yaml new file mode 100644 index 000000000..b520c10f8 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl3.yaml @@ -0,0 +1,21 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-base.yaml + +os: + selinux: + mode: disabled + + packages: + install: + - openssh-server + - veritysetup + - vim + - device-mapper + + additionalFiles: + # Enable DHCP client on all of the physical NICs. + - source: files/89-ethernet.network + destination: /etc/systemd/network/89-ethernet.network diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl4-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl4-toolsdir.yaml new file mode 100644 index 000000000..709e0b96d --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl4-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-azl4.yaml +- path: toolsdir-azl4.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl4.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl4.yaml new file mode 100644 index 000000000..b520c10f8 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-azl4.yaml @@ -0,0 +1,21 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-base.yaml + +os: + selinux: + mode: disabled + + packages: + install: + - openssh-server + - veritysetup + - vim + - device-mapper + + additionalFiles: + # Enable DHCP client on all of the physical NICs. + - source: files/89-ethernet.network + destination: /etc/systemd/network/89-ethernet.network diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-config.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-base.yaml similarity index 82% rename from toolkit/tools/pkg/imagecustomizerlib/testdata/verity-config.yaml rename to toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-base.yaml index aac274ae1..1fb50d472 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-config.yaml +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-base.yaml @@ -53,29 +53,15 @@ os: bootloader: resetType: hard-reset - selinux: - mode: disabled - kernelCommandLine: extraCommandLine: - "rd.info" - packages: - install: - - openssh-server - - veritysetup - - vim - - device-mapper - additionalFiles: # Change the directory that the sshd-keygen service writes the SSH host keys to. - source: files/sshd-keygen.service destination: /usr/lib/systemd/system/sshd-keygen.service - # Enable DHCP client on all of the physical NICs. - - source: files/89-ethernet.network - destination: /etc/systemd/network/89-ethernet.network - services: enable: - sshd diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl3-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl3-toolsdir.yaml new file mode 100644 index 000000000..607ad1a91 --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl3-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-part-labels-azl3.yaml +- path: toolsdir-azl3.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl3.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl3.yaml new file mode 100644 index 000000000..b79c1db4f --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl3.yaml @@ -0,0 +1,21 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-part-labels-base.yaml + +os: + selinux: + mode: disabled + + packages: + install: + - openssh-server + - veritysetup + - vim + - device-mapper + + additionalFiles: + # Enable DHCP client on all of the physical NICs. + - source: files/89-ethernet.network + destination: /etc/systemd/network/89-ethernet.network diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl4-toolsdir.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl4-toolsdir.yaml new file mode 100644 index 000000000..da895a38e --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl4-toolsdir.yaml @@ -0,0 +1,6 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-part-labels-azl4.yaml +- path: toolsdir-azl4.yaml diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl4.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl4.yaml new file mode 100644 index 000000000..b79c1db4f --- /dev/null +++ b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-azl4.yaml @@ -0,0 +1,21 @@ +previewFeatures: +- base-configs + +baseConfigs: +- path: verity-root-part-labels-base.yaml + +os: + selinux: + mode: disabled + + packages: + install: + - openssh-server + - veritysetup + - vim + - device-mapper + + additionalFiles: + # Enable DHCP client on all of the physical NICs. + - source: files/89-ethernet.network + destination: /etc/systemd/network/89-ethernet.network diff --git a/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-partition-labels.yaml b/toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-base.yaml similarity index 100% rename from toolkit/tools/pkg/imagecustomizerlib/testdata/verity-partition-labels.yaml rename to toolkit/tools/pkg/imagecustomizerlib/testdata/verity-root-part-labels-base.yaml