diff --git a/infoblox/datasource_infoblox_host_record.go b/infoblox/datasource_infoblox_host_record.go index 967b0b71c..eed31f90b 100644 --- a/infoblox/datasource_infoblox_host_record.go +++ b/infoblox/datasource_infoblox_host_record.go @@ -95,6 +95,14 @@ func dataSourceHostRecord() *schema.Resource { Default: true, Description: "flag that defines if the host record is to be used for DNS purposes.", }, + "aliases": { + Type: schema.TypeList, + Optional: true, + Description: "A set of IP allocation aliases", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, }, }, }, @@ -108,7 +116,7 @@ func dataSourceHostRecordRead(ctx context.Context, d *schema.ResourceData, m int var diags diag.Diagnostics n := &ibclient.HostRecord{} - n.SetReturnFields(append(n.ReturnFields(), "extattrs", "comment", "zone", "ttl", "configure_for_dns")) + n.SetReturnFields(append(n.ReturnFields(), "extattrs", "comment", "zone", "ttl", "configure_for_dns", "aliases")) filters := filterFromMap(d.Get("filters").(map[string]interface{})) qp := ibclient.NewQueryParams(false, filters) @@ -200,6 +208,9 @@ func flattenRecordHost(hostRecord ibclient.HostRecord) (map[string]interface{}, res["comment"] = *hostRecord.Comment } + if hostRecord.Aliases != nil { + res["aliases"] = hostRecord.Aliases + } return res, nil } diff --git a/infoblox/resource_infoblox_ip_allocation.go b/infoblox/resource_infoblox_ip_allocation.go index d6ab36ab0..7cfe72210 100644 --- a/infoblox/resource_infoblox_ip_allocation.go +++ b/infoblox/resource_infoblox_ip_allocation.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "sort" "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -14,6 +15,24 @@ import ( ibclient "github.com/infobloxopen/infoblox-go-client/v2" ) +func normalizeAlias(alias, domain string) string { + if !strings.HasSuffix(alias, "."+domain) { + return alias + "." + domain + } + return alias +} + +// normalizeAndSortAliases normalizes each alias by appending the domain if missing and sorts the resulting list. +func normalizeAndSortAliases(aliases []interface{}, domain string) []string { + var normalizedAliases []string + for _, alias := range aliases { + aliasStr := alias.(string) + normalizedAliases = append(normalizedAliases, normalizeAlias(aliasStr, domain)) + } + sort.Strings(normalizedAliases) + return normalizedAliases +} + func resourceIPAllocation() *schema.Resource { // TODO: move towards context-aware equivalents of these fields, as these are deprecated. return &schema.Resource{ @@ -168,6 +187,19 @@ func resourceIPAllocation() *schema.Resource { Elem: &schema.Schema{ Type: schema.TypeString, }, + DiffSuppressFunc: func(k, oldValue, newValue string, d *schema.ResourceData) bool { + enableDNS := d.Get("enable_dns").(bool) + if enableDNS { + fqdn := d.Get("fqdn").(string) + domain := strings.Join(strings.Split(fqdn, ".")[1:], ".") + oldAliases, newAliases := d.GetChange("aliases") + oldAliasesnew := normalizeAndSortAliases(oldAliases.([]interface{}), domain) + newAliasesnew := normalizeAndSortAliases(newAliases.([]interface{}), domain) + // Compare the sorted, normalized aliases + return strings.Join(oldAliasesnew, ",") == strings.Join(newAliasesnew, ",") + } + return oldValue == newValue + }, }, }, } @@ -243,16 +275,6 @@ func resourceAllocationRequest(d *schema.ResourceData, m interface{}) error { for i, alias := range aliases { aliasStrs[i] = alias.(string) } - // Check if enableDns is true, then validate the aliases - if enableDns { - parts := strings.SplitN(fqdn, ".", 2) - domain := parts[1] - for _, alias := range aliasStrs { - if !strings.HasSuffix(alias, "."+domain) { - return fmt.Errorf("invalid alias format, alias is given as %s, but should be in the format %s", alias, alias+"."+domain) - } - } - } var ttl uint32 useTtl := false tempVal := d.Get("ttl") @@ -544,13 +566,7 @@ func resourceAllocationUpdate(d *schema.ResourceData, m interface{}) (err error) if !strings.ContainsRune(fqdn, '.') { return fmt.Errorf("'fqdn' value must be an FQDN without a trailing dot") } - parts := strings.SplitN(fqdn, ".", 2) - domain := parts[1] - for _, alias := range aliasStrs { - if !strings.HasSuffix(alias, "."+domain) { - return fmt.Errorf("invalid alias format, alias is given as %s, but should be in the format %s", alias, alias+"."+domain) - } - } + } // internalId != nil here, because getOrFindHostRec() checks for this and returns an error otherwise. diff --git a/infoblox/resource_infoblox_ip_allocation_test.go b/infoblox/resource_infoblox_ip_allocation_test.go index 598ab787a..a0d61df2d 100644 --- a/infoblox/resource_infoblox_ip_allocation_test.go +++ b/infoblox/resource_infoblox_ip_allocation_test.go @@ -3,7 +3,6 @@ package infoblox import ( "fmt" "github.com/infobloxopen/infoblox-go-client/v2/utils" - "regexp" "sort" "testing" @@ -60,10 +59,6 @@ func validateAliases(expAliases, actAliases []string) error { return nil } -var ( - regexpFqdnDoesNotMatch = regexp.MustCompile("fqdn does not end with a domain name") -) - // must be used only with exp and act of the same length func validateV4Addrs(exp, act []ibclient.HostRecordIpv4Addr) error { sort.Sort(v4addrsType(exp)) @@ -492,30 +487,6 @@ func TestAcc_resourceIPAllocation(t *testing.T) { }) depends_on = [infoblox_zone_auth.zone, infoblox_ipv4_network.net1, infoblox_ipv6_network.net2] }`, - ExpectError: regexpFqdnDoesNotMatch, - }, - { - Config: ` - resource "infoblox_zone_auth" "zone" { - fqdn = "test1.com" - } - resource "infoblox_ipv4_network" "net1" { - cidr = "10.0.0.0/24" - } - resource "infoblox_ipv6_network" "net2" { - cidr = "2002:1f93:0:3::/96" - } - resource "infoblox_ip_allocation" "foo3" { - network_view = "default" - fqdn = "testhostnameip5.test1.com" - ipv4_addr = "10.0.0.2" - comment = "IPv4 and IPv6 are allocated" - aliases = ["alias3.test1.com", "alias4.test1.com"] - ext_attrs = jsonencode({ - Site = "Test site" - }) - depends_on = [infoblox_zone_auth.zone, infoblox_ipv4_network.net1, infoblox_ipv6_network.net2] - }`, Check: resource.ComposeTestCheckFunc( validateIPAllocation( "infoblox_ip_allocation.foo3",