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

dns: Support Routing Policy in DNS Record Set #11610

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
3 changes: 3 additions & 0 deletions .changelog/5909.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
dns: added `routing_policy` to `google_dns_record_set` resource
```
262 changes: 233 additions & 29 deletions google/resource_dns_record_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,69 @@ func resourceDnsRecordSet() *schema.Resource {

"rrdatas": {
Type: schema.TypeList,
Required: true,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
DiffSuppressFunc: rrdatasDnsDiffSuppress,
Description: `The string data for the records in this record set whose meaning depends on the DNS type. For TXT record, if the string data contains spaces, add surrounding \" if you don't want your string to get split on spaces. To specify a single record value longer than 255 characters such as a TXT record for DKIM, add \"\" inside the Terraform configuration string (e.g. "first255characters\"\"morecharacters").`,
ExactlyOneOf: []string{"rrdatas", "routing_policy"},
},

"routing_policy": {
Type: schema.TypeList,
Optional: true,
Description: "The configuration for steering traffic based on query. You can specify either Weighted Round Robin(WRR) type or Geolocation(GEO) type.",
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"wrr": {
Type: schema.TypeList,
Optional: true,
Description: `The configuration for Weighted Round Robin based routing policy.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"weight": {
Type: schema.TypeFloat,
Required: true,
Description: `The ratio of traffic routed to the target.`,
},
"rrdatas": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
ExactlyOneOf: []string{"routing_policy.0.wrr", "routing_policy.0.geo"},
},
"geo": {
Type: schema.TypeList,
Optional: true,
Description: `The configuration for Geo location based routing policy.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"location": {
Type: schema.TypeString,
Required: true,
Description: `The location name defined in Google Cloud.`,
},
"rrdatas": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
ExactlyOneOf: []string{"routing_policy.0.wrr", "routing_policy.0.geo"},
},
},
},
ExactlyOneOf: []string{"rrdatas", "routing_policy"},
},

"ttl": {
Expand Down Expand Up @@ -141,15 +198,19 @@ func resourceDnsRecordSetCreate(d *schema.ResourceData, meta interface{}) error
rType := d.Get("type").(string)

// Build the change
rset := &dns.ResourceRecordSet{
Name: name,
Type: rType,
Ttl: int64(d.Get("ttl").(int)),
}
if rrdatas := rrdata(d); len(rrdatas) > 0 {
rset.Rrdatas = rrdatas
}
if rp := routingPolicy(d); rp != nil {
rset.RoutingPolicy = rp
}
chg := &dns.Change{
Additions: []*dns.ResourceRecordSet{
{
Name: name,
Type: rType,
Ttl: int64(d.Get("ttl").(int)),
Rrdatas: rrdata(d),
},
},
Additions: []*dns.ResourceRecordSet{rset},
}

// The terraform provider is authoritative, so what we do here is check if
Expand Down Expand Up @@ -232,15 +293,22 @@ func resourceDnsRecordSetRead(d *schema.ResourceData, meta interface{}) error {
if len(resp.Rrsets) > 1 {
return fmt.Errorf("Only expected 1 record set, got %d", len(resp.Rrsets))
}

if err := d.Set("type", resp.Rrsets[0].Type); err != nil {
rrset := resp.Rrsets[0]
if err := d.Set("type", rrset.Type); err != nil {
return fmt.Errorf("Error setting type: %s", err)
}
if err := d.Set("ttl", resp.Rrsets[0].Ttl); err != nil {
if err := d.Set("ttl", rrset.Ttl); err != nil {
return fmt.Errorf("Error setting ttl: %s", err)
}
if err := d.Set("rrdatas", resp.Rrsets[0].Rrdatas); err != nil {
return fmt.Errorf("Error setting rrdatas: %s", err)
if len(rrset.Rrdatas) > 0 {
if err := d.Set("rrdatas", rrset.Rrdatas); err != nil {
return fmt.Errorf("Error setting rrdatas: %s", err)
}
}
if rrset.RoutingPolicy != nil {
if err := d.Set("routing_policy", flattenDnsRecordSetRoutingPolicy(rrset.RoutingPolicy)); err != nil {
return fmt.Errorf("Error setting routing_policy: %s", err)
}
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error setting project: %s", err)
Expand Down Expand Up @@ -287,10 +355,11 @@ func resourceDnsRecordSetDelete(d *schema.ResourceData, meta interface{}) error
chg := &dns.Change{
Deletions: []*dns.ResourceRecordSet{
{
Name: d.Get("name").(string),
Type: d.Get("type").(string),
Ttl: int64(d.Get("ttl").(int)),
Rrdatas: rrdata(d),
Name: d.Get("name").(string),
Type: d.Get("type").(string),
Ttl: int64(d.Get("ttl").(int)),
Rrdatas: rrdata(d),
RoutingPolicy: routingPolicy(d),
},
},
}
Expand Down Expand Up @@ -337,21 +406,26 @@ func resourceDnsRecordSetUpdate(d *schema.ResourceData, meta interface{}) error
oldCountRaw, _ := d.GetChange("rrdatas.#")
oldCount := oldCountRaw.(int)

oldRoutingPolicyRaw, _ := d.GetChange("routing_policy")
oldRoutingPolicyList := oldRoutingPolicyRaw.([]interface{})

chg := &dns.Change{
Deletions: []*dns.ResourceRecordSet{
{
Name: recordName,
Type: oldType.(string),
Ttl: int64(oldTtl.(int)),
Rrdatas: make([]string, oldCount),
Name: recordName,
Type: oldType.(string),
Ttl: int64(oldTtl.(int)),
Rrdatas: make([]string, oldCount),
RoutingPolicy: convertRoutingPolicy(oldRoutingPolicyList),
},
},
Additions: []*dns.ResourceRecordSet{
{
Name: recordName,
Type: newType.(string),
Ttl: int64(newTtl.(int)),
Rrdatas: rrdata(d),
Name: recordName,
Type: newType.(string),
Ttl: int64(newTtl.(int)),
Rrdatas: rrdata(d),
RoutingPolicy: routingPolicy(d),
},
},
}
Expand Down Expand Up @@ -402,13 +476,143 @@ func resourceDnsRecordSetImportState(d *schema.ResourceData, meta interface{}) (
return []*schema.ResourceData{d}, nil
}

func rrdata(
d *schema.ResourceData,
) []string {
func rrdata(d *schema.ResourceData) []string {
if _, ok := d.GetOk("rrdatas"); !ok {
return []string{}
}
rrdatasCount := d.Get("rrdatas.#").(int)
data := make([]string, rrdatasCount)
for i := 0; i < rrdatasCount; i++ {
data[i] = d.Get(fmt.Sprintf("rrdatas.%d", i)).(string)
}
return data
}

func routingPolicy(d *schema.ResourceData) *dns.RRSetRoutingPolicy {
rp, ok := d.GetOk("routing_policy")
if !ok {
return nil
}
rps := rp.([]interface{})
if len(rps) == 0 {
return nil
}
return convertRoutingPolicy(rps)
}

// converconvertRoutingPolicy converts []interface{} type value to *dns.RRSetRoutingPolicy one if ps is valid data.
func convertRoutingPolicy(ps []interface{}) *dns.RRSetRoutingPolicy {
if len(ps) != 1 {
return nil
}
p, ok := ps[0].(map[string]interface{})
if !ok {
return nil
}

wrrRawItems, _ := p["wrr"].([]interface{})
geoRawItems, _ := p["geo"].([]interface{})

if len(wrrRawItems) > 0 {
wrrItems := make([]*dns.RRSetRoutingPolicyWrrPolicyWrrPolicyItem, len(wrrRawItems))
for i, item := range wrrRawItems {
wi, _ := item.(map[string]interface{})
irrdatas := wi["rrdatas"].([]interface{})
if len(irrdatas) == 0 {
return nil
}
rrdatas := make([]string, len(irrdatas))
for j, rrdata := range irrdatas {
rrdatas[j], ok = rrdata.(string)
if !ok {
return nil
}
}
weight, ok := wi["weight"].(float64)
if !ok {
return nil
}
wrrItems[i] = &dns.RRSetRoutingPolicyWrrPolicyWrrPolicyItem{
Weight: weight,
Rrdatas: rrdatas,
}
}

return &dns.RRSetRoutingPolicy{
Wrr: &dns.RRSetRoutingPolicyWrrPolicy{
Items: wrrItems,
},
}
}

if len(geoRawItems) > 0 {
geoItems := make([]*dns.RRSetRoutingPolicyGeoPolicyGeoPolicyItem, len(geoRawItems))
for i, item := range geoRawItems {
gi, _ := item.(map[string]interface{})
irrdatas := gi["rrdatas"].([]interface{})
if len(irrdatas) == 0 {
return nil
}
rrdatas := make([]string, len(irrdatas))
for j, rrdata := range irrdatas {
rrdatas[j], ok = rrdata.(string)
if !ok {
return nil
}
}
location, ok := gi["location"].(string)
if !ok {
return nil
}
geoItems[i] = &dns.RRSetRoutingPolicyGeoPolicyGeoPolicyItem{
Location: location,
Rrdatas: rrdatas,
}
}

return &dns.RRSetRoutingPolicy{
Geo: &dns.RRSetRoutingPolicyGeoPolicy{
Items: geoItems,
},
}
}

return nil // unreachable here if ps is valid data
}

func flattenDnsRecordSetRoutingPolicy(policy *dns.RRSetRoutingPolicy) []interface{} {
if policy == nil {
return []interface{}{}
}
ps := make([]interface{}, 0, 1)
p := make(map[string]interface{})
if policy.Wrr != nil {
p["wrr"] = flattenDnsRecordSetRoutingPolicyWRR(policy.Wrr)
}
if policy.Geo != nil {
p["geo"] = flattenDnsRecordSetRoutingPolicyGEO(policy.Geo)
}
return append(ps, p)
}

func flattenDnsRecordSetRoutingPolicyWRR(wrr *dns.RRSetRoutingPolicyWrrPolicy) []interface{} {
ris := make([]interface{}, 0, len(wrr.Items))
for _, item := range wrr.Items {
ri := make(map[string]interface{})
ri["weight"] = item.Weight
ri["rrdatas"] = item.Rrdatas
ris = append(ris, ri)
}
return ris
}

func flattenDnsRecordSetRoutingPolicyGEO(geo *dns.RRSetRoutingPolicyGeoPolicy) []interface{} {
ris := make([]interface{}, 0, len(geo.Items))
for _, item := range geo.Items {
ri := make(map[string]interface{})
ri["location"] = item.Location
ri["rrdatas"] = item.Rrdatas
ris = append(ris, ri)
}
return ris
}
Loading