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

Commit 49ae45a

Browse files
committed
attach interface order added
1 parent 326ca35 commit 49ae45a

File tree

5 files changed

+95
-31
lines changed

5 files changed

+95
-31
lines changed

docs/resources/gcore_instance.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ Optional:
150150
- **fip_source** (String)
151151
- **ip_address** (String)
152152
- **network_id** (String) required if type is 'subnet' or 'any_subnet'
153+
- **order** (Number) Order of attaching interface
153154
- **port_id** (String) required if type is 'reserved_fixed_ip'
154155
- **subnet_id** (String) required if type is 'subnet'
155156
- **type** (String) Avalilable value is 'subnet', 'any_subnet', 'external', 'reserved_fixed_ip'

gcore/resource_gcore_instance.go

Lines changed: 35 additions & 25 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

@@ -169,6 +170,11 @@ func resourceInstance() *schema.Resource {
169170
Optional: true,
170171
Description: fmt.Sprintf("Avalilable value is '%s', '%s', '%s', '%s'", types.SubnetInterfaceType, types.AnySubnetInterfaceType, types.ExternalInterfaceType, types.ReservedFixedIpType),
171172
},
173+
"order": {
174+
Type: schema.TypeInt,
175+
Optional: true,
176+
Description: "Order of attaching interface",
177+
},
172178
"network_id": {
173179
Type: schema.TypeString,
174180
Description: "required if type is 'subnet' or 'any_subnet'",
@@ -380,6 +386,8 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
380386
}
381387

382388
ifs := d.Get("interface").(*schema.Set).List()
389+
//sort interfaces by 'order' key to attach it in right order
390+
sort.Sort(instanceInterfaces(ifs))
383391
if len(ifs) > 0 {
384392
ifaces, err := extractInstanceInterfacesMap(ifs)
385393
if err != nil {
@@ -415,6 +423,7 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
415423
createOpts.Configuration = &conf
416424
}
417425

426+
log.Printf("[DEBUG] Interface create options: %+v", createOpts)
418427
results, err := instances.Create(clientv2, createOpts).Extract()
419428
if err != nil {
420429
return diag.FromErr(err)
@@ -448,7 +457,6 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
448457

449458
func resourceInstanceRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
450459
log.Println("[DEBUG] Start Instance reading")
451-
log.Printf("[DEBUG] Start Instance reading%s", d.State())
452460
var diags diag.Diagnostics
453461
config := m.(*Config)
454462
provider := config.Provider
@@ -523,9 +531,13 @@ func resourceInstanceRead(ctx context.Context, d *schema.ResourceData, m interfa
523531

524532
//bad idea, but what to do
525533
var iOpts instances.InterfaceOpts
534+
var orderedIOpts OrderedInterfaceOpts
526535
var ok bool
536+
// we need to match our interfaces with api's interfaces
537+
// but with don't have any unique value, that's why we use exactly that list of keys
527538
for _, k := range []string{subnetID, iface.PortID, iface.NetworkID, types.ExternalInterfaceType.String()} {
528-
if iOpts, ok = interfaces[k]; ok {
539+
if orderedIOpts, ok = interfaces[k]; ok {
540+
iOpts = orderedIOpts.InterfaceOpts
529541
break
530542
}
531543
}
@@ -540,11 +552,12 @@ func resourceInstanceRead(ctx context.Context, d *schema.ResourceData, m interfa
540552
i["network_id"] = iface.NetworkID
541553
i["subnet_id"] = subnetID
542554
i["port_id"] = iface.PortID
555+
i["order"] = orderedIOpts.Order
543556
if iOpts.FloatingIP != nil {
544557
i["fip_source"] = iOpts.FloatingIP.Source.String()
545558
i["existing_fip_id"] = iOpts.FloatingIP.ExistingFloatingID
546559
}
547-
i["ip_address"] = iface.IPAssignments[0].IPAddress.String()
560+
i["ip_address"] = assignment.IPAddress.String()
548561

549562
cleanInterfaces = append(cleanInterfaces, i)
550563
}
@@ -680,41 +693,37 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
680693
if d.HasChange("interface") {
681694
ifsOldRaw, ifsNewRaw := d.GetChange("interface")
682695

683-
//ifsOld, err := extractInstanceInterfaceIntoMap(ifsOldRaw.(*schema.Set).List())
684-
//if err != nil {
685-
// return diag.FromErr(err)
686-
//}
687-
//
688-
//ifsNew, err := extractInstanceInterfaceIntoMap(ifsNewRaw.(*schema.Set).List())
689-
//if err != nil {
690-
// return diag.FromErr(err)
691-
//}
692-
693696
ifsOld := ifsOldRaw.(*schema.Set)
694697
ifsNew := ifsNewRaw.(*schema.Set)
695698

696699
for _, i := range ifsOld.List() {
697-
if ifsNew.Contains(i) {
698-
log.Println("[DEBUG] Skipped, dont need detach")
699-
continue
700-
}
701-
702700
iface := i.(map[string]interface{})
703701
var opts instances.InterfaceOpts
704702
opts.PortID = iface["port_id"].(string)
705703
opts.IpAddress = iface["ip_address"].(string)
706704

707-
if err := instances.DetachInterface(client, instanceID, opts).Err; err != nil {
705+
log.Printf("[DEBUG] detach interface: %+v", opts)
706+
results, err := instances.DetachInterface(client, instanceID, opts).Extract()
707+
if err != nil {
708708
return diag.FromErr(err)
709709
}
710-
}
711-
712-
for _, i := range ifsNew.List() {
713-
if ifsOld.Contains(i) {
714-
log.Println("[DEBUG] Skipped, dont need attach")
715-
continue
710+
taskID := results.Tasks[0]
711+
_, err = tasks.WaitTaskAndReturnResult(client, taskID, true, InstanceCreatingTimeout, func(task tasks.TaskID) (interface{}, error) {
712+
taskInfo, err := tasks.Get(client, string(task)).Extract()
713+
if err != nil {
714+
return nil, fmt.Errorf("cannot get task with ID: %s. Error: %w, task: %+v", task, err, taskInfo)
715+
}
716+
return nil, nil
717+
},
718+
)
719+
if err != nil {
720+
return diag.FromErr(err)
716721
}
722+
}
717723

724+
sortedNewIfs := ifsNew.List()
725+
sort.Sort(instanceInterfaces(sortedNewIfs))
726+
for _, i := range sortedNewIfs {
718727
iface := i.(map[string]interface{})
719728

720729
iType := types.InterfaceType(iface["type"].(string))
@@ -728,6 +737,7 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
728737
opts.PortID = iface["port_id"].(string)
729738
}
730739

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

gcore/utils.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,22 @@ var config = &mapstructure.DecoderConfig{
7575
TagName: "json",
7676
}
7777

78+
type instanceInterfaces []interface{}
79+
80+
func (s instanceInterfaces) Len() int {
81+
return len(s)
82+
}
83+
84+
func (s instanceInterfaces) Less(i, j int) bool {
85+
ifLeft := s[i].(map[string]interface{})
86+
ifRight := s[j].(map[string]interface{})
87+
return ifLeft["order"].(int) < ifRight["order"].(int)
88+
}
89+
90+
func (s instanceInterfaces) Swap(i, j int) {
91+
s[i], s[j] = s[j], s[i]
92+
}
93+
7894
func MapStructureDecoder(strct interface{}, v *map[string]interface{}, config *mapstructure.DecoderConfig) error {
7995
config.Result = strct
8096
decoder, _ := mapstructure.NewDecoder(config)
@@ -212,9 +228,14 @@ func extractInstanceInterfacesMap(interfaces []interface{}) ([]instances.Interfa
212228
return Interfaces, nil
213229
}
214230

231+
type OrderedInterfaceOpts struct {
232+
instances.InterfaceOpts
233+
Order int
234+
}
235+
215236
//todo refactoring
216-
func extractInstanceInterfaceIntoMap(interfaces []interface{}) (map[string]instances.InterfaceOpts, error) {
217-
Interfaces := make(map[string]instances.InterfaceOpts)
237+
func extractInstanceInterfaceIntoMap(interfaces []interface{}) (map[string]OrderedInterfaceOpts, error) {
238+
Interfaces := make(map[string]OrderedInterfaceOpts)
218239
for _, iface := range interfaces {
219240
if iface == nil {
220241
continue
@@ -237,11 +258,12 @@ func extractInstanceInterfaceIntoMap(interfaces []interface{}) (map[string]insta
237258
}
238259
I.FloatingIP = &fip
239260
}
240-
Interfaces[I.SubnetID] = I
241-
Interfaces[I.NetworkID] = I
242-
Interfaces[I.PortID] = I
261+
orderedInt := OrderedInterfaceOpts{I, inter["order"].(int)}
262+
Interfaces[I.SubnetID] = orderedInt
263+
Interfaces[I.NetworkID] = orderedInt
264+
Interfaces[I.PortID] = orderedInt
243265
if I.Type == types.ExternalInterfaceType {
244-
Interfaces[I.Type.String()] = I
266+
Interfaces[I.Type.String()] = orderedInt
245267
}
246268
}
247269
return Interfaces, nil
@@ -508,6 +530,8 @@ func interfaceUniqueID(i interface{}) int {
508530
h := md5.New()
509531
iType := e["type"].(string)
510532
io.WriteString(h, iType)
533+
iOrder := e["order"].(int)
534+
io.WriteString(h, strconv.Itoa(iOrder))
511535
switch types.InterfaceType(iType) {
512536
case types.ReservedFixedIpType:
513537
io.WriteString(h, e["port_id"].(string))

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/G-Core/gcorelabscdn-go v0.0.0-20210503173228-b4ac8b2402ff
99
github.com/G-Core/gcorelabscloud-go v0.4.15
1010
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
11+
github.com/hashicorp/terraform-plugin-docs v0.4.0 // indirect
1112
github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
1213
github.com/mattn/go-colorable v0.1.8 // indirect
1314
github.com/mitchellh/mapstructure v1.4.1

0 commit comments

Comments
 (0)