This commit is contained in:
2025-08-04 16:11:16 +03:00
parent bae25296bb
commit 4b3f21d9be
239 changed files with 6585 additions and 784 deletions

View File

@@ -0,0 +1,45 @@
package trunk
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/dc"
)
func dataSourceTrunkRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("dataSourceTrunkRead: called with name %s", d.Get("name").(string))
w := dc.Warnings{}
trunkItem, err := utilityTrunkCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
flattenTrunk(d, trunkItem)
return w.Get()
}
func DataSourceTrunk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceTrunkRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceTrunkSchemaMake(),
}
}

View File

@@ -0,0 +1,43 @@
package trunk
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"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/dc"
)
func dataSourceTrunkListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
w := dc.Warnings{}
trunkList, err := utilityTrunkListCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenTrunkList(trunkList))
d.Set("entry_count", trunkList.EntryCount)
return w.Get()
}
func DataSourceTrunkList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceTrunkListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceTrunkListSchemaMake(),
}
}

View File

@@ -0,0 +1,78 @@
package trunk
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/trunk"
)
func flattenTrunkResource(d *schema.ResourceData, details *trunk.ItemTrunk) {
log.Debugf("flattenTrunk: decoded Trunk ID %s",
details.ID)
d.Set("trunk_id", details.ID)
d.Set("guid", details.GUID)
d.Set("name", details.Name)
d.Set("mac", details.MAC)
d.Set("description", details.Description)
d.Set("accountIds", details.AccountIDs)
d.Set("ovsBridge", details.OVSBridge)
d.Set("nativeVlanId", details.NativeVLANID)
d.Set("status", details.Status)
d.Set("trunkTags", details.TrunkTags)
d.Set("created_at", details.CreatedAt)
d.Set("created_by", details.CreatedBy)
d.Set("updated_at", details.UpdatedAt)
d.Set("updated_by", details.UpdatedBy)
d.Set("deleted_at", details.DeletedAt)
d.Set("deleted_by", details.DeletedBy)
}
func flattenTrunk(d *schema.ResourceData, trunkItem *trunk.ItemTrunk) {
log.Debugf("flattenTrunk: decoded Trunk ID %d",
trunkItem.ID)
d.Set("trunk_id", trunkItem.ID)
d.Set("guid", trunkItem.GUID)
d.Set("name", trunkItem.Name)
d.Set("mac", trunkItem.MAC)
d.Set("description", trunkItem.Description)
d.Set("account_ids", trunkItem.AccountIDs)
d.Set("ovs_bridge", trunkItem.OVSBridge)
d.Set("native_vlan_id", trunkItem.NativeVLANID)
d.Set("status", trunkItem.Status)
d.Set("trunk_tags", trunkItem.TrunkTags)
d.Set("created_at", trunkItem.CreatedAt)
d.Set("created_by", trunkItem.CreatedBy)
d.Set("updated_at", trunkItem.UpdatedAt)
d.Set("updated_by", trunkItem.UpdatedBy)
d.Set("deleted_at", trunkItem.DeletedAt)
d.Set("deleted_by", trunkItem.DeletedBy)
}
func flattenTrunkList(trunkList *trunk.ListTrunks) []map[string]interface{} {
res := make([]map[string]interface{}, 0, len(trunkList.Data))
for _, trunkItem := range trunkList.Data {
temp := map[string]interface{}{
"account_ids": trunkItem.AccountIDs,
"created_at": trunkItem.CreatedAt,
"created_by": trunkItem.CreatedBy,
"deleted_at": trunkItem.DeletedAt,
"deleted_by": trunkItem.DeletedBy,
"description": trunkItem.Description,
"guid": trunkItem.GUID,
"id": trunkItem.ID,
"mac": trunkItem.MAC,
"name": trunkItem.Name,
"native_vlan_id": trunkItem.NativeVLANID,
"ovs_bridge": trunkItem.OVSBridge,
"status": trunkItem.Status,
"trunk_tags": trunkItem.TrunkTags,
"updated_at": trunkItem.UpdatedAt,
"updated_by": trunkItem.UpdatedBy,
}
res = append(res, temp)
}
return res
}

View File

@@ -0,0 +1,211 @@
package trunk
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/trunk"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/dc"
)
func resourceTrunkCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceTrunkCreate: called with name %s, trunk_tags %s, ovs_bridge %s", d.Get("name").(string), d.Get("trunk_tags").(string), d.Get("ovs_bridge").(string))
c := m.(*controller.ControllerCfg)
warnings := dc.Warnings{}
name := d.Get("name").(string)
trunkTags := d.Get("trunk_tags").(string)
ovsBridge := d.Get("ovs_bridge").(string)
createReq := trunk.CreateRequest{
Name: name,
TrunkTags: trunkTags,
OVSBridge: ovsBridge,
}
if description, ok := d.GetOk("description"); ok {
createReq.Description = description.(string)
}
accountIDs := make([]uint64, 0)
if accountAccess, ok := d.GetOk("account_ids"); ok {
IDs := accountAccess.(*schema.Set).List()
for _, ID := range IDs {
accountIDs = append(accountIDs, uint64(ID.(int)))
}
createReq.AccountIDs = accountIDs
}
if nativeVLANID, ok := d.GetOk("native_vlan_id"); ok {
createReq.NativeVLANID = uint64(nativeVLANID.(int))
}
trunkID, err := c.CloudBroker().Trunk().Create(ctx, createReq)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.FormatUint(trunkID, 10))
d.Set("trunk_id", trunkID)
if _, ok := d.GetOk("enable"); ok {
if err := handleTrunkEnabling(ctx, d, c, trunkID); err != nil {
warnings.Add(err)
}
}
return append(warnings.Get(), resourceTrunkRead(ctx, d, m)...)
}
func resourceTrunkRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceTrunkRead: called with name %s", d.Get("name").(string))
w := dc.Warnings{}
trunkItem, err := utilityTrunkCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
flattenTrunkResource(d, trunkItem)
return w.Get()
}
func resourceTrunkUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceTrunkUpdate: called with id %s", d.Id())
c := m.(*controller.ControllerCfg)
trunkItem, err := utilityTrunkCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
id, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
if d.HasChanges("name", "trunk_tags", "description", "native_vlan_id") {
req := trunk.UpdateRequest{
TrunkID: uint64(id),
Name: d.Get("name").(string),
TrunkTags: d.Get("trunk_tags").(string),
}
if d.HasChange("description") {
description := d.Get("description").(string)
req.Description = description
}
if d.HasChange("native_vlan_id") {
nativeVLANID := uint64(d.Get("native_vlan_id").(int))
req.NativeVLANID = nativeVLANID
}
if _, err := c.CloudBroker().Trunk().Update(ctx, req); err != nil {
return diag.FromErr(err)
}
}
if d.HasChange("enable") {
if err := handleTrunkEnabling(ctx, d, c, uint64(id)); err != nil {
return diag.FromErr(err)
}
}
if d.HasChange("account_ids") {
if err := handleAccountAccessUpdate(ctx, d, c, trunkItem); err != nil {
return diag.FromErr(err)
}
}
return resourceTrunkRead(ctx, d, m)
}
func resourceTrunkDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceTrunkDelete: called with id %s", d.Id())
trunkItem, err := utilityTrunkCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := trunk.DestroyRequest{
TrunkID: trunkItem.ID,
}
_, err = c.CloudBroker().Trunk().Destroy(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func ResourceTrunk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 2,
CustomizeDiff: func(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error {
if diff.HasChanges() || diff.HasChanges("name", "trunk_tags", "description", "native_vlan_id", "account_ids") {
diff.SetNewComputed("updated_time")
diff.SetNewComputed("updated_by")
}
if diff.HasChanges("enable") {
diff.SetNewComputed("status")
diff.SetNewComputed("updated_time")
diff.SetNewComputed("updated_by")
}
return nil
},
CreateContext: resourceTrunkCreate,
ReadContext: resourceTrunkRead,
UpdateContext: resourceTrunkUpdate,
DeleteContext: resourceTrunkDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout600s,
Read: &constants.Timeout600s,
Update: &constants.Timeout600s,
Delete: &constants.Timeout600s,
Default: &constants.Timeout600s,
},
Schema: resourceTrunkSchemaMake(),
}
}

View File

@@ -0,0 +1,336 @@
package trunk
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceTrunkSchemaMake() map[string]*schema.Schema {
log.Debugf("resourceTrunkSchemaMake: invoked")
return map[string]*schema.Schema{
"trunk_id": {
Type: schema.TypeInt,
Computed: true,
Description: "trunk id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the trunk",
},
"trunk_tags": {
Type: schema.TypeString,
Required: true,
Description: "List of trunk tags (values between 1-4095)",
},
"ovs_bridge": {
Type: schema.TypeString,
Required: true,
Description: "OVS bridge name",
},
"description": {
Type: schema.TypeString,
Optional: true,
Description: "Description of the trunk",
},
"account_ids": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of account IDs with access to this trunk",
},
"native_vlan_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Native VLAN ID",
},
"enable": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "Whether the trunk should be enabled",
},
"guid": {
Type: schema.TypeInt,
Computed: true,
Description: "GUID",
},
"mac": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "if the trunk is enabled",
},
"created_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was created",
},
"created_by": {
Type: schema.TypeString,
Computed: true,
Description: "who created the trunk",
},
"updated_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was updated",
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
Description: "who updated the trunk",
},
"deleted_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was updated",
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
Description: "who updated the trunk",
},
}
}
func dataSourceTrunkSchemaMake() map[string]*schema.Schema {
log.Debugf("dataSourceTrunkSchemaMake: invoked")
res := map[string]*schema.Schema{
"trunk_id": {
Type: schema.TypeInt,
Required: true,
Description: "trunk id",
},
"guid": {
Type: schema.TypeInt,
Computed: true,
Description: "GUID",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the trunk",
},
"mac": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the trunk",
},
"account_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of account IDs with access to this trunk",
},
"ovs_bridge": {
Type: schema.TypeString,
Computed: true,
Description: "OVS bridge name",
},
"native_vlan_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Native VLAN ID",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "if the trunk is enabled",
},
"trunk_tags": {
Type: schema.TypeString,
Computed: true,
Description: "List of trunk tags (values between 1-4095)",
},
"created_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was created",
},
"created_by": {
Type: schema.TypeString,
Computed: true,
Description: "who created the trunk",
},
"updated_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was updated",
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
Description: "who updated the trunk",
},
"deleted_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was updated",
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
Description: "who updated the trunk",
},
}
return res
}
func dataSourceTrunkListSchemaMake() map[string]*schema.Schema {
res := map[string]*schema.Schema{
"trunk_ids": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "ID of the trunk(s) to filter by",
},
"account_ids": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "Account access ID(s) to filter by",
},
"trunk_tags": {
Type: schema.TypeString,
Optional: true,
Description: "Trunk tags to filter by (value between 1-4095)",
},
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "Page number.",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "Page size.",
},
"status": {
Type: schema.TypeString,
Optional: true,
Description: "find by status",
},
"sort_by": {
Type: schema.TypeString,
Optional: true,
Description: "Sort by one of supported fields, format ±<field>",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"account_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "List of account IDs with access to this trunk",
},
"created_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was created",
},
"created_by": {
Type: schema.TypeString,
Computed: true,
Description: "who created the trunk",
},
"deleted_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was updated",
},
"deleted_by": {
Type: schema.TypeString,
Computed: true,
Description: "who updated the trunk",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the trunk",
},
"guid": {
Type: schema.TypeInt,
Computed: true,
Description: "GUID",
},
"id": {
Type: schema.TypeInt,
Computed: true,
Description: "Trunk ID",
},
"mac": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the trunk",
},
"native_vlan_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Native VLAN ID",
},
"ovs_bridge": {
Type: schema.TypeString,
Computed: true,
Description: "OVS bridge name",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "if the trunk is enabled",
},
"trunk_tags": {
Type: schema.TypeString,
Computed: true,
Description: "List of trunk tags (values between 1-4095)",
},
"updated_at": {
Type: schema.TypeInt,
Computed: true,
Description: "when the trunk was updated",
},
"updated_by": {
Type: schema.TypeString,
Computed: true,
Description: "who updated the trunk",
},
},
},
},
"entry_count": {
Type: schema.TypeInt,
Computed: true,
},
}
return res
}

View File

@@ -0,0 +1,104 @@
package trunk
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/trunk"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityTrunkCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*trunk.ItemTrunk, error) {
c := m.(*controller.ControllerCfg)
req := trunk.GetRequest{}
if d.Id() != "" {
id, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return nil, err
}
req.TrunkID = uint64(id)
} else {
req.TrunkID = uint64(d.Get("trunk_id").(int))
}
trunkInfo, err := c.CloudBroker().Trunk().Get(ctx, req)
if err != nil {
return nil, err
}
return trunkInfo, nil
}
func handleAccountAccessUpdate(ctx context.Context, d *schema.ResourceData, c *controller.ControllerCfg, trnk *trunk.ItemTrunk) error {
oldSet, newSet := d.GetChange("account_ids")
revokeSet := oldSet.(*schema.Set).Difference(newSet.(*schema.Set))
if revokeSet.Len() > 0 {
accountIDs := make([]uint64, 0)
for _, revokeAccountID := range revokeSet.List() {
accountIDs = append(accountIDs, uint64(revokeAccountID.(int)))
}
log.Debugf("cloudbroker: revoking access from %d account IDs", revokeSet.Len())
req := trunk.AccessRevokeRequest{
TrunkID: trnk.ID,
AccountIDs: accountIDs,
}
_, err := c.CloudBroker().Trunk().AccessRevoke(ctx, req)
if err != nil {
return err
}
}
grantSet := newSet.(*schema.Set).Difference(oldSet.(*schema.Set))
if grantSet.Len() > 0 {
accountIDs := make([]uint64, 0)
for _, grantAccountID := range grantSet.List() {
accountIDs = append(accountIDs, uint64(grantAccountID.(int)))
}
log.Debugf("cloudbroker: granting access to %d account IDs", grantSet.Len())
req := trunk.AccessGrantRequest{
TrunkID: trnk.ID,
AccountIDs: accountIDs,
}
_, err := c.CloudBroker().Trunk().AccessGrant(ctx, req)
if err != nil {
return err
}
}
return nil
}
func handleTrunkEnabling(ctx context.Context, d *schema.ResourceData, c *controller.ControllerCfg, trunkID uint64) error {
if d.Get("enable").(bool) {
req := trunk.EnableRequest{
TrunkID: trunkID,
}
_, err := c.CloudBroker().Trunk().Enable(ctx, req)
if err != nil {
return err
}
} else {
req := trunk.DisableRequest{
TrunkID: trunkID,
}
_, err := c.CloudBroker().Trunk().Disable(ctx, req)
if err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,48 @@
package trunk
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/trunk"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityTrunkListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*trunk.ListTrunks, error) {
c := m.(*controller.ControllerCfg)
req := trunk.ListRequest{}
if trunkIDs, ok := d.GetOk("trunk_ids"); ok {
IDs := trunkIDs.([]interface{})
for _, id := range IDs {
req.IDs = append(req.IDs, uint64(id.(int)))
}
}
if accountIDs, ok := d.GetOk("account_ids"); ok {
IDs := accountIDs.([]interface{})
for _, id := range IDs {
req.AccountIDs = append(req.AccountIDs, uint64(id.(int)))
}
}
if trunkTags, ok := d.GetOk("trunk_tags"); ok {
req.TrunkTags = trunkTags.(string)
}
if sortBy, ok := d.GetOk("sort_by"); ok {
req.SortBy = sortBy.(string)
}
if page, ok := d.GetOk("page"); ok {
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
req.Size = uint64(size.(int))
}
log.Debugf("utilityTrunkListCheckPresence: load trunk network list")
trunkList, err := c.CloudBroker().Trunk().List(ctx, req)
if err != nil {
return nil, err
}
return trunkList, nil
}