Skip to content

feat(instance): add data source for instance_server_type #3257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ func Provider(config *Config) plugin.ProviderFunc {
"scaleway_instance_security_group": instance.DataSourceSecurityGroup(),
"scaleway_instance_server": instance.DataSourceServer(),
"scaleway_instance_servers": instance.DataSourceServers(),
"scaleway_instance_server_type": instance.DataSourceServerType(),
"scaleway_instance_snapshot": instance.DataSourceSnapshot(),
"scaleway_instance_volume": instance.DataSourceVolume(),
"scaleway_iot_device": iot.DataSourceDevice(),
Expand Down
283 changes: 283 additions & 0 deletions internal/services/instance/server_type_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package instance

import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
)

func DataSourceServerType() *schema.Resource {
return &schema.Resource{
ReadContext: DataSourceInstanceServerTypeRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "The name of the server type",
// TODO: add alt names ??
},
"arch": {
Type: schema.TypeString,
Computed: true,
Description: "The architecture of the server type",
},
"cpu": {
Type: schema.TypeInt,
Computed: true,
Description: "The number of CPU cores of the server type",
},
"ram": {
Type: schema.TypeInt,
Computed: true,
Description: "The number of bytes of RAM of the server type",
},
"gpu": {
Type: schema.TypeInt,
Computed: true,
Description: "The number of GPUs of the server type",
},
"volumes": {
Type: schema.TypeList,
Computed: true,
Description: "The specifications of volumes allowed for the server type",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"min_size_total": {
Type: schema.TypeInt,
Computed: true,
Description: "The minimum total size in bytes of volumes allowed on the server type",
},
"max_size_total": {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum total size in bytes of volumes allowed on the server type",
},
"min_size_per_local_volume": {
Type: schema.TypeInt,
Computed: true,
Description: "The minimum size in bytes per local volume allowed on the server type",
},
"max_size_per_local_volume": {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum size in bytes per local volume allowed on the server type",
},
"scratch_storage_max_size": {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum size in bytes of the scratch volume allowed on the server type",
},
"block_storage": {
Type: schema.TypeBool,
Computed: true,
Description: "Whether block storage is allowed on the server type",
},
},
},
},
"capabilities": {
Type: schema.TypeList,
Computed: true,
Description: "The specific capabilities of the server type",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"boot_types": {
Type: schema.TypeList,
Computed: true,
Description: "The list of boot types allowed for the server type",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
// "placement_groups": {
// TODO: Field not in sdk, but equals 'true' for every server type
// Type: schema.TypeBool,
// Computed: true,
// Description: "Whether placement groups are allowed on the server type",
// },
// "hot_snapshots_local_volume": {
// TODO: Field not in sdk so how do we get this information ??
// Type: schema.TypeBool,
// Computed: true,
// Description: "Whether hot_snapshots_local_volume is allowed on the server type", //TODO: rewrite this
// },
// "private_networks": {
// TODO: Field not in sdk, but equals '8' for every server type
// Type: schema.TypeInt,
// Computed: true,
// Description: "The number of private networks allowed on the server type",
// },
"max_file_systems": {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum number of files systems that can be attached to the server type",
},
},
},
},
"network": {
Type: schema.TypeList,
Computed: true,
Description: "The network specifications of the server type",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"internal_bandwidth": {
Type: schema.TypeInt,
Computed: true,
Description: "The internal bandwidth of the server type",
},
"public_bandwidth": {
Type: schema.TypeInt,
Computed: true,
Description: "The public bandwidth of the server type",
},
"block_bandwidth": {
Type: schema.TypeInt,
Computed: true,
Description: "The block bandwidth of the server type",
},
// TODO: Equals 'true' for every server type, add it anyway ?
// "ipv6_support": {
// Type: schema.TypeBool,
// Computed: true,
// Description: "Whether IPv6 is supported on the server type",
// },
},
},
},
"hourly_price": {
Type: schema.TypeFloat,
Computed: true,
Description: "The hourly price of the server type in euro",
},
"end_of_service": {
Type: schema.TypeBool,
Computed: true,
Description: "Whether the server type will soon reach End Of Service",
},
"availability": {
Type: schema.TypeString,
Computed: true,
Description: "Whether the server type is available in the zone",
},
"zone": zonal.Schema(),
},
}
}

func DataSourceInstanceServerTypeRead(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics {
instanceAPI, zone, err := newAPIWithZone(d, i) // TODO: document zone field
if err != nil {
return diag.FromErr(err)
}

serverTypes, err := instanceAPI.ListServersTypes(&instance.ListServersTypesRequest{
Zone: zone,
}, scw.WithAllPages(), scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

name := d.Get("name").(string)

serverType, ok := serverTypes.Servers[name]
if !ok {
return diag.Errorf("server type %s not found", name)
}

d.SetId(name)
_ = d.Set("name", name)
_ = d.Set("arch", serverType.Arch)
_ = d.Set("cpu", int(serverType.Ncpus))
_ = d.Set("ram", int(serverType.RAM))
_ = d.Set("volumes", flattenVolumeConstraints(serverType))
_ = d.Set("capabilities", flattenCapabilities(serverType.Capabilities))
_ = d.Set("network", flattenNetwork(serverType))
_ = d.Set("hourly_price", serverType.HourlyPrice)
_ = d.Set("end_of_service", serverType.EndOfService)

if serverType.Gpu != nil {
_ = d.Set("gpu", int(*serverType.Gpu))
}

// Availability
availabilitiesResponse, err := instanceAPI.GetServerTypesAvailability(&instance.GetServerTypesAvailabilityRequest{
Zone: zone,
}, scw.WithAllPages(), scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

if availability, exists := availabilitiesResponse.Servers[name]; exists {
_ = d.Set("availability", availability.Availability.String())
}

return nil
}

func flattenVolumeConstraints(serverType *instance.ServerType) []map[string]any {
flattened := map[string]any{}

if serverType.VolumesConstraint != nil {
flattened["min_size_total"] = serverType.VolumesConstraint.MinSize
flattened["max_size_total"] = serverType.VolumesConstraint.MaxSize
}

if serverType.PerVolumeConstraint != nil && serverType.PerVolumeConstraint.LSSD != nil {
flattened["min_size_per_local_volume"] = serverType.PerVolumeConstraint.LSSD.MinSize
flattened["max_size_per_local_volume"] = serverType.PerVolumeConstraint.LSSD.MaxSize
}

if serverType.ScratchStorageMaxSize != nil {
flattened["scratch_storage_max_size"] = serverType.ScratchStorageMaxSize
}

if serverType.Capabilities != nil && serverType.Capabilities.BlockStorage != nil {
flattened["block_storage"] = *serverType.Capabilities.BlockStorage
}

return []map[string]any{flattened}
}

func flattenCapabilities(capabilities *instance.ServerTypeCapabilities) []map[string]any {
if capabilities == nil {
return nil
}

bootTypes := []string(nil)
for _, bootType := range capabilities.BootTypes {
bootTypes = append(bootTypes, bootType.String())
}

flattened := map[string]any{
"max_file_systems": capabilities.MaxFileSystems,
"boot_types": bootTypes,
}

return []map[string]any{flattened}
}

func flattenNetwork(serverType *instance.ServerType) []map[string]any {
if serverType.Network == nil {
return nil
}

flattened := map[string]any{}

if serverType.Network.SumInternalBandwidth != nil {
flattened["internal_bandwidth"] = *serverType.Network.SumInternalBandwidth
}

if serverType.Network.SumInternetBandwidth != nil {
flattened["public_bandwidth"] = *serverType.Network.SumInternetBandwidth
}

if serverType.BlockBandwidth != nil {
flattened["block_bandwidth"] = *serverType.BlockBandwidth
}

return []map[string]any{flattened}
}
Loading
Loading