Repository: StackExchange/dnscontrol
Pull request #2175 (2023-03-15 21:47:23)

LOOPIA: Linting corrections
CC @riku22 for visibility and approval.

Hi @riku22!

I don't know how I missed these before. go-staticcheck found them all.

```
providers/loopia/client.go:82:2: exported const DefaultBaseNOURL should have comment (or a comment on this block) or be unexported
providers/loopia/client.go:92:6: type name will be used as loopia.LoopiaClient by other packages, and that stutters; consider calling this Client
providers/loopia/client.go:165:38: exported method GetDomains returns unexported type []loopia.domainObject, which can be annoying to use
providers/loopia/client.go:182:75: exported method GetDomainRecords returns unexported type []loopia.zoneRecord, which can be annoying to use
providers/loopia/client.go:223:10: if block ends with a return statement, so drop this else and outdent its block
providers/loopia/loopiaProvider.go:415:9: if block ends with a return statement, so drop this else and outdent its block
providers/loopia/types.go:119:6: exported type Property should have comment or be unexported
providers/loopia/types.go:124:6: exported type Value should have comment or be unexported
providers/loopia/types.go:131:1: exported method Property.Name should have comment or be unexported
providers/loopia/types.go:133:1: exported method Property.Int should have comment or be unexported
providers/loopia/types.go:134:1: exported method Property.Bool should have comment or be unexported
```

riku22: Hi, @TomOnTime.

I don't know as I am not a maintainer of a loopia provider.
Maybe it is @systemcrash?

TomOnTime: oops!  sorry, [riku22](https://github.com/riku22)!  I copied the wrong name from OWNERS.

CC @systemcrash
systemcrash: Yeah sure - smash those in there.

Patch:
diff --git a/providers/loopia/client.go b/providers/loopia/client.go
index 43164db4..cffd5b7e 100644
--- a/providers/loopia/client.go
+++ b/providers/loopia/client.go
@@ -5,13 +5,14 @@ import (
 	"encoding/xml"
 	"errors"
 	"fmt"
-	"golang.org/x/text/cases"
-	"golang.org/x/text/language"
 	"io"
 	"net/http"
 	"strconv"
 	"strings"
 	"time"
+
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
 )
 
 /*
@@ -78,18 +79,23 @@ Loopia available API return (object) types:
 
 */
 
+// DefaultBaseNOURL and others are RPC end-points.
 const (
 	DefaultBaseNOURL = "https://api.loopia.no/RPCSERV"
 	DefaultBaseRSURL = "https://api.loopia.rs/RPCSERV"
 	DefaultBaseSEURL = "https://api.loopia.se/RPCSERV"
-	defaultNS1       = "ns1.loopia.se."
-	defaultNS2       = "ns2.loopia.se."
+)
+
+// defaultNS1      and defaultNS2 are default NS records.
+const (
+	defaultNS1 = "ns1.loopia.se."
+	defaultNS2 = "ns2.loopia.se."
 )
 
 // Section 2: Define the API client.
 
-// LoopiaClient is the LoopiaClient handle used to store any client-related state.
-type LoopiaClient struct {
+// APIClient is the APIClient handle used to store any client-related state.
+type APIClient struct {
 	APIUser            string
 	APIPassword        string
 	BaseURL            string
@@ -101,7 +107,7 @@ type LoopiaClient struct {
 }
 
 // NewClient creates a new LoopiaClient.
-func NewClient(apiUser, apiPassword string, region string, modifyns bool, fetchns bool, debug bool) *LoopiaClient {
+func NewClient(apiUser, apiPassword string, region string, modifyns bool, fetchns bool, debug bool) *APIClient {
 	// DefaultBaseURL is url to the XML-RPC api.
 	var DefaultBaseURL string
 	switch region {
@@ -114,7 +120,7 @@ func NewClient(apiUser, apiPassword string, region string, modifyns bool, fetchn
 	default:
 		DefaultBaseURL = DefaultBaseSEURL
 	}
-	return &LoopiaClient{
+	return &APIClient{
 		APIUser:           apiUser,
 		APIPassword:       apiPassword,
 		BaseURL:           DefaultBaseURL,
@@ -129,7 +135,7 @@ func NewClient(apiUser, apiPassword string, region string, modifyns bool, fetchn
 //Create
 
 // CreateRecordSimulate only prints info about a record addition. Used for debugging.
-func (c *LoopiaClient) CreateRecordSimulate(domain string, subdomain string, record paramStruct) error {
+func (c *APIClient) CreateRecordSimulate(domain string, subdomain string, record paramStruct) error {
 	if c.Debug {
 		fmt.Printf("create: domain: %s; subdomain: %s; record: %+v\n", domain, subdomain, record)
 	}
@@ -137,7 +143,7 @@ func (c *LoopiaClient) CreateRecordSimulate(domain string, subdomain string, rec
 }
 
 // CreateRecord adds a record.
-func (c *LoopiaClient) CreateRecord(domain string, subdomain string, record paramStruct) error {
+func (c *APIClient) CreateRecord(domain string, subdomain string, record paramStruct) error {
 	call := &methodCall{
 		MethodName: "addZoneRecord",
 		Params: []param{
@@ -161,8 +167,8 @@ func (c *LoopiaClient) CreateRecord(domain string, subdomain string, record para
 //CRUD: Create, Read, Update, Delete
 //Read
 
-// GetDomains lists all domains.
-func (c *LoopiaClient) GetDomains() ([]domainObject, error) {
+// getDomains lists all domains.
+func (c *APIClient) getDomains() ([]domainObject, error) {
 	call := &methodCall{
 		MethodName: "getDomains",
 		Params: []param{
@@ -178,8 +184,8 @@ func (c *LoopiaClient) GetDomains() ([]domainObject, error) {
 	return resp.Domains, err
 }
 
-// GetDomainRecords gets all records for a subdomain
-func (c *LoopiaClient) GetDomainRecords(domain string, subdomain string) ([]zoneRecord, error) {
+// getDomainRecords gets all records for a subdomain
+func (c *APIClient) getDomainRecords(domain string, subdomain string) ([]zoneRecord, error) {
 	call := &methodCall{
 		MethodName: "getZoneRecords",
 		Params: []param{
@@ -198,7 +204,7 @@ func (c *LoopiaClient) GetDomainRecords(domain string, subdomain string) ([]zone
 }
 
 // GetSubDomains gets all the subdomains within a domain, no records
-func (c *LoopiaClient) GetSubDomains(domain string) ([]string, error) {
+func (c *APIClient) GetSubDomains(domain string) ([]string, error) {
 	call := &methodCall{
 		MethodName: "getSubdomains",
 		Params: []param{
@@ -216,60 +222,59 @@ func (c *LoopiaClient) GetSubDomains(domain string) ([]string, error) {
 }
 
 // GetDomainNS gets all NS records for a subdomain, in this case, the apex "@"
-func (c *LoopiaClient) GetDomainNS(domain string) ([]string, error) {
+func (c *APIClient) GetDomainNS(domain string) ([]string, error) {
 	if c.ModifyNameServers {
-		return []string{}, nil
-	} else {
-		if c.FetchNSEntries {
-			return []string{defaultNS1, defaultNS2}, nil
-		} else {
-			//fetch from the domain - an extra API call.
-			call := &methodCall{
-				MethodName: "getZoneRecords",
-				Params: []param{
-					paramString{Value: c.APIUser},
-					paramString{Value: c.APIPassword},
-					paramString{Value: domain},
-					paramString{Value: "@"},
-				},
-			}
+		return nil, nil
+	}
 
-			resp := &zoneRecordsResponse{}
-			apexNSRecords := []string{}
-			err := c.rpcCall(call, resp)
-			if err != nil {
-				return nil, err
-			}
+	if c.FetchNSEntries {
+		return []string{defaultNS1, defaultNS2}, nil
+	}
 
+	//fetch from the domain - an extra API call.
+	call := &methodCall{
+		MethodName: "getZoneRecords",
+		Params: []param{
+			paramString{Value: c.APIUser},
+			paramString{Value: c.APIPassword},
+			paramString{Value: domain},
+			paramString{Value: "@"},
+		},
+	}
+
+	resp := &zoneRecordsResponse{}
+	apexNSRecords := []string{}
+	err := c.rpcCall(call, resp)
+	if err != nil {
+		return nil, err
+	}
+
+	if c.Debug {
+		fmt.Printf("DEBUG: getZoneRecords(@) START\n")
+	}
+	for i, rec := range resp.ZoneRecords {
+		ns := rec.GetZR()
+		if ns.Type == "NS" {
+			apexNSRecords = append(apexNSRecords, ns.Rdata)
 			if c.Debug {
-				fmt.Printf("DEBUG: getZoneRecords(@) START\n")
-			}
-			for i, rec := range resp.ZoneRecords {
-				ns := rec.GetZR()
-				if ns.Type == "NS" {
-					apexNSRecords = append(apexNSRecords, ns.Rdata)
-					if c.Debug {
-						fmt.Printf("DEBUG: HERE %d: %v\n", i, ns)
-					}
-				}
+				fmt.Printf("DEBUG: HERE %d: %v\n", i, ns)
 			}
-			return apexNSRecords, err
 		}
 	}
-	return nil, nil
+	return apexNSRecords, err
 }
 
 //CRUD: Create, Read, Update, Delete
 //Update
 
 // UpdateRecordSimulate only prints info about a record update. Used for debugging.
-func (c *LoopiaClient) UpdateRecordSimulate(domain string, subdomain string, rec paramStruct) error {
+func (c *APIClient) UpdateRecordSimulate(domain string, subdomain string, rec paramStruct) error {
 	fmt.Printf("got update: domain: %s; subdomain: %s; record: %v\n", domain, subdomain, rec)
 	return nil
 }
 
 // UpdateRecord updates a record.
-func (c *LoopiaClient) UpdateRecord(domain string, subdomain string, rec paramStruct) error {
+func (c *APIClient) UpdateRecord(domain string, subdomain string, rec paramStruct) error {
 	call := &methodCall{
 		MethodName: "updateZoneRecord",
 		Params: []param{
@@ -304,13 +309,13 @@ func (c *LoopiaClient) UpdateRecord(domain string, subdomain string, rec paramSt
 //Delete
 
 // DeleteRecordSimulate only prints info about a record deletion. Used for debugging.
-func (c *LoopiaClient) DeleteRecordSimulate(domain string, subdomain string, recordID uint32) error {
+func (c *APIClient) DeleteRecordSimulate(domain string, subdomain string, recordID uint32) error {
 	fmt.Printf("delete: domain: %s; subdomain: %s; recordID: %d\n", domain, subdomain, recordID)
 	return nil
 }
 
 // DeleteRecord deletes a record.
-func (c *LoopiaClient) DeleteRecord(domain string, subdomain string, recordID uint32) error {
+func (c *APIClient) DeleteRecord(domain string, subdomain string, recordID uint32) error {
 	call := &methodCall{
 		MethodName: "removeZoneRecord",
 		Params: []param{
@@ -332,7 +337,7 @@ func (c *LoopiaClient) DeleteRecord(domain string, subdomain string, recordID ui
 }
 
 // DeleteSubdomain deletes a sub-domain and its child records.
-func (c *LoopiaClient) DeleteSubdomain(domain, subdomain string) error {
+func (c *APIClient) DeleteSubdomain(domain, subdomain string) error {
 	call := &methodCall{
 		MethodName: "removeSubdomain",
 		Params: []param{
@@ -355,7 +360,7 @@ func (c *LoopiaClient) DeleteSubdomain(domain, subdomain string) error {
 // rpcCall makes an XML-RPC call to Loopia's RPC endpoint
 // by marshaling the data given in the call argument to XML and sending that via HTTP Post to Loopia.
 // The response is then unmarshalled into the resp argument.
-func (c *LoopiaClient) rpcCall(call *methodCall, resp response) error {
+func (c *APIClient) rpcCall(call *methodCall, resp response) error {
 	callBody, err := xml.MarshalIndent(call, "", "  ")
 	if err != nil {
 		return fmt.Errorf("error marshalling the API request XML callBody: %w", err)
@@ -398,7 +403,7 @@ func (c *LoopiaClient) rpcCall(call *methodCall, resp response) error {
 	return nil
 }
 
-func (c *LoopiaClient) httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
+func (c *APIClient) httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
 	c.requestRateLimiter.beforeRequest()
 	resp, err := c.HTTPClient.Post(url, bodyType, body)
 	c.requestRateLimiter.afterRequest()
diff --git a/providers/loopia/loopiaProvider.go b/providers/loopia/loopiaProvider.go
index d1e414aa..4f4931fd 100644
--- a/providers/loopia/loopiaProvider.go
+++ b/providers/loopia/loopiaProvider.go
@@ -79,7 +79,7 @@ func newReg(conf map[string]string) (providers.Registrar, error) {
 }
 
 // newHelper generates a handle.
-func newHelper(m map[string]string, metadata json.RawMessage) (*LoopiaClient, error) {
+func newHelper(m map[string]string, metadata json.RawMessage) (*APIClient, error) {
 	if m["username"] == "" {
 		return nil, fmt.Errorf("missing Loopia API username")
 	}
@@ -87,22 +87,22 @@ func newHelper(m map[string]string, metadata json.RawMessage) (*LoopiaClient, er
 		return nil, fmt.Errorf("missing Loopia API password")
 	}
 
-	const boolean_string_warn = " setting as a 'string': 't', 'true', 'True' etc"
+	const booleanStringWarn = " setting as a 'string': 't', 'true', 'True' etc"
 	var err error
 
-	modify_name_servers := false
+	modifyNameServers := false
 	if m["modify_name_servers"] != "" { // optional
-		modify_name_servers, err = strconv.ParseBool(m["modify_name_servers"])
+		modifyNameServers, err = strconv.ParseBool(m["modify_name_servers"])
 		if err != nil {
-			return nil, fmt.Errorf("creds.json requires the modify_name_servers" + boolean_string_warn)
+			return nil, fmt.Errorf("creds.json requires the modify_name_servers" + booleanStringWarn)
 		}
 	}
 
-	fetch_apex_ns_entries := false
+	fetchApexNSEntries := false
 	if m["fetch_apex_ns_entries"] != "" { // optional
-		fetch_apex_ns_entries, err = strconv.ParseBool(m["fetch_apex_ns_entries"])
+		fetchApexNSEntries, err = strconv.ParseBool(m["fetch_apex_ns_entries"])
 		if err != nil {
-			return nil, fmt.Errorf("creds.json requires the fetch_apex_ns_entries" + boolean_string_warn)
+			return nil, fmt.Errorf("creds.json requires the fetch_apex_ns_entries" + booleanStringWarn)
 		}
 	}
 
@@ -110,11 +110,11 @@ func newHelper(m map[string]string, metadata json.RawMessage) (*LoopiaClient, er
 	if m["debug"] != "" { //debug is optional
 		dbg, err = strconv.ParseBool(m["debug"])
 		if err != nil {
-			return nil, fmt.Errorf("creds.json requires the debug" + boolean_string_warn)
+			return nil, fmt.Errorf("creds.json requires the debug" + booleanStringWarn)
 		}
 	}
 
-	api := NewClient(m["username"], m["password"], strings.ToLower(m["region"]), modify_name_servers, fetch_apex_ns_entries, dbg)
+	api := NewClient(m["username"], m["password"], strings.ToLower(m["region"]), modifyNameServers, fetchApexNSEntries, dbg)
 
 	quota := m["rate_limit_per"]
 	err = api.requestRateLimiter.setRateLimitPer(quota)
@@ -127,9 +127,9 @@ func newHelper(m map[string]string, metadata json.RawMessage) (*LoopiaClient, er
 // Section 3: Domain Service Provider (DSP) related functions
 
 // ListZones lists the zones on this account.
-func (c *LoopiaClient) ListZones() ([]string, error) {
+func (c *APIClient) ListZones() ([]string, error) {
 
-	listResp, err := c.GetDomains()
+	listResp, err := c.getDomains()
 	if err != nil {
 		return nil, err
 	}
@@ -167,7 +167,7 @@ func (c *LoopiaClient) ListZones() ([]string, error) {
 
 // GetDomainCorrections get the current and existing records,
 // post-process them, and generate corrections.
-func (c *LoopiaClient) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
+func (c *APIClient) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
 	existing, err := c.GetZoneRecords(dc.Name)
 	if err != nil {
 		return nil, err
@@ -180,7 +180,7 @@ func (c *LoopiaClient) GetDomainCorrections(dc *models.DomainConfig) ([]*models.
 
 // GetZoneRecords gathers the DNS records and converts them to
 // dnscontrol's format.
-func (c *LoopiaClient) GetZoneRecords(domain string) (models.Records, error) {
+func (c *APIClient) GetZoneRecords(domain string) (models.Records, error) {
 
 	// Two approaches. One: get all SubDomains, and get their respective records
 	// simultaneously, or first get subdomains then fill each subdomain with its
@@ -207,7 +207,7 @@ func (c *LoopiaClient) GetZoneRecords(domain string) (models.Records, error) {
 		}
 		//step 2: records for subdomains
 		// Get subdomain records:
-		subdomainrecords, err := c.GetDomainRecords(domain, subdomain)
+		subdomainrecords, err := c.getDomainRecords(domain, subdomain)
 		if err != nil {
 			return nil, err
 		}
@@ -297,7 +297,7 @@ func gatherAffectedLabels(groups map[models.RecordKey][]string) (labels map[stri
 // a list of functions to call to actually make the desired
 // correction, and a message to output to the user when the change is
 // made.
-func (c *LoopiaClient) GenerateZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) {
+func (c *APIClient) GenerateZoneRecordsCorrections(dc *models.DomainConfig, existingRecords models.Records) ([]*models.Correction, error) {
 	if c.Debug {
 		debugRecords("GenerateZoneRecordsCorrections input:\n", existingRecords)
 	}
@@ -409,20 +409,19 @@ func debugRecords(note string, recs []*models.RecordConfig) {
 // Section 3: Registrar-related functions
 
 // GetNameservers returns a list of nameservers for domain.
-func (c *LoopiaClient) GetNameservers(domain string) ([]*models.Nameserver, error) {
+func (c *APIClient) GetNameservers(domain string) ([]*models.Nameserver, error) {
 	if c.ModifyNameServers {
 		return nil, nil
-	} else {
-		nameservers, err := c.GetDomainNS(domain)
-		if err != nil {
-			return nil, err
-		}
-		return models.ToNameserversStripTD(nameservers)
 	}
+	nameservers, err := c.GetDomainNS(domain)
+	if err != nil {
+		return nil, err
+	}
+	return models.ToNameserversStripTD(nameservers)
 }
 
 // GetRegistrarCorrections returns a list of corrections for this registrar.
-func (c *LoopiaClient) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
+func (c *APIClient) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
 
 	existingNs, err := c.GetDomainNS(dc.Name)
 	if err != nil {
diff --git a/providers/loopia/types.go b/providers/loopia/types.go
index 66776c5e..639422af 100644
--- a/providers/loopia/types.go
+++ b/providers/loopia/types.go
@@ -110,17 +110,20 @@ type zoneRecord struct {
 	// Properties map[string]interface{}
 }
 
+// zoneRecordsResponse decodes the API zoneRecords call.
 type zoneRecordsResponse struct {
 	responseFault
 	XMLName     xml.Name     `xml:"methodResponse"`
 	ZoneRecords []zoneRecord `xml:"params>param>value>array>data>value>struct"`
 }
 
+// Property is an XML Key/value.
 type Property struct {
 	Key   string `xml:"name"`
 	Value Value  `xml:"value"`
 }
 
+// Value is a xml any
 type Value struct {
 	// String string `xml:",any"`
 	String string `xml:"string"`
@@ -128,10 +131,17 @@ type Value struct {
 	Bool   bool   `xml:"bool"`
 }
 
-func (p Property) Name() string   { return p.Key }
+// Name is an accessor to the Property's name.
+func (p Property) Name() string { return p.Key }
+
+// String is an accessor to the Property's value when it is a string.
 func (p Property) String() string { return p.Value.String }
-func (p Property) Int() int       { return p.Value.Int }
-func (p Property) Bool() bool     { return p.Value.Bool }
+
+// Int is an accessor to the Property's value when it is a integer.
+func (p Property) Int() int { return p.Value.Int }
+
+// Bool is an accessor to the Property's value when it is a boolean.
+func (p Property) Bool() bool { return p.Value.Bool }
 
 func (zr *zoneRecord) GetZR() zRec {
 	record := zRec{}
@@ -157,11 +167,11 @@ func (zrec *zRec) SetZR() zoneRecord {
 	return zoneRecord{
 		XMLName: xml.Name{Local: "struct"},
 		Properties: []Property{
-			Property{Key: "type", Value: Value{String: zrec.Type}},
-			Property{Key: "ttl", Value: Value{Int: int(zrec.TTL)}},
-			Property{Key: "priority", Value: Value{Int: int(zrec.Priority)}},
-			Property{Key: "rdata", Value: Value{String: zrec.Rdata}},
-			Property{Key: "record_id", Value: Value{Int: int(zrec.RecordID)}},
+			{Key: "type", Value: Value{String: zrec.Type}},
+			{Key: "ttl", Value: Value{Int: int(zrec.TTL)}},
+			{Key: "priority", Value: Value{Int: int(zrec.Priority)}},
+			{Key: "rdata", Value: Value{String: zrec.Rdata}},
+			{Key: "record_id", Value: Value{Int: int(zrec.RecordID)}},
 		},
 	}
 }


Test patch:
diff --git a/providers/loopia/client_test.go b/providers/loopia/client_test.go
index be609b67..bab89589 100644
--- a/providers/loopia/client_test.go
+++ b/providers/loopia/client_test.go
@@ -201,7 +201,7 @@ func TestClient_GetDomainRecords(t *testing.T) {
 	client := NewClient("apiuser", "goodpassword", "", false, true, false)
 	client.BaseURL = serverURL + "/"
 
-	recordObjs, err := client.GetDomainRecords(exampleDomain, exampleSubDomain)
+	recordObjs, err := client.getDomainRecords(exampleDomain, exampleSubDomain)
 	require.NoError(t, err)
 
 	zr := zRec{