Skip to content

Commit 1ae057c

Browse files
dns: Support Routing Policy in DNS Record Set (#5909) (#11610)
Co-authored-by: Shuya Ma <[email protected]> Signed-off-by: Modular Magician <[email protected]> Co-authored-by: Shuya Ma <[email protected]>
1 parent c885004 commit 1ae057c

File tree

4 files changed

+397
-34
lines changed

4 files changed

+397
-34
lines changed

.changelog/5909.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
dns: added `routing_policy` to `google_dns_record_set` resource
3+
```

google/resource_dns_record_set.go

+233-29
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,69 @@ func resourceDnsRecordSet() *schema.Resource {
9292

9393
"rrdatas": {
9494
Type: schema.TypeList,
95-
Required: true,
95+
Optional: true,
9696
Elem: &schema.Schema{
9797
Type: schema.TypeString,
9898
},
9999
DiffSuppressFunc: rrdatasDnsDiffSuppress,
100100
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").`,
101+
ExactlyOneOf: []string{"rrdatas", "routing_policy"},
102+
},
103+
104+
"routing_policy": {
105+
Type: schema.TypeList,
106+
Optional: true,
107+
Description: "The configuration for steering traffic based on query. You can specify either Weighted Round Robin(WRR) type or Geolocation(GEO) type.",
108+
MaxItems: 1,
109+
Elem: &schema.Resource{
110+
Schema: map[string]*schema.Schema{
111+
"wrr": {
112+
Type: schema.TypeList,
113+
Optional: true,
114+
Description: `The configuration for Weighted Round Robin based routing policy.`,
115+
Elem: &schema.Resource{
116+
Schema: map[string]*schema.Schema{
117+
"weight": {
118+
Type: schema.TypeFloat,
119+
Required: true,
120+
Description: `The ratio of traffic routed to the target.`,
121+
},
122+
"rrdatas": {
123+
Type: schema.TypeList,
124+
Required: true,
125+
Elem: &schema.Schema{
126+
Type: schema.TypeString,
127+
},
128+
},
129+
},
130+
},
131+
ExactlyOneOf: []string{"routing_policy.0.wrr", "routing_policy.0.geo"},
132+
},
133+
"geo": {
134+
Type: schema.TypeList,
135+
Optional: true,
136+
Description: `The configuration for Geo location based routing policy.`,
137+
Elem: &schema.Resource{
138+
Schema: map[string]*schema.Schema{
139+
"location": {
140+
Type: schema.TypeString,
141+
Required: true,
142+
Description: `The location name defined in Google Cloud.`,
143+
},
144+
"rrdatas": {
145+
Type: schema.TypeList,
146+
Required: true,
147+
Elem: &schema.Schema{
148+
Type: schema.TypeString,
149+
},
150+
},
151+
},
152+
},
153+
ExactlyOneOf: []string{"routing_policy.0.wrr", "routing_policy.0.geo"},
154+
},
155+
},
156+
},
157+
ExactlyOneOf: []string{"rrdatas", "routing_policy"},
101158
},
102159

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

143200
// Build the change
201+
rset := &dns.ResourceRecordSet{
202+
Name: name,
203+
Type: rType,
204+
Ttl: int64(d.Get("ttl").(int)),
205+
}
206+
if rrdatas := rrdata(d); len(rrdatas) > 0 {
207+
rset.Rrdatas = rrdatas
208+
}
209+
if rp := routingPolicy(d); rp != nil {
210+
rset.RoutingPolicy = rp
211+
}
144212
chg := &dns.Change{
145-
Additions: []*dns.ResourceRecordSet{
146-
{
147-
Name: name,
148-
Type: rType,
149-
Ttl: int64(d.Get("ttl").(int)),
150-
Rrdatas: rrdata(d),
151-
},
152-
},
213+
Additions: []*dns.ResourceRecordSet{rset},
153214
}
154215

155216
// The terraform provider is authoritative, so what we do here is check if
@@ -232,15 +293,22 @@ func resourceDnsRecordSetRead(d *schema.ResourceData, meta interface{}) error {
232293
if len(resp.Rrsets) > 1 {
233294
return fmt.Errorf("Only expected 1 record set, got %d", len(resp.Rrsets))
234295
}
235-
236-
if err := d.Set("type", resp.Rrsets[0].Type); err != nil {
296+
rrset := resp.Rrsets[0]
297+
if err := d.Set("type", rrset.Type); err != nil {
237298
return fmt.Errorf("Error setting type: %s", err)
238299
}
239-
if err := d.Set("ttl", resp.Rrsets[0].Ttl); err != nil {
300+
if err := d.Set("ttl", rrset.Ttl); err != nil {
240301
return fmt.Errorf("Error setting ttl: %s", err)
241302
}
242-
if err := d.Set("rrdatas", resp.Rrsets[0].Rrdatas); err != nil {
243-
return fmt.Errorf("Error setting rrdatas: %s", err)
303+
if len(rrset.Rrdatas) > 0 {
304+
if err := d.Set("rrdatas", rrset.Rrdatas); err != nil {
305+
return fmt.Errorf("Error setting rrdatas: %s", err)
306+
}
307+
}
308+
if rrset.RoutingPolicy != nil {
309+
if err := d.Set("routing_policy", flattenDnsRecordSetRoutingPolicy(rrset.RoutingPolicy)); err != nil {
310+
return fmt.Errorf("Error setting routing_policy: %s", err)
311+
}
244312
}
245313
if err := d.Set("project", project); err != nil {
246314
return fmt.Errorf("Error setting project: %s", err)
@@ -287,10 +355,11 @@ func resourceDnsRecordSetDelete(d *schema.ResourceData, meta interface{}) error
287355
chg := &dns.Change{
288356
Deletions: []*dns.ResourceRecordSet{
289357
{
290-
Name: d.Get("name").(string),
291-
Type: d.Get("type").(string),
292-
Ttl: int64(d.Get("ttl").(int)),
293-
Rrdatas: rrdata(d),
358+
Name: d.Get("name").(string),
359+
Type: d.Get("type").(string),
360+
Ttl: int64(d.Get("ttl").(int)),
361+
Rrdatas: rrdata(d),
362+
RoutingPolicy: routingPolicy(d),
294363
},
295364
},
296365
}
@@ -337,21 +406,26 @@ func resourceDnsRecordSetUpdate(d *schema.ResourceData, meta interface{}) error
337406
oldCountRaw, _ := d.GetChange("rrdatas.#")
338407
oldCount := oldCountRaw.(int)
339408

409+
oldRoutingPolicyRaw, _ := d.GetChange("routing_policy")
410+
oldRoutingPolicyList := oldRoutingPolicyRaw.([]interface{})
411+
340412
chg := &dns.Change{
341413
Deletions: []*dns.ResourceRecordSet{
342414
{
343-
Name: recordName,
344-
Type: oldType.(string),
345-
Ttl: int64(oldTtl.(int)),
346-
Rrdatas: make([]string, oldCount),
415+
Name: recordName,
416+
Type: oldType.(string),
417+
Ttl: int64(oldTtl.(int)),
418+
Rrdatas: make([]string, oldCount),
419+
RoutingPolicy: convertRoutingPolicy(oldRoutingPolicyList),
347420
},
348421
},
349422
Additions: []*dns.ResourceRecordSet{
350423
{
351-
Name: recordName,
352-
Type: newType.(string),
353-
Ttl: int64(newTtl.(int)),
354-
Rrdatas: rrdata(d),
424+
Name: recordName,
425+
Type: newType.(string),
426+
Ttl: int64(newTtl.(int)),
427+
Rrdatas: rrdata(d),
428+
RoutingPolicy: routingPolicy(d),
355429
},
356430
},
357431
}
@@ -402,13 +476,143 @@ func resourceDnsRecordSetImportState(d *schema.ResourceData, meta interface{}) (
402476
return []*schema.ResourceData{d}, nil
403477
}
404478

405-
func rrdata(
406-
d *schema.ResourceData,
407-
) []string {
479+
func rrdata(d *schema.ResourceData) []string {
480+
if _, ok := d.GetOk("rrdatas"); !ok {
481+
return []string{}
482+
}
408483
rrdatasCount := d.Get("rrdatas.#").(int)
409484
data := make([]string, rrdatasCount)
410485
for i := 0; i < rrdatasCount; i++ {
411486
data[i] = d.Get(fmt.Sprintf("rrdatas.%d", i)).(string)
412487
}
413488
return data
414489
}
490+
491+
func routingPolicy(d *schema.ResourceData) *dns.RRSetRoutingPolicy {
492+
rp, ok := d.GetOk("routing_policy")
493+
if !ok {
494+
return nil
495+
}
496+
rps := rp.([]interface{})
497+
if len(rps) == 0 {
498+
return nil
499+
}
500+
return convertRoutingPolicy(rps)
501+
}
502+
503+
// converconvertRoutingPolicy converts []interface{} type value to *dns.RRSetRoutingPolicy one if ps is valid data.
504+
func convertRoutingPolicy(ps []interface{}) *dns.RRSetRoutingPolicy {
505+
if len(ps) != 1 {
506+
return nil
507+
}
508+
p, ok := ps[0].(map[string]interface{})
509+
if !ok {
510+
return nil
511+
}
512+
513+
wrrRawItems, _ := p["wrr"].([]interface{})
514+
geoRawItems, _ := p["geo"].([]interface{})
515+
516+
if len(wrrRawItems) > 0 {
517+
wrrItems := make([]*dns.RRSetRoutingPolicyWrrPolicyWrrPolicyItem, len(wrrRawItems))
518+
for i, item := range wrrRawItems {
519+
wi, _ := item.(map[string]interface{})
520+
irrdatas := wi["rrdatas"].([]interface{})
521+
if len(irrdatas) == 0 {
522+
return nil
523+
}
524+
rrdatas := make([]string, len(irrdatas))
525+
for j, rrdata := range irrdatas {
526+
rrdatas[j], ok = rrdata.(string)
527+
if !ok {
528+
return nil
529+
}
530+
}
531+
weight, ok := wi["weight"].(float64)
532+
if !ok {
533+
return nil
534+
}
535+
wrrItems[i] = &dns.RRSetRoutingPolicyWrrPolicyWrrPolicyItem{
536+
Weight: weight,
537+
Rrdatas: rrdatas,
538+
}
539+
}
540+
541+
return &dns.RRSetRoutingPolicy{
542+
Wrr: &dns.RRSetRoutingPolicyWrrPolicy{
543+
Items: wrrItems,
544+
},
545+
}
546+
}
547+
548+
if len(geoRawItems) > 0 {
549+
geoItems := make([]*dns.RRSetRoutingPolicyGeoPolicyGeoPolicyItem, len(geoRawItems))
550+
for i, item := range geoRawItems {
551+
gi, _ := item.(map[string]interface{})
552+
irrdatas := gi["rrdatas"].([]interface{})
553+
if len(irrdatas) == 0 {
554+
return nil
555+
}
556+
rrdatas := make([]string, len(irrdatas))
557+
for j, rrdata := range irrdatas {
558+
rrdatas[j], ok = rrdata.(string)
559+
if !ok {
560+
return nil
561+
}
562+
}
563+
location, ok := gi["location"].(string)
564+
if !ok {
565+
return nil
566+
}
567+
geoItems[i] = &dns.RRSetRoutingPolicyGeoPolicyGeoPolicyItem{
568+
Location: location,
569+
Rrdatas: rrdatas,
570+
}
571+
}
572+
573+
return &dns.RRSetRoutingPolicy{
574+
Geo: &dns.RRSetRoutingPolicyGeoPolicy{
575+
Items: geoItems,
576+
},
577+
}
578+
}
579+
580+
return nil // unreachable here if ps is valid data
581+
}
582+
583+
func flattenDnsRecordSetRoutingPolicy(policy *dns.RRSetRoutingPolicy) []interface{} {
584+
if policy == nil {
585+
return []interface{}{}
586+
}
587+
ps := make([]interface{}, 0, 1)
588+
p := make(map[string]interface{})
589+
if policy.Wrr != nil {
590+
p["wrr"] = flattenDnsRecordSetRoutingPolicyWRR(policy.Wrr)
591+
}
592+
if policy.Geo != nil {
593+
p["geo"] = flattenDnsRecordSetRoutingPolicyGEO(policy.Geo)
594+
}
595+
return append(ps, p)
596+
}
597+
598+
func flattenDnsRecordSetRoutingPolicyWRR(wrr *dns.RRSetRoutingPolicyWrrPolicy) []interface{} {
599+
ris := make([]interface{}, 0, len(wrr.Items))
600+
for _, item := range wrr.Items {
601+
ri := make(map[string]interface{})
602+
ri["weight"] = item.Weight
603+
ri["rrdatas"] = item.Rrdatas
604+
ris = append(ris, ri)
605+
}
606+
return ris
607+
}
608+
609+
func flattenDnsRecordSetRoutingPolicyGEO(geo *dns.RRSetRoutingPolicyGeoPolicy) []interface{} {
610+
ris := make([]interface{}, 0, len(geo.Items))
611+
for _, item := range geo.Items {
612+
ri := make(map[string]interface{})
613+
ri["location"] = item.Location
614+
ri["rrdatas"] = item.Rrdatas
615+
ris = append(ris, ri)
616+
}
617+
return ris
618+
}

0 commit comments

Comments
 (0)