Skip to content

Commit fdb780a

Browse files
committed
Comments addressed.
1 parent cea8a14 commit fdb780a

11 files changed

Lines changed: 134 additions & 190 deletions

File tree

docs/imagecustomizer/api/distribution-support.md

Lines changed: 67 additions & 67 deletions
Large diffs are not rendered by default.

toolkit/tools/imagecustomizerapi/previewfeaturetype.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ const (
4949

5050
// PreviewFeatureCreate enables the create command for building new images from scratch.
5151
PreviewFeatureCreate PreviewFeature = "create"
52+
53+
// PreviewFeatureAzureContainerLinux3 enables support for Azure Container Linux 3 images.
54+
PreviewFeatureAzureContainerLinux3 PreviewFeature = "azure-container-linux-3"
5255
)
5356

5457
func (pf PreviewFeature) IsValid() error {
@@ -57,7 +60,7 @@ func (pf PreviewFeature) IsValid() error {
5760
PreviewFeaturePackageSnapshotTime, PreviewFeatureKdumpBootFiles, PreviewFeatureFedora42,
5861
PreviewFeatureUbuntu2204, PreviewFeatureUbuntu2404, PreviewFeatureBaseConfigs,
5962
PreviewFeatureInputImageOci, PreviewFeatureOutputSelinuxPolicy,
60-
PreviewFeatureBtrfs, PreviewFeatureCreate:
63+
PreviewFeatureBtrfs, PreviewFeatureCreate, PreviewFeatureAzureContainerLinux3:
6164
return nil
6265
default:
6366
return fmt.Errorf("invalid preview feature: %s", pf)

toolkit/tools/pkg/imagecustomizerlib/customizeos.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,31 +55,30 @@ func doOsCustomizations(ctx context.Context, rc *ResolvedConfig, imageConnection
5555
return err
5656
}
5757

58-
// For non-GRUB distros, save UKI cmdline early so handleBootLoader/
58+
// For systemd-boot distros, save UKI cmdline early so handleBootLoader/
5959
// handleSELinux can modify it via uki-kernel-info.json.
6060
bootloaderType, err := distroHandler.DetectBootloaderType(imageChroot)
6161
if err != nil {
6262
return err
6363
}
6464

65-
if bootloaderType != BootloaderTypeGrub {
66-
err = extractAndSaveUkiCmdlineForCreateMode(rc.BuildDirAbs, imageChroot, distroHandler)
65+
// Only needed for systemd-boot distros: GRUB distros regenerate their
66+
// cmdline via grub-mkconfig in handleBootLoader, so the UKI cmdline does
67+
// not need to be saved to uki-kernel-info.json.
68+
if bootloaderType == BootloaderTypeSystemdBoot {
69+
err = extractAndSaveUkiCmdline(rc.BuildDirAbs, imageChroot, distroHandler.GetEspDir())
6770
if err != nil {
6871
return err
6972
}
7073
}
7174
}
7275
}
7376

74-
// If UKI mode is 'modify', extract cmdline early so BootCustomizer can modify it
77+
// If UKI mode is 'modify', extract cmdline early so BootCustomizer can modify it.
78+
// Unlike create mode, no bootloader-type gate is needed: any distro in modify mode
79+
// has UKIs with an embedded cmdline that must be read regardless of bootloader type.
7580
if rc.Uki != nil && rc.Uki.Mode == imagecustomizerapi.UkiModeModify {
76-
ukiBuildDir := filepath.Join(rc.BuildDirAbs, UkiBuildDir)
77-
err = os.MkdirAll(ukiBuildDir, os.ModePerm)
78-
if err != nil {
79-
return fmt.Errorf("failed to create UKI build directory:\n%w", err)
80-
}
81-
82-
err = extractAndSaveUkiCmdline(rc.BuildDirAbs, imageChroot, distroHandler)
81+
err = extractAndSaveUkiCmdline(rc.BuildDirAbs, imageChroot, distroHandler.GetEspDir())
8382
if err != nil {
8483
return fmt.Errorf("failed to extract UKI cmdline for modify mode:\n%w", err)
8584
}
@@ -221,7 +220,7 @@ func doOsCustomizations(ctx context.Context, rc *ResolvedConfig, imageConnection
221220
return err
222221
}
223222

224-
err = selinuxSetFiles(ctx, selinuxMode, imageChroot, distroHandler)
223+
err = selinuxSetFiles(ctx, selinuxMode, imageChroot, distroHandler.GetSELinuxConfigDir())
225224
if err != nil {
226225
return err
227226
}

toolkit/tools/pkg/imagecustomizerlib/customizeselinux.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ import (
1919
"golang.org/x/sys/unix"
2020
)
2121

22+
const (
23+
// selinuxConfigDirDefault is the path to the SELinux configuration directory for most distros.
24+
selinuxConfigDirDefault = "etc/selinux"
25+
)
26+
2227
var (
2328
// SELinux-related errors
2429
ErrSELinuxGetCurrentMode = NewImageCustomizerError("SELinux:GetCurrentMode", "failed to get current SELinux mode")
@@ -81,7 +86,7 @@ func handleSELinux(ctx context.Context, buildDir string, selinuxMode imagecustom
8186
}
8287
}
8388

84-
err = UpdateSELinuxModeInConfigFile(selinuxMode, imageChroot, distroHandler)
89+
err = UpdateSELinuxModeInConfigFile(selinuxMode, imageChroot, distroHandler.GetSELinuxConfigDir())
8590
if err != nil {
8691
return imagecustomizerapi.SELinuxModeDefault, err
8792
}
@@ -90,14 +95,13 @@ func handleSELinux(ctx context.Context, buildDir string, selinuxMode imagecustom
9095
}
9196

9297
func UpdateSELinuxModeInConfigFile(selinuxMode imagecustomizerapi.SELinuxMode, imageChroot safechroot.ChrootInterface,
93-
distroHandler DistroHandler,
98+
selinuxConfigDir string,
9499
) error {
95100
imagerSELinuxMode, err := selinuxModeToImager(selinuxMode)
96101
if err != nil {
97102
return err
98103
}
99104

100-
selinuxConfigDir := distroHandler.GetSELinuxConfigDir()
101105
selinuxConfigFile := filepath.Join(selinuxConfigDir, "config")
102106
selinuxConfigFileFullPath := filepath.Join(imageChroot.RootDir(), selinuxConfigFile)
103107
selinuxConfigFileExists, err := file.PathExists(selinuxConfigFileFullPath)
@@ -125,7 +129,7 @@ func UpdateSELinuxModeInConfigFile(selinuxMode imagecustomizerapi.SELinuxMode, i
125129
}
126130

127131
func selinuxSetFiles(ctx context.Context, selinuxMode imagecustomizerapi.SELinuxMode, imageChroot *safechroot.Chroot,
128-
distroHandler DistroHandler,
132+
selinuxConfigDir string,
129133
) error {
130134
if selinuxMode == imagecustomizerapi.SELinuxModeDisabled {
131135
// SELinux is disabled in the kernel command line.
@@ -149,7 +153,7 @@ func selinuxSetFiles(ctx context.Context, selinuxMode imagecustomizerapi.SELinux
149153
mountPointToFsTypeMap[mountPoint.GetTarget()] = mountPoint.GetFSType()
150154
}
151155

152-
selinuxConfigFile := filepath.Join(distroHandler.GetSELinuxConfigDir(), "config")
156+
selinuxConfigFile := filepath.Join(selinuxConfigDir, "config")
153157

154158
// Set the SELinux config file and relabel all the files.
155159
err := installutils.SELinuxRelabelFiles(imageChroot, mountPointToFsTypeMap, false, selinuxConfigFile)

toolkit/tools/pkg/imagecustomizerlib/customizeuki.go

Lines changed: 13 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -172,69 +172,25 @@ func validateUkiMode(imageConnection *imageconnection.ImageConnection, uki *imag
172172
return nil
173173
}
174174

175-
// extractAndSaveUkiCmdline extracts the kernel cmdline from existing UKI addons and saves them to uki-kernel-info.json.
176-
func extractAndSaveUkiCmdline(buildDir string, imageChroot *safechroot.Chroot, distroHandler DistroHandler) error {
177-
espDir := filepath.Join(imageChroot.RootDir(), distroHandler.GetEspDir())
178-
ukiFiles, err := getUkiFiles(espDir)
179-
if err != nil {
180-
return fmt.Errorf("failed to get UKI files:\n%w", err)
181-
}
182-
183-
if len(ukiFiles) == 0 {
184-
return fmt.Errorf("no UKI files found for cmdline extraction")
185-
}
186-
187-
// Extract cmdline from each UKI addon and create per-kernel entries
188-
kernelInfo := make(map[string]UkiKernelInfo)
189-
for _, ukiFile := range ukiFiles {
190-
ukiFileName := filepath.Base(ukiFile)
191-
kernelName := strings.TrimSuffix(ukiFileName, ".efi")
192-
addonDirPath := filepath.Join(filepath.Dir(ukiFile), fmt.Sprintf("%s.extra.d", ukiFileName))
193-
addonFilePath := filepath.Join(addonDirPath, fmt.Sprintf("%s.addon.efi", kernelName))
194-
195-
if _, err := os.Stat(addonFilePath); os.IsNotExist(err) {
196-
return fmt.Errorf("addon file does not exist: %s", addonFilePath)
197-
}
198-
199-
cmdline, err := extractCmdlineFromSinglePE(addonFilePath, buildDir)
200-
if err != nil {
201-
return fmt.Errorf("failed to extract cmdline from addon (%s):\n%w", addonFilePath, err)
202-
}
203-
204-
// In modify mode, we don't have initramfs info, so leave it empty
205-
kernelInfo[kernelName] = UkiKernelInfo{
206-
Cmdline: cmdline,
207-
Initramfs: "", // Empty for modify mode
208-
}
209-
210-
logger.Log.Debugf("Extracted cmdline from UKI (%s): %s", ukiFileName, cmdline)
211-
}
212-
213-
// Save to uki-kernel-info.json for consistency with create mode
214-
ukiKernelInfoPath := filepath.Join(buildDir, UkiBuildDir, UkiKernelInfoJson)
215-
err = writeUkiKernelInfoFile(ukiKernelInfoPath, kernelInfo)
216-
if err != nil {
217-
return fmt.Errorf("failed to write UKI kernel info file:\n%w", err)
218-
}
219-
220-
logger.Log.Debugf("Extracted and saved UKI cmdlines to: %s", ukiKernelInfoPath)
221-
return nil
222-
}
223-
224-
// extractAndSaveUkiCmdlineForCreateMode extracts kernel cmdline from existing
225-
// UKIs and their addons, saving to uki-kernel-info.json before handleBootLoader/
226-
// handleSELinux run. Needed for non-GRUB distros in UKI create mode.
227-
func extractAndSaveUkiCmdlineForCreateMode(buildDir string, imageChroot *safechroot.Chroot, distroHandler DistroHandler) error {
175+
// extractAndSaveUkiCmdline extracts the kernel cmdline from existing UKIs and their
176+
// addons (main UKI + addons in lexicographic order, mirroring systemd-boot behavior),
177+
// then saves the result to uki-kernel-info.json. Used in both modify and create modes
178+
// before handleBootLoader/handleSELinux run.
179+
func extractAndSaveUkiCmdline(buildDir string, imageChroot *safechroot.Chroot, espDir string) error {
228180
ukiBuildDir := filepath.Join(buildDir, UkiBuildDir)
229181
err := os.MkdirAll(ukiBuildDir, os.ModePerm)
230182
if err != nil {
231183
return fmt.Errorf("failed to create UKI build directory:\n%w", err)
232184
}
233185

234-
espDir := filepath.Join(imageChroot.RootDir(), distroHandler.GetEspDir())
235-
kernelToArgs, err := extractKernelCmdlineFromUkiEfis(espDir, buildDir)
186+
espAbsDir := filepath.Join(imageChroot.RootDir(), espDir)
187+
kernelToArgs, err := extractKernelCmdlineFromUkiEfis(espAbsDir, buildDir)
236188
if err != nil {
237-
return fmt.Errorf("failed to extract UKI cmdline for create mode:\n%w", err)
189+
return fmt.Errorf("failed to extract UKI cmdline:\n%w", err)
190+
}
191+
192+
if len(kernelToArgs) == 0 {
193+
return fmt.Errorf("no UKI files found for cmdline extraction")
238194
}
239195

240196
kernelInfo := make(map[string]UkiKernelInfo)
@@ -247,10 +203,9 @@ func extractAndSaveUkiCmdlineForCreateMode(buildDir string, imageChroot *safechr
247203
ukiKernelInfoPath := filepath.Join(ukiBuildDir, UkiKernelInfoJson)
248204
err = writeUkiKernelInfoFile(ukiKernelInfoPath, kernelInfo)
249205
if err != nil {
250-
return fmt.Errorf("failed to write early UKI kernel info for create mode:\n%w", err)
206+
return fmt.Errorf("failed to write UKI kernel info file:\n%w", err)
251207
}
252208

253-
logger.Log.Infof("Extracted and saved UKI cmdline early for create mode (non-GRUB distro)")
254209
return nil
255210
}
256211

@@ -362,7 +317,6 @@ func prepareUkiHelper(ctx context.Context, buildDir string, uki *imagecustomizer
362317
var cmdline string
363318
if existErr == nil {
364319
if existingInfo, ok := existingKernelInfo[kernel]; ok {
365-
// Use cmdline from early extraction (potentially modified by handleBootLoader/handleSELinux).
366320
cmdline = existingInfo.Cmdline
367321
} else {
368322
var exists bool

toolkit/tools/pkg/imagecustomizerlib/distrohandler_acl.go

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212
"os/exec"
1313
"path/filepath"
14+
"slices"
1415

1516
"github.com/sirupsen/logrus"
1617

@@ -39,27 +40,9 @@ func (d *aclDistroHandler) GetTargetOs() targetos.TargetOs {
3940
}
4041

4142
func (d *aclDistroHandler) ValidateConfig(rc *ResolvedConfig) error {
42-
// ACL supports mutable partition modifications and package installation
43-
// (when reinitializeVerity: all is used to make /usr writable).
44-
//
45-
// Supported operations:
46-
// - os.additionalFiles
47-
// - os.additionalDirs
48-
// - os.services (enable/disable)
49-
// - os.hostname, os.users, os.groups
50-
// - os.modules (writes to /etc/modprobe.d/, /etc/modules-load.d/)
51-
// - os.uki (passthrough and create modes)
52-
// - os.packages.install (via host tdnf with --installroot)
53-
// - os.selinux mode changes (via UKI cmdline)
54-
// - os.kernelCommandLine (via UKI addon)
55-
// - scripts.postCustomization, scripts.finalizeCustomization
56-
//
57-
// Not yet supported:
58-
// - os.packages.remove, os.packages.update, os.packages.updateExistingPackages
59-
// - os.uki mode: modify (requires addon naming alignment)
60-
// - os.overlays
61-
// - storage repartitioning
62-
// - bootloader hard-reset (not applicable — ACL uses systemd-boot)
43+
if !slices.Contains(rc.PreviewFeatures, imagecustomizerapi.PreviewFeatureAzureContainerLinux3) {
44+
return ErrAzureContainerLinux3PreviewFeatureRequired
45+
}
6346

6447
if rc.Storage.CustomizePartitions() {
6548
return fmt.Errorf("storage repartitioning is not yet supported for ACL")

toolkit/tools/pkg/imagecustomizerlib/distrohandler_azurelinux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func (d *azureLinuxDistroHandler) FindBootPartitionUuidFromEsp(espMountDir strin
119119
}
120120

121121
func (d *azureLinuxDistroHandler) GetSELinuxConfigDir() string {
122-
return "etc/selinux"
122+
return selinuxConfigDirDefault
123123
}
124124

125125
func (d *azureLinuxDistroHandler) SELinuxSupported() bool {

toolkit/tools/pkg/imagecustomizerlib/distrohandler_fedora.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func (d *fedoraDistroHandler) FindBootPartitionUuidFromEsp(espMountDir string) (
9898
}
9999

100100
func (d *fedoraDistroHandler) GetSELinuxConfigDir() string {
101-
return "etc/selinux"
101+
return selinuxConfigDirDefault
102102
}
103103

104104
func (d *fedoraDistroHandler) SELinuxSupported() bool {

toolkit/tools/pkg/imagecustomizerlib/distrohandler_ubuntu.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func (d *ubuntuDistroHandler) FindBootPartitionUuidFromEsp(espMountDir string) (
119119
}
120120

121121
func (d *ubuntuDistroHandler) GetSELinuxConfigDir() string {
122-
return "etc/selinux"
122+
return selinuxConfigDirDefault
123123
}
124124

125125
func (d *ubuntuDistroHandler) SELinuxSupported() bool {

toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,27 @@ import (
2626

2727
var (
2828
// Validation errors
29-
ErrInvalidOutputFormat = NewImageCustomizerError("Validation:InvalidOutputFormat", "invalid output image format")
30-
ErrCannotGenerateOutputFormat = NewImageCustomizerError("Validation:CannotGenerateOutputFormat", "cannot generate output format from input format")
31-
ErrCannotValidateTargetOS = NewImageCustomizerError("Validation:CannotValidateTargetOS", "cannot validate target OS of the base image")
32-
ErrCannotCustomizePartitionsOnIso = NewImageCustomizerError("Validation:CannotCustomizePartitionsOnIso", "cannot customize partitions when input is ISO")
33-
ErrInvalidBaseConfigs = NewImageCustomizerError("Validation:InvalidBaseConfigs", "base configs contain invalid image config")
34-
ErrInvalidImageConfig = NewImageCustomizerError("Validation:InvalidImageConfig", "invalid image config")
35-
ErrInvalidParameters = NewImageCustomizerError("Validation:InvalidParameters", "invalid parameters")
36-
ErrVerityValidation = NewImageCustomizerError("Validation:VerityValidation", "verity validation failed")
37-
ErrUnsupportedQemuImageFormat = NewImageCustomizerError("Validation:UnsupportedQemuImageFormat", "unsupported qemu-img format")
38-
ErrToolNotRunAsRoot = NewImageCustomizerError("Validation:ToolNotRunAsRoot", "tool should be run as root (e.g. by using sudo)")
39-
ErrPackageSnapshotPreviewRequired = NewImageCustomizerError("Validation:PackageSnapshotPreviewRequired", fmt.Sprintf("preview feature '%s' required to specify package snapshot time", imagecustomizerapi.PreviewFeaturePackageSnapshotTime))
40-
ErrVerityPreviewFeatureRequired = NewImageCustomizerError("Validation:VerityPreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize verity enabled base image", imagecustomizerapi.PreviewFeatureReinitializeVerity))
41-
ErrFedora42PreviewFeatureRequired = NewImageCustomizerError("Validation:Fedora42PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Fedora 42 base image", imagecustomizerapi.PreviewFeatureFedora42))
42-
ErrUbuntu2204PreviewFeatureRequired = NewImageCustomizerError("Validation:Ubuntu2204PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Ubuntu 22.04 base image", imagecustomizerapi.PreviewFeatureUbuntu2204))
43-
ErrUbuntu2404PreviewFeatureRequired = NewImageCustomizerError("Validation:Ubuntu2404PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Ubuntu 24.04 base image", imagecustomizerapi.PreviewFeatureUbuntu2404))
44-
ErrUbuntuBootLoaderHardReset = NewImageCustomizerError("Validation:UbuntuBootLoaderHardReset", "bootloader hard-reset is not supported for Ubuntu images")
45-
ErrUnsupportedUbuntuFeature = NewImageCustomizerError("Validation:UnsupportedUbuntuFeature", "unsupported feature for Ubuntu images")
46-
ErrInputImageOciPreviewRequired = NewImageCustomizerError("Validation:InputImageOciPreviewRequired", fmt.Sprintf("preview feature '%s' required to specify OCI input image", imagecustomizerapi.PreviewFeatureInputImageOci))
47-
ErrConvertUnsupportedInputFormat = NewImageCustomizerError("Validation:ConvertUnsupportedInputFormat", "input image format is not supported")
48-
ErrConvertBuildDirRequired = NewImageCustomizerError("Validation:ConvertBuildDirRequired", "build directory is required for cosi and baremetal-image output formats")
29+
ErrInvalidOutputFormat = NewImageCustomizerError("Validation:InvalidOutputFormat", "invalid output image format")
30+
ErrCannotGenerateOutputFormat = NewImageCustomizerError("Validation:CannotGenerateOutputFormat", "cannot generate output format from input format")
31+
ErrCannotValidateTargetOS = NewImageCustomizerError("Validation:CannotValidateTargetOS", "cannot validate target OS of the base image")
32+
ErrCannotCustomizePartitionsOnIso = NewImageCustomizerError("Validation:CannotCustomizePartitionsOnIso", "cannot customize partitions when input is ISO")
33+
ErrInvalidBaseConfigs = NewImageCustomizerError("Validation:InvalidBaseConfigs", "base configs contain invalid image config")
34+
ErrInvalidImageConfig = NewImageCustomizerError("Validation:InvalidImageConfig", "invalid image config")
35+
ErrInvalidParameters = NewImageCustomizerError("Validation:InvalidParameters", "invalid parameters")
36+
ErrVerityValidation = NewImageCustomizerError("Validation:VerityValidation", "verity validation failed")
37+
ErrUnsupportedQemuImageFormat = NewImageCustomizerError("Validation:UnsupportedQemuImageFormat", "unsupported qemu-img format")
38+
ErrToolNotRunAsRoot = NewImageCustomizerError("Validation:ToolNotRunAsRoot", "tool should be run as root (e.g. by using sudo)")
39+
ErrPackageSnapshotPreviewRequired = NewImageCustomizerError("Validation:PackageSnapshotPreviewRequired", fmt.Sprintf("preview feature '%s' required to specify package snapshot time", imagecustomizerapi.PreviewFeaturePackageSnapshotTime))
40+
ErrVerityPreviewFeatureRequired = NewImageCustomizerError("Validation:VerityPreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize verity enabled base image", imagecustomizerapi.PreviewFeatureReinitializeVerity))
41+
ErrFedora42PreviewFeatureRequired = NewImageCustomizerError("Validation:Fedora42PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Fedora 42 base image", imagecustomizerapi.PreviewFeatureFedora42))
42+
ErrUbuntu2204PreviewFeatureRequired = NewImageCustomizerError("Validation:Ubuntu2204PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Ubuntu 22.04 base image", imagecustomizerapi.PreviewFeatureUbuntu2204))
43+
ErrUbuntu2404PreviewFeatureRequired = NewImageCustomizerError("Validation:Ubuntu2404PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Ubuntu 24.04 base image", imagecustomizerapi.PreviewFeatureUbuntu2404))
44+
ErrAzureContainerLinux3PreviewFeatureRequired = NewImageCustomizerError("Validation:AzureContainerLinux3PreviewFeatureRequired", fmt.Sprintf("preview feature '%s' required to customize Azure Container Linux 3 base image", imagecustomizerapi.PreviewFeatureAzureContainerLinux3))
45+
ErrUbuntuBootLoaderHardReset = NewImageCustomizerError("Validation:UbuntuBootLoaderHardReset", "bootloader hard-reset is not supported for Ubuntu images")
46+
ErrUnsupportedUbuntuFeature = NewImageCustomizerError("Validation:UnsupportedUbuntuFeature", "unsupported feature for Ubuntu images")
47+
ErrInputImageOciPreviewRequired = NewImageCustomizerError("Validation:InputImageOciPreviewRequired", fmt.Sprintf("preview feature '%s' required to specify OCI input image", imagecustomizerapi.PreviewFeatureInputImageOci))
48+
ErrConvertUnsupportedInputFormat = NewImageCustomizerError("Validation:ConvertUnsupportedInputFormat", "input image format is not supported")
49+
ErrConvertBuildDirRequired = NewImageCustomizerError("Validation:ConvertBuildDirRequired", "build directory is required for cosi and baremetal-image output formats")
4950

5051
// Generic customization errors
5152
ErrGetAbsoluteConfigPath = NewImageCustomizerError("Customizer:GetAbsoluteConfigPath", "failed to get absolute path of config file directory")

0 commit comments

Comments
 (0)