diff --git a/docs/stackit_server_create.md b/docs/stackit_server_create.md index c1c4e9b21..55e34f91f 100644 --- a/docs/stackit_server_create.md +++ b/docs/stackit_server_create.md @@ -39,12 +39,16 @@ stackit server create [flags] Create a server with user data (cloud-init) $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml + + Create a server with provisioned agent + $ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-id yyy --agent-provisioned=true ``` ### Options ``` --affinity-group string The affinity group the server is assigned to + --agent-provisioned Whether to provision an agent on server creation --availability-zone string The availability zone of the server --boot-volume-delete-on-termination Delete the volume during the termination of the server. Defaults to false --boot-volume-performance-class string Boot volume performance class diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index 86f0af5dc..6c7563102 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -27,6 +27,7 @@ const ( machineTypeFlag = "machine-type" affinityGroupFlag = "affinity-group" availabilityZoneFlag = "availability-zone" + agentProvisionedFlag = "agent-provisioned" bootVolumeSourceIdFlag = "boot-volume-source-id" bootVolumeSourceTypeFlag = "boot-volume-source-type" bootVolumeSizeFlag = "boot-volume-size" @@ -49,6 +50,7 @@ type inputModel struct { MachineType *string AffinityGroup *string AvailabilityZone *string + AgentProvisioned *bool BootVolumeSourceId *string BootVolumeSourceType *string BootVolumeSize *int64 @@ -108,6 +110,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { `Create a server with user data (cloud-init)`, `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --user-data @path/to/file.yaml`, ), + examples.NewExample( + `Create a server with provisioned agent`, + `$ stackit server create --machine-type t1.1 --name server1 --boot-volume-source-id xxx --boot-volume-source-type image --boot-volume-size 64 --network-id yyy --agent-provisioned=true`, + ), ), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -167,6 +173,7 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().String(machineTypeFlag, "", "Name of the type of the machine for the server. Possible values are documented in https://docs.stackit.cloud/products/compute-engine/server/basics/machine-types/") cmd.Flags().String(affinityGroupFlag, "", "The affinity group the server is assigned to") cmd.Flags().String(availabilityZoneFlag, "", "The availability zone of the server") + cmd.Flags().Bool(agentProvisionedFlag, false, "Whether to provision an agent on server creation") cmd.Flags().String(bootVolumeSourceIdFlag, "", "ID of the source object of boot volume. It can be either an image or volume ID") cmd.Flags().String(bootVolumeSourceTypeFlag, "", "Type of the source object of boot volume. It can be either 'image' or 'volume'") cmd.Flags().Int64(bootVolumeSizeFlag, 0, "The size of the boot volume in GB. Must be provided when 'boot-volume-source-type' is 'image'") @@ -251,6 +258,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, MachineType: flags.FlagToStringPointer(p, cmd, machineTypeFlag), AffinityGroup: flags.FlagToStringPointer(p, cmd, affinityGroupFlag), AvailabilityZone: flags.FlagToStringPointer(p, cmd, availabilityZoneFlag), + AgentProvisioned: flags.FlagToBoolPointer(p, cmd, agentProvisionedFlag), BootVolumeSourceId: flags.FlagToStringPointer(p, cmd, bootVolumeSourceIdFlag), BootVolumeSourceType: flags.FlagToStringPointer(p, cmd, bootVolumeSourceTypeFlag), BootVolumeSize: flags.FlagToInt64Pointer(p, cmd, bootVolumeSizeFlag), @@ -294,6 +302,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli Labels: utils.ConvertStringMapToInterfaceMap(model.Labels), } + if model.AgentProvisioned != nil { + payload.Agent = &iaas.ServerAgent{ + Provisioned: model.AgentProvisioned, + } + } + if model.BootVolumePerformanceClass != nil || model.BootVolumeSize != nil || model.BootVolumeDeleteOnTermination != nil || model.BootVolumeSourceId != nil || model.BootVolumeSourceType != nil { payload.BootVolume = &iaas.ServerBootVolume{ PerformanceClass: model.BootVolumePerformanceClass, diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index 521b80922..3e9d698c0 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -37,6 +37,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st globalflags.ProjectIdFlag: testProjectId, globalflags.RegionFlag: testRegion, + agentProvisionedFlag: "false", availabilityZoneFlag: "eu01-1", nameFlag: "test-server-name", machineTypeFlag: "t1.1", @@ -67,6 +68,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, + AgentProvisioned: utils.Ptr(false), AvailabilityZone: utils.Ptr("eu01-1"), Name: utils.Ptr("test-server-name"), MachineType: utils.Ptr("t1.1"), @@ -118,8 +120,11 @@ func fixturePayload(mods ...func(payload *iaas.CreateServerPayload)) iaas.Create Labels: utils.Ptr(map[string]interface{}{ "key": "value", }), - MachineType: utils.Ptr("t1.1"), - Name: utils.Ptr("test-server-name"), + MachineType: utils.Ptr("t1.1"), + Name: utils.Ptr("test-server-name"), + Agent: &iaas.ServerAgent{ + Provisioned: utils.Ptr(false), + }, AvailabilityZone: utils.Ptr("eu01-1"), AffinityGroup: utils.Ptr("test-affinity-group"), KeypairName: utils.Ptr("test-keypair-name"), @@ -166,6 +171,7 @@ func TestParseInput(t *testing.T) { description: "required only", flagValues: fixtureFlagValues(func(flagValues map[string]string) { delete(flagValues, affinityGroupFlag) + delete(flagValues, agentProvisionedFlag) delete(flagValues, availabilityZoneFlag) delete(flagValues, labelFlag) delete(flagValues, bootVolumeSourceIdFlag) @@ -184,6 +190,7 @@ func TestParseInput(t *testing.T) { isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { model.AffinityGroup = nil + model.AgentProvisioned = nil model.AvailabilityZone = nil model.Labels = nil model.BootVolumeSourceId = nil @@ -329,6 +336,16 @@ func TestParseInput(t *testing.T) { model.ImageId = nil }), }, + { + description: "valid with agent-provisioned flag missing", + flagValues: fixtureFlagValues(func(flagValues map[string]string) { + delete(flagValues, agentProvisionedFlag) + }), + isValid: true, + expectedModel: fixtureInputModel(func(model *inputModel) { + model.AgentProvisioned = nil + }), + }, } for _, tt := range tests {