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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions