diff --git a/docs/stackit_image_create.md b/docs/stackit_image_create.md index 3c608126c..1dbfc5278 100644 --- a/docs/stackit_image_create.md +++ b/docs/stackit_image_create.md @@ -23,6 +23,7 @@ stackit image create [flags] ### Options ``` + --architecture string Sets the CPU architecture. By default x86 is used. --boot-menu Enables the BIOS bootmenu. --cdrom-bus string Sets CDROM bus controller type. --disk-bus string Sets Disk bus controller type. diff --git a/docs/stackit_image_update.md b/docs/stackit_image_update.md index 3c6acbe62..d088d9962 100644 --- a/docs/stackit_image_update.md +++ b/docs/stackit_image_update.md @@ -23,6 +23,7 @@ stackit image update IMAGE_ID [flags] ### Options ``` + --architecture string Sets the CPU architecture. --boot-menu Enables the BIOS bootmenu. --cdrom-bus string Sets CDROM bus controller type. --disk-bus string Sets Disk bus controller type. diff --git a/internal/cmd/image/create/create.go b/internal/cmd/image/create/create.go index d25c6adc4..0e0a84cbb 100644 --- a/internal/cmd/image/create/create.go +++ b/internal/cmd/image/create/create.go @@ -31,6 +31,7 @@ const ( localFilePathFlag = "local-file-path" noProgressIndicatorFlag = "no-progress" + architectureFlag = "architecture" bootMenuFlag = "boot-menu" cdromBusFlag = "cdrom-bus" diskBusFlag = "disk-bus" @@ -53,6 +54,7 @@ const ( ) type imageConfig struct { + Architecture *string BootMenu *bool CdromBus *string DiskBus *string @@ -261,6 +263,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(localFilePathFlag, "", "The path to the local disk image file.") cmd.Flags().Bool(noProgressIndicatorFlag, false, "Show no progress indicator for upload.") + cmd.Flags().String(architectureFlag, "", "Sets the CPU architecture. By default x86 is used.") cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") cmd.Flags().String(diskBusFlag, "", "Sets Disk bus controller type.") @@ -302,6 +305,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) { Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), NoProgressIndicator: flags.FlagToBoolPointer(p, cmd, noProgressIndicatorFlag), Config: &imageConfig{ + Architecture: flags.FlagToStringPointer(p, cmd, architectureFlag), BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), DiskBus: flags.FlagToStringPointer(p, cmd, diskBusFlag), @@ -348,21 +352,47 @@ func createPayload(_ context.Context, model *inputModel) iaas.CreateImagePayload MinRam: model.MinRam, Protected: model.Protected, } - if model.Config != nil { - payload.Config = &iaas.ImageConfig{ - BootMenu: model.Config.BootMenu, - CdromBus: iaas.NewNullableString(model.Config.CdromBus), - DiskBus: iaas.NewNullableString(model.Config.DiskBus), - NicModel: iaas.NewNullableString(model.Config.NicModel), - OperatingSystem: model.Config.OperatingSystem, - OperatingSystemDistro: iaas.NewNullableString(model.Config.OperatingSystemDistro), - OperatingSystemVersion: iaas.NewNullableString(model.Config.OperatingSystemVersion), - RescueBus: iaas.NewNullableString(model.Config.RescueBus), - RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), - SecureBoot: model.Config.SecureBoot, - Uefi: utils.Ptr(model.Config.Uefi), - VideoModel: iaas.NewNullableString(model.Config.VideoModel), - VirtioScsi: model.Config.VirtioScsi, + if config := model.Config; config != nil { + payload.Config = &iaas.ImageConfig{} + payload.Config.Uefi = utils.Ptr(config.Uefi) + if config.Architecture != nil { + payload.Config.Architecture = model.Config.Architecture + } + if config.BootMenu != nil { + payload.Config.BootMenu = model.Config.BootMenu + } + if config.CdromBus != nil { + payload.Config.CdromBus = iaas.NewNullableString(model.Config.CdromBus) + } + if config.DiskBus != nil { + payload.Config.DiskBus = iaas.NewNullableString(config.DiskBus) + } + if config.NicModel != nil { + payload.Config.NicModel = iaas.NewNullableString(config.NicModel) + } + if config.OperatingSystem != nil { + payload.Config.OperatingSystem = config.OperatingSystem + } + if config.OperatingSystemDistro != nil { + payload.Config.OperatingSystemDistro = iaas.NewNullableString(config.OperatingSystemDistro) + } + if config.OperatingSystemVersion != nil { + payload.Config.OperatingSystemVersion = iaas.NewNullableString(config.OperatingSystemVersion) + } + if config.RescueBus != nil { + payload.Config.RescueBus = iaas.NewNullableString(config.RescueBus) + } + if config.RescueDevice != nil { + payload.Config.RescueDevice = iaas.NewNullableString(config.RescueDevice) + } + if config.SecureBoot != nil { + payload.Config.SecureBoot = config.SecureBoot + } + if config.VideoModel != nil { + payload.Config.VideoModel = iaas.NewNullableString(config.VideoModel) + } + if config.VirtioScsi != nil { + payload.Config.VirtioScsi = config.VirtioScsi } } diff --git a/internal/cmd/image/create/create_test.go b/internal/cmd/image/create/create_test.go index e0ed042c9..45a926fbf 100644 --- a/internal/cmd/image/create/create_test.go +++ b/internal/cmd/image/create/create_test.go @@ -39,6 +39,7 @@ var ( testOperatingSystemVersion = "test-distro-version" testRescueBus = "test-rescue-bus" testRescueDevice = "test-rescue-device" + testArchitecture = "arm64" testBootmenu = true testSecureBoot = true testUefi = true @@ -54,6 +55,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st nameFlag: testName, diskFormatFlag: testDiskFormat, localFilePathFlag: testLocalImagePath, + architectureFlag: testArchitecture, bootMenuFlag: strconv.FormatBool(testBootmenu), cdromBusFlag: testCdRomBus, diskBusFlag: testDiskBus, @@ -96,6 +98,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { LocalFilePath: testLocalImagePath, Labels: utils.Ptr(parseLabels(testLabels)), Config: &imageConfig{ + Architecture: &testArchitecture, BootMenu: &testBootmenu, CdromBus: &testCdRomBus, DiskBus: &testDiskBus, @@ -123,6 +126,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { func fixtureCreatePayload(mods ...func(payload *iaas.CreateImagePayload)) (payload iaas.CreateImagePayload) { payload = iaas.CreateImagePayload{ Config: &iaas.ImageConfig{ + Architecture: &testArchitecture, BootMenu: &testBootmenu, CdromBus: iaas.NewNullableString(&testCdRomBus), DiskBus: iaas.NewNullableString(&testDiskBus), diff --git a/internal/cmd/image/describe/describe.go b/internal/cmd/image/describe/describe.go index d1c945b81..9a5e5e918 100644 --- a/internal/cmd/image/describe/describe.go +++ b/internal/cmd/image/describe/describe.go @@ -141,6 +141,10 @@ func outputResult(p *print.Printer, outputFormat string, resp *iaas.Image) error table.AddSeparator() } if config := resp.Config; config != nil { + if architecture := config.Architecture; architecture != nil { + table.AddRow("ARCHITECTURE", *architecture) + table.AddSeparator() + } if os := config.OperatingSystem; os != nil { table.AddRow("OPERATING SYSTEM", *os) table.AddSeparator() diff --git a/internal/cmd/image/list/list.go b/internal/cmd/image/list/list.go index 00f28b066..67e0c951c 100644 --- a/internal/cmd/image/list/list.go +++ b/internal/cmd/image/list/list.go @@ -165,14 +165,18 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err return nil default: table := tables.NewTable() - table.SetHeader("ID", "NAME", "OS", "DISTRIBUTION", "VERSION", "LABELS") + table.SetHeader("ID", "NAME", "OS", "ARCHITECTURE", "DISTRIBUTION", "VERSION", "LABELS") for _, item := range items { var ( - os string = "n/a" - distro string = "n/a" - version string = "n/a" + architecture string = "n/a" + os string = "n/a" + distro string = "n/a" + version string = "n/a" ) if cfg := item.Config; cfg != nil { + if v := cfg.Architecture; v != nil { + architecture = *v + } if v := cfg.OperatingSystem; v != nil { os = *v } @@ -186,6 +190,7 @@ func outputResult(p *print.Printer, outputFormat string, items []iaas.Image) err table.AddRow(utils.PtrString(item.Id), utils.PtrString(item.Name), os, + architecture, distro, version, utils.JoinStringKeysPtr(*item.Labels, ",")) diff --git a/internal/cmd/image/update/update.go b/internal/cmd/image/update/update.go index f461a388d..e434f1238 100644 --- a/internal/cmd/image/update/update.go +++ b/internal/cmd/image/update/update.go @@ -20,6 +20,7 @@ import ( ) type imageConfig struct { + Architecture *string BootMenu *bool CdromBus *string DiskBus *string @@ -80,6 +81,7 @@ const ( nameFlag = "name" diskFormatFlag = "disk-format" + architectureFlag = "architecture" bootMenuFlag = "boot-menu" cdromBusFlag = "cdrom-bus" diskBusFlag = "disk-bus" @@ -98,7 +100,6 @@ const ( minDiskSizeFlag = "min-disk-size" minRamFlag = "min-ram" - ownerFlag = "owner" protectedFlag = "protected" ) @@ -166,6 +167,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(nameFlag, "", "The name of the image.") cmd.Flags().String(diskFormatFlag, "", "The disk format of the image. ") + cmd.Flags().String(architectureFlag, "", "Sets the CPU architecture.") cmd.Flags().Bool(bootMenuFlag, false, "Enables the BIOS bootmenu.") cmd.Flags().String(cdromBusFlag, "", "Sets CDROM bus controller type.") cmd.Flags().String(diskBusFlag, "", "Sets Disk bus controller type.") @@ -203,6 +205,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM DiskFormat: flags.FlagToStringPointer(p, cmd, diskFormatFlag), Labels: flags.FlagToStringToStringPointer(p, cmd, labelsFlag), Config: &imageConfig{ + Architecture: flags.FlagToStringPointer(p, cmd, architectureFlag), BootMenu: flags.FlagToBoolPointer(p, cmd, bootMenuFlag), CdromBus: flags.FlagToStringPointer(p, cmd, cdromBusFlag), DiskBus: flags.FlagToStringPointer(p, cmd, diskBusFlag), @@ -226,6 +229,10 @@ func parseInput(p *print.Printer, cmd *cobra.Command, cliArgs []string) (*inputM return nil, fmt.Errorf("no flags have been passed") } + if model.Config.isEmpty() { + model.Config = nil + } + if p.IsVerbosityDebug() { modelStr, err := print.BuildDebugStrFromInputModel(model) if err != nil { @@ -249,22 +256,48 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli payload.MinRam = model.MinRam payload.Name = model.Name payload.Protected = model.Protected + payload.Config = nil - if model.Config != nil { - payload.Config = &iaas.ImageConfig{ - BootMenu: model.Config.BootMenu, - CdromBus: iaas.NewNullableString(model.Config.CdromBus), - DiskBus: iaas.NewNullableString(model.Config.DiskBus), - NicModel: iaas.NewNullableString(model.Config.NicModel), - OperatingSystem: model.Config.OperatingSystem, - OperatingSystemDistro: iaas.NewNullableString(model.Config.OperatingSystemDistro), - OperatingSystemVersion: iaas.NewNullableString(model.Config.OperatingSystemVersion), - RescueBus: iaas.NewNullableString(model.Config.RescueBus), - RescueDevice: iaas.NewNullableString(model.Config.RescueDevice), - SecureBoot: model.Config.SecureBoot, - Uefi: model.Config.Uefi, - VideoModel: iaas.NewNullableString(model.Config.VideoModel), - VirtioScsi: model.Config.VirtioScsi, + if config := model.Config; config != nil { + payload.Config = &iaas.ImageConfig{} + if model.Config.BootMenu != nil { + payload.Config.BootMenu = model.Config.BootMenu + } + if model.Config.CdromBus != nil { + payload.Config.CdromBus = iaas.NewNullableString(model.Config.CdromBus) + } + if model.Config.DiskBus != nil { + payload.Config.DiskBus = iaas.NewNullableString(model.Config.DiskBus) + } + if model.Config.NicModel != nil { + payload.Config.NicModel = iaas.NewNullableString(model.Config.NicModel) + } + if model.Config.OperatingSystem != nil { + payload.Config.OperatingSystem = model.Config.OperatingSystem + } + if model.Config.OperatingSystemDistro != nil { + payload.Config.OperatingSystemDistro = iaas.NewNullableString(model.Config.OperatingSystemDistro) + } + if model.Config.OperatingSystemVersion != nil { + payload.Config.OperatingSystemVersion = iaas.NewNullableString(model.Config.OperatingSystemVersion) + } + if model.Config.RescueBus != nil { + payload.Config.RescueBus = iaas.NewNullableString(model.Config.RescueBus) + } + if model.Config.RescueDevice != nil { + payload.Config.RescueDevice = iaas.NewNullableString(model.Config.RescueDevice) + } + if model.Config.SecureBoot != nil { + payload.Config.SecureBoot = model.Config.SecureBoot + } + if model.Config.Uefi != nil { + payload.Config.Uefi = model.Config.Uefi + } + if model.Config.VideoModel != nil { + payload.Config.VideoModel = iaas.NewNullableString(model.Config.VideoModel) + } + if model.Config.VirtioScsi != nil { + payload.Config.VirtioScsi = model.Config.VirtioScsi } } diff --git a/internal/cmd/image/update/update_test.go b/internal/cmd/image/update/update_test.go index 17216cbb9..5e4d620ca 100644 --- a/internal/cmd/image/update/update_test.go +++ b/internal/cmd/image/update/update_test.go @@ -298,6 +298,20 @@ func TestParseInput(t *testing.T) { model.Config.RescueDevice = nil }), }, + { + description: "update only name", + flagValues: map[string]string{ + projectIdFlag: testProjectId, + nameFlag: "foo", + }, + args: testImageId, + isValid: true, + expectedModel: &inputModel{ + Name: utils.Ptr("foo"), + GlobalFlagModel: &globalflags.GlobalFlagModel{ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault}, + Id: testImageId[0], + }, + }, } for _, tt := range tests { @@ -400,6 +414,17 @@ func TestBuildRequest(t *testing.T) { })) }), }, + { + description: "no config set", + model: fixtureInputModel(func(model *inputModel) { + model.Config = nil + }), + expectedRequest: fixtureRequest(func(request *iaas.ApiUpdateImageRequest) { + *request = (*request).UpdateImagePayload(fixtureCreatePayload(func(payload *iaas.UpdateImagePayload) { + payload.Config = nil + })) + }), + }, } for _, tt := range tests {