Skip to content

Commit c254da0

Browse files
committed
data source instance_server_type implem + tests + cassettes
1 parent c10d387 commit c254da0

File tree

5 files changed

+30130
-0
lines changed

5 files changed

+30130
-0
lines changed

internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ func Provider(config *Config) plugin.ProviderFunc {
290290
"scaleway_instance_security_group": instance.DataSourceSecurityGroup(),
291291
"scaleway_instance_server": instance.DataSourceServer(),
292292
"scaleway_instance_servers": instance.DataSourceServers(),
293+
"scaleway_instance_server_type": instance.DataSourceServerType(),
293294
"scaleway_instance_snapshot": instance.DataSourceSnapshot(),
294295
"scaleway_instance_volume": instance.DataSourceVolume(),
295296
"scaleway_iot_device": iot.DataSourceDevice(),
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
package instance
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
9+
"github.com/scaleway/scaleway-sdk-go/scw"
10+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/zonal"
11+
)
12+
13+
func DataSourceServerType() *schema.Resource {
14+
return &schema.Resource{
15+
ReadContext: DataSourceInstanceServerTypeRead,
16+
Schema: map[string]*schema.Schema{
17+
"name": {
18+
Type: schema.TypeString,
19+
Required: true,
20+
Description: "The name of the server type",
21+
// TODO: add alt names ??
22+
},
23+
"arch": {
24+
Type: schema.TypeString,
25+
Computed: true,
26+
Description: "The architecture of the server type",
27+
},
28+
"cpu": {
29+
Type: schema.TypeInt,
30+
Computed: true,
31+
Description: "The number of CPU cores of the server type",
32+
},
33+
"ram": {
34+
Type: schema.TypeInt,
35+
Computed: true,
36+
Description: "The number of bytes of RAM of the server type",
37+
},
38+
"gpu": {
39+
Type: schema.TypeInt,
40+
Computed: true,
41+
Description: "The number of GPUs of the server type",
42+
},
43+
"volumes": {
44+
Type: schema.TypeList,
45+
Computed: true,
46+
Description: "The specifications of volumes allowed for the server type",
47+
Elem: &schema.Resource{
48+
Schema: map[string]*schema.Schema{
49+
"min_size_total": {
50+
Type: schema.TypeInt,
51+
Computed: true,
52+
Description: "The minimum total size in bytes of volumes allowed on the server type",
53+
},
54+
"max_size_total": {
55+
Type: schema.TypeInt,
56+
Computed: true,
57+
Description: "The maximum total size in bytes of volumes allowed on the server type",
58+
},
59+
"min_size_per_local_volume": {
60+
Type: schema.TypeInt,
61+
Computed: true,
62+
Description: "The minimum size in bytes per local volume allowed on the server type",
63+
},
64+
"max_size_per_local_volume": {
65+
Type: schema.TypeInt,
66+
Computed: true,
67+
Description: "The maximum size in bytes per local volume allowed on the server type",
68+
},
69+
"scratch_storage_max_size": {
70+
Type: schema.TypeInt,
71+
Computed: true,
72+
Description: "The maximum size in bytes of the scratch volume allowed on the server type",
73+
},
74+
"block_storage": {
75+
Type: schema.TypeBool,
76+
Computed: true,
77+
Description: "Whether block storage is allowed on the server type",
78+
},
79+
},
80+
},
81+
},
82+
"capabilities": {
83+
Type: schema.TypeList,
84+
Computed: true,
85+
Description: "The specific capabilities of the server type",
86+
Elem: &schema.Resource{
87+
Schema: map[string]*schema.Schema{
88+
"boot_types": {
89+
Type: schema.TypeList,
90+
Computed: true,
91+
Description: "The list of boot types allowed for the server type",
92+
Elem: &schema.Schema{
93+
Type: schema.TypeString,
94+
},
95+
},
96+
// "placement_groups": {
97+
// TODO: Field not in sdk, but equals 'true' for every server type
98+
// Type: schema.TypeBool,
99+
// Computed: true,
100+
// Description: "Whether placement groups are allowed on the server type",
101+
// },
102+
// "hot_snapshots_local_volume": {
103+
// TODO: Field not in sdk so how do we get this information ??
104+
// Type: schema.TypeBool,
105+
// Computed: true,
106+
// Description: "Whether hot_snapshots_local_volume is allowed on the server type", //TODO: rewrite this
107+
// },
108+
// "private_networks": {
109+
// TODO: Field not in sdk, but equals '8' for every server type
110+
// Type: schema.TypeInt,
111+
// Computed: true,
112+
// Description: "The number of private networks allowed on the server type",
113+
// },
114+
"max_file_systems": {
115+
Type: schema.TypeInt,
116+
Computed: true,
117+
Description: "The maximum number of files systems that can be attached to the server type",
118+
},
119+
},
120+
},
121+
},
122+
"network": {
123+
Type: schema.TypeList,
124+
Computed: true,
125+
Description: "The network specifications of the server type",
126+
Elem: &schema.Resource{
127+
Schema: map[string]*schema.Schema{
128+
"internal_bandwidth": {
129+
Type: schema.TypeInt,
130+
Computed: true,
131+
Description: "The internal bandwidth of the server type",
132+
},
133+
"public_bandwidth": {
134+
Type: schema.TypeInt,
135+
Computed: true,
136+
Description: "The public bandwidth of the server type",
137+
},
138+
"block_bandwidth": {
139+
Type: schema.TypeInt,
140+
Computed: true,
141+
Description: "The block bandwidth of the server type",
142+
},
143+
// TODO: Equals 'true' for every server type, add it anyway ?
144+
// "ipv6_support": {
145+
// Type: schema.TypeBool,
146+
// Computed: true,
147+
// Description: "Whether IPv6 is supported on the server type",
148+
// },
149+
},
150+
},
151+
},
152+
"hourly_price": {
153+
Type: schema.TypeFloat,
154+
Computed: true,
155+
Description: "The hourly price of the server type in euro",
156+
},
157+
"end_of_service": {
158+
Type: schema.TypeBool,
159+
Computed: true,
160+
Description: "Whether the server type will soon reach End Of Service",
161+
},
162+
"availability": {
163+
Type: schema.TypeString,
164+
Computed: true,
165+
Description: "Whether the server type is available in the zone",
166+
},
167+
"zone": zonal.Schema(),
168+
},
169+
}
170+
}
171+
172+
func DataSourceInstanceServerTypeRead(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics {
173+
instanceAPI, zone, err := newAPIWithZone(d, i) // TODO: document zone field
174+
if err != nil {
175+
return diag.FromErr(err)
176+
}
177+
178+
serverTypes, err := instanceAPI.ListServersTypes(&instance.ListServersTypesRequest{
179+
Zone: zone,
180+
}, scw.WithAllPages(), scw.WithContext(ctx))
181+
if err != nil {
182+
return diag.FromErr(err)
183+
}
184+
185+
name := d.Get("name").(string)
186+
187+
serverType, ok := serverTypes.Servers[name]
188+
if !ok {
189+
return diag.Errorf("server type %s not found", name)
190+
}
191+
192+
d.SetId(name)
193+
_ = d.Set("name", name)
194+
_ = d.Set("arch", serverType.Arch)
195+
_ = d.Set("cpu", serverType.Ncpus)
196+
_ = d.Set("ram", serverType.RAM)
197+
_ = d.Set("gpu", serverType.Gpu)
198+
_ = d.Set("volumes", flattenVolumeConstraints(serverType))
199+
_ = d.Set("capabilities", flattenCapabilities(serverType.Capabilities))
200+
_ = d.Set("network", flattenNetwork(serverType))
201+
_ = d.Set("hourly_price", serverType.HourlyPrice)
202+
_ = d.Set("end_of_service", serverType.EndOfService)
203+
204+
// Availability
205+
availabilitiesResponse, err := instanceAPI.GetServerTypesAvailability(&instance.GetServerTypesAvailabilityRequest{
206+
Zone: zone,
207+
}, scw.WithAllPages(), scw.WithContext(ctx))
208+
if err != nil {
209+
return diag.FromErr(err)
210+
}
211+
212+
if availability, exists := availabilitiesResponse.Servers[name]; exists {
213+
_ = d.Set("availability", availability.Availability.String())
214+
}
215+
216+
return nil
217+
}
218+
219+
func flattenVolumeConstraints(serverType *instance.ServerType) []map[string]any {
220+
flattened := map[string]any{}
221+
222+
if serverType.VolumesConstraint != nil {
223+
flattened["min_size_total"] = serverType.VolumesConstraint.MinSize
224+
flattened["max_size_total"] = serverType.VolumesConstraint.MaxSize
225+
}
226+
227+
if serverType.PerVolumeConstraint != nil && serverType.PerVolumeConstraint.LSSD != nil {
228+
flattened["min_size_per_local_volume"] = serverType.PerVolumeConstraint.LSSD.MinSize
229+
flattened["max_size_per_local_volume"] = serverType.PerVolumeConstraint.LSSD.MaxSize
230+
}
231+
232+
if serverType.ScratchStorageMaxSize != nil {
233+
flattened["scratch_storage_max_size"] = serverType.ScratchStorageMaxSize
234+
}
235+
236+
if serverType.Capabilities != nil && serverType.Capabilities.BlockStorage != nil {
237+
flattened["block_storage"] = *serverType.Capabilities.BlockStorage
238+
}
239+
240+
return []map[string]any{flattened}
241+
}
242+
243+
func flattenCapabilities(capabilities *instance.ServerTypeCapabilities) []map[string]any {
244+
if capabilities == nil {
245+
return nil
246+
}
247+
248+
bootTypes := []string(nil)
249+
for _, bootType := range capabilities.BootTypes {
250+
bootTypes = append(bootTypes, bootType.String())
251+
}
252+
253+
flattened := map[string]any{
254+
"max_file_systems": capabilities.MaxFileSystems,
255+
"boot_types": bootTypes,
256+
}
257+
258+
return []map[string]any{flattened}
259+
}
260+
261+
func flattenNetwork(serverType *instance.ServerType) []map[string]any {
262+
if serverType.Network == nil {
263+
return nil
264+
}
265+
266+
flattened := map[string]any{}
267+
268+
if serverType.Network.SumInternalBandwidth != nil {
269+
flattened["internal_bandwidth"] = *serverType.Network.SumInternalBandwidth
270+
}
271+
272+
if serverType.Network.SumInternetBandwidth != nil {
273+
flattened["public_bandwidth"] = *serverType.Network.SumInternetBandwidth
274+
}
275+
276+
if serverType.BlockBandwidth != nil {
277+
flattened["block_bandwidth"] = *serverType.BlockBandwidth
278+
}
279+
280+
return []map[string]any{flattened}
281+
}

0 commit comments

Comments
 (0)