Skip to content

SetRecords only sets the last record provided #31

@timbretimber

Description

@timbretimber

The SetRecords function only sets the last element provided even though it takes a []libdns.Record.

I've attached a quick and dirty demonstration

example code
package main

import (
	"context"
	"fmt"
	"log"
	"net/netip"
	"time"

	"github.com/libdns/cloudflare"
	"github.com/libdns/libdns"
)

func main() {
	var apiKey = ""
	var domain = ""
	var subdomain = "cf-set-example"

	p := &cloudflare.Provider{
		APIToken: apiKey,
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	s6 := [][16]byte{{15: 1}, {15: 2}, {15: 3}}
	addrs := MakeAddr(s6)
	recs := MakeAddrRecords(addrs, subdomain)

	fmt.Printf("Input data: %q\n", GetRecordData(recs))

	result, err := p.SetRecords(ctx, domain, recs)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("SetRecords returned result: %q\n", GetRecordData(result))

	actual, err := p.GetRecords(ctx, domain)
	if err != nil {
		log.Fatal(err)
	}
	filtered := Filter(actual, subdomain, "AAAA")

	fmt.Printf("Actual result: %q\n", GetRecordData(filtered))
}

func MakeAddr(slices [][16]byte) []netip.Addr {
	var addrs = make([]netip.Addr, 0, len(slices))
	for _, slice := range slices {
		addrs = append(addrs, netip.AddrFrom16(slice))
	}
	return addrs
}

func MakeAddrRecords(addrs []netip.Addr, name string) []libdns.Record {
	recs := make([]libdns.Record, 0, len(addrs))
	for _, addr := range addrs {
		recs = append(recs, libdns.Address{
			Name: name,
			IP:   addr,
			TTL:  5 * time.Minute,
		})
	}

	return recs
}

func Filter(recs []libdns.Record, recName string, recType string) []libdns.Record {
	filteredRecs := make([]libdns.Record, 0, len(recs))
	for _, rec := range recs {
		if rec.RR().Name == recName &&
			rec.RR().Type == recType {
			filteredRecs = append(filteredRecs, rec)
		}
	}

	return filteredRecs
}

func GetRecordData(recs []libdns.Record) []string {
	data := make([]string, 0, len(recs))
	for _, rec := range recs {
		data = append(data, rec.RR().Data)
	}

	return data
}
output
Input data: ["::1" "::2" "::3"]
SetRecords returned result: ["::1" "::2" "::3"]
Actual result: ["::3"]

The input data and return from SetRecords both have three records but when retrieved with GetRecords only the last element is present. I have manually checked this is the case as well.

matches, err := p.getDNSRecords(ctx, zoneInfo, rec, false)

Checking the source, changing matchContent to true here solves this issue, but maybe it causes other issues.

output matchContent
Input data: ["::1" "::2" "::3"]
SetRecords returned result: ["::1" "::2" "::3"]
Actual result: ["::3" "::2" "::1"]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions