forked from mirrors/terraform-provider-binarylane
85f65c9391
* 👆 bump OpenAPI schema to v0.39.1, update dependencies * 📑 Update README with latest regions/sizes/images
230 lines
8.5 KiB
Go
230 lines
8.5 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"slices"
|
|
"strings"
|
|
"terraform-provider-binarylane/internal/resources"
|
|
|
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
|
"github.com/hashicorp/terraform-plugin-framework/diag"
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
)
|
|
|
|
// Ensure the implementation satisfies the expected interfaces.
|
|
var (
|
|
_ datasource.DataSource = &serverDataSource{}
|
|
_ datasource.DataSourceWithConfigure = &serverDataSource{}
|
|
)
|
|
|
|
func NewServerDataSource() datasource.DataSource {
|
|
return &serverDataSource{}
|
|
}
|
|
|
|
type serverDataSource struct {
|
|
bc *BinarylaneClient
|
|
}
|
|
|
|
type serverDataModel struct {
|
|
resources.ServerModel
|
|
PublicIpv4Addresses types.List `tfsdk:"public_ipv4_addresses"`
|
|
PrivateIPv4Addresses types.List `tfsdk:"private_ipv4_addresses"`
|
|
PublicIpv6Addresses types.List `tfsdk:"public_ipv6_addresses"`
|
|
PrivateIpv6Addresses types.List `tfsdk:"private_ipv6_addresses"`
|
|
Permalink types.String `tfsdk:"permalink"`
|
|
Memory types.Int32 `tfsdk:"memory"`
|
|
Disk types.Int32 `tfsdk:"disk"`
|
|
SourceAndDestinationCheck types.Bool `tfsdk:"source_and_destination_check"`
|
|
}
|
|
|
|
func (d *serverDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
|
if req.ProviderData == nil {
|
|
return
|
|
}
|
|
|
|
bc, ok := req.ProviderData.(BinarylaneClient)
|
|
if !ok {
|
|
resp.Diagnostics.AddError(
|
|
"Unexpected Data Source Configure Type",
|
|
fmt.Sprintf("Expected *BinarylaneClient, got: %T.", req.ProviderData),
|
|
)
|
|
|
|
return
|
|
}
|
|
|
|
d.bc = &bc
|
|
}
|
|
|
|
func (d *serverDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
|
resp.TypeName = req.ProviderTypeName + "_server"
|
|
}
|
|
|
|
func (d *serverDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
|
ds, err := convertResourceSchemaToDataSourceSchema(
|
|
serverSchema(ctx),
|
|
AttributeConfig{
|
|
RequiredAttributes: &[]string{"id"},
|
|
ExcludedAttributes: &[]string{"password", "public_ipv4_count", "password_change_supported", "timeouts"},
|
|
})
|
|
if err != nil {
|
|
resp.Diagnostics.AddError("Failed to convert resource schema to data source schema", err.Error())
|
|
return
|
|
}
|
|
resp.Schema = *ds
|
|
resp.Schema.Description = "Retrieve details about a BinaryLane Server."
|
|
}
|
|
|
|
func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
|
var diag diag.Diagnostics
|
|
var data serverDataModel
|
|
|
|
// Read Terraform configuration data into the model
|
|
diags := req.Config.Get(ctx, &data)
|
|
resp.Diagnostics.Append(diags...)
|
|
|
|
if resp.Diagnostics.HasError() {
|
|
return
|
|
}
|
|
|
|
// Read server
|
|
serverResp, err := d.bc.client.GetServersServerIdWithResponse(ctx, data.Id.ValueInt64())
|
|
if err != nil {
|
|
resp.Diagnostics.AddError(
|
|
fmt.Sprintf("Error reading server: name=%s, id=%s", data.Name.ValueString(), data.Id.String()),
|
|
err.Error(),
|
|
)
|
|
return
|
|
}
|
|
if serverResp.StatusCode() != http.StatusOK {
|
|
resp.Diagnostics.AddError(
|
|
fmt.Sprintf("Unexpected HTTP status code reading server: name=%s, id=%s", data.Name.ValueString(), data.Id.String()),
|
|
string(serverResp.Body),
|
|
)
|
|
return
|
|
}
|
|
|
|
data.Id = types.Int64Value(serverResp.JSON200.Server.Id)
|
|
data.Name = types.StringValue(serverResp.JSON200.Server.Name)
|
|
data.Image = types.StringValue(*serverResp.JSON200.Server.Image.Slug)
|
|
data.Region = types.StringValue(serverResp.JSON200.Server.Region.Slug)
|
|
data.Size = types.StringValue(serverResp.JSON200.Server.Size.Slug)
|
|
data.Backups = types.BoolValue(serverResp.JSON200.Server.NextBackupWindow != nil)
|
|
data.Ipv6 = types.BoolValue(len(serverResp.JSON200.Server.Networks.V6) > 0)
|
|
data.PortBlocking = types.BoolValue(serverResp.JSON200.Server.Networks.PortBlocking)
|
|
data.VpcId = types.Int64PointerValue(serverResp.JSON200.Server.VpcId)
|
|
data.Permalink = types.StringValue(*serverResp.JSON200.Server.Permalink)
|
|
data.Memory = types.Int32Value(serverResp.JSON200.Server.Memory)
|
|
data.Disk = types.Int32Value(serverResp.JSON200.Server.Disk)
|
|
data.SourceAndDestinationCheck = types.BoolPointerValue(serverResp.JSON200.Server.Networks.SourceAndDestinationCheck)
|
|
data.SeparatePrivateNetworkInterface = types.BoolPointerValue(serverResp.JSON200.Server.Networks.SeparatePrivateNetworkInterface)
|
|
|
|
if serverResp.JSON200.Server.VpcId == nil {
|
|
data.VpcIpv4Address = types.StringNull()
|
|
} else if len(serverResp.JSON200.Server.Networks.V4) > 0 {
|
|
for _, v4address := range serverResp.JSON200.Server.Networks.V4 {
|
|
// Skip addresses in 172.21.0.0/16, these are BL internal addresses that are not part of the user's VPC
|
|
if v4address.Type == "private" && !strings.HasPrefix(v4address.IpAddress, "172.21.") {
|
|
data.VpcIpv4Address = types.StringValue(v4address.IpAddress)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
advFeat := serverResp.JSON200.Server.AdvancedFeatures.EnabledAdvancedFeatures
|
|
data.AdvancedFeatures, diags = resources.NewAdvancedFeaturesValue(
|
|
resources.AdvancedFeaturesValue{}.AttributeTypes(ctx),
|
|
map[string]attr.Value{
|
|
"emulated_hyperv": types.BoolValue(slices.Contains(advFeat, "emulated-hyperv")),
|
|
"emulated_devices": types.BoolValue(slices.Contains(advFeat, "emulated-devices")),
|
|
"nested_virt": types.BoolValue(slices.Contains(advFeat, "nested-virt")),
|
|
"driver_disk": types.BoolValue(slices.Contains(advFeat, "driver-disk")),
|
|
"unset_uuid": types.BoolValue(slices.Contains(advFeat, "unset-uuid")),
|
|
"local_rtc": types.BoolValue(slices.Contains(advFeat, "local-rtc")),
|
|
"emulated_tpm": types.BoolValue(slices.Contains(advFeat, "emulated-tpm")),
|
|
"cloud_init": types.BoolValue(slices.Contains(advFeat, "cloud-init")),
|
|
"qemu_guest_agent": types.BoolValue(slices.Contains(advFeat, "qemu-guest-agent")),
|
|
"uefi_boot": types.BoolValue(slices.Contains(advFeat, "uefi-boot")),
|
|
})
|
|
if diags.HasError() {
|
|
data.AdvancedFeatures = resources.NewAdvancedFeaturesValueUnknown()
|
|
}
|
|
|
|
publicIpv4Addresses := []string{}
|
|
privateIpv4Addresses := []string{}
|
|
|
|
for _, v4address := range serverResp.JSON200.Server.Networks.V4 {
|
|
if v4address.Type == "public" {
|
|
publicIpv4Addresses = append(publicIpv4Addresses, v4address.IpAddress)
|
|
} else {
|
|
privateIpv4Addresses = append(privateIpv4Addresses, v4address.IpAddress)
|
|
}
|
|
}
|
|
|
|
tfPublicIpv4Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv4Addresses)
|
|
diags.Append(diag...)
|
|
if diag.HasError() {
|
|
data.PublicIpv4Addresses = types.ListUnknown(data.PublicIpv4Addresses.ElementType(ctx))
|
|
} else {
|
|
data.PublicIpv4Addresses = tfPublicIpv4Addresses
|
|
}
|
|
|
|
tfPrivateIpv4Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv4Addresses)
|
|
diags.Append(diag...)
|
|
if diag.HasError() {
|
|
data.PrivateIPv4Addresses = types.ListUnknown(data.PrivateIPv4Addresses.ElementType(ctx))
|
|
} else {
|
|
data.PrivateIPv4Addresses = tfPrivateIpv4Addresses
|
|
}
|
|
|
|
publicIpv6Addresses := []string{}
|
|
privateIpv6Addresses := []string{}
|
|
|
|
for _, v6address := range serverResp.JSON200.Server.Networks.V6 {
|
|
if v6address.Type == "public" {
|
|
publicIpv6Addresses = append(publicIpv6Addresses, v6address.IpAddress)
|
|
} else {
|
|
privateIpv6Addresses = append(privateIpv6Addresses, v6address.IpAddress)
|
|
}
|
|
}
|
|
|
|
tfPublicIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, publicIpv6Addresses)
|
|
diags.Append(diag...)
|
|
if diag.HasError() {
|
|
data.PublicIpv6Addresses = types.ListUnknown(data.PublicIpv6Addresses.ElementType(ctx))
|
|
} else {
|
|
data.PublicIpv6Addresses = tfPublicIpv6Addresses
|
|
}
|
|
|
|
tfPrivateIpv6Addresses, diag := types.ListValueFrom(ctx, types.StringType, privateIpv6Addresses)
|
|
diags.Append(diag...)
|
|
if diag.HasError() {
|
|
data.PrivateIpv6Addresses = types.ListUnknown(data.PrivateIpv6Addresses.ElementType(ctx))
|
|
} else {
|
|
data.PrivateIpv6Addresses = tfPrivateIpv6Addresses
|
|
}
|
|
|
|
// Get user data script
|
|
userDataResp, err := d.bc.client.GetServersServerIdUserDataWithResponse(ctx, data.Id.ValueInt64())
|
|
if err != nil {
|
|
resp.Diagnostics.AddError(
|
|
fmt.Sprintf("Error reading server user data: id=%s, name=%s", data.Id.String(), data.Name.ValueString()),
|
|
err.Error(),
|
|
)
|
|
return
|
|
}
|
|
if userDataResp.StatusCode() != http.StatusOK {
|
|
resp.Diagnostics.AddError(
|
|
fmt.Sprintf("Unexpected HTTP status %d reading server user data: name=%s, id=%s", userDataResp.StatusCode(), data.Name.ValueString(), data.Id.String()),
|
|
string(userDataResp.Body),
|
|
)
|
|
return
|
|
}
|
|
data.UserData = types.StringPointerValue(userDataResp.JSON200.UserData)
|
|
|
|
// Save data into Terraform state
|
|
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
|
}
|