Allow deleting root volume when deleting server (#651)
Introduce delete_on_termination field. Signed-off-by: Alexander Dahmen <alexander.dahmen@inovex.de>
This commit is contained in:
parent
11875602b8
commit
b6f3c70f15
5 changed files with 100 additions and 14 deletions
|
|
@ -168,6 +168,10 @@ func (r *serverDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
|
|||
Description: "The ID of the source, either image ID or volume ID",
|
||||
Computed: true,
|
||||
},
|
||||
"delete_on_termination": schema.BoolAttribute{
|
||||
Description: "Delete the volume during the termination of the server.",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"image_id": schema.StringAttribute{
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
|
||||
|
|
@ -80,18 +81,20 @@ type Model struct {
|
|||
|
||||
// Struct corresponding to Model.BootVolume
|
||||
type bootVolumeModel struct {
|
||||
PerformanceClass types.String `tfsdk:"performance_class"`
|
||||
Size types.Int64 `tfsdk:"size"`
|
||||
SourceType types.String `tfsdk:"source_type"`
|
||||
SourceId types.String `tfsdk:"source_id"`
|
||||
PerformanceClass types.String `tfsdk:"performance_class"`
|
||||
Size types.Int64 `tfsdk:"size"`
|
||||
SourceType types.String `tfsdk:"source_type"`
|
||||
SourceId types.String `tfsdk:"source_id"`
|
||||
DeleteOnTermination types.Bool `tfsdk:"delete_on_termination"`
|
||||
}
|
||||
|
||||
// Types corresponding to bootVolumeModel
|
||||
var bootVolumeTypes = map[string]attr.Type{
|
||||
"performance_class": basetypes.StringType{},
|
||||
"size": basetypes.Int64Type{},
|
||||
"source_type": basetypes.StringType{},
|
||||
"source_id": basetypes.StringType{},
|
||||
"performance_class": basetypes.StringType{},
|
||||
"size": basetypes.Int64Type{},
|
||||
"source_type": basetypes.StringType{},
|
||||
"source_id": basetypes.StringType{},
|
||||
"delete_on_termination": basetypes.BoolType{},
|
||||
}
|
||||
|
||||
// NewServerResource is a helper function to simplify the provider implementation.
|
||||
|
|
@ -109,6 +112,29 @@ func (r *serverResource) Metadata(_ context.Context, req resource.MetadataReques
|
|||
resp.TypeName = req.ProviderTypeName + "_server"
|
||||
}
|
||||
|
||||
func (r serverResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
|
||||
var model Model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &model)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// convert boot volume model
|
||||
var bootVolume = &bootVolumeModel{}
|
||||
if !(model.BootVolume.IsNull() || model.BootVolume.IsUnknown()) {
|
||||
diags := model.BootVolume.As(ctx, bootVolume, basetypes.ObjectAsOptions{})
|
||||
if diags.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !bootVolume.DeleteOnTermination.IsUnknown() && !bootVolume.DeleteOnTermination.IsNull() && !bootVolume.SourceType.IsUnknown() && !bootVolume.SourceType.IsNull() {
|
||||
if bootVolume.SourceType != types.StringValue("image") {
|
||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring server", "You can only provide `delete_on_termination` for `source_type` `image`.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigValidators validates the resource configuration
|
||||
func (r *serverResource) ConfigValidators(_ context.Context) []resource.ConfigValidator {
|
||||
return []resource.ConfigValidator{
|
||||
|
|
@ -276,6 +302,13 @@ func (r *serverResource) Schema(_ context.Context, _ resource.SchemaRequest, res
|
|||
stringplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
"delete_on_termination": schema.BoolAttribute{
|
||||
Description: "Delete the volume during the termination of the server. Only allowed when `source_type` is `image`.",
|
||||
Optional: true,
|
||||
PlanModifiers: []planmodifier.Bool{
|
||||
boolplanmodifier.RequiresReplace(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"image_id": schema.StringAttribute{
|
||||
|
|
@ -359,7 +392,7 @@ func (r *serverResource) Schema(_ context.Context, _ resource.SchemaRequest, res
|
|||
Computed: true,
|
||||
},
|
||||
"desired_status": schema.StringAttribute{
|
||||
Description: "The desired status of the server resource." + utils.SupportedValuesDocumentation(desiredStatusOptions),
|
||||
Description: "The desired status of the server resource. " + utils.SupportedValuesDocumentation(desiredStatusOptions),
|
||||
Optional: true,
|
||||
Validators: []validator.String{
|
||||
stringvalidator.OneOf(desiredStatusOptions...),
|
||||
|
|
@ -908,6 +941,10 @@ func toCreatePayload(ctx context.Context, model *Model) (*iaas.CreateServerPaylo
|
|||
Type: conversion.StringValueToPointer(bootVolume.SourceType),
|
||||
},
|
||||
}
|
||||
if !bootVolume.DeleteOnTermination.IsNull() && !bootVolume.DeleteOnTermination.IsUnknown() && bootVolume.DeleteOnTermination.ValueBool() {
|
||||
// it is set and true, adjust payload
|
||||
bootVolumePayload.DeleteOnTermination = conversion.BoolValueToPointer(bootVolume.DeleteOnTermination)
|
||||
}
|
||||
}
|
||||
|
||||
var userData *string
|
||||
|
|
|
|||
|
|
@ -191,10 +191,11 @@ func TestToCreatePayload(t *testing.T) {
|
|||
"key": types.StringValue("value"),
|
||||
}),
|
||||
BootVolume: types.ObjectValueMust(bootVolumeTypes, map[string]attr.Value{
|
||||
"performance_class": types.StringValue("class"),
|
||||
"size": types.Int64Value(1),
|
||||
"source_type": types.StringValue("type"),
|
||||
"source_id": types.StringValue("id"),
|
||||
"performance_class": types.StringValue("class"),
|
||||
"size": types.Int64Value(1),
|
||||
"source_type": types.StringValue("type"),
|
||||
"source_id": types.StringValue("id"),
|
||||
"delete_on_termination": types.BoolUnknown(),
|
||||
}),
|
||||
ImageId: types.StringValue("image"),
|
||||
KeypairName: types.StringValue("keypair"),
|
||||
|
|
@ -222,6 +223,48 @@ func TestToCreatePayload(t *testing.T) {
|
|||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"delete on termination is set to true",
|
||||
&Model{
|
||||
Name: types.StringValue("name"),
|
||||
AvailabilityZone: types.StringValue("zone"),
|
||||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
BootVolume: types.ObjectValueMust(bootVolumeTypes, map[string]attr.Value{
|
||||
"performance_class": types.StringValue("class"),
|
||||
"size": types.Int64Value(1),
|
||||
"source_type": types.StringValue("image"),
|
||||
"source_id": types.StringValue("id"),
|
||||
"delete_on_termination": types.BoolValue(true),
|
||||
}),
|
||||
ImageId: types.StringValue("image"),
|
||||
KeypairName: types.StringValue("keypair"),
|
||||
MachineType: types.StringValue("machine_type"),
|
||||
UserData: types.StringValue(userData),
|
||||
},
|
||||
&iaas.CreateServerPayload{
|
||||
Name: utils.Ptr("name"),
|
||||
AvailabilityZone: utils.Ptr("zone"),
|
||||
Labels: &map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
BootVolume: &iaas.CreateServerPayloadBootVolume{
|
||||
PerformanceClass: utils.Ptr("class"),
|
||||
Size: utils.Ptr(int64(1)),
|
||||
Source: &iaas.BootVolumeSource{
|
||||
Type: utils.Ptr("image"),
|
||||
Id: utils.Ptr("id"),
|
||||
},
|
||||
DeleteOnTermination: utils.Ptr(true),
|
||||
},
|
||||
ImageId: utils.Ptr("image"),
|
||||
KeypairName: utils.Ptr("keypair"),
|
||||
MachineType: utils.Ptr("machine_type"),
|
||||
UserData: utils.Ptr(base64EncodedUserData),
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue