Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added data source for ipv6 network, ipv6 network container and host record #350

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 176 additions & 0 deletions infoblox/datasource_infoblox_host_record.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
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 dataSourceHostRecord() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceHostRecordRead,
Schema: map[string]*schema.Schema{
"filters": {
Type: schema.TypeMap,
Required: true,
},

"results": {
Type: schema.TypeList,
Computed: true,
Description: "List of Host records matching filters",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"dns_view": {
Type: schema.TypeString,
Optional: true,
Default: defaultDNSView,
Description: "DNS view under which the zone has been created.",
},
"fqdn": {
Type: schema.TypeString,
Required: true,
Description: "The host name for Host Record in FQDN format.",
},
"ipv4_addr": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "IPv4 address of host record.",
},
"ipv6_addr": {
Type: schema.TypeString,
Optional: true,
Default: "",
Description: "IPv6 address of host record.",
},
"zone": {
Type: schema.TypeString,
Computed: true,
Description: "The zone which the record belongs to.",
},
"ttl": {
Type: schema.TypeInt,
Computed: true,
Description: "TTL attribute value for the record.",
},
"comment": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the Host-record.",
},
"ext_attrs": {
Type: schema.TypeString,
Computed: true,
Description: "Extensible attributes of the Host-record, as a map in JSON format",
},
},
},
},
},
}
}

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

var diags diag.Diagnostics

n := &ibclient.HostRecord{}
n.SetReturnFields(append(n.ReturnFields(), "extattrs", "comment", "zone", "ttl"))

filters := filterFromMap(d.Get("filters").(map[string]interface{}))
qp := ibclient.NewQueryParams(false, filters)
var res []ibclient.HostRecord

err := connector.GetObject(n, "", qp, &res)
if err != nil {
return diag.FromErr(fmt.Errorf("failed getting Host-record: %s", err.Error()))
}

if res == nil {
return diag.FromErr(fmt.Errorf("API returns a nil/empty ID for the Host Record"))
}

// TODO: temporary scaffold, need to rework marshalling/unmarshalling of EAs
// (avoiding additional layer of keys ("value" key)
results := make([]interface{}, 0, len(res))
for _, r := range res {
recordaFlat, err := flattenRecordHost(r)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to flatten Host Record: %w", err))
}

results = append(results, recordaFlat)
}

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 flattenRecordHost(hostRecord ibclient.HostRecord) (map[string]interface{}, error) {
var eaMap map[string]interface{}
if hostRecord.Ea != nil && len(hostRecord.Ea) > 0 {
eaMap = hostRecord.Ea
} else {
eaMap = make(map[string]interface{})
}

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

res := map[string]interface{}{
"id": hostRecord.Ref,
"zone": hostRecord.Zone,
"dns_view": hostRecord.View,
"ext_attrs": string(ea),
}

if hostRecord.Ipv4Addrs != nil {
res["ipv4_addr"] = hostRecord.Ipv4Addrs[0].Ipv4Addr
}
if hostRecord.Ipv6Addrs != nil {
res["ipv6_addr"] = hostRecord.Ipv6Addrs[0].Ipv6Addr
}

if hostRecord.UseTtl != nil {
if !*hostRecord.UseTtl {
res["ttl"] = ttlUndef
}
}

if hostRecord.Ttl != nil && *hostRecord.Ttl > 0 {
res["ttl"] = *hostRecord.Ttl
} else {
res["ttl"] = ttlUndef
}

if hostRecord.Name != nil {
res["fqdn"] = *hostRecord.Name
}

if hostRecord.Comment != nil {
res["comment"] = *hostRecord.Comment
}

return res, nil

}
118 changes: 118 additions & 0 deletions infoblox/datasource_infoblox_host_record_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package infoblox

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

func TestAccDataSourceHostRecordRead_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceHostRecordReadConfig_basic(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.infoblox_host_record.test", "id"),
resource.TestCheckResourceAttr("data.infoblox_host_record.test", "results.0.fqdn", "testhostnameip1.test.com"),
),
},
},
})
}

func TestAccDataSourceHostRecordRead_noResult(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceHostRecordReadConfig_noResult(),
ExpectError: regexp.MustCompile("failed getting Host-record: not found"),
},
},
})
}

func testAccDataSourceHostRecordReadConfig_basic() string {
return `
resource "infoblox_zone_auth" "zone" {
fqdn = "test.com"
}
resource "infoblox_ip_allocation" "foo1"{
network_view="default"
dns_view = "default"
fqdn="testhostnameip1.test.com"
ipv6_addr="2001:db8:abcd:12::1"
ipv4_addr="10.0.0.1"
ttl = 10
comment = "IPv4 and IPv6 are allocated"
ext_attrs = jsonencode({
Site = "Test site"
})
depends_on = [infoblox_zone_auth.zone]
}

data "infoblox_host_record" "test" {
filters = {
name = infoblox_ip_allocation.foo1.fqdn
}
depends_on = [infoblox_ip_allocation.foo1]
}
`
}

func testAccDataSourceHostRecordReadConfig_noResult() string {
return `
data "infoblox_host_record" "test" {
filters = {
name = "nonexistent.example.com"
}
}
`
}

func TestAccDataSourceHostRecordRead_noIPv4Address(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceHostRecordReadConfig_noIPv4Address(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.infoblox_host_record.test", "id"),
resource.TestCheckResourceAttr("data.infoblox_host_record.test", "results.0.ipv4_addr", ""),
resource.TestCheckResourceAttr("data.infoblox_host_record.test", "results.0.ipv6_addr", "2001:db8:abcd:12::1"),
),
},
},
})
}

func testAccDataSourceHostRecordReadConfig_noIPv4Address() string {
return `
resource "infoblox_zone_auth" "zone" {
fqdn = "test.com"
}
resource "infoblox_ip_allocation" "foo1"{
network_view="default"
dns_view = "default"
fqdn="testhostnameip1.test.com"
ipv6_addr="2001:db8:abcd:12::1"
ttl = 10
comment = "IPv6 allocated"
ext_attrs = jsonencode({
Site = "Test site"
})
depends_on = [infoblox_zone_auth.zone]
}

data "infoblox_host_record" "test" {
filters = {
name = infoblox_ip_allocation.foo1.fqdn
}
depends_on = [infoblox_ip_allocation.foo1]
}
`
}
Loading
Loading