Skip to content

Commit 86b4e91

Browse files
committed
Add support for axfr_ips and PTR records in Linode DNS v4
Signed-off-by: Zhiwei Liang <zhiwei.liang@zliang.me>
1 parent e9aba33 commit 86b4e91

6 files changed

Lines changed: 170 additions & 2 deletions

File tree

libcloud/dns/drivers/linode.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636

3737
VALID_ZONE_EXTRA_PARAMS_V4 = [
38+
"axfr_ips",
3839
"description",
3940
"expire_sec",
4041
"master_ips",
@@ -100,6 +101,7 @@ class LinodeDNSDriverV4(LinodeDNSDriver):
100101
RecordType.A: "A",
101102
RecordType.AAAA: "AAAA",
102103
RecordType.CNAME: "CNAME",
104+
RecordType.PTR: "PTR",
103105
RecordType.TXT: "TXT",
104106
RecordType.SRV: "SRV",
105107
RecordType.CAA: "CAA",
@@ -174,7 +176,7 @@ def create_zone(self, domain, type="master", ttl=None, extra=None):
174176
:keyword ttl: TTL for new records. (optional)
175177
:type ttl: ``int``
176178
177-
:keyword extra: Extra attributes.('description', 'expire_sec', \
179+
:keyword extra: Extra attributes.('axfr_ips', 'description', 'expire_sec', \
178180
'master_ips','refresh_sec', 'retry_sec', 'soa_email',\
179181
'status', 'tags'). 'soa_email' required for master zones
180182
:type extra: ``dict``
@@ -250,7 +252,7 @@ def update_zone(self, zone, domain, type="master", ttl=None, extra=None):
250252
:param ttl: TTL for new records. (optional)
251253
:type ttl: ``int``
252254
253-
:param extra: Extra attributes ('description', 'expire_sec', \
255+
:param extra: Extra attributes ('axfr_ips', 'description', 'expire_sec', \
254256
'master_ips','refresh_sec', 'retry_sec', 'soa_email','status', 'tags')
255257
256258
:type extra: ``dict``
@@ -367,6 +369,7 @@ def _to_record(self, item, zone=None):
367369
"priority": item["priority"],
368370
"service": item["service"],
369371
"protocol": item["protocol"],
372+
"tag": item["tag"],
370373
"created": self._to_datetime(item["created"]),
371374
"updated": self._to_datetime(item["updated"]),
372375
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"id": 22344420,
3+
"label": "test_2",
4+
"group": "",
5+
"status": "billing_suspension",
6+
"created": "2020-12-07T14:58:19",
7+
"updated": "2020-12-07T14:58:19",
8+
"type": "g6-nanode-1",
9+
"ipv4": [
10+
"212.71.239.24"
11+
],
12+
"ipv6": "2a01:7e00::f03c:92ff:fe48:dc47/64",
13+
"image": "linode/centos8",
14+
"region": "eu-west",
15+
"specs": {
16+
"disk": 25600,
17+
"memory": 1024,
18+
"vcpus": 1,
19+
"gpus": 0,
20+
"transfer": 1000
21+
},
22+
"alerts": {
23+
"cpu": 90,
24+
"network_in": 10,
25+
"network_out": 10,
26+
"transfer_quota": 80,
27+
"io": 10000
28+
},
29+
"backups": {
30+
"enabled": false,
31+
"schedule": {
32+
"day": null,
33+
"window": null
34+
},
35+
"last_successful": null
36+
},
37+
"hypervisor": "kvm",
38+
"watchdog_enabled": true,
39+
"tags": [
40+
"testing"
41+
]
42+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"data": [
3+
{
4+
"id": 22344420,
5+
"label": "test_2",
6+
"group": "",
7+
"status": "busy",
8+
"created": "2020-10-08T18:51:29",
9+
"updated": "2020-10-08T18:51:29",
10+
"type": "g6-nanode-1",
11+
"ipv4": ["138.89.34.81", "192.168.1.230"],
12+
"ipv6": "2a01:7e00::f03c:92ff:fe48:dc47/64",
13+
"image": "linode/centos7",
14+
"region": "eu-west",
15+
"specs": {
16+
"disk": 25600,
17+
"memory": 1024,
18+
"vcpus": 1,
19+
"gpus": 0,
20+
"transfer": 1000
21+
},
22+
"alerts": {
23+
"cpu": 90,
24+
"network_in": 10,
25+
"network_out": 10,
26+
"transfer_quota": 80,
27+
"io": 10000
28+
},
29+
"backups": {
30+
"enabled": false,
31+
"schedule": {"day": null, "window": null},
32+
"last_successful": null
33+
},
34+
"capabilities": ["Block Storage Encryption"],
35+
"disk_encryption": "enabled",
36+
"has_user_data": true,
37+
"hypervisor": "kvm",
38+
"host_uuid": "3a3ddd59d9a78bb8de041391075df44de62bfec8",
39+
"interface_generation": "linode",
40+
"maintenance_policy": "linode/migrate",
41+
"placement_group": {"id": 528, "label": "pg-1"},
42+
"watchdog_enabled": true,
43+
"tags": ["testing"]
44+
}
45+
],
46+
"page": 1,
47+
"pages": 1,
48+
"results": 1
49+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"id": 123,
3+
"type": "PTR",
4+
"name": "10",
5+
"target": "host.example.com",
6+
"priority": 0,
7+
"weight": 0,
8+
"port": 0,
9+
"service": null,
10+
"protocol": null,
11+
"ttl_sec": 300,
12+
"tag": null,
13+
"created": "2020-10-16T07:57:37",
14+
"updated": "2020-10-16T07:57:37"
15+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"id": 123,
3+
"type": "master",
4+
"domain": "example.com",
5+
"tags": [],
6+
"group": "",
7+
"status": "active",
8+
"description": "",
9+
"soa_email": "admin@example.com",
10+
"retry_sec": 0,
11+
"master_ips": [],
12+
"axfr_ips": [
13+
"192.0.2.10",
14+
"198.51.100.11"
15+
],
16+
"expire_sec": 0,
17+
"refresh_sec": 0,
18+
"ttl_sec": 300,
19+
"created": "2020-10-16T09:08:50",
20+
"updated": "2020-10-16T09:08:50"
21+
}

libcloud/test/dns/test_linode_v4.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414

1515
import sys
16+
import json
1617
import unittest
1718

1819
from libcloud.test import MockHttp
@@ -81,6 +82,12 @@ def test_get_record_MX_RECORD(self):
8182
self.assertEqual(record.data, "mail.example.com")
8283
self.assertEqual(record.type, "MX")
8384

85+
def test_list_records_preserves_CAA_tag(self):
86+
zone = self.driver.list_zones()[0]
87+
records = self.driver.list_records(zone)
88+
caa_record = next(record for record in records if record.type == RecordType.CAA)
89+
self.assertEqual(caa_record.extra["tag"], "issue")
90+
8491
def test_create_zone(self):
8592
domain = "example.com"
8693
ttl = 300
@@ -90,6 +97,17 @@ def test_create_zone(self):
9097
self.assertEqual(zone.domain, "example.com")
9198
self.assertEqual(zone.extra["soa_email"], "admin@example.com")
9299

100+
def test_create_zone_accepts_axfr_ips(self):
101+
LinodeMockHttpV4.type = "CREATE_ZONE_AXFR_IPS"
102+
domain = "example.com"
103+
ttl = 300
104+
extra = {
105+
"soa_email": "admin@example.com",
106+
"axfr_ips": ["192.0.2.10", "198.51.100.11"],
107+
}
108+
zone = self.driver.create_zone(domain=domain, ttl=ttl, extra=extra)
109+
self.assertEqual(zone.extra["axfr_ips"], extra["axfr_ips"])
110+
93111
def test_create_record(self):
94112
zone = self.driver.list_zones()[0]
95113
name = "test"
@@ -101,6 +119,13 @@ def test_create_record(self):
101119
self.assertEqual(record.type, "A")
102120
self.assertEqual(record.data, data)
103121

122+
def test_create_record_PTR_RECORD(self):
123+
zone = self.driver.list_zones()[0]
124+
LinodeMockHttpV4.type = "PTR_RECORD"
125+
record = self.driver.create_record("10", zone, RecordType.PTR, "host.example.com")
126+
self.assertEqual(record.type, "PTR")
127+
self.assertEqual(record.data, "host.example.com")
128+
104129
def test_update_zone(self):
105130
zone = self.driver.list_zones()[0]
106131
domain = "example.com"
@@ -144,6 +169,12 @@ def _v4_domains(self, method, url, body, headers):
144169
body = self.fixtures.load("create_zone.json")
145170
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
146171

172+
def _v4_domains_CREATE_ZONE_AXFR_IPS(self, method, url, body, headers):
173+
payload = json.loads(body)
174+
self.assertEqual(payload["axfr_ips"], ["192.0.2.10", "198.51.100.11"])
175+
body = self.fixtures.load("create_zone_axfr_ips.json")
176+
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
177+
147178
def _v4_domains_123_records(self, method, url, body, headers):
148179
if method == "GET":
149180
body = self.fixtures.load("list_records.json")
@@ -152,6 +183,13 @@ def _v4_domains_123_records(self, method, url, body, headers):
152183
body = self.fixtures.load("create_record.json")
153184
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
154185

186+
def _v4_domains_123_records_PTR_RECORD(self, method, url, body, headers):
187+
payload = json.loads(body)
188+
self.assertEqual(payload["type"], "PTR")
189+
self.assertEqual(payload["target"], "host.example.com")
190+
body = self.fixtures.load("create_record_ptr.json")
191+
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
192+
155193
def _v4_domains_123(self, method, url, body, headers):
156194
if method == "GET":
157195
body = self.fixtures.load("get_zone.json")

0 commit comments

Comments
 (0)