dnscontrol/providers/huaweicloud/convert.go
Tom Limoncelli 7fd6a74e0c
CLOUDFLAREAPI: CF_REDIRECT/CF_TEMP_REDIRECT should dtrt using Single Redirects (#3002)
Co-authored-by: Josh Zhang <jzhang1@stackoverflow.com>
2024-06-18 17:38:50 -04:00

135 lines
3.5 KiB
Go

package huaweicloud
import (
"fmt"
"slices"
"strconv"
"github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/printer"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/dns/v2/model"
)
func getRRSetIDFromRecords(rcs models.Records) []string {
ids := []string{}
for _, r := range rcs {
if r.Original == nil {
continue
}
if r.Original.(*model.ShowRecordSetByZoneResp).Id == nil {
printer.Warnf("RecordSet ID is nil for record %+v\n", r)
continue
}
ids = append(ids, *r.Original.(*model.ShowRecordSetByZoneResp).Id)
}
return slices.Compact(ids)
}
func nativeToRecords(n *model.ShowRecordSetByZoneResp, zoneName string) (models.Records, error) {
if n.Name == nil || n.Type == nil || n.Records == nil || n.Ttl == nil {
return nil, fmt.Errorf("missing required fields in Huaweicloud's RRset: %+v", n)
}
var rcs models.Records
recName := *n.Name
recType := *n.Type
// Split into records
for _, value := range *n.Records {
rc := &models.RecordConfig{
TTL: uint32(*n.Ttl),
Original: n,
Metadata: map[string]string{},
}
rc.SetLabelFromFQDN(recName, zoneName)
if err := rc.PopulateFromString(recType, value, zoneName); err != nil {
return nil, fmt.Errorf("unparsable record received from Huaweicloud: %w", err)
}
if n.Line != nil {
rc.Metadata[metaLine] = *n.Line
}
if n.Weight != nil {
rc.Metadata[metaWeight] = fmt.Sprintf("%d", *n.Weight)
}
if n.Description != nil {
rc.Metadata[metaKey] = *n.Description
}
rcs = append(rcs, rc)
}
return rcs, nil
}
func recordsToNative(rcs models.Records, expectedKey models.RecordKey) (*model.ShowRecordSetByZoneResp, error) {
// rcs length is guaranteed to be > 0
if len(rcs) == 0 {
return nil, fmt.Errorf("empty record set")
}
// line and weight should be the same for all records in the rrset
line := rcs[0].Metadata[metaLine]
weightStr := rcs[0].Metadata[metaWeight]
for _, r := range rcs {
if r.Metadata[metaLine] != line {
return nil, fmt.Errorf("all records in the rrset must have the same line %s", line)
}
if r.Metadata[metaWeight] != weightStr {
return nil, fmt.Errorf("all records in the rrset must have the same weight %s", weightStr)
}
}
// parse weight to int32
var weight *int32
if weightStr != "" {
weightInt, err := strconv.ParseInt(weightStr, 10, 32)
if err != nil {
return nil, fmt.Errorf("failed to parse weight %s to int32", weightStr)
}
weightInt32 := int32(weightInt)
// weight should be 0-1000
if weightInt32 < 0 || weightInt32 > 1000 {
return nil, fmt.Errorf("weight must be between 0 and 1000")
}
weight = &weightInt32
}
resultTTL := int32(0)
resultVal := []string{}
name := expectedKey.NameFQDN + "."
key := rcs[0].Metadata[metaKey]
result := &model.ShowRecordSetByZoneResp{
Name: &name,
Type: &expectedKey.Type,
Ttl: &resultTTL,
Records: &resultVal,
Line: &line,
Weight: weight,
Description: &key,
}
for _, r := range rcs {
key := r.Key()
if key != expectedKey {
continue
}
val := r.GetTargetCombined()
// special case for empty TXT records
if key.Type == "TXT" && len(val) == 0 {
val = "\"\""
}
resultVal = append(resultVal, val)
if resultTTL == 0 {
resultTTL = int32(r.TTL)
}
// Check if all TTLs are the same
if int32(r.TTL) != resultTTL {
printer.Warnf("All TTLs for a rrset (%v) must be the same. Using smaller of %v and %v.\n", key, r.TTL, resultTTL)
if int32(r.TTL) < resultTTL {
resultTTL = int32(r.TTL)
}
}
}
return result, nil
}