fix(server): Handle boot bolume correctly (#749)
* fix(server): Handle boot bolume correctly - Display id and delete_on_termination in datasource - Handle id and delete_on_termination in resource Signed-off-by: Alexander Dahmen <alexander.dahmen@inovex.de> * fixup Signed-off-by: Alexander Dahmen <alexander.dahmen@inovex.de> --------- Signed-off-by: Alexander Dahmen <alexander.dahmen@inovex.de>
This commit is contained in:
parent
f5f99d1709
commit
68859a3fad
9 changed files with 70 additions and 26 deletions
|
|
@ -733,6 +733,7 @@ func TestAccServer(t *testing.T) {
|
|||
// The network interface which was attached by "stackit_server_network_interface_attach" should not appear here
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "network_interfaces.#", "1"),
|
||||
resource.TestCheckNoResourceAttr("stackit_server.server", "network_interfaces.1"),
|
||||
resource.TestCheckResourceAttrSet("stackit_server.server", "boot_volume.id"),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "boot_volume.size", serverResource["size"]),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "boot_volume.source_type", serverResource["source_type"]),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "boot_volume.source_id", serverResource["source_id"]),
|
||||
|
|
@ -871,6 +872,9 @@ func TestAccServer(t *testing.T) {
|
|||
),
|
||||
resource.TestCheckResourceAttrSet("stackit_network_interface.network_interface", "network_interface_id"),
|
||||
resource.TestCheckResourceAttr("stackit_network_interface.network_interface", "name", networkInterfaceResource["name"]),
|
||||
// Boot volume
|
||||
resource.TestCheckResourceAttrSet("data.stackit_server.server", "boot_volume.id"),
|
||||
resource.TestCheckResourceAttr("data.stackit_server.server", "boot_volume.delete_on_termination", serverResource["delete_on_termination"]),
|
||||
),
|
||||
},
|
||||
// Import
|
||||
|
|
@ -1028,8 +1032,8 @@ func TestAccServer(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_network.network", "network_id"),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "name", fmt.Sprintf("%s-updated", networkResource["name"])),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.#", "2"),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.0", networkResource["nameserver0"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "nameservers.1", networkResource["nameserver1"]),
|
||||
resource.TestCheckTypeSetElemAttr("stackit_network.network", "nameservers.*", networkResource["nameserver0"]),
|
||||
resource.TestCheckTypeSetElemAttr("stackit_network.network", "nameservers.*", networkResource["nameserver1"]),
|
||||
resource.TestCheckResourceAttr("stackit_network.network", "ipv4_gateway", networkResource["ipv4_gateway"]),
|
||||
|
||||
// Server
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/diag"
|
||||
|
|
@ -18,7 +19,6 @@ import (
|
|||
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
|
||||
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils"
|
||||
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
|
||||
)
|
||||
|
||||
|
|
@ -46,6 +46,11 @@ type DataSourceModel struct {
|
|||
UpdatedAt types.String `tfsdk:"updated_at"`
|
||||
}
|
||||
|
||||
var bootVolumeDataTypes = map[string]attr.Type{
|
||||
"id": basetypes.StringType{},
|
||||
"delete_on_termination": basetypes.BoolType{},
|
||||
}
|
||||
|
||||
// NewServerDataSource is a helper function to simplify the provider implementation.
|
||||
func NewServerDataSource() datasource.DataSource {
|
||||
return &serverDataSource{}
|
||||
|
|
@ -139,20 +144,8 @@ func (r *serverDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
|
|||
Description: "The boot volume for the server",
|
||||
Computed: true,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"performance_class": schema.StringAttribute{
|
||||
Description: "The performance class of the server.",
|
||||
Computed: true,
|
||||
},
|
||||
"size": schema.Int64Attribute{
|
||||
Description: "The size of the boot volume in GB.",
|
||||
Computed: true,
|
||||
},
|
||||
"type": schema.StringAttribute{
|
||||
Description: "The type of the source. " + utils.SupportedValuesDocumentation(supportedSourceTypes),
|
||||
Computed: true,
|
||||
},
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The ID of the source, either image ID or volume ID",
|
||||
Description: "The ID of the boot volume",
|
||||
Computed: true,
|
||||
},
|
||||
"delete_on_termination": schema.BoolAttribute{
|
||||
|
|
@ -312,6 +305,19 @@ func mapDataSourceFields(ctx context.Context, serverResp *iaas.Server, model *Da
|
|||
model.NetworkInterfaces = types.ListNull(types.StringType)
|
||||
}
|
||||
|
||||
if serverResp.BootVolume != nil {
|
||||
bootVolume, diags := types.ObjectValue(bootVolumeDataTypes, map[string]attr.Value{
|
||||
"id": types.StringPointerValue(serverResp.BootVolume.Id),
|
||||
"delete_on_termination": types.BoolPointerValue(serverResp.BootVolume.DeleteOnTermination),
|
||||
})
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to map bootVolume: %w", core.DiagsToError(diags))
|
||||
}
|
||||
model.BootVolume = bootVolume
|
||||
} else {
|
||||
model.BootVolume = types.ObjectNull(bootVolumeDataTypes)
|
||||
}
|
||||
|
||||
model.AvailabilityZone = types.StringPointerValue(serverResp.AvailabilityZone)
|
||||
model.ServerId = types.StringValue(serverId)
|
||||
model.MachineType = types.StringPointerValue(serverResp.MachineType)
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ type Model struct {
|
|||
|
||||
// Struct corresponding to Model.BootVolume
|
||||
type bootVolumeModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
PerformanceClass types.String `tfsdk:"performance_class"`
|
||||
Size types.Int64 `tfsdk:"size"`
|
||||
SourceType types.String `tfsdk:"source_type"`
|
||||
|
|
@ -89,6 +90,7 @@ var bootVolumeTypes = map[string]attr.Type{
|
|||
"source_type": basetypes.StringType{},
|
||||
"source_id": basetypes.StringType{},
|
||||
"delete_on_termination": basetypes.BoolType{},
|
||||
"id": basetypes.StringType{},
|
||||
}
|
||||
|
||||
// NewServerResource is a helper function to simplify the provider implementation.
|
||||
|
|
@ -253,6 +255,13 @@ func (r *serverResource) Schema(_ context.Context, _ resource.SchemaRequest, res
|
|||
objectplanmodifier.RequiresReplace(),
|
||||
},
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The ID of the boot volume",
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"performance_class": schema.StringAttribute{
|
||||
Description: "The performance class of the server.",
|
||||
Optional: true,
|
||||
|
|
@ -911,6 +920,34 @@ func mapFields(ctx context.Context, serverResp *iaas.Server, model *Model) error
|
|||
model.NetworkInterfaces = types.ListNull(types.StringType)
|
||||
}
|
||||
|
||||
if serverResp.BootVolume != nil {
|
||||
// convert boot volume model
|
||||
var bootVolumeModel = &bootVolumeModel{}
|
||||
if !(model.BootVolume.IsNull() || model.BootVolume.IsUnknown()) {
|
||||
diags := model.BootVolume.As(ctx, bootVolumeModel, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to map bootVolume: %w", core.DiagsToError(diags))
|
||||
}
|
||||
}
|
||||
|
||||
// Only the id and delete_on_termination is returned via response.
|
||||
// Take the other values from the model.
|
||||
bootVolume, diags := types.ObjectValue(bootVolumeTypes, map[string]attr.Value{
|
||||
"id": types.StringPointerValue(serverResp.BootVolume.Id),
|
||||
"delete_on_termination": types.BoolPointerValue(serverResp.BootVolume.DeleteOnTermination),
|
||||
"source_id": bootVolumeModel.SourceId,
|
||||
"size": bootVolumeModel.Size,
|
||||
"source_type": bootVolumeModel.SourceType,
|
||||
"performance_class": bootVolumeModel.PerformanceClass,
|
||||
})
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to map bootVolume: %w", core.DiagsToError(diags))
|
||||
}
|
||||
model.BootVolume = bootVolume
|
||||
} else {
|
||||
model.BootVolume = types.ObjectNull(bootVolumeTypes)
|
||||
}
|
||||
|
||||
model.ServerId = types.StringValue(serverId)
|
||||
model.MachineType = types.StringPointerValue(serverResp.MachineType)
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,7 @@ func TestToCreatePayload(t *testing.T) {
|
|||
"source_type": types.StringValue("type"),
|
||||
"source_id": types.StringValue("id"),
|
||||
"delete_on_termination": types.BoolUnknown(),
|
||||
"id": types.StringValue("id"),
|
||||
}),
|
||||
ImageId: types.StringValue("image"),
|
||||
KeypairName: types.StringValue("keypair"),
|
||||
|
|
@ -234,6 +235,7 @@ func TestToCreatePayload(t *testing.T) {
|
|||
"source_type": types.StringValue("image"),
|
||||
"source_id": types.StringValue("id"),
|
||||
"delete_on_termination": types.BoolValue(true),
|
||||
"id": types.StringValue("id"),
|
||||
}),
|
||||
ImageId: types.StringValue("image"),
|
||||
KeypairName: types.StringValue("keypair"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue