4.8.0
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
Kasim Baybikov, <kmbaybikov@basistech.ru>
|
||||
Tim Tkachev, <tvtkachev@basistech.ru>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package extnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
|
||||
)
|
||||
|
||||
func dataSourceExtnetReservedIpRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||
reservedList, err := utilityExtnetReservedIpCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
id := uuid.New()
|
||||
d.SetId(id.String())
|
||||
d.Set("items", flattenExtnetReservedIp(reservedList))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DataSourceExtnetReservedIp() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
SchemaVersion: 1,
|
||||
|
||||
ReadContext: dataSourceExtnetReservedIpRead,
|
||||
|
||||
Timeouts: &schema.ResourceTimeout{
|
||||
Read: &constants.Timeout30s,
|
||||
Default: &constants.Timeout60s,
|
||||
},
|
||||
|
||||
Schema: dataSourceExtnetReservedIpSchemaMake(),
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,6 @@ func flattenRecordExtnetResource(d *schema.ResourceData, recNet *extnet.RecordEx
|
||||
d.Set("routes", flattenStaticRouteList(staticRouteList))
|
||||
}
|
||||
|
||||
|
||||
func flattenExtnetExcluded(ers extnet.ListReservations) []map[string]interface{} {
|
||||
res := make([]map[string]interface{}, 0)
|
||||
for _, er := range ers {
|
||||
@@ -157,6 +156,7 @@ func flattenExtnetReservations(ers extnet.ListReservations) []map[string]interfa
|
||||
res := make([]map[string]interface{}, 0)
|
||||
for _, er := range ers {
|
||||
temp := map[string]interface{}{
|
||||
"account_id": er.AccountID,
|
||||
"client_type": er.ClientType,
|
||||
"domain_name": er.DomainName,
|
||||
"hostname": er.Hostname,
|
||||
@@ -217,4 +217,30 @@ func flattenStaticRouteData(d *schema.ResourceData, route *extnet.ItemRoutes) {
|
||||
d.Set("netmask", route.Netmask)
|
||||
d.Set("compute_ids", route.ComputeIds)
|
||||
d.Set("route_id", route.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func flattenExtnetReservedIp(el []extnet.RecordReservedIP) []map[string]interface{} {
|
||||
res := make([]map[string]interface{}, 0, len(el))
|
||||
for _, e := range el {
|
||||
reservations := make([]map[string]interface{}, 0, len(e.Reservations))
|
||||
for _, r := range e.Reservations {
|
||||
temp := map[string]interface{}{
|
||||
"account_id": r.AccountID,
|
||||
"client_type": r.ClientType,
|
||||
"domain_name": r.DomainName,
|
||||
"hostname": r.Hostname,
|
||||
"ip": r.IP,
|
||||
"mac": r.Mac,
|
||||
"type": r.Type,
|
||||
"vm_id": r.VMID,
|
||||
}
|
||||
reservations = append(reservations, temp)
|
||||
}
|
||||
item := map[string]interface{}{
|
||||
"extnet_id": e.ExtnetID,
|
||||
"reservations": reservations,
|
||||
}
|
||||
res = append(res, item)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
||||
if err := ic.ExistGID(ctx, uint64(d.Get("gid").(int)), c); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
if err := checkReserveIp(ctx, d, c); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
req := extnet.CreateRequest{
|
||||
Name: d.Get("name").(string),
|
||||
@@ -191,6 +194,34 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
||||
}
|
||||
}
|
||||
|
||||
// for reserve IP extnet must be enabled
|
||||
if d.Get("reserved_ip").(*schema.Set).Len() > 0 {
|
||||
for _, reservedIP := range d.Get("reserved_ip").(*schema.Set).List() {
|
||||
reservedIPMap := reservedIP.(map[string]interface{})
|
||||
req := extnet.AddReserveIPRequest{
|
||||
AccountID: uint64(reservedIPMap["account_id"].(int)),
|
||||
ExtNetID: netID,
|
||||
}
|
||||
if ipCount, ok := reservedIPMap["ip_count"]; ok {
|
||||
req.IPCount = uint64(ipCount.(int))
|
||||
}
|
||||
if reservedIPMap["ips"].(*schema.Set).Len() > 0 {
|
||||
ips := reservedIPMap["ips"].(*schema.Set).List()
|
||||
for i, ip := range ips {
|
||||
if i >= int(req.IPCount) {
|
||||
break
|
||||
}
|
||||
req.IPs = append(req.IPs, ip.(string))
|
||||
}
|
||||
}
|
||||
|
||||
_, err := c.CloudBroker().ExtNet().AddReserveIP(ctx, req)
|
||||
if err != nil {
|
||||
w.Add(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resourceExtnetRead(ctx, d, m)
|
||||
}
|
||||
|
||||
@@ -215,6 +246,10 @@ func resourceExtnetUpdate(ctx context.Context, d *schema.ResourceData, m interfa
|
||||
log.Debugf("cloudbroker: resourceExtnetUpdate called with id %s", d.Id())
|
||||
c := m.(*controller.ControllerCfg)
|
||||
|
||||
if err := checkReserveIp(ctx, d, c); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
recNet, err := utilityExtnetCheckPresence(ctx, d, m)
|
||||
if err != nil {
|
||||
d.SetId("")
|
||||
@@ -267,6 +302,12 @@ func resourceExtnetUpdate(ctx context.Context, d *schema.ResourceData, m interfa
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("reserved_ip") {
|
||||
if err := reservedIPsUpdate(ctx, d, c, recNet); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange("shared_with") {
|
||||
if err := handleSharedWithUpdate(ctx, d, c); err != nil {
|
||||
return diag.FromErr(err)
|
||||
@@ -330,6 +371,8 @@ func ResourceExtnetCB() *schema.Resource {
|
||||
Default: &constants.Timeout300s,
|
||||
},
|
||||
|
||||
CustomizeDiff: validateReserveIPs,
|
||||
|
||||
Schema: resourceExtnetSchemaMake(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package extnet
|
||||
|
||||
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||
)
|
||||
|
||||
func dataSourceExtnetDefaultSchemaMake() map[string]*schema.Schema {
|
||||
return map[string]*schema.Schema{
|
||||
@@ -474,6 +477,10 @@ func dataSourceExtnetSchemaMake() map[string]*schema.Schema {
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"client_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
@@ -728,6 +735,30 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
||||
Type: schema.TypeInt,
|
||||
},
|
||||
},
|
||||
"reserved_ip": {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"ip_count": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
ValidateFunc: validation.IntBetween(1, 255),
|
||||
},
|
||||
"ips": {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"ckey": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
@@ -868,6 +899,10 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"client_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
@@ -905,3 +940,69 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func dataSourceExtnetReservedIpSchemaMake() map[string]*schema.Schema {
|
||||
res := map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
},
|
||||
"extnet_id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
},
|
||||
"items": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"extnet_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"reservations": {
|
||||
Type: schema.TypeList,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"account_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
"client_type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"domain_name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"hostname": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"ip": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"mac": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"type": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"vm_id": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||
Authors:
|
||||
Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||
Stanislav Solovev, <spsolovev@digitalenergy.online>
|
||||
Kasim Baybikov, <kmbaybikov@basistech.ru>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
|
||||
Orchestration Technology) with Terraform by Hashicorp.
|
||||
|
||||
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
|
||||
|
||||
Please see README.md to learn where to place source code so that it
|
||||
builds seamlessly.
|
||||
|
||||
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
|
||||
*/
|
||||
|
||||
package extnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/extnet"
|
||||
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
|
||||
)
|
||||
|
||||
func utilityExtnetReservedIpCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) ([]extnet.RecordReservedIP, error) {
|
||||
c := m.(*controller.ControllerCfg)
|
||||
req := extnet.GetReservedIP{
|
||||
AccountID: uint64(d.Get("account_id").(int)),
|
||||
}
|
||||
|
||||
if extNetID, ok := d.GetOk("extnet_id"); ok {
|
||||
req.ExtNetID = uint64(extNetID.(int))
|
||||
}
|
||||
|
||||
log.Debugf("utilityExtnetReservedIpCheckPresence")
|
||||
res, err := c.CloudBroker().ExtNet().GetReservedIP(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
@@ -35,6 +35,8 @@ package extnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -341,3 +343,255 @@ func handleMigrateUpdate(ctx context.Context, d *schema.ResourceData, c *control
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkReserveIp(ctx context.Context, d *schema.ResourceData, c *controller.ControllerCfg) error {
|
||||
var err error
|
||||
if d.Get("reserved_ip").(*schema.Set).Len() > 0 {
|
||||
reservedIPList := d.Get("reserved_ip").(*schema.Set).List()
|
||||
accountMap := make(map[int]struct{}, len(reservedIPList))
|
||||
for _, reservedIP := range reservedIPList {
|
||||
reservedIPMap := reservedIP.(map[string]interface{})
|
||||
accountId := reservedIPMap["account_id"].(int)
|
||||
if _, ok := accountMap[accountId]; ok {
|
||||
err = errors.Join(err, fmt.Errorf("checkReserveIp: you must have only one block with id %d", accountId))
|
||||
}
|
||||
accountMap[accountId] = struct{}{}
|
||||
_, okCount := reservedIPMap["ip_count"]
|
||||
if !okCount && reservedIPMap["ips"].(*schema.Set).Len() == 0 {
|
||||
err = errors.Join(err, fmt.Errorf("checkReserveIp: either ip_count or set of ips must be specified"))
|
||||
}
|
||||
existErr := ic.ExistAccount(ctx, uint64(accountId), c)
|
||||
if existErr != nil {
|
||||
err = errors.Join(err, existErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func reservedIPsUpdate(ctx context.Context, d *schema.ResourceData, c *controller.ControllerCfg, recNet *extnet.RecordExtNet) error {
|
||||
|
||||
addSet, delSet, err := differenceIPReserved(ctx, d, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(delSet) > 0 {
|
||||
for _, del := range delSet {
|
||||
delMap := del.(map[string]interface{})
|
||||
|
||||
log.Debugf("reservedIPsUpdate: removing reserved IPs for account %d", delMap["account_id"].(int))
|
||||
|
||||
req := extnet.DelReserveIPRequest{
|
||||
AccountID: uint64(delMap["account_id"].(int)),
|
||||
ExtNetID: recNet.ID,
|
||||
}
|
||||
if ipCount, ok := delMap["ip_count"]; ok {
|
||||
req.IPCount = uint64(ipCount.(int))
|
||||
}
|
||||
if delIPs, ok := delMap["ips"]; ok {
|
||||
ips := delIPs.(*schema.Set).List()
|
||||
for _, ip := range ips {
|
||||
req.IPs = append(req.IPs, ip.(string))
|
||||
}
|
||||
}
|
||||
|
||||
_, err := c.CloudBroker().ExtNet().DelReserveIP(ctx, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(addSet) > 0 {
|
||||
for _, add := range addSet {
|
||||
addMap := add.(map[string]interface{})
|
||||
|
||||
log.Debugf("reservedIPsUpdate: add reserved IPs for account %d", addMap["account_id"].(int))
|
||||
|
||||
req := extnet.AddReserveIPRequest{
|
||||
AccountID: uint64(addMap["account_id"].(int)),
|
||||
ExtNetID: recNet.ID,
|
||||
}
|
||||
if ipCount, ok := addMap["ip_count"]; ok {
|
||||
req.IPCount = uint64(ipCount.(int))
|
||||
}
|
||||
if addIPs, ok := addMap["ips"]; ok {
|
||||
ips := addIPs.(*schema.Set).List()
|
||||
for _, ip := range ips {
|
||||
req.IPs = append(req.IPs, ip.(string))
|
||||
}
|
||||
}
|
||||
|
||||
_, err := c.CloudBroker().ExtNet().AddReserveIP(ctx, req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func differenceIPReserved(ctx context.Context, d *schema.ResourceData, c *controller.ControllerCfg) (addList, delList []interface{}, errs error) {
|
||||
addList = make([]interface{}, 0)
|
||||
delList = make([]interface{}, 0)
|
||||
oldSet, newSet := d.GetChange("reserved_ip")
|
||||
oldList := oldSet.(*schema.Set).List()
|
||||
newList := newSet.(*schema.Set).List()
|
||||
for _, oldReservedIP := range oldList {
|
||||
oldMap := oldReservedIP.(map[string]interface{})
|
||||
found := false
|
||||
for _, newReservedIP := range newList {
|
||||
newMap := newReservedIP.(map[string]interface{})
|
||||
if newMap["account_id"] == oldMap["account_id"] && newMap["ip_count"] == oldMap["ip_count"] && newMap["ips"] == oldMap["ips"] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
if newMap["account_id"] == oldMap["account_id"] {
|
||||
add := make(map[string]interface{}, 0)
|
||||
del := make(map[string]interface{}, 0)
|
||||
delSet := oldMap["ips"].(*schema.Set).Difference(newMap["ips"].(*schema.Set))
|
||||
addSet := newMap["ips"].(*schema.Set).Difference(oldMap["ips"].(*schema.Set))
|
||||
if delSet.Len() > 0 {
|
||||
del["account_id"] = oldMap["account_id"].(int)
|
||||
del["ips"] = delSet
|
||||
if oldMap["ip_count"].(int)-newMap["ip_count"].(int) >= delSet.Len() {
|
||||
del["ip_count"] = oldMap["ip_count"].(int) - newMap["ip_count"].(int)
|
||||
} else {
|
||||
del["ip_count"] = delSet.Len()
|
||||
newMap["ip_count"] = newMap["ip_count"].(int) + delSet.Len()
|
||||
}
|
||||
} else if newMap["ip_count"].(int) < oldMap["ip_count"].(int) {
|
||||
del["account_id"] = oldMap["account_id"].(int)
|
||||
del["ip_count"] = oldMap["ip_count"].(int) - newMap["ip_count"].(int)
|
||||
}
|
||||
if addSet.Len() > 0 {
|
||||
add["account_id"] = oldMap["account_id"].(int)
|
||||
add["ips"] = addSet
|
||||
add["ip_count"] = newMap["ip_count"].(int) - oldMap["ip_count"].(int)
|
||||
if add["ip_count"].(int) < 0 {
|
||||
add["ip_count"] = 0
|
||||
}
|
||||
if add["ip_count"].(int)-addSet.Len() < 0 {
|
||||
del["account_id"] = oldMap["account_id"].(int)
|
||||
if _, ok := del["ip_count"]; ok {
|
||||
del["ip_count"] = del["ip_count"].(int) + addSet.Len()
|
||||
} else {
|
||||
del["ip_count"] = addSet.Len()
|
||||
}
|
||||
}
|
||||
} else if newMap["ip_count"].(int)-oldMap["ip_count"].(int) > 0 {
|
||||
add["account_id"] = oldMap["account_id"].(int)
|
||||
add["ip_count"] = newMap["ip_count"].(int) - oldMap["ip_count"].(int)
|
||||
}
|
||||
if _, ok := add["account_id"]; ok {
|
||||
addList = append(addList, add)
|
||||
}
|
||||
if _, ok := del["account_id"]; ok {
|
||||
ipsLen := 0
|
||||
if _, ok := del["ips"]; ok {
|
||||
ipsLen = del["ips"].(*schema.Set).Len()
|
||||
}
|
||||
freeCount := del["ip_count"].(int) - ipsLen
|
||||
if freeCount > 0 {
|
||||
req := extnet.GetReservedIP{
|
||||
AccountID: uint64(del["account_id"].(int)),
|
||||
ExtNetID: uint64(d.Get("extnet_id").(int)),
|
||||
}
|
||||
resIpsList, err := c.CloudBroker().ExtNet().GetReservedIP(ctx, req)
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
freeIPs := getFreeIps(resIpsList[0].Reservations, newMap["ips"], del["ips"])
|
||||
if _, ok := del["ips"]; !ok {
|
||||
del["ips"] = schema.NewSet(schema.HashString, []interface{}{})
|
||||
}
|
||||
for i := 0; i < freeCount; i++ {
|
||||
del["ips"].(*schema.Set).Add(freeIPs[i])
|
||||
}
|
||||
}
|
||||
delList = append(delList, del)
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
delList = append(delList, oldReservedIP)
|
||||
}
|
||||
|
||||
for _, newReservedIP := range newList {
|
||||
newMap := newReservedIP.(map[string]interface{})
|
||||
found := false
|
||||
for _, oldReservedIP := range oldList {
|
||||
oldMap := oldReservedIP.(map[string]interface{})
|
||||
if newMap["account_id"] == oldMap["account_id"] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
addList = append(addList, newReservedIP)
|
||||
}
|
||||
|
||||
if errs != nil {
|
||||
d.Set("reserved_ip", oldSet)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// getFreeIps returns array IPs which can be deleted
|
||||
func getFreeIps(reserved []extnet.Reservations, newIps, delIps interface{}) []string {
|
||||
newIpsList := make([]interface{}, 0)
|
||||
delIpsList := make([]interface{}, 0)
|
||||
if newIps != nil {
|
||||
newIpsList = newIps.(*schema.Set).List()
|
||||
}
|
||||
if delIps != nil {
|
||||
delIpsList = delIps.(*schema.Set).List()
|
||||
}
|
||||
newIpsMap := make(map[string]struct{}, len(newIpsList))
|
||||
delIpsMap := make(map[string]struct{}, len(delIpsList))
|
||||
freeIPs := make([]string, 0)
|
||||
for _, ip := range newIpsList {
|
||||
newIpsMap[ip.(string)] = struct{}{}
|
||||
}
|
||||
for _, ip := range delIpsList {
|
||||
delIpsMap[ip.(string)] = struct{}{}
|
||||
}
|
||||
for _, item := range reserved {
|
||||
if _, ok := newIpsMap[item.IP]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := delIpsMap[item.IP]; ok {
|
||||
continue
|
||||
}
|
||||
freeIPs = append(freeIPs, item.IP)
|
||||
}
|
||||
return freeIPs
|
||||
}
|
||||
|
||||
func validateReserveIPs(ctx context.Context, d *schema.ResourceDiff, m interface{}) error {
|
||||
list := d.Get("reserved_ip").(*schema.Set).List()
|
||||
var errs error
|
||||
for _, reservedIP := range list {
|
||||
reservedIPMap := reservedIP.(map[string]interface{})
|
||||
var countIP, ipsLen int
|
||||
if _, ok := reservedIPMap["ip_count"]; ok {
|
||||
countIP = reservedIPMap["ip_count"].(int)
|
||||
}
|
||||
if _, ok := reservedIPMap["ips"]; ok {
|
||||
ipsLen = reservedIPMap["ips"].(*schema.Set).Len()
|
||||
}
|
||||
if ipsLen > countIP {
|
||||
errs = errors.Join(errs, fmt.Errorf("for the reserved_ip block with account_id %d the count parameter must be greater than or equal to len the ips array", reservedIPMap["account_id"].(int)))
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user