Skip to content

Commit a631c5b

Browse files
CNR: Initial Performance improvement; golint review (#3391)
1 parent e1c9785 commit a631c5b

File tree

6 files changed

+63
-77
lines changed

6 files changed

+63
-77
lines changed

documentation/provider/cnr.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ Example:
1919
"apilogin": "your-cnr-account-id",
2020
"apipassword": "your-cnr-account-password",
2121
"apientity": "LIVE", // for the LIVE system; use "OTE" for the OT&E system
22-
"debugmode": "0", // set it to "1" to get debug output of the communication with our Backend System API
22+
// --- debugmode ---
23+
// "0" -> turned off (default)
24+
// "1" -> turned on, basic logging of the changes reflected as API command parameters for the CNR API
25+
// "2" -> turned on, most verbose level - showing the detailed CNR API communication
26+
"debugmode": "0"
2327
}
2428
}
2529
```
@@ -46,23 +50,27 @@ Here a working example for our OT&E System:
4650
{% endhint %}
4751

4852
With the above CentralNic Reseller entry in `creds.json`, you can run the
49-
integration tests as follows:
53+
integration tests or by specifying the data per environment vars as follows:
5054

51-
```shell
52-
dnscontrol get-zones --format=nameonly cnr CNR all
53-
```
5455
```shell
5556
# Review the output. Pick one domain and set CNR_DOMAIN.
5657
export CNR_DOMAIN=yodream.com # Pick a domain name.
5758
export CNR_ENTITY=OTE
5859
export CNR_UID=test.user
5960
export CNR_PW=test.passw0rd
61+
export CNR_DEBUGMODE=2
6062
cd integrationTest # NOTE: Not needed if already in that subdirectory
6163
go test -v -verbose -profile CNR
6264
```
6365

6466
## Usage
6567

68+
Fetch a list of all DNSZones:
69+
70+
```shell
71+
dnscontrol get-zones --format=nameonly cnr CNR all
72+
```
73+
6674
Here's an example DNS Configuration `dnsconfig.js` using our provider module.
6775
Even though it shows how you use us as Domain Registrar AND DNS Provider, we don't force you to do that.
6876
You are free to decide if you want to use both of our provider technology or just one of them.

providers/cnr/cnrProvider.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ var (
1515
version = "dev"
1616
)
1717

18-
// CNRClient describes a connection to the CNR API.
19-
type CNRClient struct {
18+
// Client describes a connection to the CNR API.
19+
type Client struct {
2020
conf map[string]string
2121
APILogin string
2222
APIPassword string
@@ -56,8 +56,8 @@ var features = providers.DocumentationNotes{
5656
providers.CanUseTLSA: providers.Can(),
5757
}
5858

59-
func newProvider(conf map[string]string) (*CNRClient, error) {
60-
api := &CNRClient{
59+
func newProvider(conf map[string]string) (*Client, error) {
60+
api := &Client{
6161
conf: conf,
6262
client: cnrcl.NewAPIClient(),
6363
}

providers/cnr/domains.go

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,25 @@ package cnr
33
// EnsureZoneExists returns an error
44
// * if access to dnszone is not allowed (not authorized) or
55
// * if it doesn't exist and creating it fails
6-
func (n *CNRClient) EnsureZoneExists(domain string) error {
7-
r := n.client.Request(map[string]interface{}{
8-
"COMMAND": "StatusDNSZone",
6+
func (n *Client) EnsureZoneExists(domain string) error {
7+
command := map[string]interface{}{
8+
"COMMAND": "AddDNSZone",
99
"DNSZONE": domain,
10-
})
11-
code := r.GetCode()
12-
if code == 545 {
13-
command := map[string]interface{}{
14-
"COMMAND": "AddDNSZone",
15-
"DNSZONE": domain,
16-
}
17-
if n.APIEntity == "OTE" {
18-
command["SOATTL"] = "33200"
19-
command["SOASERIAL"] = "0000000000"
20-
}
21-
// Create the zone
22-
r = n.client.Request(command)
23-
if !r.IsSuccess() {
24-
return n.GetCNRApiError("Failed to create not existing zone ", domain, r)
25-
}
26-
} else if code == 531 {
27-
return n.GetCNRApiError("Not authorized to manage dnszone", domain, r)
28-
} else if r.IsError() || r.IsTmpError() {
29-
return n.GetCNRApiError("Error while checking status of dnszone", domain, r)
3010
}
31-
return nil
11+
if n.APIEntity == "OTE" {
12+
command["SOATTL"] = "33200"
13+
command["SOASERIAL"] = "0000000000"
14+
}
15+
// Create the zone
16+
r := n.client.Request(command)
17+
if r.GetCode() == 549 || r.IsSuccess() {
18+
return nil
19+
}
20+
return n.GetAPIError("Failed to create not existing zone ", domain, r)
3221
}
3322

3423
// ListZones lists all the
35-
func (n *CNRClient) ListZones() ([]string, error) {
24+
func (n *Client) ListZones() ([]string, error) {
3625
var zones []string
3726

3827
// Basic
@@ -42,7 +31,7 @@ func (n *CNRClient) ListZones() ([]string, error) {
4231
})
4332
for _, r := range rs {
4433
if r.IsError() {
45-
return nil, n.GetCNRApiError("Error while QueryDNSZoneList", "Basic", &r)
34+
return nil, n.GetAPIError("Error while QueryDNSZoneList", "Basic", &r)
4635
}
4736
zoneColumn := r.GetColumn("DNSZONE")
4837
if zoneColumn != nil {

providers/cnr/error.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v5/response"
77
)
88

9-
// GetCNRApiError returns an error including API error code and error description.
10-
func (n *CNRClient) GetCNRApiError(format string, objectid string, r *response.Response) error {
9+
// GetAPIError returns an error including API error code and error description.
10+
func (n *Client) GetAPIError(format string, objectid string, r *response.Response) error {
1111
return fmt.Errorf(format+" %q. [%v %s]", objectid, r.GetCode(), r.GetDescription())
1212
}

providers/cnr/nameservers.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ var defaultNameservers = []*models.Nameserver{
1818
var nsRegex = regexp.MustCompile(`ns([1-3]{1})[0-9]+\.rrpproxy\.net`)
1919

2020
// GetNameservers gets the nameservers set on a domain.
21-
func (n *CNRClient) GetNameservers(domain string) ([]*models.Nameserver, error) {
21+
func (n *Client) GetNameservers(domain string) ([]*models.Nameserver, error) {
2222
// NOTE: This information is taken over from HX and adapted to CNR... might be wrong...
2323
// This is an interesting edge case. CNR expects you to SET the nameservers to ns[1-3].rrpproxy.net,
2424
// but it will internally set it to (ns1xyz|ns2uvw|ns3asd).rrpproxy.net, where xyz/uvw/asd is a uniqueish number.
@@ -41,14 +41,14 @@ func (n *CNRClient) GetNameservers(domain string) ([]*models.Nameserver, error)
4141
return models.ToNameservers(toUse)
4242
}
4343

44-
func (n *CNRClient) getNameserversRaw(domain string) ([]string, error) {
44+
func (n *Client) getNameserversRaw(domain string) ([]string, error) {
4545
r := n.client.Request(map[string]interface{}{
4646
"COMMAND": "StatusDomain",
4747
"DOMAIN": domain,
4848
})
4949
code := r.GetCode()
5050
if code != 200 {
51-
return nil, n.GetCNRApiError("Could not get status for domain", domain, r)
51+
return nil, n.GetAPIError("Could not get status for domain", domain, r)
5252
}
5353
nsColumn := r.GetColumn("NAMESERVER")
5454
if nsColumn == nil {
@@ -61,7 +61,7 @@ func (n *CNRClient) getNameserversRaw(domain string) ([]string, error) {
6161
}
6262

6363
// GetRegistrarCorrections gathers corrections that would being n to match dc.
64-
func (n *CNRClient) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
64+
func (n *Client) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
6565
nss, err := n.getNameserversRaw(dc.Name)
6666
if err != nil {
6767
return nil, err
@@ -87,7 +87,7 @@ func (n *CNRClient) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.
8787
return nil, nil
8888
}
8989

90-
func (n *CNRClient) updateNameservers(ns []string, domain string) func() error {
90+
func (n *Client) updateNameservers(ns []string, domain string) func() error {
9191
return func() error {
9292
cmd := map[string]interface{}{
9393
"COMMAND": "ModifyDomain",

providers/cnr/records.go

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import (
1414
"github.com/StackExchange/dnscontrol/v4/pkg/txtutil"
1515
)
1616

17-
// CNRRecord covers an individual DNS resource record.
18-
type CNRRecord struct {
17+
// Record covers an individual DNS resource record.
18+
type Record struct {
1919
// DomainName is the zone that the record belongs to.
2020
DomainName string
2121
// Host is the hostname relative to the zone: e.g. for a record for blog.example.org, domain would be "example.org" and host would be "blog".
@@ -36,7 +36,7 @@ type CNRRecord struct {
3636
}
3737

3838
// GetZoneRecords gets the records of a zone and returns them in RecordConfig format.
39-
func (n *CNRClient) GetZoneRecords(domain string, meta map[string]string) (models.Records, error) {
39+
func (n *Client) GetZoneRecords(domain string, meta map[string]string) (models.Records, error) {
4040
records, err := n.getRecords(domain)
4141
if err != nil {
4242
return nil, err
@@ -50,7 +50,7 @@ func (n *CNRClient) GetZoneRecords(domain string, meta map[string]string) (model
5050
}
5151

5252
// GetZoneRecordsCorrections returns a list of corrections that will turn existing records into dc.Records.
53-
func (n *CNRClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
53+
func (n *Client) GetZoneRecordsCorrections(dc *models.DomainConfig, actual models.Records) ([]*models.Correction, int, error) {
5454
toReport, create, del, mod, actualChangeCount, err := diff.NewCompat(dc).IncrementalDiff(actual)
5555
if err != nil {
5656
return nil, 0, err
@@ -82,7 +82,7 @@ func (n *CNRClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mo
8282
changes = true
8383
fmt.Fprintln(buf, d)
8484
key := fmt.Sprintf("DELRR%d", delrridx)
85-
oldRecordString := n.deleteRecordString(d.Existing.Original.(*CNRRecord))
85+
oldRecordString := n.deleteRecordString(d.Existing.Original.(*Record))
8686
params[key] = oldRecordString
8787
fmt.Fprintf(&builder, "\033[31m- %s = %s\033[0m\n", key, oldRecordString)
8888
delrridx++
@@ -92,7 +92,7 @@ func (n *CNRClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mo
9292
fmt.Fprintln(buf, chng)
9393
// old record deletion
9494
key := fmt.Sprintf("DELRR%d", delrridx)
95-
oldRecordString := n.deleteRecordString(chng.Existing.Original.(*CNRRecord))
95+
oldRecordString := n.deleteRecordString(chng.Existing.Original.(*Record))
9696
params[key] = oldRecordString
9797
fmt.Fprintf(&builder, "\033[31m- %s = %s\033[0m\n", key, oldRecordString)
9898
delrridx++
@@ -123,7 +123,7 @@ func (n *CNRClient) GetZoneRecordsCorrections(dc *models.DomainConfig, actual mo
123123
return corrections, actualChangeCount, nil
124124
}
125125

126-
func toRecord(r *CNRRecord, origin string) *models.RecordConfig {
126+
func toRecord(r *Record, origin string) *models.RecordConfig {
127127
rc := &models.RecordConfig{
128128
Type: r.Type,
129129
TTL: r.TTL,
@@ -159,7 +159,7 @@ func toRecord(r *CNRRecord, origin string) *models.RecordConfig {
159159
}
160160

161161
// updateZoneBy updates the zone with the provided changes.
162-
func (n *CNRClient) updateZoneBy(params map[string]interface{}, domain string) error {
162+
func (n *Client) updateZoneBy(params map[string]interface{}, domain string) error {
163163
zone := domain
164164
cmd := map[string]interface{}{
165165
"COMMAND": "ModifyDNSZone",
@@ -170,14 +170,14 @@ func (n *CNRClient) updateZoneBy(params map[string]interface{}, domain string) e
170170
}
171171
r := n.client.Request(cmd)
172172
if !r.IsSuccess() {
173-
return n.GetCNRApiError("Error while updating zone", zone, r)
173+
return n.GetAPIError("Error while updating zone", zone, r)
174174
}
175175
return nil
176176
}
177177

178-
// deleteRecordString constructs the record string based on the provided CNRRecord.
179-
func (n *CNRClient) getRecords(domain string) ([]*CNRRecord, error) {
180-
var records []*CNRRecord
178+
// deleteRecordString constructs the record string based on the provided Record.
179+
func (n *Client) getRecords(domain string) ([]*Record, error) {
180+
var records []*Record
181181

182182
// Command to find out the total numbers of resource records for the zone
183183
// so that the follow-up query can be done with the correct limit
@@ -186,7 +186,8 @@ func (n *CNRClient) getRecords(domain string) ([]*CNRRecord, error) {
186186
"DNSZONE": domain,
187187
"ORDERBY": "type",
188188
"FIRST": "0",
189-
"LIMIT": "1",
189+
"LIMIT": "10000",
190+
"WIDE": "1",
190191
}
191192
r := n.client.Request(cmd)
192193

@@ -201,29 +202,16 @@ func (n *CNRClient) getRecords(domain string) ([]*CNRRecord, error) {
201202
}
202203
} else {
203204
// Return specific error if the zone does not exist
204-
return nil, n.GetCNRApiError("Use `dnscontrol create-domains` to create not-existing zone", domain, r)
205+
return nil, n.GetAPIError("Use `dnscontrol create-domains` to create not-existing zone", domain, r)
205206
}
206207
}
207208
// Return general error for any other issues
208-
return nil, n.GetCNRApiError("Failed loading resource records for zone", domain, r)
209+
return nil, n.GetAPIError("Failed loading resource records for zone", domain, r)
209210
}
210211
totalRecords := r.GetRecordsTotalCount()
211212
if totalRecords <= 0 {
212213
return nil, nil
213214
}
214-
limitation := 100
215-
totalRecords += limitation
216-
217-
// finally request all resource records available for the zone
218-
cmd["LIMIT"] = strconv.Itoa(totalRecords)
219-
cmd["WIDE"] = "1"
220-
r = n.client.Request(cmd)
221-
222-
// Check if the request was successful
223-
if !r.IsSuccess() {
224-
// Return general error for any other issues
225-
return nil, n.GetCNRApiError("Failed loading resource records for zone", domain, r)
226-
}
227215

228216
// loop over the records array
229217
rrs := r.GetRecords()
@@ -265,8 +253,8 @@ func (n *CNRClient) getRecords(domain string) ([]*CNRRecord, error) {
265253
fqdn = fmt.Sprintf("%s.%s.", data["NAME"], domain)
266254
}
267255

268-
// Initialize a new CNRRecord
269-
record := &CNRRecord{
256+
// Initialize a new Record
257+
record := &Record{
270258
DomainName: domain,
271259
Host: data["NAME"],
272260
Fqdn: fqdn,
@@ -286,7 +274,7 @@ func (n *CNRClient) getRecords(domain string) ([]*CNRRecord, error) {
286274
}
287275

288276
// Function to create record string from given RecordConfig for the ADDRR# API parameter
289-
func (n *CNRClient) createRecordString(rc *models.RecordConfig, domain string) (string, error) {
277+
func (n *Client) createRecordString(rc *models.RecordConfig, domain string) (string, error) {
290278
host := rc.GetLabel()
291279
answer := ""
292280

@@ -339,8 +327,8 @@ func (n *CNRClient) createRecordString(rc *models.RecordConfig, domain string) (
339327
return str, nil
340328
}
341329

342-
// deleteRecordString constructs the record string based on the provided CNRRecord.
343-
func (n *CNRClient) deleteRecordString(record *CNRRecord) string {
330+
// deleteRecordString constructs the record string based on the provided Record.
331+
func (n *Client) deleteRecordString(record *Record) string {
344332
// Initialize values slice
345333
values := []string{
346334
record.Host,
@@ -375,6 +363,7 @@ func isNoPopulate() bool {
375363
}
376364

377365
// Function to check if debug mode is enabled
378-
func (n *CNRClient) isDebugOn() bool {
379-
return n.conf["debugmode"] == "1" || n.conf["debugmode"] == "2"
366+
func (n *Client) isDebugOn() bool {
367+
debugMode, exists := n.conf["debugmode"]
368+
return exists && (debugMode == "1" || debugMode == "2")
380369
}

0 commit comments

Comments
 (0)