Skip to content

Commit 2b69030

Browse files
authored
Improve error messages. (#409)
Improve the error message when user passes a nonsense file as the base image. Previously, the error was "failed to find rootfs partition". Now, it is "image does not contain a partition table". Also, add some high-level errors for these operations: - Partition customization - Reset partition UUIDs - OS customization - Verity provisioning - Creating UKIs - Outputting artifacts These extra errors will make it clearer where in the customization process the error occurred.
1 parent 7c486dc commit 2b69030

File tree

5 files changed

+70
-11
lines changed

5 files changed

+70
-11
lines changed

toolkit/tools/pkg/imagecustomizerlib/customizepackages_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ func TestCustomizeImagePackagesDiskSpace(t *testing.T) {
228228
// Customize image.
229229
err := CustomizeImageWithConfigFile(t.Context(), buildDir, configFile, baseImage, nil, outImageFilePath, "raw",
230230
true /*useBaseImageRpmRepos*/, "" /*packageSnapshotTime*/)
231-
assert.ErrorContains(t, err, "failed to customize raw image")
231+
assert.ErrorContains(t, err, "failed to customize OS")
232232
assert.ErrorContains(t, err, "failed to install packages (packages=[gcc])")
233233
}
234234

toolkit/tools/pkg/imagecustomizerlib/customizepartitions.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package imagecustomizerlib
55

66
import (
77
"context"
8+
"fmt"
89
"os"
910
"path/filepath"
1011

@@ -13,6 +14,11 @@ import (
1314
"go.opentelemetry.io/otel"
1415
)
1516

17+
var (
18+
ErrPartitionsCustomize = NewImageCustomizerError("Partitions:Customize", "failed to customize partitions")
19+
ErrPartitionsResetUuids = NewImageCustomizerError("Partitions:ResetUuids", "failed to reset partition UUIDs")
20+
)
21+
1622
func customizePartitions(ctx context.Context, buildDir string, baseConfigPath string, config *imagecustomizerapi.Config,
1723
buildImageFile string,
1824
) (bool, string, map[string]string, error) {
@@ -31,15 +37,15 @@ func customizePartitions(ctx context.Context, buildDir string, baseConfigPath st
3137
buildImageFile, newBuildImageFile)
3238
if err != nil {
3339
os.Remove(newBuildImageFile)
34-
return false, "", nil, err
40+
return false, "", nil, fmt.Errorf("%w:\n%w", ErrPartitionsCustomize, err)
3541
}
3642

3743
return true, newBuildImageFile, partIdToPartUuid, nil
3844

3945
case config.Storage.ResetPartitionsUuidsType != imagecustomizerapi.ResetPartitionsUuidsTypeDefault:
4046
err := resetPartitionsUuids(ctx, buildImageFile, buildDir)
4147
if err != nil {
42-
return false, "", nil, err
48+
return false, "", nil, fmt.Errorf("%w:\n%w", ErrPartitionsResetUuids, err)
4349
}
4450

4551
return true, buildImageFile, nil, nil

toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,11 @@ var (
6565
ErrInvalidPackageSnapshotTime = NewImageCustomizerError("Validation:InvalidPackageSnapshotTime", "invalid command-line option '--package-snapshot-time'")
6666

6767
// Generic customization errors
68-
ErrGetAbsoluteConfigPath = NewImageCustomizerError("Customizer:GetAbsoluteConfigPath", "failed to get absolute path of config file directory")
69-
ErrCustomizeRawImage = NewImageCustomizerError("Customizer:CustomizeRawImage", "failed to customize raw image")
68+
ErrGetAbsoluteConfigPath = NewImageCustomizerError("Customizer:GetAbsoluteConfigPath", "failed to get absolute path of config file directory")
69+
ErrCustomizeOs = NewImageCustomizerError("Customizer:CustomizeOs", "failed to customize OS")
70+
ErrCustomizeProvisionVerity = NewImageCustomizerError("Customizer:ProvisionVerity", "failed to provision verity")
71+
ErrCustomizeCreateUkis = NewImageCustomizerError("Customizer:CreateUkis", "failed to create UKIs")
72+
ErrCustomizeOutputArtifacts = NewImageCustomizerError("Customizer:OutputArtifacts", "failed to output artifacts")
7073

7174
// Image conversion errors
7275
ErrConvertInputImage = NewImageCustomizerError("ImageConversion:ConvertInput", "failed to convert input image to a raw image")
@@ -398,7 +401,7 @@ func CustomizeImage(ctx context.Context, buildDir string, baseConfigPath string,
398401

399402
err = customizeOSContents(ctx, imageCustomizerParameters)
400403
if err != nil {
401-
return fmt.Errorf("%w:\n%w", ErrCustomizeRawImage, err)
404+
return err
402405
}
403406

404407
if config.Output.Artifacts != nil {
@@ -407,7 +410,7 @@ func CustomizeImage(ctx context.Context, buildDir string, baseConfigPath string,
407410
err = outputArtifacts(ctx, config.Output.Artifacts.Items, outputDir, imageCustomizerParameters.buildDirAbs,
408411
imageCustomizerParameters.rawImageFile, imageCustomizerParameters.verityMetadata)
409412
if err != nil {
410-
return err
413+
return fmt.Errorf("%w:\n%w", ErrCustomizeOutputArtifacts, err)
411414
}
412415
}
413416

@@ -605,7 +608,7 @@ func customizeOSContents(ctx context.Context, ic *ImageCustomizerParameters) err
605608
ic.buildDirAbs, ic.configPath, ic.config, ic.rawImageFile, ic.rpmsSources, ic.useBaseImageRpmRepos,
606609
partitionsCustomized, ic.imageUuidStr, ic.packageSnapshotTime, ic.outputImageFormat)
607610
if err != nil {
608-
return err
611+
return fmt.Errorf("%w:\n%w", ErrCustomizeOs, err)
609612
}
610613

611614
if len(baseImageVerityMetadata) > 0 {
@@ -634,7 +637,7 @@ func customizeOSContents(ctx context.Context, ic *ImageCustomizerParameters) err
634637
verityMetadata, err := customizeVerityImageHelper(ctx, ic.buildDirAbs, ic.config, ic.rawImageFile, partIdToPartUuid,
635638
shrinkPartitions, ic.baseImageVerityMetadata, readonlyPartUuids)
636639
if err != nil {
637-
return err
640+
return fmt.Errorf("%w:\n%w", ErrCustomizeProvisionVerity, err)
638641
}
639642

640643
ic.verityMetadata = verityMetadata
@@ -643,7 +646,7 @@ func customizeOSContents(ctx context.Context, ic *ImageCustomizerParameters) err
643646
if ic.config.OS.Uki != nil {
644647
err = createUki(ctx, ic.config.OS.Uki, ic.buildDirAbs, ic.rawImageFile)
645648
if err != nil {
646-
return err
649+
return fmt.Errorf("%w:\n%w", ErrCustomizeCreateUkis, err)
647650
}
648651
}
649652

toolkit/tools/pkg/imagecustomizerlib/imagecustomizer_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,47 @@ func testConvertImageToRawSuccess(t *testing.T, testName string, qemuImgArgs []s
10491049
assert.Equal(t, int64(diskSize), testRawFileStat.Size())
10501050
}
10511051

1052+
func TestCustomizeImageBaseImageMissing(t *testing.T) {
1053+
testutils.CheckSkipForCustomizeImageRequirements(t)
1054+
1055+
qemuimgExists, err := file.CommandExists("qemu-img")
1056+
assert.NoError(t, err)
1057+
if !qemuimgExists {
1058+
t.Skip("The 'qemu-img' command is not available")
1059+
}
1060+
1061+
testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageBaseImageMissing")
1062+
buildDir := filepath.Join(testTmpDir, "build")
1063+
configFile := filepath.Join(testDir, "partitions-config.yaml")
1064+
baseImage := filepath.Join(testTmpDir, "missing.qcow2")
1065+
outImageFilePath := filepath.Join(testTmpDir, "image.raw")
1066+
1067+
err = CustomizeImageWithConfigFile(t.Context(), buildDir, configFile, baseImage, nil, outImageFilePath,
1068+
"raw", false /*useBaseImageRpmRepos*/, "" /*packageSnapshotTime*/)
1069+
assert.ErrorContains(t, err, "no such file or directory")
1070+
}
1071+
1072+
func TestCustomizeImageBaseImageInvalid(t *testing.T) {
1073+
testutils.CheckSkipForCustomizeImageRequirements(t)
1074+
1075+
qemuimgExists, err := file.CommandExists("qemu-img")
1076+
assert.NoError(t, err)
1077+
if !qemuimgExists {
1078+
t.Skip("The 'qemu-img' command is not available")
1079+
}
1080+
1081+
testTmpDir := filepath.Join(tmpDir, "TestCustomizeImageBaseImageInvalid")
1082+
buildDir := filepath.Join(testTmpDir, "build")
1083+
configFile := filepath.Join(testDir, "partitions-config.yaml")
1084+
baseImage := configFile
1085+
outImageFilePath := filepath.Join(testTmpDir, "image.raw")
1086+
1087+
err = CustomizeImageWithConfigFile(t.Context(), buildDir, configFile, baseImage, nil, outImageFilePath,
1088+
"raw", false /*useBaseImageRpmRepos*/, "" /*packageSnapshotTime*/)
1089+
assert.ErrorContains(t, err, "failed to open image file:")
1090+
assert.ErrorContains(t, err, "image does not contain a partition table")
1091+
}
1092+
10521093
func checkFileType(t *testing.T, filePath string, expectedFileType string) {
10531094
fileType, err := testutils.GetImageFileType(filePath)
10541095
assert.NoError(t, err)

toolkit/tools/pkg/imagecustomizerlib/imageutils.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func connectToExistingImage(ctx context.Context, imageFilePath string, buildDir
3434
imageFilePath, buildDir, chrootDirName, includeDefaultMounts, readonly, readOnlyVerity, ignoreOverlays)
3535
if err != nil {
3636
imageConnection.Close()
37-
return nil, nil, nil, nil, err
37+
return nil, nil, nil, nil, fmt.Errorf("failed to open image file:\n%w", err)
3838
}
3939

4040
return imageConnection, partUuidToMountPath, verityMetadata, readonlyPartUuids, nil
@@ -50,6 +50,15 @@ func connectToExistingImageHelper(imageConnection *imageconnection.ImageConnecti
5050
return nil, nil, nil, err
5151
}
5252

53+
partitionTable, err := diskutils.ReadDiskPartitionTable(imageConnection.Loopback().DevicePath())
54+
if err != nil {
55+
return nil, nil, nil, fmt.Errorf("failed to read image's partition table:\n%w", err)
56+
}
57+
58+
if partitionTable == nil {
59+
return nil, nil, nil, fmt.Errorf("image does not contain a partition table")
60+
}
61+
5362
partitions, err := diskutils.GetDiskPartitions(imageConnection.Loopback().DevicePath())
5463
if err != nil {
5564
return nil, nil, nil, err

0 commit comments

Comments
 (0)