Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/stackit_server_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-provisioning-policy ALWAYS
```

### Options

```
--affinity-group string The affinity group the server is assigned to
--agent-provisioning-policy string Whether to provision an agent on server creation, one of ["ALWAYS" "NEVER" "INHERIT"] (default "INHERIT")
--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
Expand Down
18 changes: 18 additions & 0 deletions internal/cmd/server/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
machineTypeFlag = "machine-type"
affinityGroupFlag = "affinity-group"
availabilityZoneFlag = "availability-zone"
agentProvisioningPolicyFlag = "agent-provisioning-policy"
bootVolumeSourceIdFlag = "boot-volume-source-id"
bootVolumeSourceTypeFlag = "boot-volume-source-type"
bootVolumeSizeFlag = "boot-volume-size"
Expand All @@ -50,6 +51,7 @@ type inputModel struct {
MachineType *string
AffinityGroup *string
AvailabilityZone *string
AgentProvisioningPolicy *string
BootVolumeSourceId *string
BootVolumeSourceType *string
BootVolumeSize *int64
Expand Down Expand Up @@ -109,6 +111,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-provisioning-policy ALWAYS`,
),
),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
Expand Down Expand Up @@ -162,6 +168,8 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
}

func configureFlags(cmd *cobra.Command) {
agentProvisioningPolicyOptions := []string{"ALWAYS", "NEVER", "INHERIT"}
cmd.Flags().Var(flags.EnumFlag(false, "INHERIT", agentProvisioningPolicyOptions...), agentProvisioningPolicyFlag, fmt.Sprintf("Whether to provision an agent on server creation, one of %q", agentProvisioningPolicyOptions))
cmd.Flags().StringP(nameFlag, "n", "", "Server name")
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")
Expand Down Expand Up @@ -250,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),
AgentProvisioningPolicy: flags.FlagToStringPointer(p, cmd, agentProvisioningPolicyFlag),
BootVolumeSourceId: flags.FlagToStringPointer(p, cmd, bootVolumeSourceIdFlag),
BootVolumeSourceType: flags.FlagToStringPointer(p, cmd, bootVolumeSourceTypeFlag),
BootVolumeSize: flags.FlagToInt64Pointer(p, cmd, bootVolumeSizeFlag),
Expand Down Expand Up @@ -293,6 +302,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli
Labels: utils.ConvertStringMapToInterfaceMap(model.Labels),
}

if model.AgentProvisioningPolicy != nil {
switch *model.AgentProvisioningPolicy {
case "ALWAYS":
payload.Agent = &iaas.ServerAgent{Provisioned: utils.Ptr(true)}
case "NEVER":
payload.Agent = &iaas.ServerAgent{Provisioned: utils.Ptr(false)}
}
}

if model.BootVolumePerformanceClass != nil || model.BootVolumeSize != nil || model.BootVolumeDeleteOnTermination != nil || model.BootVolumeSourceId != nil || model.BootVolumeSourceType != nil {
payload.BootVolume = &iaas.ServerBootVolume{
PerformanceClass: model.BootVolumePerformanceClass,
Expand Down
37 changes: 37 additions & 0 deletions internal/cmd/server/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st
globalflags.ProjectIdFlag: testProjectId,
globalflags.RegionFlag: testRegion,

agentProvisioningPolicyFlag: "INHERIT",
availabilityZoneFlag: "eu01-1",
nameFlag: "test-server-name",
machineTypeFlag: "t1.1",
Expand Down Expand Up @@ -65,6 +66,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
Region: testRegion,
Verbosity: globalflags.VerbosityDefault,
},
AgentProvisioningPolicy: utils.Ptr("INHERIT"),
AvailabilityZone: utils.Ptr("eu01-1"),
Name: utils.Ptr("test-server-name"),
MachineType: utils.Ptr("t1.1"),
Expand Down Expand Up @@ -164,6 +166,7 @@ func TestParseInput(t *testing.T) {
description: "required only",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, affinityGroupFlag)
delete(flagValues, agentProvisioningPolicyFlag)
delete(flagValues, availabilityZoneFlag)
delete(flagValues, labelFlag)
delete(flagValues, bootVolumeSourceIdFlag)
Expand All @@ -182,6 +185,7 @@ func TestParseInput(t *testing.T) {
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.AffinityGroup = nil
model.AgentProvisioningPolicy = nil
model.AvailabilityZone = nil
model.Labels = nil
model.BootVolumeSourceId = nil
Expand Down Expand Up @@ -327,6 +331,26 @@ func TestParseInput(t *testing.T) {
model.ImageId = nil
}),
},
{
description: "valid with agent-provisioned flag missing",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, agentProvisioningPolicyFlag)
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.AgentProvisioningPolicy = nil
}),
},
Comment thread
aeter marked this conversation as resolved.
{
description: "agent-provisioned flag properly handled",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[agentProvisioningPolicyFlag] = "ALWAYS"
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.AgentProvisioningPolicy = utils.Ptr("ALWAYS")
}),
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -360,6 +384,19 @@ func TestBuildRequest(t *testing.T) {
},
expectedRequest: fixtureRequiredRequest(),
},
{
description: "with provisioned agent",
model: fixtureInputModel(func(model *inputModel) {
model.AgentProvisioningPolicy = utils.Ptr("ALWAYS")
}),
expectedRequest: fixtureRequest(func(request *iaas.ApiCreateServerRequest) {
payload := fixturePayload()
payload.Agent = &iaas.ServerAgent{
Provisioned: utils.Ptr(true),
}
*request = (*request).CreateServerPayload(payload)
}),
},
}

for _, tt := range tests {
Expand Down
5 changes: 5 additions & 0 deletions internal/cmd/server/describe/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ func outputResult(p *print.Printer, outputFormat string, server *iaas.Server) er
table.AddSeparator()
}

if server.Agent != nil && server.Agent.Provisioned != nil {
table.AddRow("AGENT", *server.Agent.Provisioned)
table.AddSeparator()
}

if server.MachineType != nil {
table.AddRow("MACHINE TYPE", *server.MachineType)
table.AddSeparator()
Expand Down
8 changes: 7 additions & 1 deletion internal/cmd/server/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server)
return nil
default:
table := tables.NewTable()
table.SetHeader("ID", "Name", "Status", "Machine Type", "Availability Zones", "Nic IPv4", "Public IPs")
table.SetHeader("ID", "Name", "Status", "Machine Type", "Availability Zones", "Nic IPv4", "Public IPs", "Agent")

for i := range servers {
server := servers[i]
Expand All @@ -186,6 +186,11 @@ func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server)
}
}

agent := ""
if server.Agent != nil {
agent = utils.PtrString(server.Agent.Provisioned)
}

table.AddRow(
utils.PtrString(server.Id),
utils.PtrString(server.Name),
Expand All @@ -194,6 +199,7 @@ func outputResult(p *print.Printer, outputFormat string, servers []iaas.Server)
utils.PtrString(server.AvailabilityZone),
nicIPv4,
publicIPs,
agent,
)
}

Expand Down
2 changes: 2 additions & 0 deletions internal/pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ type Base64PatchedServer struct {
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
UserData *Base64Bytes `json:"userData,omitempty"`
Volumes *[]string `json:"volumes,omitempty"`
Agent *iaas.ServerAgent `json:"agent,omitempty"`
}

// ConvertToBase64PatchedServer converts an iaas.Server to Base64PatchedServer
Expand Down Expand Up @@ -241,6 +242,7 @@ func ConvertToBase64PatchedServer(server *iaas.Server) *Base64PatchedServer {
UpdatedAt: server.UpdatedAt,
UserData: userData,
Volumes: server.Volumes,
Agent: server.Agent,
}
}

Expand Down
21 changes: 21 additions & 0 deletions internal/pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,27 @@ func TestConvertToBase64PatchedServer(t *testing.T) {
UserData: nil,
},
},
{
name: "server with agent",
input: &iaas.Server{
Id: Ptr("server-456"),
Name: Ptr("test-server-2"),
Status: Ptr("STOPPED"),
AvailabilityZone: Ptr("eu01-2"),
MachineType: Ptr("t1.2"),
UserData: &emptyUserData,
Agent: &iaas.ServerAgent{Provisioned: Ptr(true)},
},
expected: &Base64PatchedServer{
Id: Ptr("server-456"),
Name: Ptr("test-server-2"),
Status: Ptr("STOPPED"),
AvailabilityZone: Ptr("eu01-2"),
MachineType: Ptr("t1.2"),
UserData: Ptr(Base64Bytes(emptyUserData)),
Agent: Ptr(iaas.ServerAgent{Provisioned: Ptr(true)}),
},
},
}

for _, tt := range tests {
Expand Down
Loading