From 008f7fdf87ac51b27c780f33545f0921861a56a2 Mon Sep 17 00:00:00 2001 From: Himaja Kesari Date: Wed, 17 Sep 2025 12:57:33 -0700 Subject: [PATCH 1/6] Add distribution validation with structured error handling - Add Distribution type with validation logic - Move validation logic to separate distribution.go file - Add proper error messages for invalid distribution/version combinations --- toolkit/tools/imagecreator/distribution.go | 54 +++++++++++++++++++ toolkit/tools/imagecreator/main.go | 11 ++-- .../tools/imagecustomizerapi/distribution.go | 17 ++++++ .../pkg/imagecustomizerlib/distrohandler.go | 23 +------- 4 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 toolkit/tools/imagecreator/distribution.go create mode 100644 toolkit/tools/imagecustomizerapi/distribution.go diff --git a/toolkit/tools/imagecreator/distribution.go b/toolkit/tools/imagecreator/distribution.go new file mode 100644 index 000000000..9e1a9c624 --- /dev/null +++ b/toolkit/tools/imagecreator/distribution.go @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package main + +import ( + "fmt" + "strings" + + "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" +) + +// distribution represents a supported Linux distribution and version combination +type distribution struct { + name string + version string +} + +// GetDistribution validates and returns a distribution from the CLI args +func (c *ImageCreatorCmd) getDistribution() (*distribution, error) { + dist := &distribution{ + name: c.Distro, + version: c.DistroVersion, + } + if err := dist.validate(); err != nil { + return nil, err + } + return dist, nil +} + +// Validate ensures the distribution and version combination is supported +func (d *distribution) validate() error { + // Get supported versions for this distribution + + supportedDistros := imagecustomizerapi.GetSupportedDistros() + validVersions, exists := supportedDistros[d.name] + if !exists { + distros := make([]string, 0, len(supportedDistros)) + for d := range supportedDistros { + distros = append(distros, d) + } + return fmt.Errorf("unsupported distribution %q. Supported distributions are: %s", + d.name, strings.Join(distros, ", ")) + } + + // Validate version + for _, v := range validVersions { + if v == d.version { + return nil + } + } + return fmt.Errorf("unsupported version %q for distribution %q. Supported versions: %s", + d.version, d.name, strings.Join(validVersions, ", ")) +} diff --git a/toolkit/tools/imagecreator/main.go b/toolkit/tools/imagecreator/main.go index df9cab88b..27c6d31c7 100644 --- a/toolkit/tools/imagecreator/main.go +++ b/toolkit/tools/imagecreator/main.go @@ -28,7 +28,7 @@ type ImageCreatorCmd struct { OutputImageFile string `name:"output-image-file" help:"Path to write the customized image to."` OutputImageFormat string `name:"output-image-format" placeholder:"(vhd|vhd-fixed|vhdx|qcow2|raw)" help:"Format of output image." enum:"${imageformat}" default:""` Distro string `name:"distro" help:"Target distribution for the image." enum:"azurelinux,fedora" default:"azurelinux"` - DistroVersion string `name:"distro-version" help:"Target distribution version (e.g., 3.0 for Azure Linux, 42 for Fedora)." default:""` + DistroVersion string `name:"distro-version" help:"Target distribution version (e.g., 3.0 for Azure Linux, 42 for Fedora)." default:"3.0"` exekong.LogFlags PackageSnapshotTime string `name:"package-snapshot-time" help:"Only packages published before this snapshot time will be available during customization. Supports 'YYYY-MM-DD' or full RFC3339 timestamp (e.g., 2024-05-20T23:59:59Z)."` } @@ -54,8 +54,13 @@ func main() { logger.InitBestEffort(ptrutils.PtrTo(cli.LogFlags.AsLoggerFlags())) - err := imagecreatorlib.CreateImageWithConfigFile(ctx, cli.BuildDir, cli.ConfigFile, cli.RpmSources, - cli.ToolsTar, cli.OutputImageFile, cli.OutputImageFormat, cli.Distro, cli.DistroVersion, + dist, err := cli.getDistribution() + if err != nil { + log.Fatalf("invalid distribution arguments: %v", err) + } + + err = imagecreatorlib.CreateImageWithConfigFile(ctx, cli.BuildDir, cli.ConfigFile, cli.RpmSources, + cli.ToolsTar, cli.OutputImageFile, cli.OutputImageFormat, dist.name, dist.version, cli.PackageSnapshotTime) if err != nil { log.Fatalf("image creation failed:\n%v", err) diff --git a/toolkit/tools/imagecustomizerapi/distribution.go b/toolkit/tools/imagecustomizerapi/distribution.go new file mode 100644 index 000000000..fdd46c635 --- /dev/null +++ b/toolkit/tools/imagecustomizerapi/distribution.go @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +package imagecustomizerapi + +const ( + DistroNameAzureLinux string = "azurelinux" + DistroNameFedora string = "fedora" +) + +func GetSupportedDistros() map[string][]string { + // supportedDistros defines valid distribution and version combinations + return map[string][]string{ + DistroNameAzureLinux: {"2.0", "3.0"}, + DistroNameFedora: {"42"}, + } +} diff --git a/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go b/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go index 7167890f6..92d31963a 100644 --- a/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go +++ b/toolkit/tools/pkg/imagecustomizerlib/distrohandler.go @@ -12,25 +12,6 @@ import ( "github.com/microsoft/azure-linux-image-tools/toolkit/tools/internal/targetos" ) -// PackageManagerType represents the type of package manager -type PackageManagerType string - -const ( - packageManagerTDNF PackageManagerType = "tdnf" - packageManagerDNF PackageManagerType = "dnf" -) - -// PackageType represents the type of package format -type PackageType string - -// DistroName represents the distribution name -type DistroName string - -const ( - distroNameAzureLinux DistroName = "azurelinux" - distroNameFedora DistroName = "fedora" -) - // distroHandler represents the interface for distribution-specific configuration type distroHandler interface { GetTargetOs() targetos.TargetOs @@ -68,9 +49,9 @@ func NewDistroHandlerFromImageConnection(imageConnection *imageconnection.ImageC // NewDistroHandler creates the appropriate distro handler with version support (legacy) func NewDistroHandler(distroName string, version string) distroHandler { switch distroName { - case string(distroNameFedora): + case string(imagecustomizerapi.DistroNameFedora): return newFedoraDistroHandler(version) - case string(distroNameAzureLinux): + case string(imagecustomizerapi.DistroNameAzureLinux): return newAzureLinuxDistroHandler(version) default: panic("unsupported distro name: " + distroName) From 151c9daf95b2a2b580fecb1910effa7ff8728234 Mon Sep 17 00:00:00 2001 From: Himaja Kesari Date: Wed, 17 Sep 2025 16:42:26 -0700 Subject: [PATCH 2/6] resolve feedback --- toolkit/tools/imagecreator/distribution.go | 54 ------------------- toolkit/tools/imagecreator/main.go | 14 ++++- .../tools/imagecustomizerapi/distribution.go | 38 ++++++++++++- 3 files changed, 50 insertions(+), 56 deletions(-) delete mode 100644 toolkit/tools/imagecreator/distribution.go diff --git a/toolkit/tools/imagecreator/distribution.go b/toolkit/tools/imagecreator/distribution.go deleted file mode 100644 index 9e1a9c624..000000000 --- a/toolkit/tools/imagecreator/distribution.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -package main - -import ( - "fmt" - "strings" - - "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" -) - -// distribution represents a supported Linux distribution and version combination -type distribution struct { - name string - version string -} - -// GetDistribution validates and returns a distribution from the CLI args -func (c *ImageCreatorCmd) getDistribution() (*distribution, error) { - dist := &distribution{ - name: c.Distro, - version: c.DistroVersion, - } - if err := dist.validate(); err != nil { - return nil, err - } - return dist, nil -} - -// Validate ensures the distribution and version combination is supported -func (d *distribution) validate() error { - // Get supported versions for this distribution - - supportedDistros := imagecustomizerapi.GetSupportedDistros() - validVersions, exists := supportedDistros[d.name] - if !exists { - distros := make([]string, 0, len(supportedDistros)) - for d := range supportedDistros { - distros = append(distros, d) - } - return fmt.Errorf("unsupported distribution %q. Supported distributions are: %s", - d.name, strings.Join(distros, ", ")) - } - - // Validate version - for _, v := range validVersions { - if v == d.version { - return nil - } - } - return fmt.Errorf("unsupported version %q for distribution %q. Supported versions: %s", - d.version, d.name, strings.Join(validVersions, ", ")) -} diff --git a/toolkit/tools/imagecreator/main.go b/toolkit/tools/imagecreator/main.go index 27c6d31c7..507f6ca18 100644 --- a/toolkit/tools/imagecreator/main.go +++ b/toolkit/tools/imagecreator/main.go @@ -33,6 +33,18 @@ type ImageCreatorCmd struct { PackageSnapshotTime string `name:"package-snapshot-time" help:"Only packages published before this snapshot time will be available during customization. Supports 'YYYY-MM-DD' or full RFC3339 timestamp (e.g., 2024-05-20T23:59:59Z)."` } +// GetDistribution validates and returns a distribution from the CLI args +func (c *ImageCreatorCmd) getDistribution() (*imagecustomizerapi.Distribution, error) { + dist := &imagecustomizerapi.Distribution{ + Name: c.Distro, + Version: c.DistroVersion, + } + if err := dist.Validate(); err != nil { + return nil, err + } + return dist, nil +} + func main() { ctx := context.Background() @@ -60,7 +72,7 @@ func main() { } err = imagecreatorlib.CreateImageWithConfigFile(ctx, cli.BuildDir, cli.ConfigFile, cli.RpmSources, - cli.ToolsTar, cli.OutputImageFile, cli.OutputImageFormat, dist.name, dist.version, + cli.ToolsTar, cli.OutputImageFile, cli.OutputImageFormat, dist.Name, dist.Version, cli.PackageSnapshotTime) if err != nil { log.Fatalf("image creation failed:\n%v", err) diff --git a/toolkit/tools/imagecustomizerapi/distribution.go b/toolkit/tools/imagecustomizerapi/distribution.go index fdd46c635..86a50c6d9 100644 --- a/toolkit/tools/imagecustomizerapi/distribution.go +++ b/toolkit/tools/imagecustomizerapi/distribution.go @@ -3,12 +3,48 @@ package imagecustomizerapi +import ( + "fmt" + "strings" +) + const ( DistroNameAzureLinux string = "azurelinux" DistroNameFedora string = "fedora" ) -func GetSupportedDistros() map[string][]string { +// distribution represents a supported Linux distribution and version combination +type Distribution struct { + Name string + Version string +} + +// Validate ensures the distribution and version combination is supported +func (d *Distribution) Validate() error { + // Get supported versions for this distribution + + supportedDistros := getSupportedDistros() + validVersions, exists := supportedDistros[d.Name] + if !exists { + distros := make([]string, 0, len(supportedDistros)) + for d := range supportedDistros { + distros = append(distros, string(d)) + } + return fmt.Errorf("unsupported distribution %q. Supported distributions are: %s", + d.Name, strings.Join(distros, ", ")) + } + + // Validate version + for _, v := range validVersions { + if v == d.Version { + return nil + } + } + return fmt.Errorf("unsupported version %q for distribution %q. Supported versions: %s", + d.Version, d.Name, strings.Join(validVersions, ", ")) +} + +func getSupportedDistros() map[string][]string { // supportedDistros defines valid distribution and version combinations return map[string][]string{ DistroNameAzureLinux: {"2.0", "3.0"}, From 2703009514950ea949dbe6016d8c6d5a2eef64a4 Mon Sep 17 00:00:00 2001 From: Himaja Kesari Date: Wed, 17 Sep 2025 16:51:54 -0700 Subject: [PATCH 3/6] resolve feedback --- toolkit/tools/imagecreator/main.go | 4 +- .../tools/imagecustomizerapi/distribution.go | 38 +----------------- .../distribution_validation.go | 39 +++++++++++++++++++ 3 files changed, 42 insertions(+), 39 deletions(-) create mode 100644 toolkit/tools/pkg/imagecreatorlib/distribution_validation.go diff --git a/toolkit/tools/imagecreator/main.go b/toolkit/tools/imagecreator/main.go index 507f6ca18..99ed32701 100644 --- a/toolkit/tools/imagecreator/main.go +++ b/toolkit/tools/imagecreator/main.go @@ -34,8 +34,8 @@ type ImageCreatorCmd struct { } // GetDistribution validates and returns a distribution from the CLI args -func (c *ImageCreatorCmd) getDistribution() (*imagecustomizerapi.Distribution, error) { - dist := &imagecustomizerapi.Distribution{ +func (c *ImageCreatorCmd) getDistribution() (*imagecreatorlib.Distribution, error) { + dist := &imagecreatorlib.Distribution{ Name: c.Distro, Version: c.DistroVersion, } diff --git a/toolkit/tools/imagecustomizerapi/distribution.go b/toolkit/tools/imagecustomizerapi/distribution.go index 86a50c6d9..fdd46c635 100644 --- a/toolkit/tools/imagecustomizerapi/distribution.go +++ b/toolkit/tools/imagecustomizerapi/distribution.go @@ -3,48 +3,12 @@ package imagecustomizerapi -import ( - "fmt" - "strings" -) - const ( DistroNameAzureLinux string = "azurelinux" DistroNameFedora string = "fedora" ) -// distribution represents a supported Linux distribution and version combination -type Distribution struct { - Name string - Version string -} - -// Validate ensures the distribution and version combination is supported -func (d *Distribution) Validate() error { - // Get supported versions for this distribution - - supportedDistros := getSupportedDistros() - validVersions, exists := supportedDistros[d.Name] - if !exists { - distros := make([]string, 0, len(supportedDistros)) - for d := range supportedDistros { - distros = append(distros, string(d)) - } - return fmt.Errorf("unsupported distribution %q. Supported distributions are: %s", - d.Name, strings.Join(distros, ", ")) - } - - // Validate version - for _, v := range validVersions { - if v == d.Version { - return nil - } - } - return fmt.Errorf("unsupported version %q for distribution %q. Supported versions: %s", - d.Version, d.Name, strings.Join(validVersions, ", ")) -} - -func getSupportedDistros() map[string][]string { +func GetSupportedDistros() map[string][]string { // supportedDistros defines valid distribution and version combinations return map[string][]string{ DistroNameAzureLinux: {"2.0", "3.0"}, diff --git a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go new file mode 100644 index 000000000..e483a6df8 --- /dev/null +++ b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go @@ -0,0 +1,39 @@ +package imagecreatorlib + +import ( + "fmt" + "strings" + + "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" +) + +// distribution represents a supported Linux distribution and version combination +type Distribution struct { + Name string + Version string +} + +// Validate ensures the distribution and version combination is supported +func (d *Distribution) Validate() error { + // Get supported versions for this distribution + + supportedDistros := imagecustomizerapi.GetSupportedDistros() + validVersions, exists := supportedDistros[d.Name] + if !exists { + distros := make([]string, 0, len(supportedDistros)) + for d := range supportedDistros { + distros = append(distros, string(d)) + } + return fmt.Errorf("unsupported distribution %q. Supported distributions are: %s", + d.Name, strings.Join(distros, ", ")) + } + + // Validate version + for _, v := range validVersions { + if v == d.Version { + return nil + } + } + return fmt.Errorf("unsupported version %q for distribution %q. Supported versions: %s", + d.Version, d.Name, strings.Join(validVersions, ", ")) +} From a9234f5399a2a2c4e0e2abcd63a50b73116aa7a8 Mon Sep 17 00:00:00 2001 From: Himaja Kesari Date: Wed, 17 Sep 2025 17:18:22 -0700 Subject: [PATCH 4/6] resolve feedback --- .../distribution_validation.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go index e483a6df8..c2c695667 100644 --- a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go +++ b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go @@ -5,6 +5,17 @@ import ( "strings" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" + "github.com/microsoft/azure-linux-image-tools/toolkit/tools/pkg/imagecustomizerlib" +) + +var ( + // ErrUnsupportedDistribution indicates an unsupported Linux distribution + ErrUnsupportedDistribution = imagecustomizerlib.NewImageCustomizerError("Distribution:UnsupportedDistribution", + "unsupported distro") + + // ErrUnsupportedVersion indicates an unsupported version for a given distribution + ErrUnsupportedVersion = imagecustomizerlib.NewImageCustomizerError("Distribution:UnsupportedVersion", + "unsupported distro-version") ) // distribution represents a supported Linux distribution and version combination @@ -24,8 +35,8 @@ func (d *Distribution) Validate() error { for d := range supportedDistros { distros = append(distros, string(d)) } - return fmt.Errorf("unsupported distribution %q. Supported distributions are: %s", - d.Name, strings.Join(distros, ", ")) + return fmt.Errorf("%w: Supported distributions are: %s", + ErrUnsupportedDistribution, strings.Join(distros, ", ")) } // Validate version @@ -34,6 +45,6 @@ func (d *Distribution) Validate() error { return nil } } - return fmt.Errorf("unsupported version %q for distribution %q. Supported versions: %s", - d.Version, d.Name, strings.Join(validVersions, ", ")) + return fmt.Errorf("%w: %q. Supported versions for %q are: %s", + ErrUnsupportedVersion, d.Version, d.Name, strings.Join(validVersions, ", ")) } From 68876f35888ad188e2aadd04b91f256323aa6c80 Mon Sep 17 00:00:00 2001 From: Himaja Kesari Date: Thu, 18 Sep 2025 13:29:09 -0700 Subject: [PATCH 5/6] resolve feedback --- toolkit/tools/imagecreator/main.go | 27 +++++------------- .../distribution_validation.go | 11 +++++--- .../tools/pkg/imagecreatorlib/imagecreator.go | 17 +++++++---- .../pkg/imagecreatorlib/imagecreator_test.go | 28 +++++++++++++++---- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/toolkit/tools/imagecreator/main.go b/toolkit/tools/imagecreator/main.go index 99ed32701..d23066b2c 100644 --- a/toolkit/tools/imagecreator/main.go +++ b/toolkit/tools/imagecreator/main.go @@ -27,24 +27,12 @@ type ImageCreatorCmd struct { ToolsTar string `name:"tools-file" help:"Path to tdnf worker tarball" required:""` OutputImageFile string `name:"output-image-file" help:"Path to write the customized image to."` OutputImageFormat string `name:"output-image-format" placeholder:"(vhd|vhd-fixed|vhdx|qcow2|raw)" help:"Format of output image." enum:"${imageformat}" default:""` - Distro string `name:"distro" help:"Target distribution for the image." enum:"azurelinux,fedora" default:"azurelinux"` - DistroVersion string `name:"distro-version" help:"Target distribution version (e.g., 3.0 for Azure Linux, 42 for Fedora)." default:"3.0"` + Distro string `name:"distro" help:"Target distribution for the image." enum:"azurelinux,fedora" required:""` + DistroVersion string `name:"distro-version" help:"Target distribution version (e.g., 3.0 for Azure Linux, 42 for Fedora)." required:""` exekong.LogFlags PackageSnapshotTime string `name:"package-snapshot-time" help:"Only packages published before this snapshot time will be available during customization. Supports 'YYYY-MM-DD' or full RFC3339 timestamp (e.g., 2024-05-20T23:59:59Z)."` } -// GetDistribution validates and returns a distribution from the CLI args -func (c *ImageCreatorCmd) getDistribution() (*imagecreatorlib.Distribution, error) { - dist := &imagecreatorlib.Distribution{ - Name: c.Distro, - Version: c.DistroVersion, - } - if err := dist.Validate(); err != nil { - return nil, err - } - return dist, nil -} - func main() { ctx := context.Background() @@ -66,14 +54,13 @@ func main() { logger.InitBestEffort(ptrutils.PtrTo(cli.LogFlags.AsLoggerFlags())) - dist, err := cli.getDistribution() - if err != nil { - log.Fatalf("invalid distribution arguments: %v", err) + distro := imagecreatorlib.Distribution{ + Name: cli.Distro, + Version: cli.DistroVersion, } - err = imagecreatorlib.CreateImageWithConfigFile(ctx, cli.BuildDir, cli.ConfigFile, cli.RpmSources, - cli.ToolsTar, cli.OutputImageFile, cli.OutputImageFormat, dist.Name, dist.Version, - cli.PackageSnapshotTime) + err := imagecreatorlib.CreateImageWithConfigFile(ctx, cli.BuildDir, cli.ConfigFile, cli.RpmSources, + cli.ToolsTar, cli.OutputImageFile, cli.OutputImageFormat, distro, cli.PackageSnapshotTime) if err != nil { log.Fatalf("image creation failed:\n%v", err) } diff --git a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go index c2c695667..fb262834c 100644 --- a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go +++ b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go @@ -2,6 +2,8 @@ package imagecreatorlib import ( "fmt" + "maps" + "slices" "strings" "github.com/microsoft/azure-linux-image-tools/toolkit/tools/imagecustomizerapi" @@ -31,12 +33,13 @@ func (d *Distribution) Validate() error { supportedDistros := imagecustomizerapi.GetSupportedDistros() validVersions, exists := supportedDistros[d.Name] if !exists { - distros := make([]string, 0, len(supportedDistros)) + // Get sorted list of supported distributions + distros := slices.Collect(maps.Keys(supportedDistros)) for d := range supportedDistros { distros = append(distros, string(d)) } - return fmt.Errorf("%w: Supported distributions are: %s", - ErrUnsupportedDistribution, strings.Join(distros, ", ")) + return fmt.Errorf("%w (%q)\nsupported distributions are: (%s)", + ErrUnsupportedDistribution, d.Name, strings.Join(distros, ", ")) } // Validate version @@ -45,6 +48,6 @@ func (d *Distribution) Validate() error { return nil } } - return fmt.Errorf("%w: %q. Supported versions for %q are: %s", + return fmt.Errorf("%w (%q)\nsupported versions for %q distro are: (%s)", ErrUnsupportedVersion, d.Version, d.Name, strings.Join(validVersions, ", ")) } diff --git a/toolkit/tools/pkg/imagecreatorlib/imagecreator.go b/toolkit/tools/pkg/imagecreatorlib/imagecreator.go index 49d88bf59..fedd46b32 100644 --- a/toolkit/tools/pkg/imagecreatorlib/imagecreator.go +++ b/toolkit/tools/pkg/imagecreatorlib/imagecreator.go @@ -48,7 +48,7 @@ type ImageCreatorParameters struct { } func CreateImageWithConfigFile(ctx context.Context, buildDir string, configFile string, rpmsSources []string, - toolsTar string, outputImageFile string, outputImageFormat string, distro string, distroVersion string, + toolsTar string, outputImageFile string, outputImageFormat string, distro Distribution, packageSnapshotTime string, ) error { var config imagecustomizerapi.Config @@ -66,7 +66,7 @@ func CreateImageWithConfigFile(ctx context.Context, buildDir string, configFile err = createNewImage( ctx, buildDir, absBaseConfigPath, config, rpmsSources, outputImageFile, - outputImageFormat, toolsTar, distro, distroVersion, packageSnapshotTime) + outputImageFormat, toolsTar, distro, packageSnapshotTime) if err != nil { return err } @@ -75,10 +75,15 @@ func CreateImageWithConfigFile(ctx context.Context, buildDir string, configFile } func createNewImage(ctx context.Context, buildDir string, baseConfigPath string, config imagecustomizerapi.Config, - rpmsSources []string, outputImageFile string, outputImageFormat string, toolsTar string, distro string, - distroVersion string, packageSnapshotTime string, + rpmsSources []string, outputImageFile string, outputImageFormat string, toolsTar string, distro Distribution, + packageSnapshotTime string, ) error { - err := validateConfig( + err := distro.Validate() + if err != nil { + return fmt.Errorf("invalid distribution arguments:\n%w", err) + } + + err = validateConfig( ctx, baseConfigPath, &config, rpmsSources, toolsTar, outputImageFile, outputImageFormat, packageSnapshotTime) if err != nil { @@ -119,7 +124,7 @@ func createNewImage(ctx context.Context, buildDir string, baseConfigPath string, logger.Log.Infof("Creating new image with parameters: %+v\n", imageCreatorParameters) // Create distro config from distro name and version - distroHandler := imagecustomizerlib.NewDistroHandler(distro, distroVersion) + distroHandler := imagecustomizerlib.NewDistroHandler(distro.Name, distro.Version) partIdToPartUuid, err := imagecustomizerlib.CreateNewImage( distroHandler.GetTargetOs(), imageCreatorParameters.rawImageFile, diff --git a/toolkit/tools/pkg/imagecreatorlib/imagecreator_test.go b/toolkit/tools/pkg/imagecreatorlib/imagecreator_test.go index bb8818a18..b9f01f90c 100644 --- a/toolkit/tools/pkg/imagecreatorlib/imagecreator_test.go +++ b/toolkit/tools/pkg/imagecreatorlib/imagecreator_test.go @@ -28,9 +28,13 @@ func TestCreateImageRaw(t *testing.T) { rpmSources := []string{downloadedRpmsRepoFile} toolsFile := testutils.GetDownloadedToolsFile(t, testutilsDir, "3.0", true) + distro := Distribution{ + Name: "azurelinux", + Version: "3.0", + } err := CreateImageWithConfigFile( t.Context(), buildDir, partitionsConfigFile, rpmSources, toolsFile, - outputImageFilePath, outputImageFormat, "azurelinux", "3.0", "") + outputImageFilePath, outputImageFormat, distro, "") if !assert.NoError(t, err) { return } @@ -73,8 +77,12 @@ func TestCreateImageRawNoTar(t *testing.T) { downloadedRpmsRepoFile := testutils.GetDownloadedRpmsRepoFile(t, testutilsDir, "3.0", false, true) rpmSources := []string{downloadedRpmsRepoFile} + distro := Distribution{ + Name: "azurelinux", + Version: "3.0", + } err := CreateImageWithConfigFile(t.Context(), buildDir, partitionsConfigFile, rpmSources, "", - outputImageFilePath, "raw", "azurelinux", "3.0", "") + outputImageFilePath, "raw", distro, "") assert.ErrorContains(t, err, "tools tar file is required for image creation") } @@ -87,12 +95,16 @@ func TestCreateImageEmptyConfig(t *testing.T) { // create an empty config file emptyConfigFile := filepath.Join(testDir, "empty-config.yaml") + distro := Distribution{ + Name: "azurelinux", + Version: "3.0", + } err := CreateImageWithConfigFile(t.Context(), buildDir, "", []string{}, "", outputImageFilePath, "raw", - "azurelinux", "3.0", "") + distro, "") assert.ErrorContains(t, err, "failed to unmarshal config file") err = CreateImageWithConfigFile(t.Context(), buildDir, emptyConfigFile, []string{}, "", outputImageFilePath, "raw", - "azurelinux", "3.0", "") + distro, "") assert.ErrorContains(t, err, "failed to unmarshal config file") } @@ -123,8 +135,12 @@ func TestCreateImage_OutputImageFileAsRelativePath(t *testing.T) { // Pass the output image file relative to the current working directory through the argument. // This will create the file at the absolute path. + distro := Distribution{ + Name: "azurelinux", + Version: "3.0", + } err = createNewImage(t.Context(), buildDir, baseConfigPath, config, rpmSources, outputImageFile, - outputImageFormat, toolsFile, "azurelinux", "3.0", "") + outputImageFormat, toolsFile, distro, "") assert.NoError(t, err) assert.FileExists(t, outputImageFileAbsolute) err = os.Remove(outputImageFileAbsolute) @@ -136,7 +152,7 @@ func TestCreateImage_OutputImageFileAsRelativePath(t *testing.T) { // Pass the output image file relative to the config file through the config. This will create // the file at the absolute path. err = createNewImage(t.Context(), buildDir, baseConfigPath, config, rpmSources, outputImageFile, - outputImageFormat, toolsFile, "azurelinux", "3.0", "") + outputImageFormat, toolsFile, distro, "") assert.NoError(t, err) assert.FileExists(t, outputImageFileAbsolute) err = os.Remove(outputImageFileAbsolute) From 7e3ef1c0a1e4ceb1181745eca4fd55c4e6e8b4ad Mon Sep 17 00:00:00 2001 From: Himaja Kesari Date: Tue, 30 Sep 2025 08:48:12 -0700 Subject: [PATCH 6/6] fix validate --- .../distribution_validation.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go index fb262834c..e76c795cf 100644 --- a/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go +++ b/toolkit/tools/pkg/imagecreatorlib/distribution_validation.go @@ -28,26 +28,23 @@ type Distribution struct { // Validate ensures the distribution and version combination is supported func (d *Distribution) Validate() error { - // Get supported versions for this distribution - + // Get all supported distributions and their versions supportedDistros := imagecustomizerapi.GetSupportedDistros() + + // Check if the distribution is supported validVersions, exists := supportedDistros[d.Name] if !exists { - // Get sorted list of supported distributions + // Get list of supported distributions distros := slices.Collect(maps.Keys(supportedDistros)) - for d := range supportedDistros { - distros = append(distros, string(d)) - } return fmt.Errorf("%w (%q)\nsupported distributions are: (%s)", ErrUnsupportedDistribution, d.Name, strings.Join(distros, ", ")) } - // Validate version - for _, v := range validVersions { - if v == d.Version { - return nil - } + // Check if the version is supported for this distribution + if slices.Contains(validVersions, d.Version) { + return nil } + return fmt.Errorf("%w (%q)\nsupported versions for %q distro are: (%s)", ErrUnsupportedVersion, d.Version, d.Name, strings.Join(validVersions, ", ")) }