From 2996bbc0d1ebeaaf08127bbd30ce649d8dbab824 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Tue, 27 May 2025 10:58:26 +0200 Subject: [PATCH] image-builder: fix cross-arch uploading This commit fixes the cross-arch uploading in the most simple case by reading the `--arch` when `image-builder build --upload` is used. Note that this is not a complete fix as it will not take boot mode into account nor will it (by default) DTRT when `image-builder upload` is used on a previously build images for a different architecture. Thanks to `FrostyX` for reporting the issue. --- cmd/image-builder/main.go | 1 + cmd/image-builder/upload.go | 9 +++- cmd/image-builder/upload_test.go | 73 +++++++++++++++++++------------- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/cmd/image-builder/main.go b/cmd/image-builder/main.go index e1c9378..94ecf47 100644 --- a/cmd/image-builder/main.go +++ b/cmd/image-builder/main.go @@ -477,6 +477,7 @@ operating systems like Fedora, CentOS and RHEL with easy customizations support. uploadCmd.Flags().String("aws-ami-name", "", "name for the AMI in AWS (only for type=ami)") uploadCmd.Flags().String("aws-bucket", "", "target S3 bucket name for intermediate storage when creating AMI (only for type=ami)") uploadCmd.Flags().String("aws-region", "", "target region for AWS uploads (only for type=ami)") + uploadCmd.Flags().String("arch", "", "upload for the given architecture") rootCmd.AddCommand(uploadCmd) buildCmd := &cobra.Command{ diff --git a/cmd/image-builder/upload.go b/cmd/image-builder/upload.go index 3d15321..62ef80a 100644 --- a/cmd/image-builder/upload.go +++ b/cmd/image-builder/upload.go @@ -84,6 +84,10 @@ func uploaderForCmdAWS(cmd *cobra.Command) (cloud.Uploader, error) { if err != nil { return nil, err } + targetArch, err := cmd.Flags().GetString("arch") + if err != nil { + return nil, err + } var missing []string requiredArgs := []string{"aws-ami-name", "aws-bucket", "aws-region"} @@ -103,8 +107,11 @@ func uploaderForCmdAWS(cmd *cobra.Command) (cloud.Uploader, error) { return nil, fmt.Errorf("%w: %q", ErrMissingUploadConfig, missing) } + opts := &awscloud.UploaderOptions{ + TargetArch: targetArch, + } - return awscloudNewUploader(region, bucketName, amiName, nil) + return awscloudNewUploader(region, bucketName, amiName, opts) } func cmdUpload(cmd *cobra.Command, args []string) error { diff --git a/cmd/image-builder/upload_test.go b/cmd/image-builder/upload_test.go index 5631e82..ab28db8 100644 --- a/cmd/image-builder/upload_test.go +++ b/cmd/image-builder/upload_test.go @@ -51,41 +51,54 @@ func TestUploadWithAWSMock(t *testing.T) { assert.NoError(t, err) var regionName, bucketName, amiName string - var fa fakeAwsUploader - restore := main.MockAwscloudNewUploader(func(region string, bucket string, ami string, opts *awscloud.UploaderOptions) (cloud.Uploader, error) { - regionName = region - bucketName = bucket - amiName = ami - return &fa, nil - }) - defer restore() + var uploadOpts *awscloud.UploaderOptions - var fakeStdout bytes.Buffer - restore = main.MockOsStdout(&fakeStdout) - defer restore() + for _, tc := range []struct { + targetArchArg string + expectedUploadArch string + }{ + {"", ""}, + {"aarch64", "aarch64"}, + } { + var fa fakeAwsUploader + restore := main.MockAwscloudNewUploader(func(region string, bucket string, ami string, opts *awscloud.UploaderOptions) (cloud.Uploader, error) { + regionName = region + bucketName = bucket + amiName = ami + uploadOpts = opts + return &fa, nil + }) + defer restore() - restore = main.MockOsArgs([]string{ - "upload", - "--to=aws", - "--aws-region=aws-region-1", - "--aws-bucket=aws-bucket-2", - "--aws-ami-name=aws-ami-3", - fakeImageFilePath, - }) - defer restore() + var fakeStdout bytes.Buffer + restore = main.MockOsStdout(&fakeStdout) + defer restore() - err = main.Run() - require.NoError(t, err) + restore = main.MockOsArgs([]string{ + "upload", + "--to=aws", + "--aws-region=aws-region-1", + "--aws-bucket=aws-bucket-2", + "--aws-ami-name=aws-ami-3", + "--arch=" + tc.targetArchArg, + fakeImageFilePath, + }) + defer restore() - assert.Equal(t, regionName, "aws-region-1") - assert.Equal(t, bucketName, "aws-bucket-2") - assert.Equal(t, amiName, "aws-ami-3") + err = main.Run() + require.NoError(t, err) - assert.Equal(t, 0, fa.checkCalls) - assert.Equal(t, 1, fa.uploadAndRegisterCalls) - assert.Equal(t, fakeDiskContent, fa.uploadAndRegisterRead.String()) - // progress was rendered - assert.Contains(t, fakeStdout.String(), "--] 100.00%") + assert.Equal(t, regionName, "aws-region-1") + assert.Equal(t, bucketName, "aws-bucket-2") + assert.Equal(t, amiName, "aws-ami-3") + assert.Equal(t, &awscloud.UploaderOptions{TargetArch: tc.expectedUploadArch}, uploadOpts) + + assert.Equal(t, 0, fa.checkCalls) + assert.Equal(t, 1, fa.uploadAndRegisterCalls) + assert.Equal(t, fakeDiskContent, fa.uploadAndRegisterRead.String()) + // progress was rendered + assert.Contains(t, fakeStdout.String(), "--] 100.00%") + } } func TestUploadCmdlineErrors(t *testing.T) {