Skip to content
This repository was archived by the owner on Mar 1, 2023. It is now read-only.

Commit 3d29f2b

Browse files
committed
read/update interface for baremetal fixed
1 parent 04bb0a7 commit 3d29f2b

File tree

9 files changed

+176
-38
lines changed

9 files changed

+176
-38
lines changed

docs/resources/gcore_baremetal.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,17 @@ resource "gcore_baremetal" "bm" {
2727
flavor_id = "bm1-infrastructure-small"
2828
image_id = "1ee7ccee-5003-48c9-8ae0-d96063af75b2" // your image id
2929
30-
//additional interface, 'subnet' only, 'external' interface create automatically
30+
//additional interface, available type is 'subnet' or 'external'
3131
// interface {
3232
// type = "subnet"
3333
// network_id = "9c7867fb-f404-4a2d-8bb5-24acf2fccaf1" //your network_id
3434
// subnet_id = "b68ea6e2-c2b6-4a8d-95eb-7194d12a2156" // your subnet_id
3535
// }
3636
37+
// interface {
38+
// type = "external"
39+
// }
40+
3741
keypair_name = "test" // your keypair name
3842
}
3943
```
@@ -44,6 +48,7 @@ resource "gcore_baremetal" "bm" {
4448
### Required
4549

4650
- **flavor_id** (String)
51+
- **interface** (Block Set, Min: 1) (see [below for nested schema](#nestedblock--interface))
4752
- **name** (String)
4853

4954
### Optional
@@ -52,7 +57,6 @@ resource "gcore_baremetal" "bm" {
5257
- **apptemplate_id** (String)
5358
- **id** (String) The ID of this resource.
5459
- **image_id** (String)
55-
- **interface** (Block Set) (see [below for nested schema](#nestedblock--interface))
5660
- **keypair_name** (String)
5761
- **last_updated** (String)
5862
- **metadata** (Block List) (see [below for nested schema](#nestedblock--metadata))
@@ -90,6 +94,7 @@ Optional:
9094
Read-Only:
9195

9296
- **ip_address** (String)
97+
- **is_trunk** (Boolean) Calculated after creation. Can't detach interface if is_trunk true
9398
- **port_id** (String)
9499

95100

docs/resources/gcore_lblistener.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ resource "gcore_lblistener" "listener" {
6767
- **project_name** (String)
6868
- **region_id** (Number)
6969
- **region_name** (String)
70+
- **secret_id** (String)
71+
- **sni_secret_id** (List of String)
7072
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
7173

7274
### Read-Only

docs/resources/gcore_loadbalancer.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ resource "gcore_loadbalancer" "lb" {
3838

3939
### Required
4040

41-
- **listener** (Block List, Min: 1) (see [below for nested schema](#nestedblock--listener))
41+
- **listener** (Block List, Min: 1, Max: 1) (see [below for nested schema](#nestedblock--listener))
4242
- **name** (String)
4343

4444
### Optional
@@ -71,7 +71,10 @@ Optional:
7171

7272
- **certificate** (String)
7373
- **certificate_chain** (String)
74+
- **insert_x_forwarded** (Boolean)
7475
- **private_key** (String)
76+
- **secret_id** (String)
77+
- **sni_secret_id** (List of String)
7578

7679
Read-Only:
7780

docs/resources/gcore_securitygroup.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Required:
7474

7575
- **direction** (String) Available value is 'ingress', 'egress'
7676
- **ethertype** (String) Available value is 'IPv4', 'IPv6'
77-
- **protocol** (String) Available value is udp,tcp,any,icmp,ah,dccp,egp,esp,gre,igmp,ospf,pgm,rsvp,sctp,udplite,vrrp,51,50,112
77+
- **protocol** (String) Available value is udp,tcp,any,icmp,ah,dccp,egp,esp,gre,igmp,ospf,pgm,rsvp,sctp,udplite,vrrp,51,50,112,0
7878

7979
Optional:
8080

examples/resources/gcore_baremetal/resource.tf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ resource "gcore_baremetal" "bm" {
1212
flavor_id = "bm1-infrastructure-small"
1313
image_id = "1ee7ccee-5003-48c9-8ae0-d96063af75b2" // your image id
1414

15-
//additional interface, 'subnet' only, 'external' interface create automatically
15+
//additional interface, available type is 'subnet' or 'external'
1616
// interface {
1717
// type = "subnet"
1818
// network_id = "9c7867fb-f404-4a2d-8bb5-24acf2fccaf1" //your network_id
1919
// subnet_id = "b68ea6e2-c2b6-4a8d-95eb-7194d12a2156" // your subnet_id
2020
// }
2121

22+
// interface {
23+
// type = "external"
24+
// }
25+
2226
keypair_name = "test" // your keypair name
2327
}

gcore/resource_gcore_baremetal.go

Lines changed: 100 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"log"
7+
"sort"
78
"strconv"
89
"time"
910

@@ -12,7 +13,6 @@ import (
1213
"github.com/G-Core/gcorelabscloud-go/gcore/instance/v1/instances"
1314
"github.com/G-Core/gcorelabscloud-go/gcore/instance/v1/types"
1415
"github.com/G-Core/gcorelabscloud-go/gcore/task/v1/tasks"
15-
"github.com/hashicorp/go-cty/cty"
1616
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1717
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1818
)
@@ -114,20 +114,18 @@ func resourceBmInstance() *schema.Resource {
114114
"interface": &schema.Schema{
115115
Type: schema.TypeSet,
116116
Set: interfaceUniqueID,
117-
Optional: true,
117+
Required: true,
118118
Elem: &schema.Resource{
119119
Schema: map[string]*schema.Schema{
120120
"type": {
121121
Type: schema.TypeString,
122122
Required: true,
123123
Description: fmt.Sprintf("Avalilable value is '%s', '%s'", types.SubnetInterfaceType, types.ExternalInterfaceType),
124-
ValidateDiagFunc: func(val interface{}, path cty.Path) diag.Diagnostics {
125-
v := types.InterfaceType(val.(string))
126-
if v != types.SubnetInterfaceType {
127-
return diag.Errorf("subnet type only")
128-
}
129-
return nil
130-
},
124+
},
125+
"is_trunk": {
126+
Type: schema.TypeBool,
127+
Computed: true,
128+
Description: "Calculated after creation. Can't detach interface if is_trunk true",
131129
},
132130
"network_id": {
133131
Type: schema.TypeString,
@@ -273,10 +271,6 @@ func resourceBmInstanceCreate(ctx context.Context, d *schema.ResourceData, m int
273271
}
274272
newInterface[i] = newIface
275273
}
276-
//for api interface is required, but we cant attach external, and not receive it in interfaceList method
277-
if len(ints) == 0 {
278-
newInterface = []bminstances.InterfaceOpts{{Type: types.ExternalInterfaceType}}
279-
}
280274

281275
opts := bminstances.CreateOpts{
282276
Flavor: d.Get("flavor_id").(string),
@@ -372,33 +366,80 @@ func resourceBmInstanceRead(ctx context.Context, d *schema.ResourceData, m inter
372366
}
373367

374368
var cleanInterfaces []interface{}
375-
for _, iface := range ifs[0].SubPorts {
376-
if len(iface.IPAssignments) == 0 {
377-
continue
378-
}
379-
369+
for _, iface := range ifs {
380370
for _, assignment := range iface.IPAssignments {
381371
subnetID := assignment.SubnetID
382372

383-
_, ok := interfaces[subnetID]
373+
//bad idea, but what to do
374+
var iOpts instances.InterfaceOpts
375+
var orderedIOpts OrderedInterfaceOpts
376+
var ok bool
377+
// we need to match our interfaces with api's interfaces
378+
// but with don't have any unique value, that's why we use exactly that list of keys
379+
for _, k := range []string{subnetID, iface.PortID, iface.NetworkID, types.ExternalInterfaceType.String()} {
380+
if orderedIOpts, ok = interfaces[k]; ok {
381+
iOpts = orderedIOpts.InterfaceOpts
382+
break
383+
}
384+
}
385+
384386
if !ok {
385387
continue
386388
}
387389

388390
i := make(map[string]interface{})
389391

390-
i["type"] = interfaces[subnetID].Type.String()
392+
i["type"] = iOpts.Type.String()
391393
i["network_id"] = iface.NetworkID
392394
i["subnet_id"] = subnetID
393395
i["port_id"] = iface.PortID
394-
if interfaces[subnetID].FloatingIP != nil {
395-
i["fip_source"] = interfaces[subnetID].FloatingIP.Source.String()
396-
i["existing_fip_id"] = interfaces[subnetID].FloatingIP.ExistingFloatingID
396+
i["is_trunk"] = true
397+
if iOpts.FloatingIP != nil {
398+
i["fip_source"] = iOpts.FloatingIP.Source.String()
399+
i["existing_fip_id"] = iOpts.FloatingIP.ExistingFloatingID
397400
}
398-
i["ip_address"] = iface.IPAssignments[0].IPAddress.String()
401+
i["ip_address"] = assignment.IPAddress.String()
399402

400403
cleanInterfaces = append(cleanInterfaces, i)
401404
}
405+
406+
for _, iface1 := range iface.SubPorts {
407+
for _, assignment := range iface1.IPAssignments {
408+
subnetID := assignment.SubnetID
409+
410+
//bad idea, but what to do
411+
var iOpts instances.InterfaceOpts
412+
var orderedIOpts OrderedInterfaceOpts
413+
var ok bool
414+
// we need to match our interfaces with api's interfaces
415+
// but with don't have any unique value, that's why we use exactly that list of keys
416+
for _, k := range []string{subnetID, iface1.PortID, iface1.NetworkID, types.ExternalInterfaceType.String()} {
417+
if orderedIOpts, ok = interfaces[k]; ok {
418+
iOpts = orderedIOpts.InterfaceOpts
419+
break
420+
}
421+
}
422+
423+
if !ok {
424+
continue
425+
}
426+
427+
i := make(map[string]interface{})
428+
429+
i["type"] = iOpts.Type.String()
430+
i["network_id"] = iface1.NetworkID
431+
i["subnet_id"] = subnetID
432+
i["port_id"] = iface1.PortID
433+
i["is_trunk"] = false
434+
if iOpts.FloatingIP != nil {
435+
i["fip_source"] = iOpts.FloatingIP.Source.String()
436+
i["existing_fip_id"] = iOpts.FloatingIP.ExistingFloatingID
437+
}
438+
i["ip_address"] = assignment.IPAddress.String()
439+
440+
cleanInterfaces = append(cleanInterfaces, i)
441+
}
442+
}
402443
}
403444
if err := d.Set("interface", schema.NewSet(interfaceUniqueID, cleanInterfaces)); err != nil {
404445
return diag.FromErr(err)
@@ -500,33 +541,62 @@ func resourceBmInstanceUpdate(ctx context.Context, d *schema.ResourceData, m int
500541
}
501542

502543
iface := i.(map[string]interface{})
544+
if iface["is_trunk"].(bool) {
545+
return diag.Errorf("could not detach trunk interface")
546+
}
547+
503548
var opts instances.InterfaceOpts
504549
opts.PortID = iface["port_id"].(string)
505550
opts.IpAddress = iface["ip_address"].(string)
506551

507-
if err := instances.DetachInterface(client, instanceID, opts).Err; err != nil {
552+
log.Printf("[DEBUG] detach interface: %+v", opts)
553+
results, err := instances.DetachInterface(client, instanceID, opts).Extract()
554+
if err != nil {
508555
return diag.FromErr(err)
509556
}
557+
taskID := results.Tasks[0]
558+
_, err = tasks.WaitTaskAndReturnResult(client, taskID, true, InstanceCreatingTimeout, func(task tasks.TaskID) (interface{}, error) {
559+
taskInfo, err := tasks.Get(client, string(task)).Extract()
560+
if err != nil {
561+
return nil, fmt.Errorf("cannot get task with ID: %s. Error: %w, task: %+v", task, err, taskInfo)
562+
}
563+
return nil, nil
564+
},
565+
)
566+
if err != nil {
567+
return diag.FromErr(err)
568+
}
569+
}
570+
571+
currentIfs, err := instances.ListInterfacesAll(client, d.Id())
572+
if err != nil {
573+
return diag.FromErr(err)
510574
}
511575

512-
for _, i := range ifsNew.List() {
576+
sortedNewIfs := ifsNew.List()
577+
sort.Sort(instanceInterfaces(sortedNewIfs))
578+
for _, i := range sortedNewIfs {
513579
if ifsOld.Contains(i) {
514580
log.Println("[DEBUG] Skipped, dont need attach")
515581
continue
516582
}
517-
518583
iface := i.(map[string]interface{})
584+
if isInterfaceAttached(currentIfs, iface) {
585+
continue
586+
}
519587

520588
iType := types.InterfaceType(iface["type"].(string))
521589
opts := instances.InterfaceOpts{Type: iType}
522590
switch iType {
523591
case types.SubnetInterfaceType:
524592
opts.SubnetID = iface["subnet_id"].(string)
525-
//opts.NetworkID = iface["network_id"].(string)
526-
case types.ExternalInterfaceType:
527-
continue
593+
case types.AnySubnetInterfaceType:
594+
opts.NetworkID = iface["network_id"].(string)
595+
case types.ReservedFixedIpType:
596+
opts.PortID = iface["port_id"].(string)
528597
}
529598

599+
log.Printf("[DEBUG] attach interface: %+v", opts)
530600
results, err := instances.AttachInterface(client, instanceID, opts).Extract()
531601
if err != nil {
532602
return diag.Errorf("cannot attach interface: %s. Error: %s", iType, err)

gcore/utils.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ func (s instanceInterfaces) Len() int {
8484
func (s instanceInterfaces) Less(i, j int) bool {
8585
ifLeft := s[i].(map[string]interface{})
8686
ifRight := s[j].(map[string]interface{})
87-
return ifLeft["order"].(int) < ifRight["order"].(int)
87+
lOrder, _ := ifLeft["order"].(int)
88+
rOrder, _ := ifRight["order"].(int)
89+
return lOrder < rOrder
8890
}
8991

9092
func (s instanceInterfaces) Swap(i, j int) {
@@ -669,3 +671,29 @@ func parseCIDRFromString(cidr string) (gcorecloud.CIDR, error) {
669671
gccidr.Mask = netIPNet.Mask
670672
return gccidr, nil
671673
}
674+
675+
func isInterfaceAttached(ifs []instances.Interface, ifs2 map[string]interface{}) bool {
676+
subnetID, _ := ifs2["subnet_id"].(string)
677+
iType := types.InterfaceType(ifs2["type"].(string))
678+
for _, i := range ifs {
679+
if iType == types.ExternalInterfaceType && i.NetworkDetails.External {
680+
return true
681+
}
682+
for _, assignement := range i.IPAssignments {
683+
if assignement.SubnetID == subnetID {
684+
return true
685+
}
686+
}
687+
for _, subPort := range i.SubPorts {
688+
if iType == types.ExternalInterfaceType && subPort.NetworkDetails.External {
689+
return true
690+
}
691+
for _, assignement := range subPort.IPAssignments {
692+
if assignement.SubnetID == subnetID {
693+
return true
694+
}
695+
}
696+
}
697+
}
698+
return false
699+
}

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ require (
1010
github.com/G-Core/gcorelabscdn-go v0.1.2
1111
github.com/G-Core/gcorelabscloud-go v0.4.34
1212
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
13+
github.com/hashicorp/terraform-plugin-docs v0.5.1 // indirect
1314
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
14-
github.com/mattn/go-colorable v0.1.8 // indirect
15+
github.com/mattn/go-colorable v0.1.11 // indirect
1516
github.com/mitchellh/mapstructure v1.4.1
16-
github.com/zclconf/go-cty v1.9.1 // indirect
17+
github.com/zclconf/go-cty v1.10.0 // indirect
1718
)

0 commit comments

Comments
 (0)