Skip to content

Commit 6f1e76d

Browse files
author
Krauss Vesset
committed
feat(instance) public cloud instances with multiple network interfaces
1 parent 42d688c commit 6f1e76d

File tree

3 files changed

+190
-79
lines changed

3 files changed

+190
-79
lines changed

env.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env bash
2+
3+
export OVH_ENDPOINT="ovh-eu"
4+
export OVH_APPLICATION_KEY="000693a9655db1b5"
5+
export OVH_APPLICATION_SECRET="dda3dcae9b4fbd41461c07d100da6586"
6+
export OVH_CONSUMER_KEY="055d118f9c3ca88b4fba9ae1b984fdf8"
7+
8+
export OVH_DOMAIN_TEST="syk-edu.com"
9+
10+
export TF_ACC=1
11+
12+
echo "[OK] OVH environment variables exported for acceptance tests."

ovh/resource_cloud_project_instance.go

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,10 @@ func resourceCloudProjectInstance() *schema.Resource {
184184
ForceNew: true,
185185
},
186186
"network": {
187-
Type: schema.TypeSet,
187+
Type: schema.TypeList,
188188
Required: true,
189189
ForceNew: true,
190-
MaxItems: 1,
191-
Description: "Network information",
190+
Description: "Network information(multiple NICs)",
192191
Elem: &schema.Resource{
193192
Schema: map[string]*schema.Schema{
194193
"public": {
@@ -197,10 +196,9 @@ func resourceCloudProjectInstance() *schema.Resource {
197196
Optional: true,
198197
},
199198
"private": {
200-
Type: schema.TypeSet,
199+
Type: schema.TypeList,
201200
Optional: true,
202201
ForceNew: true,
203-
MaxItems: 1,
204202
Description: "Private network information",
205203
Elem: &schema.Resource{
206204
Schema: map[string]*schema.Schema{
@@ -425,6 +423,7 @@ func resourceCloudProjectInstance() *schema.Resource {
425423
},
426424
},
427425
}
426+
428427
}
429428

430429
func resourceCloudProjectInstanceCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
@@ -439,9 +438,24 @@ func resourceCloudProjectInstanceCreate(ctx context.Context, d *schema.ResourceD
439438
url.PathEscape(region),
440439
)
441440

441+
payload := map[string]interface{}{
442+
"auto_backup": params.AutoBackup,
443+
"availabilityZone": params.AvailabilityZone,
444+
"billingPeriod": params.BillingPeriod,
445+
"bootFrom": params.BootFrom,
446+
"bulk": params.Bulk,
447+
"flavor": params.Flavor,
448+
"group": params.Group,
449+
"name": params.Name,
450+
"sshKey": params.SshKey,
451+
"sshKeyCreate": params.SshKeyCreate,
452+
"userData": params.UserData,
453+
"network": networksToPayload(params.Networks), // multi NIC
454+
}
455+
442456
r := &CloudProjectOperationResponse{}
443-
if err := config.OVHClient.Post(endpoint, params, r); err != nil {
444-
return diag.Errorf("calling %s with params %v:\n\t %q", endpoint, params, err)
457+
if err := config.OVHClient.Post(endpoint, payload, r); err != nil {
458+
return diag.Errorf("calling %s with params %v:\n\t %q", endpoint, payload, err)
445459
}
446460

447461
instanceID, err := waitForCloudProjectOperation(ctx, config.OVHClient, serviceName, r.Id, "instance#create", d.Timeout(schema.TimeoutCreate))
@@ -528,3 +542,76 @@ func resourceCloudProjectInstanceDelete(ctx context.Context, d *schema.ResourceD
528542
log.Printf("[DEBUG] Deleted Public Cloud %s Instance %s", serviceName, id)
529543
return nil
530544
}
545+
546+
func networksToPayload(networks []*Network) []interface{} {
547+
payload := make([]interface{}, 0, len(networks))
548+
for _, net := range networks {
549+
netMap := map[string]interface{}{
550+
"public": net.Public,
551+
}
552+
553+
if len(net.Private) > 0 {
554+
privateList := make([]interface{}, 0, len(net.Private))
555+
for _, p := range net.Private {
556+
pMap := map[string]interface{}{}
557+
558+
if p.FloatingIP != nil {
559+
pMap["floating_ip"] = []map[string]interface{}{
560+
{"id": p.FloatingIP.ID},
561+
}
562+
}
563+
564+
if p.FloatingIPCreate != nil {
565+
pMap["floating_ip_create"] = []map[string]interface{}{
566+
{"description": p.FloatingIPCreate.Description},
567+
}
568+
}
569+
570+
if p.Gateway != nil {
571+
pMap["gateway"] = []map[string]interface{}{
572+
{"id": p.Gateway.ID},
573+
}
574+
}
575+
576+
if p.GatewayCreate != nil {
577+
pMap["gateway_create"] = []map[string]interface{}{
578+
{"model": p.GatewayCreate.Model, "name": p.GatewayCreate.Name},
579+
}
580+
}
581+
582+
if p.IP != "" {
583+
pMap["ip"] = p.IP
584+
}
585+
586+
if p.Network != nil {
587+
pMap["network"] = []map[string]interface{}{
588+
{"id": p.Network.ID, "subnet_id": p.Network.SubnetID},
589+
}
590+
}
591+
592+
if p.NetworkCreate != nil {
593+
subnetList := []map[string]interface{}{
594+
{
595+
"cidr": p.NetworkCreate.Subnet.CIDR,
596+
"enable_dhcp": p.NetworkCreate.Subnet.EnableDHCP,
597+
"ip_version": p.NetworkCreate.Subnet.IPVersion,
598+
},
599+
}
600+
pMap["network_create"] = []map[string]interface{}{
601+
{
602+
"name": p.NetworkCreate.Name,
603+
"vlan_id": p.NetworkCreate.VlanId,
604+
"subnet": subnetList,
605+
},
606+
}
607+
}
608+
609+
privateList = append(privateList, pMap)
610+
}
611+
netMap["private"] = privateList
612+
}
613+
614+
payload = append(payload, netMap)
615+
}
616+
return payload
617+
}

ovh/types_cloud_project_instance.go

Lines changed: 84 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ type SshKeyCreate struct {
4040
}
4141

4242
type Network struct {
43-
Public bool `json:"public"`
44-
Private *PrivateNetwork `json:"private,omitempty"`
43+
Public bool `json:"public"`
44+
Private []*PrivateNetwork `json:"private,omitempty"`
4545
}
4646

4747
type PrivateNetwork struct {
@@ -100,7 +100,7 @@ type CloudProjectInstanceCreateOpts struct {
100100
SshKey *SshKey `json:"sshKey,omitempty"`
101101
SshKeyCreate *SshKeyCreate `json:"sshKeyCreate,omitempty"`
102102
UserData *string `json:"userData,omitempty"`
103-
Network *Network `json:"network,omitempty"`
103+
Networks []*Network `json:"network,omitempty"`
104104
}
105105

106106
type Address struct {
@@ -279,102 +279,99 @@ func GetSshKeyCreate(i interface{}) *SshKeyCreate {
279279
return &sshCreateOutput
280280
}
281281

282-
func GetNetwork(i interface{}) *Network {
283-
if i == nil {
284-
return nil
282+
func GetNetwork(mapping map[string]interface{}) *Network {
283+
networkOutput := &Network{}
284+
285+
// Public NIC
286+
if v, ok := mapping["public"]; ok {
287+
networkOutput.Public = v.(bool)
285288
}
286-
networkOutput := Network{}
287289

288-
networkSet := i.(*schema.Set).List()
289-
for _, network := range networkSet {
290-
mapping := network.(map[string]interface{})
291-
networkOutput.Public = mapping["public"].(bool)
290+
// Private NICs
291+
privateRaw, ok := mapping["private"]
292+
if !ok || privateRaw == nil || privateRaw.(*schema.Set).Len() == 0 {
293+
return networkOutput
294+
}
292295

293-
privateNet, ok := mapping["private"]
294-
if !ok || privateNet == nil || privateNet.(*schema.Set).Len() == 0 {
295-
continue
296-
}
296+
privateSet := privateRaw.(*schema.Set).List()
297+
networkOutput.Private = make([]*PrivateNetwork, 0, len(privateSet))
297298

298-
for _, priv := range privateNet.(*schema.Set).List() {
299-
networkOutput.Private = &PrivateNetwork{}
300-
private := priv.(map[string]interface{})
299+
for _, priv := range privateSet {
300+
private := priv.(map[string]interface{})
301+
pn := &PrivateNetwork{}
301302

302-
if floatingIP, ok := private["floating_ip"]; ok {
303-
for _, float := range floatingIP.(*schema.Set).List() {
304-
params := float.(map[string]interface{})
305-
networkOutput.Private.FloatingIP = &PrivateNetworkFloatingIP{
306-
ID: params["id"].(string),
307-
}
308-
}
303+
if floatingIP, ok := private["floating_ip"]; ok && floatingIP != nil {
304+
for _, float := range floatingIP.(*schema.Set).List() {
305+
params := float.(map[string]interface{})
306+
pn.FloatingIP = &PrivateNetworkFloatingIP{ID: params["id"].(string)}
309307
}
308+
}
310309

311-
if floatingIPCreate, ok := private["floating_ip_create"]; ok {
312-
for _, float := range floatingIPCreate.(*schema.Set).List() {
313-
params := float.(map[string]interface{})
314-
networkOutput.Private.FloatingIPCreate = &PrivateNetworkFloatingIPCreate{
315-
Description: params["description"].(string),
316-
}
317-
}
310+
if floatingIPCreate, ok := private["floating_ip_create"]; ok && floatingIPCreate != nil {
311+
for _, float := range floatingIPCreate.(*schema.Set).List() {
312+
params := float.(map[string]interface{})
313+
pn.FloatingIPCreate = &PrivateNetworkFloatingIPCreate{Description: params["description"].(string)}
318314
}
315+
}
319316

320-
if gateway, ok := private["gateway"]; ok {
321-
for _, gateway := range gateway.(*schema.Set).List() {
322-
params := gateway.(map[string]interface{})
323-
networkOutput.Private.Gateway = &PrivateNetworkGateway{
324-
ID: params["id"].(string),
325-
}
326-
}
317+
if gateway, ok := private["gateway"]; ok && gateway != nil {
318+
for _, g := range gateway.(*schema.Set).List() {
319+
params := g.(map[string]interface{})
320+
pn.Gateway = &PrivateNetworkGateway{ID: params["id"].(string)}
327321
}
322+
}
328323

329-
if gatewayCreate, ok := private["gateway_create"]; ok {
330-
for _, gateway := range gatewayCreate.(*schema.Set).List() {
331-
params := gateway.(map[string]interface{})
332-
networkOutput.Private.GatewayCreate = &PrivateNetworkGatewayCreate{
333-
Model: params["model"].(string),
334-
Name: params["name"].(string),
335-
}
324+
if gatewayCreate, ok := private["gateway_create"]; ok && gatewayCreate != nil {
325+
for _, gc := range gatewayCreate.(*schema.Set).List() {
326+
params := gc.(map[string]interface{})
327+
pn.GatewayCreate = &PrivateNetworkGatewayCreate{
328+
Model: params["model"].(string),
329+
Name: params["name"].(string),
336330
}
337331
}
332+
}
338333

339-
networkOutput.Private.IP = private["ip"].(string)
334+
if ip, ok := private["ip"]; ok && ip != nil {
335+
pn.IP = ip.(string)
336+
}
340337

341-
if network, ok := private["network"]; ok {
342-
for _, net := range network.(*schema.Set).List() {
343-
params := net.(map[string]interface{})
344-
networkOutput.Private.Network = &PrivateNetworkInformation{
345-
ID: params["id"].(string),
346-
SubnetID: params["subnet_id"].(string),
347-
}
338+
if networkMap, ok := private["network"]; ok && networkMap != nil {
339+
for _, net := range networkMap.(*schema.Set).List() {
340+
params := net.(map[string]interface{})
341+
pn.Network = &PrivateNetworkInformation{
342+
ID: params["id"].(string),
343+
SubnetID: params["subnet_id"].(string),
348344
}
349345
}
346+
}
350347

351-
if networkCreate, ok := private["network_create"]; ok {
352-
for _, net := range networkCreate.(*schema.Set).List() {
353-
params := net.(map[string]interface{})
354-
networkOutput.Private.NetworkCreate = &PrivateNetworkInformationCreate{
355-
Name: params["name"].(string),
356-
}
348+
if networkCreate, ok := private["network_create"]; ok && networkCreate != nil {
349+
for _, net := range networkCreate.(*schema.Set).List() {
350+
params := net.(map[string]interface{})
351+
pn.NetworkCreate = &PrivateNetworkInformationCreate{Name: params["name"].(string)}
357352

358-
if vlanID, ok := params["vlan_id"]; ok {
359-
intVlanID := vlanID.(int)
360-
networkOutput.Private.NetworkCreate.VlanId = &intVlanID
361-
}
353+
if vlanID, ok := params["vlan_id"]; ok && vlanID != nil {
354+
intVlanID := vlanID.(int)
355+
pn.NetworkCreate.VlanId = &intVlanID
356+
}
362357

363-
for _, subnet := range params["subnet"].(*schema.Set).List() {
364-
subnetParams := subnet.(map[string]interface{})
365-
networkOutput.Private.NetworkCreate.Subnet = PrivateNetworkInformationSubnetCreate{
366-
CIDR: subnetParams["cidr"].(string),
367-
EnableDHCP: subnetParams["enable_dhcp"].(bool),
368-
IPVersion: subnetParams["ip_version"].(int),
358+
if subnetVal, ok := params["subnet"]; ok && subnetVal != nil {
359+
for _, subnet := range subnetVal.(*schema.Set).List() {
360+
sn := subnet.(map[string]interface{})
361+
pn.NetworkCreate.Subnet = PrivateNetworkInformationSubnetCreate{
362+
CIDR: sn["cidr"].(string),
363+
EnableDHCP: sn["enable_dhcp"].(bool),
364+
IPVersion: sn["ip_version"].(int),
369365
}
370366
}
371367
}
372368
}
373369
}
374370

371+
networkOutput.Private = append(networkOutput.Private, pn)
375372
}
376373

377-
return &networkOutput
374+
return networkOutput
378375
}
379376

380377
func (cpir *CloudProjectInstanceCreateOpts) FromResource(d *schema.ResourceData) {
@@ -384,7 +381,7 @@ func (cpir *CloudProjectInstanceCreateOpts) FromResource(d *schema.ResourceData)
384381
cpir.Group = GetGroup(d.Get("group"))
385382
cpir.SshKey = GetSshKey(d.Get("ssh_key"))
386383
cpir.SshKeyCreate = GetSshKeyCreate(d.Get("ssh_key_create"))
387-
cpir.Network = GetNetwork(d.Get("network"))
384+
cpir.Networks = expandNetworks(d.Get("network"))
388385
cpir.BillingPeriod = d.Get("billing_period").(string)
389386
cpir.Name = d.Get("name").(string)
390387
cpir.AvailabilityZone = helpers.GetNilStringPointerFromData(d, "availability_zone")
@@ -413,3 +410,18 @@ func waitForCloudProjectInstance(ctx context.Context, c *ovhwrap.Client, service
413410

414411
return err
415412
}
413+
414+
func expandNetworks(i interface{}) []*Network {
415+
if i == nil {
416+
return nil
417+
}
418+
419+
networksSet := i.(*schema.Set).List()
420+
networks := make([]*Network, 0, len(networksSet))
421+
422+
for _, n := range networksSet {
423+
networks = append(networks, GetNetwork(n.(map[string]interface{})))
424+
}
425+
426+
return networks
427+
}

0 commit comments

Comments
 (0)