4
4
"context"
5
5
"fmt"
6
6
"log"
7
+ "sort"
7
8
"strconv"
8
9
"time"
9
10
@@ -169,6 +170,11 @@ func resourceInstance() *schema.Resource {
169
170
Optional : true ,
170
171
Description : fmt .Sprintf ("Avalilable value is '%s', '%s', '%s', '%s'" , types .SubnetInterfaceType , types .AnySubnetInterfaceType , types .ExternalInterfaceType , types .ReservedFixedIpType ),
171
172
},
173
+ "order" : {
174
+ Type : schema .TypeInt ,
175
+ Optional : true ,
176
+ Description : "Order of attaching interface" ,
177
+ },
172
178
"network_id" : {
173
179
Type : schema .TypeString ,
174
180
Description : "required if type is 'subnet' or 'any_subnet'" ,
@@ -380,6 +386,8 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
380
386
}
381
387
382
388
ifs := d .Get ("interface" ).(* schema.Set ).List ()
389
+ //sort interfaces by 'order' key to attach it in right order
390
+ sort .Sort (instanceInterfaces (ifs ))
383
391
if len (ifs ) > 0 {
384
392
ifaces , err := extractInstanceInterfacesMap (ifs )
385
393
if err != nil {
@@ -415,6 +423,7 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
415
423
createOpts .Configuration = & conf
416
424
}
417
425
426
+ log .Printf ("[DEBUG] Interface create options: %+v" , createOpts )
418
427
results , err := instances .Create (clientv2 , createOpts ).Extract ()
419
428
if err != nil {
420
429
return diag .FromErr (err )
@@ -448,7 +457,6 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter
448
457
449
458
func resourceInstanceRead (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
450
459
log .Println ("[DEBUG] Start Instance reading" )
451
- log .Printf ("[DEBUG] Start Instance reading%s" , d .State ())
452
460
var diags diag.Diagnostics
453
461
config := m .(* Config )
454
462
provider := config .Provider
@@ -523,9 +531,13 @@ func resourceInstanceRead(ctx context.Context, d *schema.ResourceData, m interfa
523
531
524
532
//bad idea, but what to do
525
533
var iOpts instances.InterfaceOpts
534
+ var orderedIOpts OrderedInterfaceOpts
526
535
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
527
538
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
529
541
break
530
542
}
531
543
}
@@ -540,11 +552,12 @@ func resourceInstanceRead(ctx context.Context, d *schema.ResourceData, m interfa
540
552
i ["network_id" ] = iface .NetworkID
541
553
i ["subnet_id" ] = subnetID
542
554
i ["port_id" ] = iface .PortID
555
+ i ["order" ] = orderedIOpts .Order
543
556
if iOpts .FloatingIP != nil {
544
557
i ["fip_source" ] = iOpts .FloatingIP .Source .String ()
545
558
i ["existing_fip_id" ] = iOpts .FloatingIP .ExistingFloatingID
546
559
}
547
- i ["ip_address" ] = iface . IPAssignments [ 0 ] .IPAddress .String ()
560
+ i ["ip_address" ] = assignment .IPAddress .String ()
548
561
549
562
cleanInterfaces = append (cleanInterfaces , i )
550
563
}
@@ -680,41 +693,37 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
680
693
if d .HasChange ("interface" ) {
681
694
ifsOldRaw , ifsNewRaw := d .GetChange ("interface" )
682
695
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
-
693
696
ifsOld := ifsOldRaw .(* schema.Set )
694
697
ifsNew := ifsNewRaw .(* schema.Set )
695
698
696
699
for _ , i := range ifsOld .List () {
697
- if ifsNew .Contains (i ) {
698
- log .Println ("[DEBUG] Skipped, dont need detach" )
699
- continue
700
- }
701
-
702
700
iface := i .(map [string ]interface {})
703
701
var opts instances.InterfaceOpts
704
702
opts .PortID = iface ["port_id" ].(string )
705
703
opts .IpAddress = iface ["ip_address" ].(string )
706
704
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 {
708
708
return diag .FromErr (err )
709
709
}
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 )
716
721
}
722
+ }
717
723
724
+ sortedNewIfs := ifsNew .List ()
725
+ sort .Sort (instanceInterfaces (sortedNewIfs ))
726
+ for _ , i := range sortedNewIfs {
718
727
iface := i .(map [string ]interface {})
719
728
720
729
iType := types .InterfaceType (iface ["type" ].(string ))
@@ -728,6 +737,7 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter
728
737
opts .PortID = iface ["port_id" ].(string )
729
738
}
730
739
740
+ log .Printf ("[DEBUG] attach interface: %+v" , opts )
731
741
results , err := instances .AttachInterface (client , instanceID , opts ).Extract ()
732
742
if err != nil {
733
743
return diag .Errorf ("cannot attach interface: %s. Error: %s" , iType , err )
0 commit comments