CHORE: Linting

This commit is contained in:
Thomas Limoncelli 2025-12-09 11:26:49 -05:00
parent d8927449dc
commit ba6ac834b8
No known key found for this signature in database
23 changed files with 124 additions and 55 deletions

View file

@ -10,10 +10,17 @@ import (
)
const (
DomainTag = "dnscontrol_tag" // A copy of DomainConfig.Tag
DomainUniqueName = "dnscontrol_uniquename" // A copy of DomainConfig.UniqueName
DomainNameRaw = "dnscontrol_nameraw" // A copy of DomainConfig.NameRaw
DomainNameUnicode = "dnscontrol_nameunicode" // A copy of DomainConfig.NameUnicode
// DomainTag is the key used to store a copy of DomainConfig.Tag in the Metadata map.
DomainTag = "dnscontrol_tag"
// DomainUniqueName is the key used to store a copy of DomainConfig.UniqueName in the Metadata map.
DomainUniqueName = "dnscontrol_uniquename"
// DomainNameRaw is the key used to store a copy of DomainConfig.NameRaw in the Metadata map.
DomainNameRaw = "dnscontrol_nameraw"
// DomainNameUnicode is the key used to store a copy of DomainConfig.NameUnicode in the Metadata map.
DomainNameUnicode = "dnscontrol_nameunicode"
)
// DomainConfig describes a DNS domain (technically a DNS zone).

View file

@ -540,8 +540,20 @@ func (rc *RecordConfig) GetSVCBValue() []dns.SVCBKeyValue {
return nil
}
// IsModernType returns true if this RecordConfig uses the new "F" field to store its rdata.
// Once all record types have been migrated to use "F", this function can be removed.
// IsModernType returns true if this RecordConfig is implemented in the new
// ("Modern") way (i.e. uses the RecordConfig .F field to store the rdata of the
// record).
//
// Since this check if .F != nil, it must be used only after the RecordConfig
// has been populated. Otherwise, use rtypecontrol.IsModernType(recordTypeName),
// which takes the type name as input.
//
// NOTE: Do not confuse this with rtypeinfo.IsModernType() which provides
// similar functionality. The difference is that this function is used to have
// a RecordConfig reveal if it uses a modern type. rtypeinfo.IsModernType()
// takes the rtype name as a string argument.
//
// FUTURE(tlim): Once all record types have been migrated to use ".F", this function can be removed.
func (rc *RecordConfig) IsModernType() bool {
return rc.F != nil
}

View file

@ -200,6 +200,7 @@ func getENotationInt(x float32) (uint8, error) {
return packedValue, nil
}
// ReverseLatitude takes the packed latitude and returns the hemisphere, degrees, minutes, and seconds.
func ReverseLatitude(lat uint32) (string, uint8, uint8, float64) {
var hemisphere string
if lat >= dns.LOC_EQUATOR {
@ -218,6 +219,7 @@ func ReverseLatitude(lat uint32) (string, uint8, uint8, float64) {
return hemisphere, degrees, minutes, seconds
}
// ReverseLongitude takes the packed longitude and returns the hemisphere, degrees, minutes, and seconds.
func ReverseLongitude(lon uint32) (string, uint8, uint8, float64) {
var hemisphere string
if lon >= dns.LOC_PRIMEMERIDIAN {
@ -236,6 +238,7 @@ func ReverseLongitude(lon uint32) (string, uint8, uint8, float64) {
return hemisphere, degrees, minutes, seconds
}
// ReverseAltitude takes the packed altitude and returns the altitude in meters.
func ReverseAltitude(packedAltitude uint32) float64 {
return float64(packedAltitude)/100 - 100000
}

View file

@ -280,8 +280,8 @@ func Test_ignore_external_dns(t *testing.T) {
// Check that external-dns records are in the result (so they won't be deleted)
foundMyappA := false
foundMyappTXT := false
foundApiCNAME := false
foundApiTXT := false
foundAPICNAME := false
foundAPITXT := false
foundStatic := false
for _, rec := range result {
@ -291,9 +291,9 @@ func Test_ignore_external_dns(t *testing.T) {
case rec.GetLabel() == "a-myapp" && rec.Type == "TXT":
foundMyappTXT = true
case rec.GetLabel() == "api" && rec.Type == "CNAME":
foundApiCNAME = true
foundAPICNAME = true
case rec.GetLabel() == "cname-api" && rec.Type == "TXT":
foundApiTXT = true
foundAPITXT = true
case rec.GetLabel() == "static" && rec.Type == "A":
foundStatic = true
}
@ -305,10 +305,10 @@ func Test_ignore_external_dns(t *testing.T) {
if !foundMyappTXT {
t.Error("Expected a-myapp TXT record to be preserved")
}
if !foundApiCNAME {
if !foundAPICNAME {
t.Error("Expected api CNAME record to be preserved")
}
if !foundApiTXT {
if !foundAPITXT {
t.Error("Expected cname-api TXT record to be preserved")
}
if !foundStatic {

View file

@ -2,28 +2,28 @@ package domaintags
import "golang.org/x/net/idna"
// EfficientToASCII converts a domain name to its ASCII representation using IDNA, on error returns the original name, and avoids wasting memory when possible.
func EfficientToASCII(name string) string {
nameIDN, err := idna.ToASCII(name)
if err != nil {
return name // Fallback to raw name on error.
} else {
// Avoid pointless duplication.
if nameIDN == name {
return name
}
}
// Avoid pointless duplication.
if nameIDN == name {
return name
}
return nameIDN
}
// EfficientToUnicode converts a domain name to its Unicode representation using IDNA, on error returns the original name, and avoids wasting memory when possible.
func EfficientToUnicode(name string) string {
nameUnicode, err := idna.ToUnicode(name)
if err != nil {
return name // Fallback to raw name on error.
} else {
// Avoid pointless duplication.
if nameUnicode == name {
return name
}
}
// Avoid pointless duplication.
if nameUnicode == name {
return name
}
return nameUnicode
}

View file

@ -4,6 +4,10 @@ import (
"strings"
)
// PermitList is a structure that holds a pre-compiled version of the --domains
// commmand line argument. "all" means all domains are permitted and the rest
// of the list is ignored. Otherwise, the list contains each element stored in a
// variety of ways useful to the matching algorithm.
type PermitList struct {
// If the permit list is "all" or "".
all bool
@ -33,6 +37,7 @@ func CompilePermitList(s string) PermitList {
return sl
}
// Permitted returns whether a domain is permitted by the PermitList.
func (pl *PermitList) Permitted(domToCheck string) bool {
// If the permit list is "all", everything is permitted.

View file

@ -17,6 +17,7 @@ type RP struct {
dns.RP
}
// Name returns the DNS record type as a string.
func (handle *RP) Name() string {
return "RP"
}
@ -46,6 +47,7 @@ func (handle *RP) FromStruct(dcn *domaintags.DomainNameVarieties, rec *models.Re
return nil
}
// CopyToLegacyFields populates the legacy fields of the RecordConfig using the fields in .F.
func (handle *RP) CopyToLegacyFields(rec *models.RecordConfig) {
rp := rec.F.(*RP)
_ = rec.SetTarget(rp.Mbox + " " + rp.Txt)

View file

@ -32,6 +32,9 @@ func ImportRawRecords(domains []*models.DomainConfig) error {
return nil
}
// NewRecordConfigFromRaw creates a new RecordConfig from the raw ([]any) args,
// usually from the parsed dnsconfig.js file, but also useful when a provider
// returns the fields of a record as individual values.
func NewRecordConfigFromRaw(t string, ttl uint32, args []any, dcn *domaintags.DomainNameVarieties) (*models.RecordConfig, error) {
if _, ok := Func[t]; !ok {
return nil, fmt.Errorf("record type %q is not supported", t)
@ -57,6 +60,9 @@ func NewRecordConfigFromRaw(t string, ttl uint32, args []any, dcn *domaintags.Do
return rec, nil
}
// NewRecordConfigFromString creates a new RecordConfig from a string in the
// format usually used in a zonefile but typically also used by providers
// returning the fields of a record as a string.
func NewRecordConfigFromString(name string, ttl uint32, t string, s string, dcn *domaintags.DomainNameVarieties) (*models.RecordConfig, error) {
if _, ok := Func[t]; !ok {
return nil, fmt.Errorf("record type %q is not supported", t)
@ -73,6 +79,9 @@ func NewRecordConfigFromString(name string, ttl uint32, t string, s string, dcn
}
// NewRecordConfigFromStruct creates a new RecordConfig from a struct, typically
// a miekg/dns struct. It must be the exact struct type used by the FromStruct()
// method of the rtype package.
func NewRecordConfigFromStruct(name string, ttl uint32, t string, fields any, dcn *domaintags.DomainNameVarieties) (*models.RecordConfig, error) {
if _, ok := Func[t]; !ok {
return nil, fmt.Errorf("record type %q is not supported", t)

View file

@ -8,9 +8,7 @@ import (
"github.com/StackExchange/dnscontrol/v4/providers"
)
// backwards compatibility:
//var validTypes = map[string]struct{}{}
// RType is an interface that defines the methods required for a DNS record type.
type RType interface {
// Returns the name of the rtype ("A", "MX", etc.)
Name() string
@ -22,9 +20,13 @@ type RType interface {
CopyToLegacyFields(*models.RecordConfig)
}
// Fun is a map of registered rtypes.
// Func is a map of registered rtypes.
var Func map[string]RType = map[string]RType{}
// Register registers a new RType (Record Type) implementation. It can be used
// to register an RFC-defined type, a new custom type, or a "builder".
//
// It panics if the type is already registered, to prevent accidental overwrites.
func Register(t RType) {
name := t.Name()
if _, ok := Func[name]; ok {
@ -36,8 +38,3 @@ func Register(t RType) {
// For compatibility with legacy systems:
providers.RegisterCustomRecordType(name, "", "")
}
func IsModernType(name string) bool {
_, ok := Func[name]
return ok
}

View file

@ -2,6 +2,19 @@ package rtypeinfo
import "github.com/StackExchange/dnscontrol/v4/pkg/rtypecontrol"
// IsModernType returns true if the given record type is implemented in the new
// ("Modern") way. (i.e. uses the RecordConfig .F field to store the record's
// rdata).
//
// Note that this does not simply check if .F != nil, which makes this function
// useful before the RecordConfig is fully populated.
//
// NOTE: Do not confuse this with RecordConfig.IsModernType() which provides
// similar functionality. The difference is that this function receives the
// type as a string, while RecordConfig.IsModernType() is a method on
// RecordConfig that reveals if that specific RecordConfig instance is modern.
//
// FUTURE(tlim): Once all record types have been migrated to use ".F", this function can be removed.
func IsModernType(t string) bool {
_, ok := rtypecontrol.Func[t]
return ok

View file

@ -104,15 +104,15 @@ func IPToList(address net.IP, transforms []IPConversion) ([]net.IP, error) {
return nil, err
}
for _, conv := range transforms {
min_, err := ipToUint(conv.Low)
minIP, err := ipToUint(conv.Low)
if err != nil {
return nil, err
}
max_, err := ipToUint(conv.High)
maxIP, err := ipToUint(conv.High)
if err != nil {
return nil, err
}
if (thisIP >= min_) && (thisIP <= max_) {
if (thisIP >= minIP) && (thisIP <= maxIP) {
if len(conv.NewIPs) > 0 {
return conv.NewIPs, nil
}
@ -122,7 +122,7 @@ func IPToList(address net.IP, transforms []IPConversion) ([]net.IP, error) {
if err != nil {
return nil, err
}
list = append(list, UintToIP(newbase+(thisIP-min_)))
list = append(list, UintToIP(newbase+(thisIP-minIP)))
}
return list, nil
}

View file

@ -5,12 +5,15 @@ import (
"sync"
)
// New creates a new ZoneCache of the given Zone type.
func New[Zone any](fetchAll func() (map[string]Zone, error)) ZoneCache[Zone] {
return ZoneCache[Zone]{fetchAll: fetchAll}
}
// ErrZoneNotFound is returned when a requested zone is not found (in the cache).
var ErrZoneNotFound = errors.New("zone not found")
// ZoneCache is a thread-safe cache for DNS zones at this provider.
type ZoneCache[Zone any] struct {
mu sync.Mutex
cached bool
@ -36,6 +39,7 @@ func (c *ZoneCache[Zone]) ensureCached() error {
return nil
}
// HasZone returns true if the zone with the given name exists (in the cache).
func (c *ZoneCache[Zone]) HasZone(name string) (bool, error) {
c.mu.Lock()
defer c.mu.Unlock()

View file

@ -72,9 +72,8 @@ retry:
if resp.StatusCode == http.StatusOK {
return bodyString, nil
} else {
return nil, errors.New(string(bodyString))
}
return nil, errors.New(string(bodyString))
}
func (c *adguardHomeProvider) get(endpoint string) ([]byte, error) {
@ -112,9 +111,8 @@ retry:
if resp.StatusCode == http.StatusOK {
return bodyString, nil
} else {
return nil, errors.New(string(bodyString))
}
return nil, errors.New(string(bodyString))
}
func (c *adguardHomeProvider) createRecord(r rewriteEntry) error {

View file

@ -70,6 +70,7 @@ type Domain struct {
Zone *Zone `json:"zone,omitempty"`
}
// NameServer represents a nameserver in API calls.
type NameServer struct {
// Host name of the nameserver written as a Fully-Qualified-Domain-Name (FQDN).
Name string `json:"name"`
@ -85,6 +86,7 @@ type JSONResponseDataZone struct {
Data []*Zone `json:"data"`
}
// JSONResponseDataDomain represents the response to the DataDomain call.
type JSONResponseDataDomain struct {
// The data for the response. The type of the objects are depending on the request and are also specified in the responseObject value of the response.
Data []*Domain `json:"data"`

View file

@ -13,6 +13,7 @@ func init() {
rtypecontrol.Register(&CfTempRedirect{})
}
// CfRedirect represents the CF_REDIRECT rtype, which is a builder that produces CLOUDFLAREAPI_SINGLE_REDIRECT.
type CfRedirect struct{}
// Name returns the text (all caps) name of the rtype.
@ -20,18 +21,22 @@ func (handle *CfRedirect) Name() string {
return "CF_REDIRECT"
}
// FromArgs populates a RecordConfig from the raw ([]any) args.
func (handle *CfRedirect) FromArgs(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, args []any) error {
return FromArgsHelper(dcn, rec, args, 301)
return fromArgsHelper(dcn, rec, args, 301)
}
// FromStruct populates a RecordConfig from a struct, which will be stored in rec.F.
func (handle *CfRedirect) FromStruct(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, name string, fields any) error {
panic("CF_REDIRECT: FromStruct not implemented")
}
// CopyToLegacyFields copies data from rec.F to the legacy fields in rec.
func (handle *CfRedirect) CopyToLegacyFields(rec *models.RecordConfig) {
// Nothing needs to be copied. The CLOUDFLAREAPI_SINGLE_REDIRECT FromArgs copies everything needed.
}
// CfTempRedirect represents the CF_TEMP_REDIRECT rtype, which is a builder that produces CLOUDFLAREAPI_SINGLE_REDIRECT.
type CfTempRedirect struct{}
// Name returns the text (all caps) name of the rtype.
@ -39,19 +44,22 @@ func (handle *CfTempRedirect) Name() string {
return "CF_TEMP_REDIRECT"
}
// FromArgs populates a RecordConfig from the raw ([]any) args.
func (handle *CfTempRedirect) FromArgs(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, args []any) error {
return FromArgsHelper(dcn, rec, args, 302)
return fromArgsHelper(dcn, rec, args, 302)
}
// FromStruct populates a RecordConfig from a struct, which will be stored in rec.F.
func (handle *CfTempRedirect) FromStruct(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, name string, fields any) error {
panic("CF_TEMP_REDIRECT: FromStruct not implemented")
}
// CopyToLegacyFields copies data from rec.F to the legacy fields in rec.
func (handle *CfTempRedirect) CopyToLegacyFields(rec *models.RecordConfig) {
// Nothing needs to be copied. The CLOUDFLAREAPI_SINGLE_REDIRECT FromArgs copies everything needed.
}
func FromArgsHelper(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, args []any, code int) error {
func fromArgsHelper(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, args []any, code int) error {
// Pave the args to be the expected types.
if err := rtypecontrol.PaveArgs(args, "ss"); err != nil {

View file

@ -31,6 +31,7 @@ func (handle *SingleRedirectConfig) Name() string {
return "CLOUDFLAREAPI_SINGLE_REDIRECT"
}
// FromArgs populates a RecordConfig from the raw ([]any) args.
func (handle *SingleRedirectConfig) FromArgs(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, args []any) error {
// Pave the args to be the expected types.
if err := rtypecontrol.PaveArgs(args, "siss"); err != nil {
@ -77,6 +78,7 @@ func (handle *SingleRedirectConfig) FromArgs(dcn *domaintags.DomainNameVarieties
return nil
}
// FromStruct populates a RecordConfig from a struct, which will be stored in rec.F.
func (handle *SingleRedirectConfig) FromStruct(dcn *domaintags.DomainNameVarieties, rec *models.RecordConfig, name string, fields any) error {
panic("CLOUDFLAREAPI_SINGLE_REDIRECT: FromStruct not implemented")
}
@ -91,6 +93,7 @@ func targetFromRaw(name string, code uint16, when, then string) string {
)
}
// CopyToLegacyFields copies data from rec.F to the legacy fields in rec.
func (handle *SingleRedirectConfig) CopyToLegacyFields(rec *models.RecordConfig) {
_ = rec.SetTarget(rec.F.(*SingleRedirectConfig).SRDisplay)
}

View file

@ -219,11 +219,11 @@ func (c *exoscaleProvider) GetZoneRecordsCorrections(dc *models.DomainConfig, ex
}
for _, mod := range modify {
old_ := mod.Existing.Original.(*egoscale.DNSDomainRecord)
new_ := mod.Desired
oldRec := mod.Existing.Original.(*egoscale.DNSDomainRecord)
newRec := mod.Desired
corrections = append(corrections, &models.Correction{
Msg: mod.String(),
F: c.updateRecordFunc(old_, new_, domainID),
F: c.updateRecordFunc(oldRec, newRec, domainID),
})
}

View file

@ -45,8 +45,7 @@ type fortigateProvider struct {
client *apiClient
}
// Constructor
// NewFortiGate creates a new instance of the FortiGate DNS provider.
func NewFortiGate(m map[string]string, _ json.RawMessage) (providers.DNSServiceProvider, error) {
host, vdom, apiKey := m["host"], m["vdom"], m["apiKey"]

View file

@ -92,10 +92,10 @@ func (n *HXClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mod
for _, chng := range mod {
changes = true
fmt.Fprintln(buf, chng)
old_ := chng.Existing.Original.(*HXRecord)
new_ := chng.Desired
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(old_)
newRecordString, err := n.createRecordString(new_, dc.Name)
oldRec := chng.Existing.Original.(*HXRecord)
newRec := chng.Desired
params[fmt.Sprintf("DELRR%d", delrridx)] = n.deleteRecordString(oldRec)
newRecordString, err := n.createRecordString(newRec, dc.Name)
if err != nil {
return corrections, 0, err
}

View file

@ -56,14 +56,14 @@ func (n *namedotcomProvider) GetZoneRecordsCorrections(dc *models.DomainConfig,
corrections = append(corrections, c)
}
for _, chng := range mod {
old_ := chng.Existing.Original.(*namecom.Record)
new_ := chng.Desired
oldRec := chng.Existing.Original.(*namecom.Record)
newRec := chng.Desired
c := &models.Correction{Msg: chng.String(), F: func() error {
err := n.deleteRecord(old_.ID, dc.Name)
err := n.deleteRecord(oldRec.ID, dc.Name)
if err != nil {
return err
}
return n.createRecord(new_, dc.Name)
return n.createRecord(newRec, dc.Name)
}}
corrections = append(corrections, c)
}

View file

@ -74,8 +74,10 @@ func RegisterDomainServiceProviderType(name string, fns DspFuncs, pm ...Provider
unwrapProviderCapabilities(name, pm)
}
// ProviderMaintainers stores the GitHub usernames of maintainers for each provider.
var ProviderMaintainers = map[string]string{}
// RegisterMaintainer registers the GitHub username of the maintainer for a provider.
func RegisterMaintainer(
providerName string,
gitHubUsername string,

View file

@ -16,14 +16,17 @@ type realtimeregisterAPI struct {
ServiceType string
}
// Zones represents a collection of DNS zones in Realtime Register.
type Zones struct {
Entities []Zone `json:"entities"`
}
// Domain represents a domain in Realtime Register.
type Domain struct {
Nameservers []string `json:"ns"`
}
// Zone represents a DNS zone in Realtime Register.
type Zone struct {
Name string `json:"name,omitempty"`
Service string `json:"service,omitempty"`
@ -32,6 +35,7 @@ type Zone struct {
Dnssec bool `json:"dnssec"`
}
// Record represents a DNS record in Realtime Register.
type Record struct {
Name string `json:"name"`
Type string `json:"type"`

View file

@ -269,6 +269,7 @@ type sakuracloudAPI struct {
commonServiceItemMap map[string]*commonServiceItem
}
// NewSakuracloudAPI creates and returns a sakuracloudAPI instance.
func NewSakuracloudAPI(accessToken, accessTokenSecret, endpoint string) (*sakuracloudAPI, error) {
baseURL, err := url.Parse(endpoint)
if err != nil {