4.12.2
4.12.2
This commit is contained in:
51
CHANGELOG.md
51
CHANGELOG.md
@@ -1,8 +1,53 @@
|
|||||||
## Version 4.12.1
|
## Version 4.12.2
|
||||||
|
|
||||||
|
### Добавлено
|
||||||
|
|
||||||
|
#### SDN logicalports
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1363 | Вычисляемые поля `id`, `logical_port_id` и `assigned_at` в блоке `logical_port_addresses` в resource `decort_sdn_logical_port` в sdn/logicalports |
|
||||||
|
|
||||||
|
#### extnet
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1375 | Вычисляемые поля `sec_vnfdev_id` и `pre_reservations` в resource `decort_cb_extnet` в cloudbroker/extnet |
|
||||||
|
|
||||||
|
#### kvmvm
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1375 | Вычисляемое поле `user_data` в resource `decort_cb_kvmvm` в cloudbroker/kvmvm |
|
||||||
|
|
||||||
|
|
||||||
|
### Изменено
|
||||||
|
|
||||||
|
#### SDN logicalports
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1363 | Тип поля `logical_port_addresses` с `list` на `set` в resource `decort_sdn_logical_port` в sdn/logicalports |
|
||||||
|
| BATF-1363 | Тип поля `unique_identifier` с опционального на опционально-вычисляемое в resource `decort_sdn_logical_port` в sdn/logicalports |
|
||||||
|
| BATF-1363 | Тип поля `is_primary` в блоке `logical_port_addresses` с обязательного на опциональное в resource `decort_sdn_logical_port` в sdn/logicalports |
|
||||||
|
|
||||||
|
#### k8ci
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1376 | Опциональное поле `enabled` получило значение по умолчанию `true` в resource `decort_cb_k8ci` в cloudbroker/k8ci |
|
||||||
|
|
||||||
|
#### storage policy
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1373 | Тип поля `limit_iops` с опционального на опционально-вычисляемое в resource `decort_cb_storage_policy` в cloudbroker/stpolicy |
|
||||||
|
|
||||||
|
|
||||||
### Исправлено
|
### Исправлено
|
||||||
|
|
||||||
#### sdn logicalports
|
#### SDN logicalports
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BATF-1357 | Ошибка поля `adapter_mac` при обновлении resource `decort_sdn_logical_port` в sdn/logicalports |
|
| BATF-1363 | Баг с полем `labels` при обновлении resource `decort_sdn_logical_port` в sdn/logicalports |
|
||||||
|
| BATF-1363 | Каскадное изменение адресов `logical_port_addresses` при редактировании списка блоков адресов в resource `decort_sdn_logical_port` в sdn/logicalports |
|
||||||
|
|
||||||
|
#### extnet
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BATF-1375 | Баги с полями `shared_with`, `vnfdev_ip`, `default_qos`, `default_qos`, `highly_available`, `mtu` и `sec_vnfdev_id` при создании resource `decort_cb_extnet` в cloudbroker/extnet |
|
||||||
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -7,7 +7,7 @@ ZIPDIR = ./zip
|
|||||||
BINARY=${NAME}
|
BINARY=${NAME}
|
||||||
WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH}
|
WORKPATH= ./examples/terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAMESPACE}/${VERSION}/${OS_ARCH}
|
||||||
MAINPATH = ./cmd/decort/
|
MAINPATH = ./cmd/decort/
|
||||||
VERSION=4.12.1
|
VERSION=4.12.2
|
||||||
OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH)
|
OS_ARCH=$(shell go env GOHOSTOS)_$(shell go env GOHOSTARCH)
|
||||||
|
|
||||||
FILES = ${BINARY}_${VERSION}_darwin_amd64\
|
FILES = ${BINARY}_${VERSION}_darwin_amd64\
|
||||||
|
|||||||
@@ -64,10 +64,12 @@ description: |-
|
|||||||
- `milestones` (Number)
|
- `milestones` (Number)
|
||||||
- `network` (String)
|
- `network` (String)
|
||||||
- `network_ids` (List of Object) (see [below for nested schema](#nestedatt--network_ids))
|
- `network_ids` (List of Object) (see [below for nested schema](#nestedatt--network_ids))
|
||||||
|
- `pre_reservations` (List of Object) (see [below for nested schema](#nestedatt--pre_reservations))
|
||||||
- `prefix` (Number)
|
- `prefix` (Number)
|
||||||
- `pri_vnfdev_id` (Number)
|
- `pri_vnfdev_id` (Number)
|
||||||
- `reservations` (List of Object) (see [below for nested schema](#nestedatt--reservations))
|
- `reservations` (List of Object) (see [below for nested schema](#nestedatt--reservations))
|
||||||
- `routes` (List of Object) (see [below for nested schema](#nestedatt--routes))
|
- `routes` (List of Object) (see [below for nested schema](#nestedatt--routes))
|
||||||
|
- `sec_vnfdev_id` (Number)
|
||||||
- `status` (String)
|
- `status` (String)
|
||||||
- `vnfs` (List of Object) (see [below for nested schema](#nestedatt--vnfs))
|
- `vnfs` (List of Object) (see [below for nested schema](#nestedatt--vnfs))
|
||||||
|
|
||||||
@@ -125,6 +127,7 @@ Optional:
|
|||||||
Read-Only:
|
Read-Only:
|
||||||
|
|
||||||
- `client_type` (String)
|
- `client_type` (String)
|
||||||
|
- `desc` (String)
|
||||||
- `domain_name` (String)
|
- `domain_name` (String)
|
||||||
- `hostname` (String)
|
- `hostname` (String)
|
||||||
- `ip` (String)
|
- `ip` (String)
|
||||||
@@ -142,6 +145,22 @@ Read-Only:
|
|||||||
- `secondary` (Number)
|
- `secondary` (Number)
|
||||||
|
|
||||||
|
|
||||||
|
<a id="nestedatt--pre_reservations"></a>
|
||||||
|
### Nested Schema for `pre_reservations`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `account_id` (Number)
|
||||||
|
- `client_type` (String)
|
||||||
|
- `desc` (String)
|
||||||
|
- `domain_name` (String)
|
||||||
|
- `hostname` (String)
|
||||||
|
- `ip` (String)
|
||||||
|
- `mac` (String)
|
||||||
|
- `type` (String)
|
||||||
|
- `vm_id` (Number)
|
||||||
|
|
||||||
|
|
||||||
<a id="nestedatt--reservations"></a>
|
<a id="nestedatt--reservations"></a>
|
||||||
### Nested Schema for `reservations`
|
### Nested Schema for `reservations`
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ description: |-
|
|||||||
- `tech_status` (String)
|
- `tech_status` (String)
|
||||||
- `updated_by` (String)
|
- `updated_by` (String)
|
||||||
- `updated_time` (Number)
|
- `updated_time` (Number)
|
||||||
|
- `user_data` (String)
|
||||||
- `user_managed` (Boolean)
|
- `user_managed` (Boolean)
|
||||||
- `vgpus` (List of Object) List of virtual GPUs (see [below for nested schema](#nestedatt--vgpus))
|
- `vgpus` (List of Object) List of virtual GPUs (see [below for nested schema](#nestedatt--vgpus))
|
||||||
- `virtual_image_name` (String)
|
- `virtual_image_name` (String)
|
||||||
|
|||||||
@@ -17,21 +17,21 @@ description: |-
|
|||||||
|
|
||||||
### Required
|
### Required
|
||||||
|
|
||||||
- `access_group_id` (String) Access Group ID
|
- `access_group_id` (String) UUID of the access group
|
||||||
- `description` (String) Description
|
- `description` (String) Description
|
||||||
- `display_name` (String) Display Name
|
- `display_name` (String) Display Name
|
||||||
- `enabled` (Boolean) Whether the logical port should be enabled
|
- `enabled` (Boolean) Whether the logical port should be enabled
|
||||||
- `hypervisor` (String) Hypervisor
|
- `hypervisor` (String) Associated hypervisor
|
||||||
- `port_security` (Boolean) Whether the port security is enabled
|
- `port_security` (Boolean) Whether the port security is enabled
|
||||||
- `segment_id` (String) Segment ID
|
- `segment_id` (String) UUID of the network segment
|
||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
- `adapter_mac` (String) Adapter MAC address
|
- `adapter_mac` (String) Adapter MAC address
|
||||||
- `force` (Boolean)
|
- `force` (Boolean)
|
||||||
- `labels` (Block List, Max: 1) Labels (see [below for nested schema](#nestedblock--labels))
|
- `labels` (Block List, Max: 1) Labels (see [below for nested schema](#nestedblock--labels))
|
||||||
- `logical_port_addresses` (Block List) (see [below for nested schema](#nestedblock--logical_port_addresses))
|
- `logical_port_addresses` (Block Set) (see [below for nested schema](#nestedblock--logical_port_addresses))
|
||||||
- `migrate` (Boolean) If true, triggers live migration to the hypervisor specified in the 'hypervisor' field. If false, hypervisor changes are applied via the regular update endpoint.
|
- `migrate` (Boolean) If true, triggers live migration to the hypervisor specified in the 'hypervisor' field. If false, hypervisor changes are applied via the regular update endpoint
|
||||||
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
|
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
|
||||||
- `unique_identifier` (String) Unique identifier of the logical port
|
- `unique_identifier` (String) Unique identifier of the logical port
|
||||||
|
|
||||||
@@ -41,11 +41,13 @@ description: |-
|
|||||||
- `address_detection` (Boolean)
|
- `address_detection` (Boolean)
|
||||||
- `bindings` (List of Object) (see [below for nested schema](#nestedatt--bindings))
|
- `bindings` (List of Object) (see [below for nested schema](#nestedatt--bindings))
|
||||||
- `created_at` (String)
|
- `created_at` (String)
|
||||||
|
- `exclude_firewall` (List of Object) (see [below for nested schema](#nestedatt--exclude_firewall))
|
||||||
- `external_network_id` (String)
|
- `external_network_id` (String)
|
||||||
- `hypervisor_display_name` (String)
|
- `hypervisor_display_name` (String)
|
||||||
- `id` (String) ID of the logical port
|
- `id` (String) ID of the logical port
|
||||||
- `live_migration_target_hv` (String)
|
- `live_migration_target_hv` (String)
|
||||||
- `status` (List of Object) (see [below for nested schema](#nestedatt--status))
|
- `status` (List of Object) (see [below for nested schema](#nestedatt--status))
|
||||||
|
- `updated_at` (String) Last update time of the logical port
|
||||||
- `version_id` (Number) Version ID of the logical port
|
- `version_id` (Number) Version ID of the logical port
|
||||||
|
|
||||||
<a id="nestedblock--labels"></a>
|
<a id="nestedblock--labels"></a>
|
||||||
@@ -63,13 +65,19 @@ Optional:
|
|||||||
Required:
|
Required:
|
||||||
|
|
||||||
- `ip` (String) IP address of the logical port
|
- `ip` (String) IP address of the logical port
|
||||||
- `ip_type` (String)
|
- `ip_type` (String) IP type
|
||||||
- `is_primary` (Boolean)
|
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
|
|
||||||
- `is_discovered` (Boolean)
|
- `is_discovered` (Boolean)
|
||||||
- `mac` (String)
|
- `is_primary` (Boolean)
|
||||||
|
- `mac` (String) MAC address; optional on initial port creation & required when adding or updating addresses in an existing logical port
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `assigned_at` (String) Timestamp when the address was assigned
|
||||||
|
- `id` (String) ID of the address, assigned by the platform
|
||||||
|
- `logical_port_id` (String) ID of the parent logical port
|
||||||
|
|
||||||
|
|
||||||
<a id="nestedblock--timeouts"></a>
|
<a id="nestedblock--timeouts"></a>
|
||||||
@@ -115,6 +123,16 @@ Read-Only:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a id="nestedatt--exclude_firewall"></a>
|
||||||
|
### Nested Schema for `exclude_firewall`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `exclusion_reason` (String)
|
||||||
|
- `logical_port_addresses_excluded` (Boolean)
|
||||||
|
- `logical_port_excluded` (Boolean)
|
||||||
|
|
||||||
|
|
||||||
<a id="nestedatt--status"></a>
|
<a id="nestedatt--status"></a>
|
||||||
### Nested Schema for `status`
|
### Nested Schema for `status`
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -9,7 +9,7 @@ require (
|
|||||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1
|
github.com/hashicorp/terraform-plugin-sdk/v2 v2.38.1
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
golang.org/x/net v0.44.0
|
golang.org/x/net v0.44.0
|
||||||
repository.basistech.ru/BASIS/decort-golang-sdk v1.14.12
|
repository.basistech.ru/BASIS/decort-golang-sdk v1.14.13
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -318,5 +318,5 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
repository.basistech.ru/BASIS/decort-golang-sdk v1.14.12 h1:R3qmiYmeF+cun3VyBm4FR3pMvXByp7HY19Jsyoj66gA=
|
repository.basistech.ru/BASIS/decort-golang-sdk v1.14.13 h1:kYopwej9i4QORHzCyo8AXdHQplyCBD10771PJFBB+4A=
|
||||||
repository.basistech.ru/BASIS/decort-golang-sdk v1.14.12/go.mod h1:S/f7GxwWcE88eFpORV+I9xqEf8zDW5srQHpG2XQCLZM=
|
repository.basistech.ru/BASIS/decort-golang-sdk v1.14.13/go.mod h1:S/f7GxwWcE88eFpORV+I9xqEf8zDW5srQHpG2XQCLZM=
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func flattenRecordExtnet(d *schema.ResourceData, recNet *extnet.RecordExtNet) {
|
|||||||
d.Set("ipcidr", recNet.IPCIDR)
|
d.Set("ipcidr", recNet.IPCIDR)
|
||||||
d.Set("milestones", recNet.Milestones)
|
d.Set("milestones", recNet.Milestones)
|
||||||
d.Set("name", recNet.Name)
|
d.Set("name", recNet.Name)
|
||||||
d.Set("network_ids", recNet.NetworkIDs)
|
d.Set("network_ids", flattenNetworkIDs(recNet.NetworkIDs))
|
||||||
d.Set("ntp", recNet.NTP)
|
d.Set("ntp", recNet.NTP)
|
||||||
d.Set("ovs_bridge", recNet.OVSBridge)
|
d.Set("ovs_bridge", recNet.OVSBridge)
|
||||||
d.Set("pre_reservations_num", recNet.PreReservationsNum)
|
d.Set("pre_reservations_num", recNet.PreReservationsNum)
|
||||||
@@ -142,9 +142,13 @@ func flattenRecordExtnetResource(d *schema.ResourceData, recNet *extnet.RecordEx
|
|||||||
d.Set("default_qos", flattenExtnetDefaultQos(recNet.DefaultQOS))
|
d.Set("default_qos", flattenExtnetDefaultQos(recNet.DefaultQOS))
|
||||||
d.Set("vnfs", flattenExtnetVNFS(recNet.VNFs))
|
d.Set("vnfs", flattenExtnetVNFS(recNet.VNFs))
|
||||||
d.Set("reservations", flattenExtnetReservations(recNet.Reservations))
|
d.Set("reservations", flattenExtnetReservations(recNet.Reservations))
|
||||||
|
d.Set("pre_reservations", flattenExtnetReservations(recNet.PreReservations))
|
||||||
d.Set("routes", flattenStaticRouteList(staticRouteList))
|
d.Set("routes", flattenStaticRouteList(staticRouteList))
|
||||||
d.Set("zone_id", recNet.ZoneID)
|
d.Set("zone_id", recNet.ZoneID)
|
||||||
d.Set("enable_secgroups", recNet.EnableSecGroups)
|
d.Set("enable_secgroups", recNet.EnableSecGroups)
|
||||||
|
d.Set("sec_vnfdev_id", recNet.SecVNFDevID)
|
||||||
|
d.Set("highly_available", recNet.Redundant)
|
||||||
|
d.Set("mtu", recNet.MTU)
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenExtnetExcluded(ers extnet.ListReservations) []map[string]interface{} {
|
func flattenExtnetExcluded(ers extnet.ListReservations) []map[string]interface{} {
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ package extnet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
@@ -65,6 +67,19 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
|||||||
VLANID: uint64(d.Get("vlan_id").(int)),
|
VLANID: uint64(d.Get("vlan_id").(int)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var diags diag.Diagnostics
|
||||||
|
|
||||||
|
if _, ipNet, err := net.ParseCIDR(req.IPCIDR); err == nil {
|
||||||
|
normalized := ipNet.String()
|
||||||
|
if normalized != req.IPCIDR {
|
||||||
|
diags = append(diags, diag.Diagnostic{
|
||||||
|
Severity: diag.Warning,
|
||||||
|
Summary: "ipcidr will be normalized by the platform",
|
||||||
|
Detail: fmt.Sprintf("CIDR will be: %q", normalized),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if gateway, ok := d.GetOk("gateway"); ok {
|
if gateway, ok := d.GetOk("gateway"); ok {
|
||||||
req.Gateway = gateway.(string)
|
req.Gateway = gateway.(string)
|
||||||
}
|
}
|
||||||
@@ -132,6 +147,10 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
|||||||
req.SecVNFDevIP = sec_vnfdev_ip.(string)
|
req.SecVNFDevIP = sec_vnfdev_ip.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if vnfdev_ip, ok := d.GetOk("vnfdev_ip"); ok {
|
||||||
|
req.PriVNFDevIP = vnfdev_ip.(string)
|
||||||
|
}
|
||||||
|
|
||||||
if mtu, ok := d.GetOk("mtu"); ok {
|
if mtu, ok := d.GetOk("mtu"); ok {
|
||||||
req.MTU = uint(mtu.(int))
|
req.MTU = uint(mtu.(int))
|
||||||
}
|
}
|
||||||
@@ -170,12 +189,12 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
|||||||
|
|
||||||
if d.Get("shared_with").(*schema.Set).Len() > 0 {
|
if d.Get("shared_with").(*schema.Set).Len() > 0 {
|
||||||
for _, id := range d.Get("shared_with").(*schema.Set).List() {
|
for _, id := range d.Get("shared_with").(*schema.Set).List() {
|
||||||
req := extnet.AccessRemoveRequest{
|
req := extnet.AccessAddRequest{
|
||||||
NetID: uint64(d.Get("extnet_id").(int)),
|
NetID: uint64(d.Get("extnet_id").(int)),
|
||||||
AccountID: uint64(id.(int)),
|
AccountID: uint64(id.(int)),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := c.CloudBroker().ExtNet().AccessRemove(ctx, req)
|
_, err := c.CloudBroker().ExtNet().AccessAdd(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Add(err)
|
w.Add(err)
|
||||||
}
|
}
|
||||||
@@ -208,6 +227,12 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if qos, ok := d.GetOk("default_qos"); ok && len(qos.([]interface{})) > 0 {
|
||||||
|
if err := handleDefaultQOSUpdate(ctx, d, c, &extnet.RecordExtNet{ID: netID}); err != nil {
|
||||||
|
w.Add(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// for reserve IP extnet must be enabled
|
// for reserve IP extnet must be enabled
|
||||||
if d.Get("reserved_ip").(*schema.Set).Len() > 0 {
|
if d.Get("reserved_ip").(*schema.Set).Len() > 0 {
|
||||||
for _, reservedIP := range d.Get("reserved_ip").(*schema.Set).List() {
|
for _, reservedIP := range d.Get("reserved_ip").(*schema.Set).List() {
|
||||||
@@ -236,7 +261,9 @@ func resourceExtnetCreate(ctx context.Context, d *schema.ResourceData, m interfa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceExtnetRead(ctx, d, m)
|
diags = append(diags, w.Get()...)
|
||||||
|
|
||||||
|
return append(diags, resourceExtnetRead(ctx, d, m)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceExtnetRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
func resourceExtnetRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package extnet
|
package extnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||||
)
|
)
|
||||||
@@ -691,6 +693,14 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Required: true,
|
Required: true,
|
||||||
// ForceNew: true,
|
// ForceNew: true,
|
||||||
Description: "IP network CIDR",
|
Description: "IP network CIDR",
|
||||||
|
ValidateFunc: validation.IsCIDR,
|
||||||
|
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
||||||
|
_, ipnet, err := net.ParseCIDR(new)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return old == ipnet.String()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"vlan_id": {
|
"vlan_id": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
@@ -703,6 +713,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "External network gateway IP address",
|
Description: "External network gateway IP address",
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
"zone_id": {
|
"zone_id": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
@@ -721,6 +732,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
Elem: &schema.Schema{
|
Elem: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
Description: "List of DNS addresses",
|
Description: "List of DNS addresses",
|
||||||
},
|
},
|
||||||
@@ -730,6 +742,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
Elem: &schema.Schema{
|
Elem: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
Description: "List of NTP addresses",
|
Description: "List of NTP addresses",
|
||||||
},
|
},
|
||||||
@@ -739,6 +752,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
Elem: &schema.Schema{
|
Elem: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
Description: "IPs to check network availability",
|
Description: "IPs to check network availability",
|
||||||
},
|
},
|
||||||
@@ -757,16 +771,19 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "Start of IP range to be explicitly included",
|
Description: "Start of IP range to be explicitly included",
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
"end_ip": {
|
"end_ip": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "End of IP range to be explicitly included",
|
Description: "End of IP range to be explicitly included",
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
"vnfdev_ip": {
|
"vnfdev_ip": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "IP to create VNFDev with",
|
Description: "IP to create VNFDev with",
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
"pre_reservations_num": {
|
"pre_reservations_num": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
@@ -797,6 +814,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
Elem: &schema.Schema{
|
Elem: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
Description: "IPs to exclude in current extnet pool",
|
Description: "IPs to exclude in current extnet pool",
|
||||||
},
|
},
|
||||||
@@ -808,10 +826,12 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
"ip_start": {
|
"ip_start": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
"ip_end": {
|
"ip_end": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -882,6 +902,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
Elem: &schema.Schema{
|
Elem: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -896,6 +917,7 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
ValidateFunc: validation.IsIPAddress,
|
||||||
},
|
},
|
||||||
"mtu": {
|
"mtu": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
@@ -954,6 +976,10 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"sec_vnfdev_id": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
@@ -979,6 +1005,10 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"desc": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
"domain_name": {
|
"domain_name": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
@@ -1014,6 +1044,50 @@ func resourceExtnetSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"pre_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,
|
||||||
|
},
|
||||||
|
"desc": {
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"routes": {
|
"routes": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8ci"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8ci"
|
||||||
|
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
func flattenK8CIListItems(list *k8ci.ListK8CI) []map[string]interface{} {
|
func flattenK8CIListItems(list *k8ci.ListK8CI) []map[string]interface{} {
|
||||||
@@ -69,6 +70,7 @@ func flattenK8CIItems(d *schema.ResourceData, data *k8ci.RecordK8CI) error {
|
|||||||
log.Debugf("flattenK8CI: ID %d", data.ID)
|
log.Debugf("flattenK8CI: ID %d", data.ID)
|
||||||
|
|
||||||
d.Set("desc", data.Description)
|
d.Set("desc", data.Description)
|
||||||
|
d.Set("enabled", data.Status == status.Enabled)
|
||||||
d.Set("gid", data.GID)
|
d.Set("gid", data.GID)
|
||||||
d.Set("guid", data.GUID)
|
d.Set("guid", data.GUID)
|
||||||
d.Set("k8ci_id", data.ID)
|
d.Set("k8ci_id", data.ID)
|
||||||
|
|||||||
@@ -93,9 +93,9 @@ func resourceK8CICreate(ctx context.Context, d *schema.ResourceData, m interface
|
|||||||
|
|
||||||
warnings := dc.Warnings{}
|
warnings := dc.Warnings{}
|
||||||
|
|
||||||
if enabled, ok := d.GetOk("enabled"); ok {
|
enabled := d.Get("enabled").(bool)
|
||||||
log.Debugf("resourceK8CICreate: enable=%t k8ci_id %d after completing its resource configuration", enabled, k8ciID)
|
log.Debugf("resourceK8CICreate: enable=%t k8ci_id %d after completing its resource configuration", enabled, k8ciID)
|
||||||
if enabled.(bool) {
|
if enabled {
|
||||||
enabledReq := k8ci.EnableRequest{
|
enabledReq := k8ci.EnableRequest{
|
||||||
K8CIID: k8ciID,
|
K8CIID: k8ciID,
|
||||||
}
|
}
|
||||||
@@ -110,7 +110,6 @@ func resourceK8CICreate(ctx context.Context, d *schema.ResourceData, m interface
|
|||||||
warnings.Add(err)
|
warnings.Add(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return append(warnings.Get(), resourceK8CIRead(ctx, d, m)...)
|
return append(warnings.Get(), resourceK8CIRead(ctx, d, m)...)
|
||||||
}
|
}
|
||||||
@@ -199,8 +198,8 @@ func resourceK8CIUpdate(ctx context.Context, d *schema.ResourceData, m interface
|
|||||||
return diag.FromErr(err)
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enabled, ok := d.GetOk("enabled"); ok {
|
if enabled, ok := d.Get("enabled").(bool); ok {
|
||||||
if enabled.(bool) {
|
if enabled {
|
||||||
enabledReq := k8ci.EnableRequest{K8CIID: k8ciRec.ID}
|
enabledReq := k8ci.EnableRequest{K8CIID: k8ciRec.ID}
|
||||||
_, err := c.CloudBroker().K8CI().Enable(ctx, enabledReq)
|
_, err := c.CloudBroker().K8CI().Enable(ctx, enabledReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -388,6 +388,7 @@ func resourceK8CISchemaMake() map[string]*schema.Schema {
|
|||||||
"enabled": {
|
"enabled": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Default: true,
|
||||||
},
|
},
|
||||||
"permanently": {
|
"permanently": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
|
|||||||
@@ -4672,6 +4672,10 @@ func resourceComputeSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"user_data": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
"user_managed": {
|
"user_managed": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
|||||||
@@ -62,9 +62,8 @@ func resourceStoragePolicyCreate(ctx context.Context, d *schema.ResourceData, m
|
|||||||
|
|
||||||
d.SetId(strconv.FormatUint(storagePolicyID, 10))
|
d.SetId(strconv.FormatUint(storagePolicyID, 10))
|
||||||
|
|
||||||
if enabled, ok := d.GetOk("enabled"); ok {
|
if enabled, ok := d.Get("enabled").(bool); ok {
|
||||||
isToEnable := enabled.(bool)
|
if err := handleStoragePolicyEnabling(ctx, d, c, storagePolicyID, enabled); err != nil {
|
||||||
if err := handleStoragePolicyEnabling(ctx, d, c, storagePolicyID, isToEnable); err != nil {
|
|
||||||
warnings.Add(err)
|
warnings.Add(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ func resourceStoragePolicySchemaMake() map[string]*schema.Schema {
|
|||||||
"limit_iops": {
|
"limit_iops": {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
},
|
},
|
||||||
"enabled": {
|
"enabled": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
|
|||||||
22
internal/service/sdn/logicalports/address_hash.go
Normal file
22
internal/service/sdn/logicalports/address_hash.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func hashLogicalPortAddress(v interface{}) int {
|
||||||
|
m := v.(map[string]interface{})
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fmt.Fprintf(&buf, "ip:%s;", m["ip"].(string))
|
||||||
|
fmt.Fprintf(&buf, "ip_type:%s;", m["ip_type"].(string))
|
||||||
|
fmt.Fprintf(&buf, "is_primary:%t;", m["is_primary"].(bool))
|
||||||
|
fmt.Fprintf(&buf, "is_discovered:%t;", m["is_discovered"].(bool))
|
||||||
|
fmt.Fprintf(&buf, "mac:%s;", m["mac"].(string))
|
||||||
|
|
||||||
|
hs := fnv.New32a()
|
||||||
|
hs.Write(buf.Bytes())
|
||||||
|
return int(hs.Sum32())
|
||||||
|
}
|
||||||
@@ -24,6 +24,20 @@ func flattenLogicalPortResource(d *schema.ResourceData, logicalPort *logicalport
|
|||||||
d.Set("bindings", flattenBindings(logicalPort.Bindings))
|
d.Set("bindings", flattenBindings(logicalPort.Bindings))
|
||||||
d.Set("labels", flattenLabels(logicalPort.Labels))
|
d.Set("labels", flattenLabels(logicalPort.Labels))
|
||||||
d.Set("created_at", logicalPort.CreatedAt)
|
d.Set("created_at", logicalPort.CreatedAt)
|
||||||
|
d.Set("updated_at", logicalPort.UpdatedAt)
|
||||||
|
d.Set("exclude_firewall", flattenExcludeFirewall(logicalPort.ExcludeFirewall))
|
||||||
|
d.Set("logical_port_addresses", flattenLogicalPortAddresses(logicalPort.Bindings.LogicalPortAddresses))
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenExcludeFirewall(excludeFirewall logicalports.ExcludeFirewall) []map[string]interface{} {
|
||||||
|
res := make([]map[string]interface{}, 0)
|
||||||
|
temp := map[string]interface{}{
|
||||||
|
"exclusion_reason": excludeFirewall.ExclusionReason,
|
||||||
|
"logical_port_addresses_excluded": excludeFirewall.LogicalPortAddressesExcluded,
|
||||||
|
"logical_port_excluded": excludeFirewall.LogicalPortExcluded,
|
||||||
|
}
|
||||||
|
res = append(res, temp)
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenLogicalPortList(lpl *logicalports.LogicalPortsList) []map[string]interface{} {
|
func flattenLogicalPortList(lpl *logicalports.LogicalPortsList) []map[string]interface{} {
|
||||||
@@ -79,7 +93,7 @@ func flattenLogicalPort(d *schema.ResourceData, logicalPort *logicalports.Logica
|
|||||||
|
|
||||||
func flattenLabels(labels logicalports.Labels) []map[string]interface{} {
|
func flattenLabels(labels logicalports.Labels) []map[string]interface{} {
|
||||||
if labels.VMID == "" && labels.VMName == "" {
|
if labels.VMID == "" && labels.VMName == "" {
|
||||||
return []map[string]interface{}{}
|
return nil
|
||||||
}
|
}
|
||||||
return []map[string]interface{}{
|
return []map[string]interface{}{
|
||||||
{
|
{
|
||||||
@@ -106,10 +120,8 @@ func flattenBindings(bindings logicalports.Bindings) []map[string]interface{} {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenLogicalPortAddresses(addrs []logicalports.LogicalPortAddress) []map[string]interface{} {
|
func flattenLogicalPortAddress(a logicalports.LogicalPortAddress) map[string]interface{} {
|
||||||
res := make([]map[string]interface{}, 0, len(addrs))
|
return map[string]interface{}{
|
||||||
for _, a := range addrs {
|
|
||||||
res = append(res, map[string]interface{}{
|
|
||||||
"ip": a.IP,
|
"ip": a.IP,
|
||||||
"ip_type": a.IPType,
|
"ip_type": a.IPType,
|
||||||
"mac": a.MAC,
|
"mac": a.MAC,
|
||||||
@@ -118,7 +130,13 @@ func flattenLogicalPortAddresses(addrs []logicalports.LogicalPortAddress) []map[
|
|||||||
"assigned_at": a.AssignedAt,
|
"assigned_at": a.AssignedAt,
|
||||||
"is_discovered": a.IsDiscovered,
|
"is_discovered": a.IsDiscovered,
|
||||||
"is_primary": a.IsPrimary,
|
"is_primary": a.IsPrimary,
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func flattenLogicalPortAddresses(addrs []logicalports.LogicalPortAddress) []map[string]interface{} {
|
||||||
|
res := make([]map[string]interface{}, 0, len(addrs))
|
||||||
|
for _, a := range addrs {
|
||||||
|
res = append(res, flattenLogicalPortAddress(a))
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
259
internal/service/sdn/logicalports/old_schemas.go
Normal file
259
internal/service/sdn/logicalports/old_schemas.go
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceLogicalPortResourceV1() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"access_group_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Access Group ID",
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Description",
|
||||||
|
},
|
||||||
|
"display_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Display Name",
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
Description: "Whether the logical port should be enabled",
|
||||||
|
},
|
||||||
|
"hypervisor": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Hypervisor",
|
||||||
|
},
|
||||||
|
"port_security": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
Description: "Whether the port security is enabled",
|
||||||
|
},
|
||||||
|
"segment_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "Segment ID",
|
||||||
|
},
|
||||||
|
"adapter_mac": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Adapter MAC address",
|
||||||
|
},
|
||||||
|
"unique_identifier": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "Unique identifier of the logical port",
|
||||||
|
},
|
||||||
|
"force": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
},
|
||||||
|
"migrate": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
Description: "If true, triggers live migration to the hypervisor specified in the 'hypervisor' field. If false, hypervisor changes are applied via the regular update endpoint.",
|
||||||
|
},
|
||||||
|
"logical_port_addresses": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"ip": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Description: "IP address of the logical port",
|
||||||
|
},
|
||||||
|
"ip_type": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validation.StringInSlice([]string{"IPv4", "IPv6"}, false),
|
||||||
|
},
|
||||||
|
"is_primary": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"is_discovered": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
},
|
||||||
|
"mac": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the logical port",
|
||||||
|
},
|
||||||
|
"access_group_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Name of the access group",
|
||||||
|
},
|
||||||
|
"address_detection": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"external_network_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"hypervisor_display_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"live_migration_target_hv": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"operation_status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Operation status",
|
||||||
|
},
|
||||||
|
"hypervisor_status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Hypervisor status",
|
||||||
|
},
|
||||||
|
"hypervisors": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"operation_status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Operation status of the hypervisor",
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Name of the hypervisor",
|
||||||
|
},
|
||||||
|
"display_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Display name of the hypervisor",
|
||||||
|
},
|
||||||
|
"hypervisor_status": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Status of the hypervisor",
|
||||||
|
},
|
||||||
|
"synced_at": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Sync time of the hypervisor",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"bindings": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Unique identifier of the binding",
|
||||||
|
},
|
||||||
|
"segment_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Unique identifier of the segment",
|
||||||
|
},
|
||||||
|
"segment_display_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Display name of the segment",
|
||||||
|
},
|
||||||
|
"port_security": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
Description: "If the port is secured",
|
||||||
|
},
|
||||||
|
"address_detection": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
Description: "If the adapter address detection is enabled",
|
||||||
|
},
|
||||||
|
"version_id": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Version ID of the binding",
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Creation time of the binding",
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Update time of the binding",
|
||||||
|
},
|
||||||
|
"logical_port_addresses": logicalPortAddressesSchema(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"version_id": {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Version ID of the logical port",
|
||||||
|
},
|
||||||
|
"labels": {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
MaxItems: 1,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"vm_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Description: "VM ID label",
|
||||||
|
},
|
||||||
|
"vm_name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
Description: "VM name label",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Description: "Labels",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package logicalports
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
@@ -16,6 +18,8 @@ func resourceLogicalPortCreate(ctx context.Context, d *schema.ResourceData, m in
|
|||||||
d.Get("display_name").(string))
|
d.Get("display_name").(string))
|
||||||
c := m.(*controller.ControllerCfg)
|
c := m.(*controller.ControllerCfg)
|
||||||
|
|
||||||
|
var diags diag.Diagnostics
|
||||||
|
|
||||||
req := logicalports.CreateRequest{
|
req := logicalports.CreateRequest{
|
||||||
AccessGroupID: d.Get("access_group_id").(string),
|
AccessGroupID: d.Get("access_group_id").(string),
|
||||||
Description: d.Get("description").(string),
|
Description: d.Get("description").(string),
|
||||||
@@ -36,42 +40,74 @@ func resourceLogicalPortCreate(ctx context.Context, d *schema.ResourceData, m in
|
|||||||
labelsList := labelsRaw.([]interface{})
|
labelsList := labelsRaw.([]interface{})
|
||||||
if len(labelsList) > 0 {
|
if len(labelsList) > 0 {
|
||||||
labelsMap := labelsList[0].(map[string]interface{})
|
labelsMap := labelsList[0].(map[string]interface{})
|
||||||
req.Labels = logicalports.CreateLabels{
|
req.Labels = &logicalports.CreateLabels{
|
||||||
VMID: labelsMap["vm_id"].(string),
|
VMID: labelsMap["vm_id"].(string),
|
||||||
VMName: labelsMap["vm_name"].(string),
|
VMName: labelsMap["vm_name"].(string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if logicalPortAddresses, ok := d.GetOk("logical_port_addresses"); ok {
|
if logicalPortAddresses, ok := d.GetOk("logical_port_addresses"); ok {
|
||||||
logicalPortAddressesList := logicalPortAddresses.([]interface{})
|
logicalPortAddressesList := logicalPortAddresses.(*schema.Set).List()
|
||||||
logicalPortsAddressesArr := make([]logicalports.LogicalPortAddress, 0)
|
logicalPortsAddressesArr := make([]logicalports.LogicalPortAddressRequest, 0)
|
||||||
|
primaryCount := 0
|
||||||
|
ipMap := make(map[string]bool)
|
||||||
|
blankMACIPs := make([]string, 0)
|
||||||
|
|
||||||
for _, logicalPortAddressRaw := range logicalPortAddressesList {
|
for _, logicalPortAddressRaw := range logicalPortAddressesList {
|
||||||
logicalPortAddressMap := logicalPortAddressRaw.(map[string]interface{})
|
logicalPortAddressMap := logicalPortAddressRaw.(map[string]interface{})
|
||||||
logicalPortAddress := logicalports.LogicalPortAddress{
|
ip := logicalPortAddressMap["ip"].(string)
|
||||||
IP: logicalPortAddressMap["ip"].(string),
|
isPrimary := logicalPortAddressMap["is_primary"].(bool)
|
||||||
|
|
||||||
|
if isPrimary {
|
||||||
|
primaryCount++
|
||||||
|
if primaryCount > 1 {
|
||||||
|
return diag.Errorf("logical_port_addresses: only one address can be primary (is_primary = true)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipMap[ip] {
|
||||||
|
return diag.Errorf("logical_port_addresses: duplicate IP address %s is not allowed", ip)
|
||||||
|
}
|
||||||
|
ipMap[ip] = true
|
||||||
|
|
||||||
|
mac := logicalPortAddressMap["mac"].(string)
|
||||||
|
if mac == "" {
|
||||||
|
blankMACIPs = append(blankMACIPs, ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
logicalPortsAddressesArr = append(logicalPortsAddressesArr, logicalports.LogicalPortAddressRequest{
|
||||||
|
IP: ip,
|
||||||
IPType: logicalPortAddressMap["ip_type"].(string),
|
IPType: logicalPortAddressMap["ip_type"].(string),
|
||||||
IsPrimary: logicalPortAddressMap["is_primary"].(bool),
|
IsPrimary: isPrimary,
|
||||||
|
IsDiscovered: logicalPortAddressMap["is_discovered"].(bool),
|
||||||
|
MAC: mac,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if isDiscovered, ok := logicalPortAddressMap["is_discovered"]; ok {
|
|
||||||
logicalPortAddress.IsDiscovered = isDiscovered.(bool)
|
if len(blankMACIPs) > 0 {
|
||||||
}
|
diags = append(diags, diag.Diagnostic{
|
||||||
if mac, ok := logicalPortAddressMap["mac"]; ok {
|
Severity: diag.Warning,
|
||||||
logicalPortAddress.MAC = mac.(string)
|
Summary: "logical_port_addresses: mac not set, will be auto-generated",
|
||||||
}
|
Detail: fmt.Sprintf(
|
||||||
logicalPortsAddressesArr = append(logicalPortsAddressesArr, logicalPortAddress)
|
"MAC is not set for the following addresses, the platform will auto-generate it for each: %s. "+
|
||||||
|
"Every subsequent \"terraform plan\" will show these addresses as changed (a harmless no-op diff) until mac is set explicitly.",
|
||||||
|
strings.Join(blankMACIPs, ", "),
|
||||||
|
),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
req.LogicalPortAddresses = logicalPortsAddressesArr
|
req.LogicalPortAddresses = logicalPortsAddressesArr
|
||||||
}
|
}
|
||||||
|
|
||||||
logicalPort, err := c.SDN().LogicalPorts().Create(ctx, req)
|
logicalPort, err := c.SDN().LogicalPorts().Create(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.SetId("")
|
d.SetId("")
|
||||||
return diag.FromErr(err)
|
return append(diags, diag.FromErr(err)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId(logicalPort.ID)
|
d.SetId(logicalPort.ID)
|
||||||
|
|
||||||
return resourceLogicalPortRead(ctx, d, m)
|
return append(diags, resourceLogicalPortRead(ctx, d, m)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceLogicalPortRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
func resourceLogicalPortRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||||
@@ -95,6 +131,12 @@ func resourceLogicalPortUpdate(ctx context.Context, d *schema.ResourceData, m in
|
|||||||
|
|
||||||
migrate := d.Get("migrate").(bool)
|
migrate := d.Get("migrate").(bool)
|
||||||
|
|
||||||
|
if _, ok := d.GetOk("adapter_mac"); !ok {
|
||||||
|
return diag.Errorf("the adapter_mac field is required when updating")
|
||||||
|
}
|
||||||
|
|
||||||
|
var diags diag.Diagnostics
|
||||||
|
|
||||||
req := logicalports.UpdateRequest{
|
req := logicalports.UpdateRequest{
|
||||||
LogicalPortID: d.Id(),
|
LogicalPortID: d.Id(),
|
||||||
VersionID: uint64(d.Get("version_id").(int)),
|
VersionID: uint64(d.Get("version_id").(int)),
|
||||||
@@ -106,132 +148,167 @@ func resourceLogicalPortUpdate(ctx context.Context, d *schema.ResourceData, m in
|
|||||||
SegmentID: d.Get("segment_id").(string),
|
SegmentID: d.Get("segment_id").(string),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !migrate {
|
hvChanged := d.HasChange("hypervisor")
|
||||||
req.Hypervisor = d.Get("hypervisor").(string)
|
if migrate && hvChanged {
|
||||||
} else {
|
|
||||||
old, _ := d.GetChange("hypervisor")
|
old, _ := d.GetChange("hypervisor")
|
||||||
req.Hypervisor = old.(string)
|
req.Hypervisor = old.(string)
|
||||||
|
} else {
|
||||||
|
req.Hypervisor = d.Get("hypervisor").(string)
|
||||||
|
if hvChanged {
|
||||||
|
diags = append(diags, diag.Diagnostic{
|
||||||
|
Severity: diag.Warning,
|
||||||
|
Summary: "hypervisor changed without migrate=true",
|
||||||
|
Detail: "hypervisor was changed but flag \"migrate\" is false, this change is being sent via the regular " +
|
||||||
|
"update endpoint instead of a live migration. If you intended to live migrate this logical port, " +
|
||||||
|
"set migrate = true.",
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.HasChange("labels") {
|
|
||||||
if labelsRaw, ok := d.GetOk("labels"); ok {
|
if labelsRaw, ok := d.GetOk("labels"); ok {
|
||||||
labelsList := labelsRaw.([]interface{})
|
labelsList := labelsRaw.([]interface{})
|
||||||
if len(labelsList) > 0 {
|
if len(labelsList) > 0 {
|
||||||
labelsMap := labelsList[0].(map[string]interface{})
|
labelsMap := labelsList[0].(map[string]interface{})
|
||||||
req.Labels = logicalports.UpdateLabels{
|
req.Labels = &logicalports.UpdateLabels{
|
||||||
VMID: labelsMap["vm_id"].(string),
|
VMID: labelsMap["vm_id"].(string),
|
||||||
VMName: labelsMap["vm_name"].(string),
|
VMName: labelsMap["vm_name"].(string),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if d.HasChange("logical_port_addresses") {
|
if d.HasChange("logical_port_addresses") {
|
||||||
oldAddresses, newAddresses := d.GetChange("logical_port_addresses")
|
oldAddresses, newAddresses := d.GetChange("logical_port_addresses")
|
||||||
oldAddressesList := oldAddresses.([]interface{})
|
|
||||||
newAddressesList := newAddresses.([]interface{})
|
oldAddressesList := oldAddresses.(*schema.Set).List()
|
||||||
oldAddressesMap := make(map[string]logicalports.LogicalPortAddress)
|
oldAddressesMap := make(map[string]logicalports.LogicalPortAddress, len(oldAddressesList))
|
||||||
for _, oldAddressRaw := range oldAddressesList {
|
for _, oldAddressRaw := range oldAddressesList {
|
||||||
logicalPortAddressMap := oldAddressRaw.(map[string]interface{})
|
logicalPortAddressMap := oldAddressRaw.(map[string]interface{})
|
||||||
logicalPortAddress := logicalports.LogicalPortAddress{
|
logicalPortAddress := logicalports.LogicalPortAddress{
|
||||||
|
ID: logicalPortAddressMap["id"].(string),
|
||||||
IP: logicalPortAddressMap["ip"].(string),
|
IP: logicalPortAddressMap["ip"].(string),
|
||||||
IPType: logicalPortAddressMap["ip_type"].(string),
|
IPType: logicalPortAddressMap["ip_type"].(string),
|
||||||
IsPrimary: logicalPortAddressMap["is_primary"].(bool),
|
IsPrimary: logicalPortAddressMap["is_primary"].(bool),
|
||||||
}
|
IsDiscovered: logicalPortAddressMap["is_discovered"].(bool),
|
||||||
if isDiscovered, ok := logicalPortAddressMap["is_discovered"]; ok {
|
MAC: logicalPortAddressMap["mac"].(string),
|
||||||
logicalPortAddress.IsDiscovered = isDiscovered.(bool)
|
|
||||||
}
|
|
||||||
if mac, ok := logicalPortAddressMap["mac"]; ok {
|
|
||||||
logicalPortAddress.MAC = mac.(string)
|
|
||||||
}
|
}
|
||||||
oldAddressesMap[logicalPortAddress.IP] = logicalPortAddress
|
oldAddressesMap[logicalPortAddress.IP] = logicalPortAddress
|
||||||
}
|
}
|
||||||
newAddressesMap := make(map[string]logicalports.LogicalPortAddress)
|
|
||||||
|
newAddressesList := newAddresses.(*schema.Set).List()
|
||||||
|
newAddressesMap := make(map[string]logicalports.LogicalPortAddress, len(newAddressesList))
|
||||||
|
primaryCount := 0
|
||||||
for _, newAddressRaw := range newAddressesList {
|
for _, newAddressRaw := range newAddressesList {
|
||||||
logicalPortAddressMap := newAddressRaw.(map[string]interface{})
|
logicalPortAddressMap := newAddressRaw.(map[string]interface{})
|
||||||
logicalPortAddress := logicalports.LogicalPortAddress{
|
logicalPortAddress := logicalports.LogicalPortAddress{
|
||||||
|
ID: logicalPortAddressMap["id"].(string),
|
||||||
IP: logicalPortAddressMap["ip"].(string),
|
IP: logicalPortAddressMap["ip"].(string),
|
||||||
IPType: logicalPortAddressMap["ip_type"].(string),
|
IPType: logicalPortAddressMap["ip_type"].(string),
|
||||||
IsPrimary: logicalPortAddressMap["is_primary"].(bool),
|
IsPrimary: logicalPortAddressMap["is_primary"].(bool),
|
||||||
|
IsDiscovered: logicalPortAddressMap["is_discovered"].(bool),
|
||||||
|
MAC: logicalPortAddressMap["mac"].(string),
|
||||||
}
|
}
|
||||||
if isDiscovered, ok := logicalPortAddressMap["is_discovered"]; ok {
|
if logicalPortAddress.IsPrimary {
|
||||||
logicalPortAddress.IsDiscovered = isDiscovered.(bool)
|
primaryCount++
|
||||||
|
if primaryCount > 1 {
|
||||||
|
return append(diags, diag.Errorf("logical_port_addresses: only one address can be primary (is_primary = true)")...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if logicalPortAddress.IP != "" {
|
||||||
|
if bar, ok := newAddressesMap[logicalPortAddress.IP]; ok {
|
||||||
|
return append(diags, diag.Errorf("it is impossible to create ports with the same IP %s", bar.IP)...)
|
||||||
}
|
}
|
||||||
if mac, ok := logicalPortAddressMap["mac"]; ok {
|
|
||||||
logicalPortAddress.MAC = mac.(string)
|
|
||||||
}
|
}
|
||||||
newAddressesMap[logicalPortAddress.IP] = logicalPortAddress
|
newAddressesMap[logicalPortAddress.IP] = logicalPortAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAddresses := make([]string, 0)
|
removeAddresses := make([]string, 0)
|
||||||
for addressIP := range oldAddressesMap {
|
for addressIP, lp := range oldAddressesMap {
|
||||||
if _, exists := newAddressesMap[addressIP]; !exists {
|
if _, exists := newAddressesMap[addressIP]; !exists {
|
||||||
removeAddresses = append(removeAddresses, addressIP)
|
removeAddresses = append(removeAddresses, lp.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req.RemoveAddresses = removeAddresses
|
req.RemoveAddresses = removeAddresses
|
||||||
|
|
||||||
for addressIP, address := range newAddressesMap {
|
for addressIP, address := range newAddressesMap {
|
||||||
if oldAddressIP, exists := oldAddressesMap[addressIP]; !exists || address != oldAddressIP {
|
oldAddress, exists := oldAddressesMap[addressIP]
|
||||||
if !exists {
|
|
||||||
logicalPortAddress := logicalports.AddAddress{
|
// mac field fallback
|
||||||
IP: address.IP,
|
currMac := address.MAC
|
||||||
IPType: address.IPType,
|
if exists && currMac == "" {
|
||||||
IsPrimary: address.IsPrimary,
|
currMac = oldAddress.MAC
|
||||||
IsDiscovered: address.IsDiscovered,
|
|
||||||
MAC: address.MAC,
|
|
||||||
}
|
|
||||||
req.AddAddresses = append(req.AddAddresses, logicalPortAddress)
|
|
||||||
} else if address != oldAddressIP {
|
|
||||||
logicalPortAddress := logicalports.UpdateAddress{
|
|
||||||
IP: address.IP,
|
|
||||||
IPType: address.IPType,
|
|
||||||
IsPrimary: address.IsPrimary,
|
|
||||||
IsDiscovered: address.IsDiscovered,
|
|
||||||
MAC: address.MAC,
|
|
||||||
}
|
|
||||||
req.UpdateAddresses = append(req.UpdateAddresses, logicalPortAddress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
if currMac == "" {
|
||||||
|
return append(diags, diag.Errorf("logical_port_addresses: mac is required when adding a new address to an existing logical port (ip=%s)", address.IP)...)
|
||||||
|
}
|
||||||
|
req.AddAddresses = append(req.AddAddresses, logicalports.AddAddress{
|
||||||
|
IP: address.IP,
|
||||||
|
IPType: address.IPType,
|
||||||
|
IsPrimary: address.IsPrimary,
|
||||||
|
IsDiscovered: address.IsDiscovered,
|
||||||
|
MAC: currMac,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare without compute fields: id, logical_port_id, assigned_at
|
||||||
|
changed := currMac != oldAddress.MAC ||
|
||||||
|
address.IPType != oldAddress.IPType ||
|
||||||
|
address.IsPrimary != oldAddress.IsPrimary ||
|
||||||
|
address.IsDiscovered != oldAddress.IsDiscovered
|
||||||
|
if !changed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldAddress.ID == "" {
|
||||||
|
return append(diags, diag.Errorf("logical_port_addresses: internal error, missing platform id for existing address (ip=%s)", address.IP)...)
|
||||||
|
}
|
||||||
|
req.UpdateAddresses = append(req.UpdateAddresses, logicalports.UpdateAddress{
|
||||||
|
ID: oldAddress.ID,
|
||||||
|
IP: address.IP,
|
||||||
|
IPType: address.IPType,
|
||||||
|
IsPrimary: address.IsPrimary,
|
||||||
|
IsDiscovered: address.IsDiscovered,
|
||||||
|
MAC: currMac,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := c.SDN().LogicalPorts().Update(ctx, req)
|
_, err := c.SDN().LogicalPorts().Update(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.SetId("")
|
return append(diags, diag.FromErr(err)...)
|
||||||
return diag.FromErr(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if migrate {
|
if migrate && hvChanged {
|
||||||
if targetHV, ok := d.GetOk("hypervisor"); ok {
|
targetHV := d.Get("hypervisor").(string)
|
||||||
// Re-read version_id
|
|
||||||
|
// re-read version_id
|
||||||
lp, err := utilityLogicalPortCheckPresence(ctx, d, m)
|
lp, err := utilityLogicalPortCheckPresence(ctx, d, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diag.FromErr(err)
|
return append(diags, diag.FromErr(err)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
migrateReq := logicalports.MigrateStartRequest{
|
migrateReq := logicalports.MigrateStartRequest{
|
||||||
LogicalPortID: d.Id(),
|
LogicalPortID: d.Id(),
|
||||||
VersionID: lp.VersionID,
|
VersionID: lp.VersionID,
|
||||||
TargetHypervisor: targetHV.(string),
|
TargetHypervisor: targetHV,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.SDN().LogicalPorts().StartMigrate(ctx, migrateReq)
|
_, err = c.SDN().LogicalPorts().StartMigrate(ctx, migrateReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diag.FromErr(err)
|
return append(diags, diag.FromErr(err)...)
|
||||||
}
|
}
|
||||||
// to prevent drift on the next plan
|
// to prevent drift on the next plan
|
||||||
diags := resourceLogicalPortRead(ctx, d, m)
|
readDiags := resourceLogicalPortRead(ctx, d, m)
|
||||||
if diags.HasError() {
|
if readDiags.HasError() {
|
||||||
return diags
|
return append(diags, readDiags...)
|
||||||
}
|
|
||||||
d.Set("hypervisor", targetHV.(string))
|
|
||||||
return diags
|
|
||||||
}
|
}
|
||||||
|
d.Set("hypervisor", targetHV)
|
||||||
|
return append(diags, readDiags...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceLogicalPortRead(ctx, d, m)
|
return append(diags, resourceLogicalPortRead(ctx, d, m)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceLogicalPortDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
func resourceLogicalPortDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
||||||
@@ -259,7 +336,7 @@ func resourceLogicalPortDelete(ctx context.Context, d *schema.ResourceData, m in
|
|||||||
|
|
||||||
func ResourceLogicalPort() *schema.Resource {
|
func ResourceLogicalPort() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
SchemaVersion: 1,
|
SchemaVersion: 2,
|
||||||
|
|
||||||
CreateContext: resourceLogicalPortCreate,
|
CreateContext: resourceLogicalPortCreate,
|
||||||
ReadContext: resourceLogicalPortRead,
|
ReadContext: resourceLogicalPortRead,
|
||||||
@@ -279,5 +356,12 @@ func ResourceLogicalPort() *schema.Resource {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Schema: resourceLogicalPortSchemaMake(),
|
Schema: resourceLogicalPortSchemaMake(),
|
||||||
|
StateUpgraders: []schema.StateUpgrader{
|
||||||
|
{
|
||||||
|
Type: resourceLogicalPortResourceV1().CoreConfigSchema().ImpliedType(),
|
||||||
|
Upgrade: resourceLogicalPortUpgradeV1,
|
||||||
|
Version: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,38 @@ func logicalPortAddressesSchema() *schema.Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func excludeFirewallSchema() *schema.Schema {
|
||||||
|
return &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"exclusion_reason": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Reason for the firewall exclusion",
|
||||||
|
},
|
||||||
|
"logical_port_addresses_excluded": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Whether logical port addresses are excluded from the firewall",
|
||||||
|
},
|
||||||
|
"logical_port_excluded": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Whether the logical port is excluded from the firewall",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
||||||
res := map[string]*schema.Schema{
|
res := map[string]*schema.Schema{
|
||||||
"access_group_id": {
|
"access_group_id": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Access Group ID",
|
Description: "UUID of the access group",
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@@ -73,7 +99,7 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
"hypervisor": {
|
"hypervisor": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Hypervisor",
|
Description: "Associated hypervisor",
|
||||||
},
|
},
|
||||||
"port_security": {
|
"port_security": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
@@ -83,7 +109,7 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
"segment_id": {
|
"segment_id": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "Segment ID",
|
Description: "UUID of the network segment",
|
||||||
},
|
},
|
||||||
"adapter_mac": {
|
"adapter_mac": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@@ -94,6 +120,7 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
"unique_identifier": {
|
"unique_identifier": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
Description: "Unique identifier of the logical port",
|
Description: "Unique identifier of the logical port",
|
||||||
},
|
},
|
||||||
"force": {
|
"force": {
|
||||||
@@ -105,26 +132,29 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: false,
|
Default: false,
|
||||||
Description: "If true, triggers live migration to the hypervisor specified in the 'hypervisor' field. If false, hypervisor changes are applied via the regular update endpoint.",
|
Description: "If true, triggers live migration to the hypervisor specified in the 'hypervisor' field. If false, hypervisor changes are applied via the regular update endpoint",
|
||||||
},
|
},
|
||||||
"logical_port_addresses": {
|
"logical_port_addresses": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Set: hashLogicalPortAddress,
|
||||||
Elem: &schema.Resource{
|
Elem: &schema.Resource{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
|
"ip_type": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ValidateFunc: validation.StringInSlice([]string{"IPv4", "IPv6"}, false),
|
||||||
|
Description: "IP type",
|
||||||
|
},
|
||||||
"ip": {
|
"ip": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
Description: "IP address of the logical port",
|
Description: "IP address of the logical port",
|
||||||
},
|
},
|
||||||
"ip_type": {
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Required: true,
|
|
||||||
ValidateFunc: validation.StringInSlice([]string{"IPv4", "IPv6"}, false),
|
|
||||||
},
|
|
||||||
"is_primary": {
|
"is_primary": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Required: true,
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
},
|
},
|
||||||
"is_discovered": {
|
"is_discovered": {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
@@ -134,6 +164,24 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
"mac": {
|
"mac": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
|
ValidateFunc: validation.IsMACAddress,
|
||||||
|
Description: "MAC address; optional on initial port creation & required when adding or updating addresses in an existing logical port",
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the address, assigned by the platform",
|
||||||
|
},
|
||||||
|
"logical_port_id": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "ID of the parent logical port",
|
||||||
|
},
|
||||||
|
"assigned_at": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Timestamp when the address was assigned",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -156,6 +204,11 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"updated_at": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
Description: "Last update time of the logical port",
|
||||||
|
},
|
||||||
"external_network_id": {
|
"external_network_id": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
@@ -168,6 +221,7 @@ func resourceLogicalPortSchemaMake() map[string]*schema.Schema {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
"exclude_firewall": excludeFirewallSchema(),
|
||||||
"status": {
|
"status": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
|
|||||||
13
internal/service/sdn/logicalports/state_upgraders.go
Normal file
13
internal/service/sdn/logicalports/state_upgraders.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// "logical_port_addresses" from TypeList to TypeSet
|
||||||
|
func resourceLogicalPortUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
|
||||||
|
log.Debug("resourceLogicalPortUpgradeV1: upgrading state")
|
||||||
|
return rawState, nil
|
||||||
|
}
|
||||||
@@ -171,7 +171,7 @@ resource "decort_cb_extnet" "new_extnet" {
|
|||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
#тип - блок,
|
#тип - блок,
|
||||||
#тип вложенных полей - целое число
|
#тип вложенных полей - целое число
|
||||||
#используется при обновлении
|
#используется при создании и обновлении
|
||||||
#default_qos {
|
#default_qos {
|
||||||
#ограничение внутреннего трафика в кбит
|
#ограничение внутреннего трафика в кбит
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
|
|||||||
@@ -75,12 +75,14 @@ resource "decort_cb_k8ci" "k8ci" {
|
|||||||
|
|
||||||
#доступность k8ci
|
#доступность k8ci
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
|
#по умолчанию - true
|
||||||
#тип - булев
|
#тип - булев
|
||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
#enabled = false
|
#enabled = false
|
||||||
|
|
||||||
#флаг для удаления k8ci, без возможности восстановления
|
#флаг для удаления k8ci, без возможности восстановления
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
|
#по умолчанию - false
|
||||||
#тип - булев
|
#тип - булев
|
||||||
#используется при удалении
|
#используется при удалении
|
||||||
#permanently = true
|
#permanently = true
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ terraform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
provider "decort" {
|
provider "decort" {
|
||||||
authenticator = "decs3o"
|
authenticator = "decs3o"
|
||||||
#controller_url = <DECORT_CONTROLLER_URL>
|
#controller_url = <DECORT_CONTROLLER_URL>
|
||||||
@@ -31,7 +32,7 @@ provider "decort" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "decort_sdn_logical_port" "test" {
|
resource "decort_sdn_logical_port" "test" {
|
||||||
#id группы доступа
|
#uuid группы доступа
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
#тип - строка
|
#тип - строка
|
||||||
#используется при создании
|
#используется при создании
|
||||||
@@ -49,17 +50,18 @@ resource "decort_sdn_logical_port" "test" {
|
|||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
display_name = "name"
|
display_name = "name"
|
||||||
|
|
||||||
#включенение порта
|
#включение порта
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
#тип - булев
|
#тип - булев
|
||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
#связанный гипервизор
|
#имя связанного гипервизора
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
#тип - строка
|
#тип - строка
|
||||||
|
#для миграции на другой гипервизор необходимо выставить флаг migrate = true
|
||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
hypervisor = "hypervisor"
|
hypervisor = "hypervisor-name"
|
||||||
|
|
||||||
#статус безопасности порта
|
#статус безопасности порта
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
@@ -67,56 +69,58 @@ resource "decort_sdn_logical_port" "test" {
|
|||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
port_security = true
|
port_security = true
|
||||||
|
|
||||||
#id сегмента сети
|
#uuid сегмента сети
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
#тип - строка
|
#тип - строка
|
||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
segment_id = "a866059a-1900-4f7f-89c1-0f98880f5f4c"
|
segment_id = "a866059a-1900-4f7f-89c1-0f98880f5f4c"
|
||||||
|
|
||||||
#MAC адрес адаптера
|
#MAC адрес адаптера
|
||||||
#опциональный параметр
|
#опциональный параметр при создании
|
||||||
#тип - строка
|
|
||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
#adapter_mac = "^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$ default: null"
|
#adapter_mac = "52:54:00:12:34:56"
|
||||||
|
|
||||||
#уникальный идентификатор порта
|
#uuid порта
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
#тип - строка
|
#тип - строка
|
||||||
#используется при создании
|
#используется при создании
|
||||||
#unique_identifier = "b2c3d4e5-f6g7-8901-h2i3-j4k5l6m7n8o9"
|
#unique_identifier = "b2c3d4e5-f6g7-8901-h2i3-j4k5l6m7n8o9"
|
||||||
|
|
||||||
#управление списком адресов логических портов
|
#список ip-адресов логического порта
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
#тип - блок
|
#тип - множество блоков
|
||||||
#используется при создании и обновлении
|
#используется при создании и обновлении
|
||||||
#logical_port_addresses {
|
#logical_port_addresses {
|
||||||
#ip
|
#ip адрес
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
#тип - строка
|
#тип - строка
|
||||||
#ip = "192.168.0.1"
|
#используется при создании и обновлении
|
||||||
|
#ip = "192.168.1.14"
|
||||||
|
|
||||||
#тип ip
|
#тип ip
|
||||||
#обязательный параметр
|
#обязательный параметр
|
||||||
#тип - строка
|
#тип - строка
|
||||||
#возможные значения - IPv4, IPv6
|
#допустимые значения: "IPv4", "IPv6"
|
||||||
#ip_type = IPv4"
|
#ip_type = "IPv4"
|
||||||
|
|
||||||
#обнаружен/не обнаружен
|
#является ли адрес основным (primary) для порта
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
|
#по умолчанию: false
|
||||||
|
#среди всех блоков logical_port_addresses максимум один может иметь is_primary = true
|
||||||
#тип - булев
|
#тип - булев
|
||||||
#значение по умолчанию - false
|
|
||||||
#is_discovered = false
|
|
||||||
|
|
||||||
#является ли основным
|
|
||||||
#обязательный параметр
|
|
||||||
#тип - булев
|
|
||||||
#значение по умолчанию - true
|
|
||||||
#is_primary = true
|
#is_primary = true
|
||||||
|
|
||||||
#MAC адрес
|
#был ли адрес обнаружен автоматически
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
|
#по умолчанию: false
|
||||||
|
#тип - булев
|
||||||
|
#is_discovered = false
|
||||||
|
|
||||||
|
#MAC адрес, привязанный к ip-адресу
|
||||||
|
#опциональный параметр при создании порта (сервер сгенерирует, если не указан)
|
||||||
|
#обязателен, если адрес добавляется на уже существующий порт
|
||||||
#тип - строка
|
#тип - строка
|
||||||
#mac = "^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$"
|
#mac = "aa:bb:cc:dd:ee:fd"
|
||||||
#}
|
#}
|
||||||
|
|
||||||
#метки
|
#метки
|
||||||
@@ -127,25 +131,26 @@ resource "decort_sdn_logical_port" "test" {
|
|||||||
# #идентификатор виртуальной машины
|
# #идентификатор виртуальной машины
|
||||||
# #опциональный параметр
|
# #опциональный параметр
|
||||||
# #тип - строка
|
# #тип - строка
|
||||||
# #vm_id = "vmid-420"
|
# vm_id = "vmid-420"
|
||||||
|
|
||||||
# #имя виртуальной машины
|
# #имя виртуальной машины
|
||||||
# #опциональный параметр
|
# #опциональный параметр
|
||||||
# #тип - строка
|
# #тип - строка
|
||||||
# #vm_name = "my-vm"
|
# vm_name = "my-vm"
|
||||||
#}
|
#}
|
||||||
|
|
||||||
#флаг инициации миграции на гипервизор из поля hypervisor
|
#флаг инициации миграции на гипервизор из поля hypervisor
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
#тип - булев
|
#тип - булев
|
||||||
#значение по умолчанию - false
|
#значение по умолчанию - false
|
||||||
#используется при обновлении
|
#используется только при обновлении
|
||||||
#migrate = true
|
#migrate = true
|
||||||
|
|
||||||
#флаг принудительного удаления
|
#флаг принудительного удаления
|
||||||
#опциональный параметр
|
#опциональный параметр
|
||||||
#тип - булев
|
#тип - булев
|
||||||
#используется при обновлении
|
#значение по умолчанию - false
|
||||||
|
#используется только при удалении
|
||||||
#force = true
|
#force = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user