Skip to content

Commit

Permalink
implementation of DTC LBDN resource and datasource and DTC Pool datas…
Browse files Browse the repository at this point in the history
…ource (#423)

* implementation of DTC LBDN resource and datasource and DTC Pool datasource

* adding acceptance tests for lbdn

* updating auth_zones and topology fields handling

* updating go.mod to use latest commit for go-client and lbdn changes

* adding go.mod and go.sum changes

* updating vendor folder

* updating pool datasource

* adding checks to persistence, priority and pool ratio fields of LBDN object
  • Loading branch information
Aish-sp authored Jan 10, 2025
1 parent 4916890 commit 2d97661
Show file tree
Hide file tree
Showing 14 changed files with 2,808 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/google/uuid v1.6.0
github.com/hashicorp/terraform-plugin-log v0.9.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0
github.com/infobloxopen/infoblox-go-client/v2 v2.8.0
github.com/infobloxopen/infoblox-go-client/v2 v2.8.1-0.20250107110944-605cad462ca6
github.com/sirupsen/logrus v1.9.3
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/infobloxopen/infoblox-go-client/v2 v2.8.0 h1:JWdBwjuXOLV7Fwf8yGMBdU/SbS+Cm4f/lgO12yg7Jjs=
github.com/infobloxopen/infoblox-go-client/v2 v2.8.0/go.mod h1:NeNJpz09efw/edzqkVivGv1bWqBXTomqYBRFbP+XBqg=
github.com/infobloxopen/infoblox-go-client/v2 v2.8.1-0.20250107110944-605cad462ca6 h1:p8pB9c/o/xuJtrv34pCT+K+h3wt5zPsVvqLqGXrrspc=
github.com/infobloxopen/infoblox-go-client/v2 v2.8.1-0.20250107110944-605cad462ca6/go.mod h1:NeNJpz09efw/edzqkVivGv1bWqBXTomqYBRFbP+XBqg=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
Expand Down
255 changes: 255 additions & 0 deletions infoblox/datasource_infoblox_dtc_lbdn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
package infoblox

import (
"context"
"encoding/json"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
ibclient "github.com/infobloxopen/infoblox-go-client/v2"
"strconv"
"time"
)

func dataSourceDtcLbdnRecord() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceDtcLbdnRecordRead,
Schema: map[string]*schema.Schema{
"filters": {
Type: schema.TypeMap,
Required: true,
},
"results": {
Type: schema.TypeList,
Computed: true,
Description: "List of DTC LBDN Records matching filters",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "The display name of the DTC LBDN.",
},
"auth_zones": {
Type: schema.TypeList,
Optional: true,
Description: "List of linked auth zones.",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"auto_consolidated_monitors": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Flag for enabling auto managing DTC Consolidated Monitors on related DTC Pools.",
},
"comment": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "Description of the DTC LBDN record.",
},
"ext_attrs": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "Extensible attributes of the DTC LBDN record to be added/updated, as a map in JSON format.",
},
"disable": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Determines whether the DTC LBDN is disabled or not. When this is set to False, the fixed address is enabled.",
},
"lb_method": {
Type: schema.TypeString,
Required: true,
Description: "The load balancing method. Used to select pool. Valid values are GLOBAL_AVAILABILITY, RATIO, ROUND_ROBIN, SOURCE_IP_HASH and TOPOLOGY.",
},
"patterns": {
Type: schema.TypeList,
Optional: true,
Description: "LBDN wildcards for pattern match.",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"persistence": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "Maximum time, in seconds, for which client specific LBDN responses will be cached. Zero specifies no caching.",
},
"pools": {
Type: schema.TypeList,
Optional: true,
Description: "The maximum time, in seconds, for which client specific LBDN responses will be cached. Zero specifies no caching.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"pool": {
Type: schema.TypeString,
Required: true,
Description: "The pool to link with.",
},
"ratio": {
Type: schema.TypeInt,
Required: true,
Description: "The weight of pool.",
},
},
},
},
"priority": {
Type: schema.TypeInt,
Optional: true,
Description: "The LBDN pattern match priority for “overlapping” DTC LBDN objects. LBDNs are “overlapping” if " +
"they are simultaneously assigned to a zone and have patterns that can match the same FQDN. The matching LBDN with highest priority (lowest ordinal) will be used.",
},
"topology": {
Type: schema.TypeString,
Optional: true,
Description: "The topology rules for TOPOLOGY method.",
},
"ttl": {
Type: schema.TypeInt,
Optional: true,
Default: ttlUndef,
Description: "The Time To Live (TTL) value for the DTC LBDN. A 32-bit unsigned integer that represents the duration, in seconds, for which the record is valid (cached). Zero indicates that the record should not be cached.",
},
"types": {
Type: schema.TypeList,
Optional: true,
Description: "The list of resource record types supported by LBDN. Valid values are A, AAAA, CNAME, NAPTR, SRV. Default value is A and AAAA",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
}
}

func dataSourceDtcLbdnRecordRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
connector := m.(ibclient.IBConnector)

var diags diag.Diagnostics

filters := filterFromMap(d.Get("filters").(map[string]interface{}))

objMgr := ibclient.NewObjectManager(connector, "Terraform", "")

qp := ibclient.NewQueryParams(false, filters)
res, err := objMgr.GetAllDtcLbdn(qp)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to get DTC LBDN records: %w", err))
}

if res == nil {
return diag.FromErr(fmt.Errorf("API returns a nil/empty ID for DTC LBDN"))
}
results := make([]interface{}, 0, len(res))
for _, r := range res {
dtcLbdn, err := flattenDtcLbdn(r, connector)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to flatten DTC LBDN : %w", err))
}
results = append(results, dtcLbdn)
}

err = d.Set("results", results)
if err != nil {
return diag.FromErr(err)
}

// always run
d.SetId(strconv.FormatInt(time.Now().Unix(), 10))

return diags
}

func flattenDtcLbdn(lbdn ibclient.DtcLbdn, connector ibclient.IBConnector) (map[string]interface{}, error) {
var eaMap map[string]interface{}
if lbdn.Ea != nil && len(lbdn.Ea) > 0 {
eaMap = lbdn.Ea
} else {
eaMap = make(map[string]interface{})
}

ea, err := json.Marshal(eaMap)
if err != nil {
return nil, err
}

res := map[string]interface{}{
"id": lbdn.Ref,
"name": lbdn.Name,
"ext_attrs": string(ea),
"lb_method": lbdn.LbMethod,
}
if lbdn.Comment != nil {
res["comment"] = *lbdn.Comment
}
if lbdn.Disable != nil {
res["disable"] = *lbdn.Disable
}
if lbdn.AuthZones != nil {
authZones, err := ConvertAuthZonesToInterface(connector, &lbdn)
if err != nil {
return nil, err
}
res["auth_zones"] = authZones
}

if lbdn.AutoConsolidatedMonitors != nil {
res["auto_consolidated_monitors"] = *lbdn.AutoConsolidatedMonitors
}

if lbdn.Patterns != nil {
res["patterns"] = convertSliceToInterface(lbdn.Patterns)
}

if lbdn.Persistence != nil {
res["persistence"] = lbdn.Persistence
}

if lbdn.Pools != nil {
pools, err := convertPoolsToInterface(&lbdn, connector)
if err != nil {
return nil, err
} else {
res["pools"] = pools
}
}
if lbdn.Priority != nil {
res["priority"] = lbdn.Priority
}
if lbdn.Topology != nil {
var topology ibclient.DtcTopology
err := connector.GetObject(&ibclient.DtcTopology{}, *lbdn.Topology, nil, &topology)
if err != nil {
return nil, fmt.Errorf("error getting %s DtcTopology object: %s", *lbdn.Topology, err)
}
res["topology"] = *topology.Name
}
if lbdn.Types != nil {
res["types"] = convertSliceToInterface(lbdn.Types)
}
if lbdn.UseTtl != nil {
if !*lbdn.UseTtl {
res["ttl"] = ttlUndef
}
}
if lbdn.Ttl != nil && *lbdn.Ttl > 0 {
res["ttl"] = *lbdn.Ttl
} else {
res["ttl"] = ttlUndef
}
return res, nil
}
105 changes: 105 additions & 0 deletions infoblox/datasource_infoblox_dtc_lbdn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package infoblox

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"testing"
)

var testAccDataSourceDtcLbdn = fmt.Sprintf(`resource "infoblox_dtc_lbdn" "testLbdn_src_1" {
name = "testLbdn444"
lb_method = "RATIO"
}
data "infoblox_dtc_lbdn" "testLbdn_src_read1" {
filters = {
name = infoblox_dtc_lbdn.testLbdn_src_1.name
}
depends_on = [infoblox_dtc_lbdn.testLbdn_src_1]
}`)

var testAccDatasourceDtcLbdn = fmt.Sprintf(`resource "infoblox_dtc_lbdn" "testLbdn_src" {
name = "testLbdn888"
auth_zones = ["test.com"]
comment = "test lbdn with max params"
ext_attrs = jsonencode({
"Site" = "Malpe"
})
lb_method = "TOPOLOGY"
patterns = ["test.com*", "info.com*"]
pools {
pool = "pool2"
ratio = 2
}
pools {
pool = "rrpool"
ratio = 3
}
pools {
pool = "test-pool"
ratio = 6
}
topology = "test-topo"
ttl = 120
disable = true
types = ["A", "AAAA", "CNAME"]
persistence = 60
priority = 2
}
data "infoblox_dtc_lbdn" "testLbdn_src_read" {
filters = {
name = infoblox_dtc_lbdn.testLbdn_src.name
}
depends_on = [infoblox_dtc_lbdn.testLbdn_src]
}`)

func TestAccDataSourceDtcLbdn(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceDtcLbdn,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read1", "results.0.name", "testLbdn444"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read1", "results.0.lb_method", "RATIO"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read1", "results.0.types.0", "A"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read1", "results.0.types.1", "AAAA"),
),
},
},
})
}

func TestAccDataSourceDtcLbdnSearchByEA(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDatasourceDtcLbdn,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.#", "1"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.name", "testLbdn888"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.auth_zones.0", "test.com"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.comment", "test lbdn with max params"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.lb_method", "TOPOLOGY"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.topology", "test-topo"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.pools.0.pool", "pool2"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.pools.0.ratio", "2"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.pools.1.pool", "rrpool"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.pools.1.ratio", "3"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.pools.2.pool", "test-pool"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.pools.2.ratio", "6"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.ttl", "120"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.disable", "true"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.types.0", "A"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.types.1", "AAAA"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.types.2", "CNAME"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.persistence", "60"),
resource.TestCheckResourceAttr("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.priority", "2"),
resource.TestCheckResourceAttrPair("data.infoblox_dtc_lbdn.testLbdn_src_read", "results.0.ext_attrs.Site", "infoblox_dtc_lbdn.testLbdn_src", "ext_attrs.Site"),
),
},
},
})
}
Loading

0 comments on commit 2d97661

Please sign in to comment.